// slang-repro.h #ifndef SLANG_REPRO_H_INCLUDED #define SLANG_REPRO_H_INCLUDED #include "../core/slang-riff.h" #include "../core/slang-string.h" // For TranslationUnitRequest #include "slang-compiler.h" #include "../core/slang-offset-container.h" #include "../core/slang-file-system.h" namespace Slang { /* Facilities to be able to save and load the full state of a compilation, including source files, and all compilation options into 'slang-repro' files. Repro is short for 'reproducible' and it's main purposes is to make compilations easily reproducible as everything that is needed from a compilation environment is packaged up into a single file. The single file can be used to repeat the compilation, or extracted such that everything that was specified in the compilation can be inspected and modified. */ struct ReproUtil { enum { kMajorVersion = 0, kMinorVersion = 0, kPatchVersion = 0, }; static const uint32_t kSlangStateFourCC = SLANG_FOUR_CC('S', 'L', 'S', 'T'); ///< Holds all the slang specific chunks static const RiffSemanticVersion g_semanticVersion; struct Header { RiffHeader m_chunk; ///< The chunk RiffSemanticVersion m_semanticVersion; ///< The semantic version uint32_t m_typeHash; ///< A hash based on the binary representation. If doesn't match then not binary compatible (extra check over semantic versioning) }; struct FileState { Offset32Ptr uniqueIdentity; ///< The unique identity for the file (from ISlangFileSystem), or nullptr Offset32Ptr contents; ///< The contents of this file Offset32Ptr canonicalPath; ///< The canonical name of this file (or nullptr) Offset32Ptr foundPath; ///< The 'found' path Offset32Ptr uniqueName; ///< A generated unique name (not used by slang, but used as mechanism to replace files) }; struct PathInfoState { typedef CacheFileSystem::CompressedResult CompressedResult; SlangPathType pathType = SLANG_PATH_TYPE_FILE; CompressedResult loadFileResult = CompressedResult::Uninitialized; CompressedResult getPathTypeResult = CompressedResult::Uninitialized; CompressedResult getCanonicalPathResult = CompressedResult::Uninitialized; Offset32Ptr file; ///< File contents }; struct PathAndPathInfo { Offset32Ptr path; Offset32Ptr pathInfo; }; struct OutputState { int32_t entryPointIndex; Offset32Ptr outputPath; }; // spSetCodeGenTarget/spAddCodeGenTarget // spSetTargetProfile // spSetTargetFlags // spSetTargetFloatingPointMode // spSetTargetMatrixLayoutMode struct TargetRequestState { Profile profile; CodeGenTarget target; SlangTargetFlags targetFlags; FloatingPointMode floatingPointMode; Offset32Array outputStates; }; struct StringPair { Offset32Ptr first; Offset32Ptr second; }; struct SourceFileState { PathInfo::Type type; ///< The type of this file Offset32Ptr foundPath; ///< The Path this was found along Offset32Ptr file; ///< The file contents }; // spAddTranslationUnit struct TranslationUnitRequestState { SourceLanguage language; Offset32Ptr moduleName; // spTranslationUnit_addPreprocessorDefine Offset32Array preprocessorDefinitions; Offset32Array > sourceFiles; }; struct EntryPointState { Offset32Ptr name; Profile profile; uint32_t translationUnitIndex; Offset32Array> specializationArgStrings; }; struct RequestState { Offset32Array> files; ///< All of the files Offset32Array> sourceFiles; ///< All of the source files (from source manager) // spSetCompileFlags SlangCompileFlags compileFlags; // spSetDumpIntermediates bool shouldDumpIntermediates; // spSetLineDirectiveMode LineDirectiveMode lineDirectiveMode; Offset32Array targetRequests; // spSetDebugInfoLevel DebugInfoLevel debugInfoLevel; // spSetOptimizationLevel OptimizationLevel optimizationLevel; // spSetOutputContainerFormat ContainerFormat containerFormat; // spSetPassThrough PassThroughMode passThroughMode; // spAddSearchPath Offset32Array > searchPaths; // spAddPreprocessorDefine Offset32Array preprocessorDefinitions; bool useUnknownImageFormatAsDefault = false; bool obfuscateCode = false; Offset32Array pathInfoMap; ///< Stores all the accesses to the file system Offset32Array translationUnits; Offset32Array entryPoints; SlangMatrixLayoutMode defaultMatrixLayoutMode; }; static SlangResult store(EndToEndCompileRequest* request, OffsetContainer& inOutContainer, Offset32Ptr& outRequest); static SlangResult saveState(EndToEndCompileRequest* request, const String& filename); static SlangResult saveState(EndToEndCompileRequest* request, Stream* stream); /// Create a cache file system that uses contents of the request state. /// The passed in fileSystem is used for accessing any file accesses not found in the cache static SlangResult loadFileSystem(OffsetBase& base, RequestState* requestState, ISlangFileSystem* fileSystem, RefPtr& outFileSystem); /// Load the requestState into request /// The fileSystem is optional and can be passed as nullptr. If set, as each file is loaded /// it will attempt to load from fileSystem the *uniqueName* static SlangResult load(OffsetBase& base, RequestState* requestState, ISlangFileSystem* fileSystem, EndToEndCompileRequest* request); static SlangResult loadState(const String& filename, DiagnosticSink* sink, List& outBuffer); static SlangResult loadState(Stream* stream, DiagnosticSink* sink, List& outBuffer); static SlangResult loadState(const uint8_t* data, size_t size, DiagnosticSink* sink, List& outBuffer); static RequestState* getRequest(const List& inBuffer); static SlangResult extractFilesToDirectory(const String& file, DiagnosticSink* sink); static SlangResult extractFiles(OffsetBase& base, RequestState* requestState, ISlangMutableFileSystem* fileSystem); /// Given the repo file work out a suitable path static SlangResult calcDirectoryPathFromFilename(const String& filename, String& outPath); /// Given a request trys to determine a suitable dump file name, that is unique. static SlangResult findUniqueReproDumpStream(EndToEndCompileRequest* request, String& outFileName, RefPtr& outStream); }; } // namespace Slang #endif