summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/repro.md20
-rw-r--r--slang.h30
-rw-r--r--source/core/slang-io.cpp4
-rw-r--r--source/core/slang-riff.cpp14
-rw-r--r--source/core/slang-stream.cpp478
-rw-r--r--source/core/slang-stream.h255
-rw-r--r--source/core/slang-text-io.cpp14
-rw-r--r--source/core/slang-text-io.h6
-rw-r--r--source/slang/slang-compiler.h13
-rw-r--r--source/slang/slang-file-system.cpp2
-rw-r--r--source/slang/slang-ir-serialize.cpp42
-rw-r--r--source/slang/slang-options.cpp2
-rw-r--r--source/slang/slang-state-serialize.cpp102
-rw-r--r--source/slang/slang-state-serialize.h8
-rw-r--r--source/slang/slang.cpp65
15 files changed, 637 insertions, 418 deletions
diff --git a/docs/repro.md b/docs/repro.md
index c50fc2a70..cbdd88c2f 100644
--- a/docs/repro.md
+++ b/docs/repro.md
@@ -34,9 +34,12 @@ There currently isn't a mechanism to alter the options of a repro from the comma
1) Altering the include paths - unless this may break the mechanism used to map paths to files stored in the repro file
2) Altering the ISlangFileSystem. That to make the contents of the file system appear to be that of the repro, slang uses a ISlangFileSystemExt that uses the contents of the repro file and/or the `repro directory`. If you replace the file system this mechanism will no longer work.
-There are currently two API calls for using the repro functionality
+There are currently several API calls for using the repro functionality
```
+SLANG_API SlangResult spEnableReproCapture(
+ SlangCompileRequest* request);
+
SLANG_API SlangResult spLoadRepro(
SlangCompileRequest* request,
ISlangFileSystem* fileSystem,
@@ -47,12 +50,21 @@ SLANG_API SlangResult spSaveRepro(
SlangCompileRequest* request,
ISlangBlob** outBlob
);
+
+SLANG_API SlangResult spExtractRepro(
+ SlangSession* session,
+ const void* reproData,
+ size_t reproDataSize,
+ ISlangFileSystemExt* fileSystem);
+
```
-The fileSystem parameter passed to `spLoadRepro` provides the mechanism for client code to replace the files that are held within the repro. NOTE! That the files will be loaded from this file system with their `unique names` as if they are part of the flat file system. If an attempt to load a file fails, the file within the repro is used. That `spLoadRepro` is typically performed on a new 'unused' SlangCompileRequest.
-
-That after `spLoadRepro`, normal functions to alter the state of the SlangCompileRequest are available.
+The fileSystem parameter passed to `spLoadRepro` provides the mechanism for client code to replace the files that are held within the repro. NOTE! That the files will be loaded from this file system with their `unique names` as if they are part of the flat file system. If an attempt to load a file fails, the file within the repro is used. That `spLoadRepro` is typically performed on a new 'unused' SlangCompileRequest. After a call to `spLoadRepro` normal functions to alter the state of the SlangCompileRequest are available.
+The function `spEnableReproCapture` should be set after any ISlangFileSystem has been set (if any), but before any compilation. It ensures that everything that the ISlangFileSystem accesses will be correctly recorded. Note that if a ISlangFileSystem/ISlangFileSystemExt isn't explicitly set (ie the default is used), then a request will automatically be set up to record everything appropriate and a call to this function isn't strictly required.
+
+The function `spExtractRepro` allows for extracting the files used in a request (along with the associated manifest). They files and manifest are stored under the 'unique names' in the root of the user provided ISlangFileSystemExt.
+
Repro files are currently stored in a binary format. This format is sensitive to changes in the API, as well as internal state within a SlangCompileRequest. This means that the functionality can only be guarenteed to work with exactly the same version of Slang on the same version of compiler. In practice things are typically not so draconian, and future versions will aim to provide a more clear slang repro versioning system, and work will be performed to make more generally usable.
Finally this version of the repo system does not take into account endianess at all. The system the repro is saved from must have the same endianess as the system loaded on.
diff --git a/slang.h b/slang.h
index a7e4b8aa7..3766dd457 100644
--- a/slang.h
+++ b/slang.h
@@ -1647,6 +1647,36 @@ extern "C"
ISlangBlob** outBlob
);
+ /** Enable repro capture.
+
+ Should be set after any ISlangFileSystem has been set, but before any compilation. It ensures that everything
+ that the ISlangFileSystem accesses will be correctly recorded.
+ Note that if a ISlangFileSystem/ISlangFileSystemExt isn't explicitly set (ie the default is used), then the
+ request will automatically be set up to record everything appropriate.
+
+ @param request The request
+ @returns A `SlangResult` to indicate success or failure.
+ */
+ SLANG_API SlangResult spEnableReproCapture(
+ SlangCompileRequest* request);
+
+ /** Extract contents of a repro.
+
+ Writes the contained files and manifest with their 'unique' names into fileSystem. For more details read the
+ docs/repro.md documentation.
+
+ @param session The slang session
+ @param reproData Holds the repro data
+ @param reproDataSize The size of the repro data
+ @param fileSystem File system that the contents of the repro will be written to
+ @returns A `SlangResult` to indicate success or failure.
+ */
+ SLANG_API SlangResult spExtractRepro(
+ SlangSession* session,
+ const void* reproData,
+ size_t reproDataSize,
+ ISlangFileSystemExt* fileSystem);
+
/*
Forward declarations of types used in the reflection interface;
*/
diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp
index caa45c8f4..6cff8e1c9 100644
--- a/source/core/slang-io.cpp
+++ b/source/core/slang-io.cpp
@@ -660,10 +660,10 @@ namespace Slang
{
RefPtr<FileStream> fs = new FileStream(fileName, FileMode::Open, FileAccess::Read, FileShare::ReadWrite);
List<unsigned char> buffer;
- while (!fs->IsEnd())
+ while (!fs->isEnd())
{
unsigned char ch;
- int read = (int)fs->Read(&ch, 1);
+ int read = (int)fs->read(&ch, 1);
if (read)
buffer.add(ch);
else
diff --git a/source/core/slang-riff.cpp b/source/core/slang-riff.cpp
index df2076013..ce8b7129b 100644
--- a/source/core/slang-riff.cpp
+++ b/source/core/slang-riff.cpp
@@ -20,7 +20,7 @@ namespace Slang
}
// Skip the payload (we don't need to skip the Chunk because that was already read
- stream->Seek(SeekOrigin::Current, chunkSize - sizeof(RiffChunk));
+ stream->seek(SeekOrigin::Current, chunkSize - sizeof(RiffChunk));
return SLANG_OK;
}
@@ -29,7 +29,7 @@ namespace Slang
{
try
{
- stream->Read(&outChunk, sizeof(RiffChunk));
+ stream->read(&outChunk, sizeof(RiffChunk));
}
catch (IOException&)
{
@@ -53,13 +53,13 @@ namespace Slang
try
{
- out->Write(&chunk, sizeof(chunk));
- out->Write(data, size);
+ out->write(&chunk, sizeof(chunk));
+ out->write(data, size);
size_t remaining = size & 3;
if (remaining)
{
uint8_t end[4] = { 0, 0, 0, 0};
- out->Write(end, 4 - remaining);
+ out->write(end, 4 - remaining);
}
}
catch (IOException&)
@@ -79,13 +79,13 @@ namespace Slang
try
{
- stream->Read(data.getBuffer(), outChunk.m_size);
+ stream->read(data.getBuffer(), outChunk.m_size);
// Skip to the alignment
uint32_t remaining = outChunk.m_size & 3;
if (remaining)
{
- stream->Seek(SeekOrigin::Current, 4 - remaining);
+ stream->seek(SeekOrigin::Current, 4 - remaining);
}
}
catch (IOException&)
diff --git a/source/core/slang-stream.cpp b/source/core/slang-stream.cpp
index ee194c451..b5eef1d9b 100644
--- a/source/core/slang-stream.cpp
+++ b/source/core/slang-stream.cpp
@@ -6,289 +6,301 @@
namespace Slang
{
- FileStream::FileStream(const Slang::String & fileName, FileMode fileMode)
- {
- Init(fileName, fileMode, fileMode==FileMode::Open?FileAccess::Read:FileAccess::Write, FileShare::None);
- }
- FileStream::FileStream(const Slang::String & fileName, FileMode fileMode, FileAccess access, FileShare share)
- {
- Init(fileName, fileMode, access, share);
- }
- void FileStream::Init(const Slang::String & fileName, FileMode fileMode, FileAccess access, FileShare share)
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FileStream !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+FileStream::FileStream(const String& fileName, FileMode fileMode)
+{
+ _init(fileName, fileMode, fileMode==FileMode::Open?FileAccess::Read:FileAccess::Write, FileShare::None);
+}
+
+FileStream::FileStream(const String& fileName, FileMode fileMode, FileAccess access, FileShare share)
+{
+ _init(fileName, fileMode, access, share);
+}
+
+void FileStream::_init(const String& fileName, FileMode fileMode, FileAccess access, FileShare share)
+{
+ const wchar_t * mode = L"rt";
+ const char* modeMBCS = "rt";
+ switch (fileMode)
{
- const wchar_t * mode = L"rt";
- const char* modeMBCS = "rt";
- switch (fileMode)
+ case FileMode::Create:
+ if (access == FileAccess::Read)
+ throw ArgumentException("Read-only access is incompatible with Create mode.");
+ else if (access == FileAccess::ReadWrite)
{
- case Slang::FileMode::Create:
- if (access == FileAccess::Read)
- throw ArgumentException("Read-only access is incompatible with Create mode.");
- else if (access == FileAccess::ReadWrite)
- {
- mode = L"w+b";
- modeMBCS = "w+b";
- this->fileAccess = FileAccess::ReadWrite;
- }
- else
- {
- mode = L"wb";
- modeMBCS = "wb";
- this->fileAccess = FileAccess::Write;
- }
- break;
- case Slang::FileMode::Open:
- if (access == FileAccess::Read)
- {
- mode = L"rb";
- modeMBCS = "rb";
- this->fileAccess = FileAccess::Read;
- }
- else if (access == FileAccess::ReadWrite)
- {
- mode = L"r+b";
- modeMBCS = "r+b";
- this->fileAccess = FileAccess::ReadWrite;
- }
- else
- {
- mode = L"wb";
- modeMBCS = "wb";
- this->fileAccess = FileAccess::Write;
- }
- break;
- case Slang::FileMode::CreateNew:
- if (File::exists(fileName))
- {
- throw IOException("Failed opening '" + fileName + "', file already exists.");
- }
- if (access == FileAccess::Read)
- throw ArgumentException("Read-only access is incompatible with Create mode.");
- else if (access == FileAccess::ReadWrite)
- {
- mode = L"w+b";
- this->fileAccess = FileAccess::ReadWrite;
- }
- else
- {
- mode = L"wb";
- this->fileAccess = FileAccess::Write;
- }
- break;
- case Slang::FileMode::Append:
- if (access == FileAccess::Read)
- throw ArgumentException("Read-only access is incompatible with Append mode.");
- else if (access == FileAccess::ReadWrite)
- {
- mode = L"a+b";
- this->fileAccess = FileAccess::ReadWrite;
- }
- else
- {
- mode = L"ab";
- this->fileAccess = FileAccess::Write;
- }
- break;
- default:
- break;
+ mode = L"w+b";
+ modeMBCS = "w+b";
+ this->m_fileAccess = FileAccess::ReadWrite;
}
-#ifdef _WIN32
- int shFlag = _SH_DENYRW;
- switch (share)
+ else
{
- case Slang::FileShare::None:
- shFlag = _SH_DENYRW;
- break;
- case Slang::FileShare::ReadOnly:
- shFlag = _SH_DENYWR;
- break;
- case Slang::FileShare::WriteOnly:
- shFlag = _SH_DENYRD;
- break;
- case Slang::FileShare::ReadWrite:
- shFlag = _SH_DENYNO;
- break;
- default:
- throw ArgumentException("Invalid file share mode.");
- break;
+ mode = L"wb";
+ modeMBCS = "wb";
+ this->m_fileAccess = FileAccess::Write;
}
- if (share == Slang::FileShare::None)
-#pragma warning(suppress:4996)
- handle = _wfopen(fileName.toWString(), mode);
- else
- handle = _wfsopen(fileName.toWString(), mode, shFlag);
-#else
- handle = fopen(fileName.getBuffer(), modeMBCS);
-#endif
- if (!handle)
+ break;
+ case FileMode::Open:
+ if (access == FileAccess::Read)
+ {
+ mode = L"rb";
+ modeMBCS = "rb";
+ this->m_fileAccess = FileAccess::Read;
+ }
+ else if (access == FileAccess::ReadWrite)
+ {
+ mode = L"r+b";
+ modeMBCS = "r+b";
+ this->m_fileAccess = FileAccess::ReadWrite;
+ }
+ else
{
- throw IOException("Cannot open file '" + fileName + "'");
+ mode = L"wb";
+ modeMBCS = "wb";
+ this->m_fileAccess = FileAccess::Write;
}
+ break;
+ case FileMode::CreateNew:
+ if (File::exists(fileName))
+ {
+ throw IOException("Failed opening '" + fileName + "', file already exists.");
+ }
+ if (access == FileAccess::Read)
+ throw ArgumentException("Read-only access is incompatible with Create mode.");
+ else if (access == FileAccess::ReadWrite)
+ {
+ mode = L"w+b";
+ this->m_fileAccess = FileAccess::ReadWrite;
+ }
+ else
+ {
+ mode = L"wb";
+ this->m_fileAccess = FileAccess::Write;
+ }
+ break;
+ case FileMode::Append:
+ if (access == FileAccess::Read)
+ throw ArgumentException("Read-only access is incompatible with Append mode.");
+ else if (access == FileAccess::ReadWrite)
+ {
+ mode = L"a+b";
+ this->m_fileAccess = FileAccess::ReadWrite;
+ }
+ else
+ {
+ mode = L"ab";
+ this->m_fileAccess = FileAccess::Write;
+ }
+ break;
+ default:
+ break;
}
- FileStream::~FileStream()
+#ifdef _WIN32
+ int shFlag = _SH_DENYRW;
+ switch (share)
{
- Close();
+ case FileShare::None:
+ shFlag = _SH_DENYRW;
+ break;
+ case FileShare::ReadOnly:
+ shFlag = _SH_DENYWR;
+ break;
+ case FileShare::WriteOnly:
+ shFlag = _SH_DENYRD;
+ break;
+ case FileShare::ReadWrite:
+ shFlag = _SH_DENYNO;
+ break;
+ default:
+ throw ArgumentException("Invalid file share mode.");
+ break;
}
- Int64 FileStream::GetPosition()
+ if (share == FileShare::None)
+#pragma warning(suppress:4996)
+ m_handle = _wfopen(fileName.toWString(), mode);
+ else
+ m_handle = _wfsopen(fileName.toWString(), mode, shFlag);
+#else
+ m_handle = fopen(fileName.getBuffer(), modeMBCS);
+#endif
+ if (!m_handle)
{
+ throw IOException("Cannot open file '" + fileName + "'");
+ }
+}
+
+FileStream::~FileStream()
+{
+ close();
+}
+
+Int64 FileStream::getPosition()
+{
#if defined(_WIN32) || defined(__CYGWIN__)
- fpos_t pos;
- fgetpos(handle, &pos);
- return pos;
+ fpos_t pos;
+ fgetpos(m_handle, &pos);
+ return pos;
#elif defined(__APPLE__)
- return ftell(handle);
+ return ftell(m_handle);
#else
- fpos64_t pos;
- fgetpos64(handle, &pos);
- return *(Int64*)(&pos);
+ fpos64_t pos;
+ fgetpos64(m_handle, &pos);
+ return *(Int64*)(&pos);
#endif
- }
- void FileStream::Seek(SeekOrigin origin, Int64 offset)
+}
+void FileStream::seek(SeekOrigin origin, Int64 offset)
+{
+ int _origin;
+ switch (origin)
{
- int _origin;
- switch (origin)
- {
- case Slang::SeekOrigin::Start:
- _origin = SEEK_SET;
- endReached = false;
- break;
- case Slang::SeekOrigin::End:
- _origin = SEEK_END;
- // JS TODO: This doesn't seem right, the offset can mean it's not at the end
- endReached = true;
- break;
- case Slang::SeekOrigin::Current:
- _origin = SEEK_CUR;
- endReached = false;
- break;
- default:
- throw NotSupportedException("Unsupported seek origin.");
- break;
- }
+ case SeekOrigin::Start:
+ _origin = SEEK_SET;
+ m_endReached = false;
+ break;
+ case SeekOrigin::End:
+ _origin = SEEK_END;
+ // JS TODO: This doesn't seem right, the offset can mean it's not at the end
+ m_endReached = true;
+ break;
+ case SeekOrigin::Current:
+ _origin = SEEK_CUR;
+ m_endReached = false;
+ break;
+ default:
+ throw NotSupportedException("Unsupported seek origin.");
+ break;
+ }
#ifdef _WIN32
- int rs = _fseeki64(handle, offset, _origin);
+ int rs = _fseeki64(m_handle, offset, _origin);
#else
- int rs = fseek(handle, (int)offset, _origin);
+ int rs = fseek(m_handle, (int)offset, _origin);
#endif
- if (rs != 0)
- {
- throw IOException("FileStream seek failed.");
- }
- }
- Int64 FileStream::Read(void * buffer, Int64 length)
- {
- auto bytes = fread_s(buffer, (size_t)length, 1, (size_t)length, handle);
- if (bytes == 0 && length > 0)
- {
- if (!feof(handle))
- throw IOException("FileStream read failed.");
- else if (endReached)
- throw EndOfStreamException("End of file is reached.");
- endReached = true;
- }
- return (int)bytes;
- }
- Int64 FileStream::Write(const void * buffer, Int64 length)
- {
- auto bytes = (Int64)fwrite(buffer, 1, (size_t)length, handle);
- if (bytes < length)
- {
- throw IOException("FileStream write failed.");
- }
- return bytes;
- }
- bool FileStream::CanRead()
+ if (rs != 0)
{
- return ((int)fileAccess & (int)FileAccess::Read) != 0;
+ throw IOException("FileStream seek failed.");
}
- bool FileStream::CanWrite()
+}
+Int64 FileStream::read(void* buffer, Int64 length)
+{
+ auto bytes = fread_s(buffer, (size_t)length, 1, (size_t)length, m_handle);
+ if (bytes == 0 && length > 0)
{
- return ((int)fileAccess & (int)FileAccess::Write) != 0;
+ if (!feof(m_handle))
+ throw IOException("FileStream read failed.");
+ else if (m_endReached)
+ throw EndOfStreamException("End of file is reached.");
+ m_endReached = true;
}
- void FileStream::Close()
+ return (int)bytes;
+}
+Int64 FileStream::write(const void* buffer, Int64 length)
+{
+ auto bytes = (Int64)fwrite(buffer, 1, (size_t)length, m_handle);
+ if (bytes < length)
{
- if (handle)
- {
- fclose(handle);
- handle = 0;
- }
+ throw IOException("FileStream write failed.");
}
- bool FileStream::IsEnd()
+ return bytes;
+}
+bool FileStream::canRead()
+{
+ return ((int)m_fileAccess & (int)FileAccess::Read) != 0;
+}
+bool FileStream::canWrite()
+{
+ return ((int)m_fileAccess & (int)FileAccess::Write) != 0;
+}
+void FileStream::close()
+{
+ if (m_handle)
{
- return endReached;
+ fclose(m_handle);
+ m_handle = 0;
}
+}
+bool FileStream::isEnd()
+{
+ return m_endReached;
+}
- // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MemoryStream !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MemoryStreamBase !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- void MemoryStream::Seek(SeekOrigin origin, Int64 offset)
+void MemoryStreamBase::seek(SeekOrigin origin, Int64 offset)
+{
+ Int64 pos = 0;
+ switch (origin)
{
- Int64 pos = 0;
- switch (origin)
- {
- case Slang::SeekOrigin::Start:
+ case SeekOrigin::Start:
pos = offset;
break;
- case Slang::SeekOrigin::End:
- pos = Int64(m_contents.getCount()) + offset;
+ case SeekOrigin::End:
+ pos = Int64(m_contentsSize) + offset;
break;
- case Slang::SeekOrigin::Current:
+ case SeekOrigin::Current:
pos = Int64(m_position) + offset;
break;
default:
throw NotSupportedException("Unsupported seek origin.");
break;
- }
+ }
- m_atEnd = false;
+ m_atEnd = false;
- // Clamp to the valid range
- pos = (pos < 0) ? 0 : pos;
- pos = (pos > Int64(m_contents.getCount())) ? Int64(m_contents.getCount()) : pos;
+ // Clamp to the valid range
+ pos = (pos < 0) ? 0 : pos;
+ pos = (pos > Int64(m_contentsSize)) ? Int64(m_contentsSize) : pos;
- m_position = UInt(pos);
+ m_position = UInt(pos);
+}
+
+Int64 MemoryStreamBase::read(void* buffer, Int64 length)
+{
+ if (!canRead())
+ {
+ throw IOException("Cannot read this stream.");
}
- Int64 MemoryStream::Read(void * buffer, Int64 length)
+ const Int64 maxRead = Int64(m_contentsSize - m_position);
+
+ if (maxRead == 0 && length > 0)
{
- if (!CanRead())
- {
- throw IOException("Cannot read this stream.");
- }
+ m_atEnd = true;
+ throw EndOfStreamException("End of file is reached.");
+ }
- const Int64 maxRead = Int64(m_contents.getCount() - m_position);
-
- if (maxRead == 0 && length > 0)
- {
- m_atEnd = true;
- throw EndOfStreamException("End of file is reached.");
- }
+ length = length > maxRead ? maxRead : length;
- length = length > maxRead ? maxRead : length;
+ ::memcpy(buffer, m_contents + m_position, size_t(length));
+ m_position += UInt(length);
+ return maxRead;
+}
- ::memcpy(buffer, m_contents.begin() + m_position, size_t(length));
- m_position += UInt(length);
- return maxRead;
- }
-
- Int64 MemoryStream::Write(const void * buffer, Int64 length)
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! OwnedMemoryStream !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+Int64 OwnedMemoryStream::write(const void * buffer, Int64 length)
+{
+ if (!canWrite())
{
- if (!CanWrite())
- {
- throw IOException("Cannot write this stream.");
- }
+ throw IOException("Cannot write this stream.");
+ }
- if (m_position == m_contents.getCount())
- {
- m_contents.addRange((const uint8_t*)buffer, UInt(length));
- }
- else
- {
- m_contents.insertRange(m_position, (const uint8_t*)buffer, UInt(length));
- }
+ if (m_position == m_ownedContents.getCount())
+ {
+ m_ownedContents.addRange((const uint8_t*)buffer, UInt(length));
+ }
+ else
+ {
+ m_ownedContents.insertRange(m_position, (const uint8_t*)buffer, UInt(length));
+ }
- m_atEnd = false;
+ m_contents = m_ownedContents.getBuffer();
+ m_contentsSize = ptrdiff_t(m_ownedContents.getCount());
- m_position += UInt(length);
- return length;
- }
+ m_atEnd = false;
+ m_position += ptrdiff_t(length);
+ return length;
}
+
+} // namespace Slang
diff --git a/source/core/slang-stream.h b/source/core/slang-stream.h
index 67e04fa6a..8b8a6decf 100644
--- a/source/core/slang-stream.h
+++ b/source/core/slang-stream.h
@@ -5,109 +5,170 @@
namespace Slang
{
- class IOException : public Exception
- {
- public:
- IOException()
- {}
- IOException(const String & message)
- : Slang::Exception(message)
- {
- }
- };
-
- class EndOfStreamException : public IOException
- {
- public:
- EndOfStreamException()
- {}
- EndOfStreamException(const String & message)
- : IOException(message)
- {
- }
- };
-
- enum class SeekOrigin
- {
- Start, End, Current
- };
- class Stream : public RefObject
- {
- public:
- virtual ~Stream() {}
- virtual Int64 GetPosition()=0;
- virtual void Seek(SeekOrigin origin, Int64 offset)=0;
- virtual Int64 Read(void * buffer, Int64 length) = 0;
- virtual Int64 Write(const void * buffer, Int64 length) = 0;
- virtual bool IsEnd() = 0;
- virtual bool CanRead() = 0;
- virtual bool CanWrite() = 0;
- virtual void Close() = 0;
- };
-
- enum class FileMode
+class IOException : public Exception
+{
+public:
+ IOException()
+ {}
+ IOException(const String & message)
+ : Slang::Exception(message)
{
- Create, Open, CreateNew, Append
- };
+ }
+};
- enum class FileAccess
+class EndOfStreamException : public IOException
+{
+public:
+ EndOfStreamException()
+ {}
+ EndOfStreamException(const String & message)
+ : IOException(message)
{
- None = 0, Read = 1, Write = 2, ReadWrite = 3
- };
+ }
+};
- enum class FileShare
- {
- None, ReadOnly, WriteOnly, ReadWrite
- };
+enum class SeekOrigin
+{
+ Start, End, Current
+};
+
+class Stream : public RefObject
+{
+public:
+ virtual ~Stream() {}
+ virtual Int64 getPosition()=0;
+ virtual void seek(SeekOrigin origin, Int64 offset)=0;
+ virtual Int64 read(void * buffer, Int64 length) = 0;
+ virtual Int64 write(const void * buffer, Int64 length) = 0;
+ virtual bool isEnd() = 0;
+ virtual bool canRead() = 0;
+ virtual bool canWrite() = 0;
+ virtual void close() = 0;
+};
+
+enum class FileMode
+{
+ Create, Open, CreateNew, Append
+};
+
+enum class FileAccess
+{
+ None = 0, Read = 1, Write = 2, ReadWrite = 3
+};
- class MemoryStream : public Stream
+enum class FileShare
+{
+ None, ReadOnly, WriteOnly, ReadWrite
+};
+
+/// Base class for memory streams. Only supports reading and does NOT own contained data.
+class MemoryStreamBase : public Stream
+{
+public:
+ typedef Stream Super;
+
+ virtual Int64 getPosition() SLANG_OVERRIDE { return m_position; }
+ virtual void seek(SeekOrigin origin, Int64 offset) SLANG_OVERRIDE;
+ virtual Int64 read(void * buffer, Int64 length) SLANG_OVERRIDE;
+ virtual Int64 write(const void * buffer, Int64 length) SLANG_OVERRIDE { SLANG_UNUSED(buffer); SLANG_UNUSED(length); return 0; }
+ virtual bool isEnd() SLANG_OVERRIDE { return m_atEnd; }
+ virtual bool canRead() SLANG_OVERRIDE { return (int(m_access) & int(FileAccess::Read)) != 0; }
+ virtual bool canWrite() SLANG_OVERRIDE { return (int(m_access) & int(FileAccess::Write)) != 0; }
+ virtual void close() SLANG_OVERRIDE { m_access = FileAccess::None; }
+
+ MemoryStreamBase(FileAccess access = FileAccess::Read, const void* contents = nullptr, size_t contentsSize = 0):
+ m_access(access)
{
- public:
- virtual Int64 GetPosition() SLANG_OVERRIDE { return m_position; }
- virtual void Seek(SeekOrigin origin, Int64 offset) SLANG_OVERRIDE;
- virtual Int64 Read(void * buffer, Int64 length) SLANG_OVERRIDE;
- virtual Int64 Write(const void * buffer, Int64 length) SLANG_OVERRIDE;
- virtual bool IsEnd() SLANG_OVERRIDE { return m_atEnd; }
- virtual bool CanRead() SLANG_OVERRIDE { return (int(m_access) & int(FileAccess::Read)) != 0; }
- virtual bool CanWrite() SLANG_OVERRIDE { return (int(m_access) & int(FileAccess::Write)) != 0; }
- virtual void Close() SLANG_OVERRIDE { m_access = FileAccess::None; }
-
- MemoryStream(FileAccess access) :
- m_access(access),
- m_position(0),
- m_atEnd(false)
- {}
-
- Index m_position;
-
- bool m_atEnd; ///< Happens when a read is done and nothing can be returned because already at end
-
- FileAccess m_access;
- List<uint8_t> m_contents;
- };
-
- class FileStream : public Stream
- {
- private:
- FILE * handle;
- FileAccess fileAccess;
- bool endReached = false;
- void Init(const Slang::String & fileName, FileMode fileMode, FileAccess access, FileShare share);
- public:
- FileStream(const Slang::String & fileName, FileMode fileMode = FileMode::Open);
- FileStream(const Slang::String & fileName, FileMode fileMode, FileAccess access, FileShare share);
- ~FileStream();
- public:
- virtual Int64 GetPosition();
- virtual void Seek(SeekOrigin origin, Int64 offset);
- virtual Int64 Read(void * buffer, Int64 length);
- virtual Int64 Write(const void * buffer, Int64 length);
- virtual bool CanRead();
- virtual bool CanWrite();
- virtual void Close();
- virtual bool IsEnd();
- };
-}
+ _setContents(contents, contentsSize);
+ }
+
+protected:
+ /// Set to replace wholly current content with specified content
+ void _setContents(const void* contents, size_t contentsSize)
+ {
+ m_contents = (const uint8_t*)contents;
+ m_contentsSize = ptrdiff_t(contentsSize);
+ m_position = 0;
+ m_atEnd = false;
+ }
+ /// Update means that the content has changed, but position should be maintained
+ void _updateContents(const void* contents, size_t contentsSize)
+ {
+ const ptrdiff_t newPosition = (m_position > ptrdiff_t(contentsSize)) ? ptrdiff_t(contentsSize) : m_position;
+ _setContents(contents, contentsSize);
+ m_position = newPosition;
+ }
+
+ const uint8_t* m_contents; ///< The content held in the stream
+
+ // Using ptrdiff_t (as opposed to size_t) as makes maths simpler
+ ptrdiff_t m_contentsSize; ///< Total size of the content in bytes
+ ptrdiff_t m_position; ///< The current position within content (valid values can only be between 0 and m_contentSize)
+
+ bool m_atEnd; ///< Happens when a read is done and nothing can be returned because already at end
+
+ FileAccess m_access;
+};
+
+/// Memory stream that owns it's contents
+class OwnedMemoryStream : public MemoryStreamBase
+{
+public:
+ typedef MemoryStreamBase Super;
+
+ virtual Int64 write(const void* buffer, Int64 length) SLANG_OVERRIDE;
+
+ /// Set the contents
+ void setContent(const void* contents, size_t contentsSize)
+ {
+ m_ownedContents.setCount(contentsSize);
+ ::memcpy(m_ownedContents.getBuffer(), contents, contentsSize);
+ _setContents(m_ownedContents.getBuffer(), m_ownedContents.getCount());
+ }
+
+ void swapContents(List<uint8_t>& rhs)
+ {
+ rhs.swapWith(m_ownedContents);
+ _setContents(m_ownedContents.getBuffer(), m_ownedContents.getCount());
+ }
+
+ OwnedMemoryStream(FileAccess access) :
+ Super(access)
+ {}
+
+protected:
+
+ List<uint8_t> m_ownedContents;
+};
+
+class FileStream : public Stream
+{
+public:
+ typedef Stream Super;
+
+ // Stream interface
+ virtual Int64 getPosition();
+ virtual void seek(SeekOrigin origin, Int64 offset);
+ virtual Int64 read(void* buffer, Int64 length);
+ virtual Int64 write(const void* buffer, Int64 length);
+ virtual bool canRead();
+ virtual bool canWrite();
+ virtual void close();
+ virtual bool isEnd();
+
+ FileStream(const String& fileName, FileMode fileMode = FileMode::Open);
+ FileStream(const String& fileName, FileMode fileMode, FileAccess access, FileShare share);
+ ~FileStream();
+
+private:
+ void _init(const String& fileName, FileMode fileMode, FileAccess access, FileShare share);
+
+ FILE* m_handle;
+ FileAccess m_fileAccess;
+ bool m_endReached = false;
+};
+
+} // namespace Slang
#endif
diff --git a/source/core/slang-text-io.cpp b/source/core/slang-text-io.cpp
index 18039e41b..4e989b627 100644
--- a/source/core/slang-text-io.cpp
+++ b/source/core/slang-text-io.cpp
@@ -126,11 +126,11 @@ namespace Slang
this->encoding = encoding;
if (encoding == Encoding::UTF16)
{
- this->stream->Write(&Utf16Header, 2);
+ this->stream->write(&Utf16Header, 2);
}
else if (encoding == Encoding::UTF16Reversed)
{
- this->stream->Write(&Utf16ReversedHeader, 2);
+ this->stream->write(&Utf16ReversedHeader, 2);
}
}
StreamWriter::StreamWriter(RefPtr<Stream> stream, Encoding * encoding)
@@ -139,11 +139,11 @@ namespace Slang
this->encoding = encoding;
if (encoding == Encoding::UTF16)
{
- this->stream->Write(&Utf16Header, 2);
+ this->stream->write(&Utf16Header, 2);
}
else if (encoding == Encoding::UTF16Reversed)
{
- this->stream->Write(&Utf16ReversedHeader, 2);
+ this->stream->write(&Utf16ReversedHeader, 2);
}
}
void StreamWriter::Write(const String & str)
@@ -169,7 +169,7 @@ namespace Slang
sb << str[i];
}
encoding->GetBytes(encodingBuffer, sb.ProduceString());
- stream->Write(encodingBuffer.getBuffer(), encodingBuffer.getCount());
+ stream->write(encodingBuffer.getBuffer(), encodingBuffer.getCount());
}
void StreamWriter::Write(const char * str)
{
@@ -237,7 +237,7 @@ namespace Slang
{
buffer.setCount(4096);
memset(buffer.getBuffer(), 0, buffer.getCount() * sizeof(buffer[0]));
- auto len = stream->Read(buffer.getBuffer(), buffer.getCount());
+ auto len = stream->read(buffer.getBuffer(), buffer.getCount());
buffer.setCount((int)len);
ptr = 0;
}
@@ -248,7 +248,7 @@ namespace Slang
{
return buffer[ptr++];
}
- if (!stream->IsEnd())
+ if (!stream->isEnd())
ReadBuffer();
if (ptr<buffer.getCount())
{
diff --git a/source/core/slang-text-io.h b/source/core/slang-text-io.h
index ac9a4f5dc..b5a9ad0e1 100644
--- a/source/core/slang-text-io.h
+++ b/source/core/slang-text-io.h
@@ -259,7 +259,7 @@ namespace Slang
virtual void Write(const char * str);
virtual void Close()
{
- stream->Close();
+ stream->close();
}
void ReleaseStream()
{
@@ -300,11 +300,11 @@ namespace Slang
virtual String ReadToEnd();
virtual bool IsEnd()
{
- return ptr == buffer.getCount() && stream->IsEnd();
+ return ptr == buffer.getCount() && stream->isEnd();
}
virtual void Close()
{
- stream->Close();
+ stream->close();
}
void ReleaseStream()
{
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index 9b361064d..1e1f166de 100644
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -1172,17 +1172,19 @@ namespace Slang
/// If this member is `null`, a default implementation that tries
/// to use the native OS filesystem will be used instead.
///
- ComPtr<ISlangFileSystem> fileSystem;
+ ComPtr<ISlangFileSystem> m_fileSystem;
/// The extended file system implementation. Will be set to a default implementation
/// if fileSystem is nullptr. Otherwise it will either be fileSystem's interface,
/// or a wrapped impl that makes fileSystem operate as fileSystemExt
- ComPtr<ISlangFileSystemExt> fileSystemExt;
+ ComPtr<ISlangFileSystemExt> m_fileSystemExt;
+
/// Set if fileSystemExt is a cache file system
- RefPtr<CacheFileSystem> cacheFileSystem;
+ RefPtr<CacheFileSystem> m_cacheFileSystem;
- ISlangFileSystemExt* getFileSystemExt() { return fileSystemExt; }
+ ISlangFileSystemExt* getFileSystemExt() { return m_fileSystemExt; }
+ CacheFileSystem* getCacheFileSystem() const { return m_cacheFileSystem; }
/// Load a file into memory using the configured file system.
///
@@ -1192,7 +1194,6 @@ namespace Slang
///
SlangResult loadFile(String const& path, PathInfo& outPathInfo, ISlangBlob** outBlob);
-
RefPtr<Expr> parseTypeString(String typeStr, RefPtr<Scope> scope);
Type* specializeType(
@@ -1230,7 +1231,7 @@ namespace Slang
return m_sourceManager;
}
- /// Override the source manager for the linakge.
+ /// Override the source manager for the linkage.
///
/// This is only used to install a temporary override when
/// parsing stuff from strings (where we don't want to retain
diff --git a/source/slang/slang-file-system.cpp b/source/slang/slang-file-system.cpp
index 4ee961df5..7d6d6df66 100644
--- a/source/slang/slang-file-system.cpp
+++ b/source/slang/slang-file-system.cpp
@@ -138,7 +138,7 @@ SLANG_NO_THROW SlangResult SLANG_MCALL OSFileSystemExt::saveFile(const char* pat
{
FileStream stream(pathIn, FileMode::Create, FileAccess::Write, FileShare::ReadWrite);
- int64_t numWritten = stream.Write(data, size);
+ int64_t numWritten = stream.write(data, size);
if (numWritten != int64_t(size))
{
diff --git a/source/slang/slang-ir-serialize.cpp b/source/slang/slang-ir-serialize.cpp
index 02ed3142d..c82592527 100644
--- a/source/slang/slang-ir-serialize.cpp
+++ b/source/slang/slang-ir-serialize.cpp
@@ -847,9 +847,9 @@ static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType,
header.m_chunk.m_size = uint32_t(payloadSize);
header.m_numEntries = uint32_t(numEntries);
- stream->Write(&header, sizeof(header));
+ stream->write(&header, sizeof(header));
- stream->Write(data, typeSize * numEntries);
+ stream->write(data, typeSize * numEntries);
break;
}
case Bin::CompressionType::VariableByteLite:
@@ -868,9 +868,9 @@ static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType,
header.m_numEntries = uint32_t(numEntries);
header.m_numCompressedEntries = uint32_t(numCompressedEntries);
- stream->Write(&header, sizeof(header));
+ stream->write(&header, sizeof(header));
- stream->Write(compressedPayload.begin(), compressedPayload.getCount());
+ stream->write(compressedPayload.begin(), compressedPayload.getCount());
break;
}
default:
@@ -884,7 +884,7 @@ static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType,
const uint8_t pad[4] = { 0, 0, 0, 0 };
// Pad outs
int padSize = 4 - (payloadSize & 3);
- stream->Write(pad, padSize);
+ stream->write(pad, padSize);
}
return SLANG_OK;
@@ -1013,8 +1013,8 @@ Result _writeInstArrayChunk(IRSerialBinary::CompressionType compressionType, uin
header.m_numEntries = uint32_t(array.getCount());
header.m_numCompressedEntries = 0;
- stream->Write(&header, sizeof(header));
- stream->Write(compressedPayload.begin(), compressedPayload.getCount());
+ stream->write(&header, sizeof(header));
+ stream->write(compressedPayload.begin(), compressedPayload.getCount());
// All chunks have sizes rounded to dword size
if (payloadSize & 3)
@@ -1022,7 +1022,7 @@ Result _writeInstArrayChunk(IRSerialBinary::CompressionType compressionType, uin
const uint8_t pad[4] = { 0, 0, 0, 0 };
// Pad outs
int padSize = 4 - (payloadSize & 3);
- stream->Write(pad, padSize);
+ stream->write(pad, padSize);
}
return SLANG_OK;
}
@@ -1128,7 +1128,7 @@ static size_t _calcInstChunkSize(IRSerialBinary::CompressionType compressionType
riffHeader.m_type = Bin::kRiffFourCc;
riffHeader.m_size = uint32_t(totalSize);
- stream->Write(&riffHeader, sizeof(riffHeader));
+ stream->write(&riffHeader, sizeof(riffHeader));
}
{
Bin::SlangHeader slangHeader;
@@ -1136,7 +1136,7 @@ static size_t _calcInstChunkSize(IRSerialBinary::CompressionType compressionType
slangHeader.m_chunk.m_size = uint32_t(sizeof(slangHeader) - sizeof(RiffChunk));
slangHeader.m_compressionType = uint32_t(Bin::CompressionType::VariableByteLite);
- stream->Write(&slangHeader, sizeof(slangHeader));
+ stream->write(&slangHeader, sizeof(slangHeader));
}
SLANG_RETURN_ON_FAIL(_writeInstArrayChunk(compressionType, Bin::kInstFourCc, data.m_insts, stream));
@@ -1206,7 +1206,7 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, c
Bin::CompressedArrayHeader header;
header.m_chunk = chunk;
- stream->Read(&header.m_chunk + 1, sizeof(header) - sizeof(RiffChunk));
+ stream->read(&header.m_chunk + 1, sizeof(header) - sizeof(RiffChunk));
*numReadInOut += sizeof(header) - sizeof(RiffChunk);
void* data = listOut.setSize(header.m_numEntries);
@@ -1217,7 +1217,7 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, c
List<uint8_t> compressedPayload;
compressedPayload.setCount(payloadSize);
- stream->Read(compressedPayload.begin(), payloadSize);
+ stream->read(compressedPayload.begin(), payloadSize);
*numReadInOut += payloadSize;
SLANG_ASSERT(header.m_numCompressedEntries == uint32_t((header.m_numEntries * typeSize) / sizeof(uint32_t)));
@@ -1232,14 +1232,14 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, c
Bin::ArrayHeader header;
header.m_chunk = chunk;
- stream->Read(&header.m_chunk + 1, sizeof(header) - sizeof(RiffChunk));
+ stream->read(&header.m_chunk + 1, sizeof(header) - sizeof(RiffChunk));
*numReadInOut += sizeof(header) - sizeof(RiffChunk);
const size_t payloadSize = header.m_numEntries * typeSize;
void* data = listOut.setSize(header.m_numEntries);
- stream->Read(data, payloadSize);
+ stream->read(data, payloadSize);
*numReadInOut += payloadSize;
break;
}
@@ -1251,7 +1251,7 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, c
const uint8_t pad[4] = { 0, 0, 0, 0 };
// Pad outs
int padSize = 4 - int(*numReadInOut & 3);
- stream->Seek(SeekOrigin::Current, padSize);
+ stream->seek(SeekOrigin::Current, padSize);
*numReadInOut += padSize;
}
@@ -1374,7 +1374,7 @@ static Result _readInstArrayChunk(const IRSerialBinary::SlangHeader& slangHeader
Bin::CompressedArrayHeader header;
header.m_chunk = chunk;
- stream->Read(&header.m_chunk + 1, sizeof(header) - sizeof(RiffChunk));
+ stream->read(&header.m_chunk + 1, sizeof(header) - sizeof(RiffChunk));
*numReadInOut += sizeof(header) - sizeof(RiffChunk);
// Need to read all the compressed data...
@@ -1383,7 +1383,7 @@ static Result _readInstArrayChunk(const IRSerialBinary::SlangHeader& slangHeader
List<uint8_t> compressedPayload;
compressedPayload.setCount(payloadSize);
- stream->Read(compressedPayload.begin(), payloadSize);
+ stream->read(compressedPayload.begin(), payloadSize);
*numReadInOut += payloadSize;
arrayOut.setCount(header.m_numEntries);
@@ -1402,7 +1402,7 @@ static Result _readInstArrayChunk(const IRSerialBinary::SlangHeader& slangHeader
{
// Pad outs
int padSize = 4 - int(*numReadInOut & 3);
- stream->Seek(SeekOrigin::Current, padSize);
+ stream->seek(SeekOrigin::Current, padSize);
*numReadInOut += padSize;
}
@@ -1449,7 +1449,7 @@ static Result _readInstArrayChunk(const IRSerialBinary::SlangHeader& slangHeader
// NOTE! Really we should only read what we know the size to be...
// and skip if it's larger
- stream->Read(&slangHeader.m_chunk + 1, sizeof(slangHeader) - sizeof(chunk));
+ stream->read(&slangHeader.m_chunk + 1, sizeof(slangHeader) - sizeof(chunk));
remainingBytes -= RiffUtil::calcChunkTotalSize(chunk);
break;
@@ -1964,11 +1964,11 @@ static int _calcFixSourceLoc(const IRSerialData::DebugSourceInfo& info, SourceVi
}
// Write the data out to stream
- MemoryStream memoryStream(FileAccess::ReadWrite);
+ OwnedMemoryStream memoryStream(FileAccess::ReadWrite);
SLANG_RETURN_ON_FAIL(IRSerialWriter::writeStream(serialData, compressionType, &memoryStream));
// Reset stream
- memoryStream.Seek(SeekOrigin::Start, 0);
+ memoryStream.seek(SeekOrigin::Start, 0);
IRSerialData readData;
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index 2e1b625d9..6b09179db 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -496,7 +496,7 @@ struct OptionsParser
else if (argStr == "-dump-repro")
{
SLANG_RETURN_ON_FAIL(tryReadCommandLineArgument(sink, arg, &argCursor, argEnd, requestImpl->dumpRepro));
- requestImpl->getLinkage()->setRequireCacheFileSystem(true);
+ spEnableReproCapture(asExternal(requestImpl));
}
else if (argStr == "-extract-repro")
{
diff --git a/source/slang/slang-state-serialize.cpp b/source/slang/slang-state-serialize.cpp
index b37529121..110ea52b2 100644
--- a/source/slang/slang-state-serialize.cpp
+++ b/source/slang/slang-state-serialize.cpp
@@ -318,15 +318,49 @@ static bool _isStorable(const PathInfo::Type type)
for (Index i = 0; i < linkage->targets.getCount(); ++i)
{
- auto& dst = dstTargets[i];
- TargetRequest* targetRequest = linkage->targets[i];
+ TargetRequest* srcTargetRequest = linkage->targets[i];
- dst.target = targetRequest->getTarget();
- dst.profile = targetRequest->getTargetProfile();
- dst.targetFlags = targetRequest->targetFlags;
- dst.floatingPointMode = targetRequest->floatingPointMode;
- }
+ // Copy the simple stuff
+ {
+ auto& dst = dstTargets[i];
+ dst.target = srcTargetRequest->getTarget();
+ dst.profile = srcTargetRequest->getTargetProfile();
+ dst.targetFlags = srcTargetRequest->targetFlags;
+ dst.floatingPointMode = srcTargetRequest->floatingPointMode;
+ }
+
+ // Copy the entry point/target output names
+ {
+ const auto& srcTargetInfos = request->targetInfos;
+
+ if (RefPtr<EndToEndCompileRequest::TargetInfo>* infosPtr = srcTargetInfos.TryGetValue(srcTargetRequest))
+ {
+ EndToEndCompileRequest::TargetInfo* infos = *infosPtr;
+
+ const auto& entryPointOutputPaths = infos->entryPointOutputPaths;
+
+ Safe32Array<OutputState> dstOutputStates;
+ dstOutputStates = inOutContainer.allocateArray<OutputState>(entryPointOutputPaths.Count());
+ Index index = 0;
+ for (const auto& pair : entryPointOutputPaths)
+ {
+ Safe32Ptr<RelativeString> outputPath = inOutContainer.newString(pair.Value.getUnownedSlice());
+
+ auto& dstOutputState = dstOutputStates[index];
+
+ dstOutputState.entryPointIndex = int32_t(pair.Key);
+ dstOutputState.outputPath = outputPath;
+
+ index++;
+ }
+
+ dstTargets[i].outputStates = dstOutputStates;
+ }
+ }
+ }
+
+ // Save the result
requestState->targetRequests = dstTargets;
}
@@ -383,7 +417,12 @@ static bool _isStorable(const PathInfo::Type type)
// Find files from the file system, and mapping paths to files
{
- CacheFileSystem* cacheFileSystem = linkage->cacheFileSystem;
+ CacheFileSystem* cacheFileSystem = linkage->getCacheFileSystem();
+ if (!cacheFileSystem)
+ {
+ return SLANG_FAIL;
+ }
+
// Traverse the references (in process we will construct the map from PathInfo)
{
const auto& srcFiles = cacheFileSystem->getPathMap();
@@ -651,8 +690,17 @@ static void _loadDefines(const Relative32Array<StateSerializeUtil::StringPair>&
{
auto externalRequest = asExternal(request);
+
auto linkage = request->getLinkage();
+ // TODO(JS): Really should be more exhaustive here, and set up to initial state ideally
+ // Reset state
+ {
+ request->targetInfos.Clear();
+ // Remove any requests
+ linkage->targets.clear();
+ }
+
LoadContext context(linkage->getSourceManager(), fileSystem);
// Try to set state through API - as doing so means if state stored in multiple places it will be ok
@@ -671,20 +719,41 @@ static void _loadDefines(const Relative32Array<StateSerializeUtil::StringPair>&
linkage->setMatrixLayoutMode(requestState->defaultMatrixLayoutMode);
}
+
+ // Add the target requests
{
for (Index i = 0; i < requestState->targetRequests.getCount(); ++i)
{
TargetRequestState& src = requestState->targetRequests[i];
int index = spAddCodeGenTarget(externalRequest, SlangCompileTarget(src.target));
- SLANG_UNUSED(index);
SLANG_ASSERT(index == i);
- auto dstTarget = linkage->targets[i];
+ auto dstTarget = linkage->targets[index];
SLANG_ASSERT(dstTarget->getTarget() == src.target);
dstTarget->targetProfile = src.profile;
dstTarget->targetFlags = src.targetFlags;
dstTarget->floatingPointMode = src.floatingPointMode;
+
+ // If there is output state (like output filenames) add here
+ if (src.outputStates.getCount())
+ {
+ RefPtr<EndToEndCompileRequest::TargetInfo> dstTargetInfo(new EndToEndCompileRequest::TargetInfo);
+ request->targetInfos[dstTarget] = dstTargetInfo;
+
+ for (const auto& srcOutputState : src.outputStates)
+ {
+ SLANG_ASSERT(srcOutputState.entryPointIndex < requestState->entryPoints.getCount());
+
+ String entryPointPath;
+ if (srcOutputState.outputPath)
+ {
+ entryPointPath = srcOutputState.outputPath->getSlice();
+ }
+
+ dstTargetInfo->entryPointOutputPaths.Add(srcOutputState.entryPointIndex, entryPointPath);
+ }
+ }
}
}
@@ -744,6 +813,9 @@ static void _loadDefines(const Relative32Array<StateSerializeUtil::StringPair>&
// Entry points
{
+ // Check there aren't any set entry point
+ SLANG_ASSERT(request->getFrontEndReq()->m_entryPointReqs.getCount() == 0);
+
for (const auto& srcEntryPoint : requestState->entryPoints)
{
const char* name = srcEntryPoint.name ? srcEntryPoint.name->getCstr() : nullptr;
@@ -782,8 +854,8 @@ static void _loadDefines(const Relative32Array<StateSerializeUtil::StringPair>&
// This is a bit of a hack, we are going to replace the file system, with our one which is filled in
// with what was read from the file.
- linkage->fileSystemExt = cacheFileSystem;
- linkage->cacheFileSystem = cacheFileSystem;
+ linkage->m_fileSystemExt = cacheFileSystem;
+ linkage->m_cacheFileSystem = cacheFileSystem;
}
return SLANG_OK;
@@ -834,11 +906,7 @@ static void _loadDefines(const Relative32Array<StateSerializeUtil::StringPair>&
/* static */SlangResult StateSerializeUtil::loadState(const uint8_t* data, size_t size, List<uint8_t>& outBuffer)
{
- MemoryStream stream(FileAccess::Read);
-
- stream.m_contents.setCount(size);
- ::memcpy(stream.m_contents.getBuffer(), data, size);
-
+ MemoryStreamBase stream(FileAccess::Read, data, size);
return loadState(&stream, outBuffer);
}
diff --git a/source/slang/slang-state-serialize.h b/source/slang/slang-state-serialize.h
index f43cc8d45..dbd1e3992 100644
--- a/source/slang/slang-state-serialize.h
+++ b/source/slang/slang-state-serialize.h
@@ -52,6 +52,12 @@ struct StateSerializeUtil
Relative32Ptr<PathInfoState> pathInfo;
};
+ struct OutputState
+ {
+ int32_t entryPointIndex;
+ Relative32Ptr<RelativeString> outputPath;
+ };
+
// spSetCodeGenTarget/spAddCodeGenTarget
// spSetTargetProfile
// spSetTargetFlags
@@ -63,6 +69,8 @@ struct StateSerializeUtil
CodeGenTarget target;
SlangTargetFlags targetFlags;
FloatingPointMode floatingPointMode;
+
+ Relative32Array<OutputState> outputStates;
};
struct FileReference
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 19ac6ea1f..8479d3202 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -800,11 +800,11 @@ SlangResult Linkage::loadFile(String const& path, PathInfo& outPathInfo, ISlangB
{
outPathInfo.type = PathInfo::Type::Unknown;
- SLANG_RETURN_ON_FAIL(fileSystemExt->loadFile(path.getBuffer(), outBlob));
+ SLANG_RETURN_ON_FAIL(m_fileSystemExt->loadFile(path.getBuffer(), outBlob));
ComPtr<ISlangBlob> uniqueIdentity;
// Get the unique identity
- SLANG_RETURN_ON_FAIL(fileSystemExt->getFileUniqueIdentity(path.getBuffer(), uniqueIdentity.writeRef()));
+ SLANG_RETURN_ON_FAIL(m_fileSystemExt->getFileUniqueIdentity(path.getBuffer(), uniqueIdentity.writeRef()));
outPathInfo.foundPath = path;
outPathInfo.type = PathInfo::Type::FoundPath;
@@ -2489,17 +2489,17 @@ static const Slang::Guid IID_SlangCacheFileSystem = SLANG_UUID_CacheFileSystem;
void Linkage::setFileSystem(ISlangFileSystem* inFileSystem)
{
// Set the fileSystem
- fileSystem = inFileSystem;
+ m_fileSystem = inFileSystem;
// Release what's there
- fileSystemExt.setNull();
- cacheFileSystem.setNull();
+ m_fileSystemExt.setNull();
+ m_cacheFileSystem.setNull();
// If nullptr passed in set up default
if (inFileSystem == nullptr)
{
- cacheFileSystem = new Slang::CacheFileSystem(Slang::OSFileSystemExt::getSingleton());
- fileSystemExt = cacheFileSystem;
+ m_cacheFileSystem = new Slang::CacheFileSystem(Slang::OSFileSystemExt::getSingleton());
+ m_fileSystemExt = m_cacheFileSystem;
}
else
{
@@ -2507,34 +2507,34 @@ void Linkage::setFileSystem(ISlangFileSystem* inFileSystem)
inFileSystem->queryInterface(IID_SlangCacheFileSystem, (void**)&cacheFileSystemPtr);
if (cacheFileSystemPtr)
{
- cacheFileSystem = cacheFileSystemPtr;
- fileSystemExt = cacheFileSystemPtr;
+ m_cacheFileSystem = cacheFileSystemPtr;
+ m_fileSystemExt = cacheFileSystemPtr;
}
else
{
if (m_requireCacheFileSystem)
{
- cacheFileSystem = new Slang::CacheFileSystem(inFileSystem);
- fileSystemExt = cacheFileSystem;
+ m_cacheFileSystem = new Slang::CacheFileSystem(inFileSystem);
+ m_fileSystemExt = m_cacheFileSystem;
}
else
{
// See if we have the full ISlangFileSystemExt interface, if we do just use it
- inFileSystem->queryInterface(IID_ISlangFileSystemExt, (void**)fileSystemExt.writeRef());
+ inFileSystem->queryInterface(IID_ISlangFileSystemExt, (void**)m_fileSystemExt.writeRef());
// If not wrap with CacheFileSystem that emulates ISlangFileSystemExt from the ISlangFileSystem interface
- if (!fileSystemExt)
+ if (!m_fileSystemExt)
{
// Construct a wrapper to emulate the extended interface behavior
- cacheFileSystem = new Slang::CacheFileSystem(fileSystem);
- fileSystemExt = cacheFileSystem;
+ m_cacheFileSystem = new Slang::CacheFileSystem(m_fileSystem);
+ m_fileSystemExt = m_cacheFileSystem;
}
}
}
}
// Set the file system used on the source manager
- getSourceManager()->setFileSystemExt(fileSystemExt);
+ getSourceManager()->setFileSystemExt(m_fileSystemExt);
}
void Linkage::setRequireCacheFileSystem(bool requireCacheFileSystem)
@@ -2544,7 +2544,7 @@ void Linkage::setRequireCacheFileSystem(bool requireCacheFileSystem)
return;
}
- ComPtr<ISlangFileSystem> scopeFileSystem(fileSystem);
+ ComPtr<ISlangFileSystem> scopeFileSystem(m_fileSystem);
m_requireCacheFileSystem = requireCacheFileSystem;
setFileSystem(scopeFileSystem);
@@ -3478,17 +3478,44 @@ SLANG_API SlangResult spSaveRepro(
using namespace Slang;
auto request = asInternal(inRequest);
- MemoryStream stream(FileAccess::Write);
+ OwnedMemoryStream stream(FileAccess::Write);
SLANG_RETURN_ON_FAIL(StateSerializeUtil::saveState(request, &stream));
RefPtr<ListBlob> listBlob(new ListBlob);
- listBlob->m_data.swapWith(stream.m_contents);
+
+ // Put the content of the stream in the blob
+ stream.swapContents(listBlob->m_data);
*outBlob = listBlob.detach();
return SLANG_OK;
}
+SLANG_API SlangResult spEnableReproCapture(
+ SlangCompileRequest* inRequest)
+{
+ using namespace Slang;
+ auto request = asInternal(inRequest);
+
+ request->getLinkage()->setRequireCacheFileSystem(true);
+ return SLANG_OK;
+}
+
+SLANG_API SlangResult spExtractRepro(SlangSession* session, const void* reproData, size_t reproDataSize, ISlangFileSystemExt* fileSystem)
+{
+ using namespace Slang;
+ SLANG_UNUSED(session);
+
+ List<uint8_t> buffer;
+ {
+ MemoryStreamBase memoryStream(FileAccess::Read, reproData, reproDataSize);
+ SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadState(&memoryStream, buffer));
+ }
+
+ StateSerializeUtil::RequestState* requestState = StateSerializeUtil::getRequest(buffer);
+ return StateSerializeUtil::extractFiles(requestState, fileSystem);
+}
+
// Reflection API
SLANG_API SlangResult spCompileRequest_getProgram(