1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
|
// 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<OffsetString> uniqueIdentity; ///< The unique identity for the file (from ISlangFileSystem), or nullptr
Offset32Ptr<OffsetString> contents; ///< The contents of this file
Offset32Ptr<OffsetString> canonicalPath; ///< The canonical name of this file (or nullptr)
Offset32Ptr<OffsetString> foundPath; ///< The 'found' path
Offset32Ptr<OffsetString> 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<FileState> file; ///< File contents
};
struct PathAndPathInfo
{
Offset32Ptr<OffsetString> path;
Offset32Ptr<PathInfoState> pathInfo;
};
struct OutputState
{
int32_t entryPointIndex;
Offset32Ptr<OffsetString> outputPath;
};
// spSetCodeGenTarget/spAddCodeGenTarget
// spSetTargetProfile
// spSetTargetFlags
// spSetTargetFloatingPointMode
// spSetTargetMatrixLayoutMode
struct TargetRequestState
{
Profile profile;
CodeGenTarget target;
SlangTargetFlags targetFlags;
FloatingPointMode floatingPointMode;
Offset32Array<OutputState> outputStates;
};
struct StringPair
{
Offset32Ptr<OffsetString> first;
Offset32Ptr<OffsetString> second;
};
struct SourceFileState
{
PathInfo::Type type; ///< The type of this file
Offset32Ptr<OffsetString> foundPath; ///< The Path this was found along
Offset32Ptr<FileState> file; ///< The file contents
};
// spAddTranslationUnit
struct TranslationUnitRequestState
{
SourceLanguage language;
Offset32Ptr<OffsetString> moduleName;
// spTranslationUnit_addPreprocessorDefine
Offset32Array<StringPair> preprocessorDefinitions;
Offset32Array<Offset32Ptr<SourceFileState> > sourceFiles;
};
struct EntryPointState
{
Offset32Ptr<OffsetString> name;
Profile profile;
uint32_t translationUnitIndex;
Offset32Array<Offset32Ptr<OffsetString>> specializationArgStrings;
};
struct RequestState
{
Offset32Array<Offset32Ptr<FileState>> files; ///< All of the files
Offset32Array<Offset32Ptr<SourceFileState>> sourceFiles; ///< All of the source files (from source manager)
// spSetCompileFlags
SlangCompileFlags compileFlags;
// spSetDumpIntermediates
bool shouldDumpIntermediates;
// spSetLineDirectiveMode
LineDirectiveMode lineDirectiveMode;
Offset32Array<TargetRequestState> targetRequests;
// spSetDebugInfoLevel
DebugInfoLevel debugInfoLevel;
// spSetOptimizationLevel
OptimizationLevel optimizationLevel;
// spSetOutputContainerFormat
ContainerFormat containerFormat;
// spSetPassThrough
PassThroughMode passThroughMode;
// spAddSearchPath
Offset32Array<Offset32Ptr<OffsetString> > searchPaths;
// spAddPreprocessorDefine
Offset32Array<StringPair> preprocessorDefinitions;
bool useUnknownImageFormatAsDefault = false;
bool obfuscateCode = false;
Offset32Array<PathAndPathInfo> pathInfoMap; ///< Stores all the accesses to the file system
Offset32Array<TranslationUnitRequestState> translationUnits;
Offset32Array<EntryPointState> entryPoints;
SlangMatrixLayoutMode defaultMatrixLayoutMode;
};
static SlangResult store(EndToEndCompileRequest* request, OffsetContainer& inOutContainer, Offset32Ptr<RequestState>& 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<CacheFileSystem>& 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<uint8_t>& outBuffer);
static SlangResult loadState(Stream* stream, DiagnosticSink* sink, List<uint8_t>& outBuffer);
static SlangResult loadState(const uint8_t* data, size_t size, DiagnosticSink* sink, List<uint8_t>& outBuffer);
static RequestState* getRequest(const List<uint8_t>& 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<Stream>& outStream);
};
} // namespace Slang
#endif
|