summaryrefslogtreecommitdiffstats
path: root/source/slang/slang.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang.cpp')
-rw-r--r--source/slang/slang.cpp185
1 files changed, 116 insertions, 69 deletions
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 613fb7090..602446cda 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -687,34 +687,31 @@ SlangResult Session::_readBuiltinModule(
StringBuilder moduleFilename;
moduleFilename << moduleName << ".slang-module";
- RiffContainer riffContainer;
- {
- // Load it
- ComPtr<ISlangBlob> blob;
- SLANG_RETURN_ON_FAIL(fileSystem->loadFile(moduleFilename.getBuffer(), blob.writeRef()));
-
- // Set up a stream
- MemoryStreamBase stream(FileAccess::Read, blob->getBufferPointer(), blob->getBufferSize());
+ // Load it
+ ComPtr<ISlangBlob> fileContents;
+ SLANG_RETURN_ON_FAIL(fileSystem->loadFile(moduleFilename.getBuffer(), fileContents.writeRef()));
- // Load the riff container
- SLANG_RETURN_ON_FAIL(RiffUtil::read(&stream, riffContainer));
+ RIFF::RootChunk const* rootChunk = RIFF::RootChunk::getFromBlob(fileContents);
+ if (!rootChunk)
+ {
+ return SLANG_FAIL;
}
Linkage* linkage = getBuiltinLinkage();
SourceManager* sourceManager = getBuiltinSourceManager();
NamePool* sessionNamePool = &namePool;
- auto moduleChunk = ModuleChunkRef::find(&riffContainer);
+ auto moduleChunk = ModuleChunk::find(rootChunk);
if (!moduleChunk)
return SLANG_FAIL;
- SHA1::Digest moduleDigest = moduleChunk.getDigest();
+ SHA1::Digest moduleDigest = moduleChunk->getDigest();
- auto irChunk = moduleChunk.findIR();
+ auto irChunk = moduleChunk->findIR();
if (!irChunk)
return SLANG_FAIL;
- auto astChunk = moduleChunk.findAST();
+ auto astChunk = moduleChunk->findAST();
if (!astChunk)
return SLANG_FAIL;
@@ -724,7 +721,7 @@ SlangResult Session::_readBuiltinModule(
// in the IR and AST deserialization (if we find anything).
//
RefPtr<SerialSourceLocReader> sourceLocReader;
- if (auto debugChunk = findDebugChunk(moduleChunk.ptr()))
+ if (auto debugChunk = DebugChunk::find(moduleChunk))
{
SLANG_RETURN_ON_FAIL(
readSourceLocationsFromDebugChunk(debugChunk, sourceManager, sourceLocReader));
@@ -4134,7 +4131,8 @@ void Linkage::loadParsedModule(
}
RefPtr<Module> Linkage::findOrLoadSerializedModuleForModuleLibrary(
- ModuleChunkRef moduleChunk,
+ ModuleChunk const* moduleChunk,
+ RIFF::ListChunk const* libraryChunk,
DiagnosticSink* sink)
{
RefPtr<Module> resultModule;
@@ -4147,7 +4145,7 @@ RefPtr<Module> Linkage::findOrLoadSerializedModuleForModuleLibrary(
// The first step is to simply decode the module name, and
// see if we have a already loaded a matching module.
- auto moduleName = getNamePool()->getName(moduleChunk.getName());
+ auto moduleName = getNamePool()->getName(moduleChunk->getName());
if (mapNameToLoadedModules.tryGetValue(moduleName, resultModule))
return resultModule;
@@ -4163,12 +4161,12 @@ RefPtr<Module> Linkage::findOrLoadSerializedModuleForModuleLibrary(
// already. It isn't something that can be fixed in just one
// place at this point.
- auto fileDependenciesChunk = moduleChunk.getFileDependencies();
- auto firstFileDependencyChunk = fileDependenciesChunk.getFirst();
+ auto fileDependenciesList = moduleChunk->getFileDependencies();
+ auto firstFileDependencyChunk = fileDependenciesList.getFirst();
if (!firstFileDependencyChunk)
return nullptr;
- auto modulePathInfo = PathInfo::makePath(firstFileDependencyChunk.getValue());
+ auto modulePathInfo = PathInfo::makePath(firstFileDependencyChunk->getValue());
if (mapPathToLoadedModule.tryGetValue(modulePathInfo.getMostUniqueIdentity(), resultModule))
return resultModule;
@@ -4176,13 +4174,20 @@ RefPtr<Module> Linkage::findOrLoadSerializedModuleForModuleLibrary(
// will go ahead and load the module from the serialized form.
//
PathInfo filePathInfo;
- return loadSerializedModule(moduleName, modulePathInfo, moduleChunk, SourceLoc(), sink);
+ return loadSerializedModule(
+ moduleName,
+ modulePathInfo,
+ moduleChunk,
+ libraryChunk,
+ SourceLoc(),
+ sink);
}
RefPtr<Module> Linkage::loadSerializedModule(
Name* moduleName,
const PathInfo& moduleFilePathInfo,
- ModuleChunkRef moduleChunk,
+ ModuleChunk const* moduleChunk,
+ RIFF::ListChunk const* containerChunk,
SourceLoc const& requestingLoc,
DiagnosticSink* sink)
{
@@ -4211,8 +4216,12 @@ RefPtr<Module> Linkage::loadSerializedModule(
mapNameToLoadedModules.add(moduleName, module);
try
{
- if (SLANG_FAILED(
- loadSerializedModuleContents(module, moduleFilePathInfo, moduleChunk, sink)))
+ if (SLANG_FAILED(loadSerializedModuleContents(
+ module,
+ moduleFilePathInfo,
+ moduleChunk,
+ containerChunk,
+ sink)))
{
mapPathToLoadedModule.remove(mostUniqueIdentity);
mapNameToLoadedModules.remove(moduleName);
@@ -4240,24 +4249,17 @@ RefPtr<Module> Linkage::loadBinaryModuleImpl(
auto astBuilder = getASTBuilder();
SLANG_AST_BUILDER_RAII(astBuilder);
- // We start by reading the content of the file into
+ // We start by reading the content of the file as
// an in-memory RIFF container.
//
- // TODO(tfoley): this is an unnecessary copy step, since
- // we can simply use the contents of the blob directly
- // and navigate it in-memory.
- //
- RiffContainer riffContainer;
+ auto rootChunk = RIFF::RootChunk::getFromBlob(moduleFileContents);
+ if (!rootChunk)
{
- MemoryStreamBase readStream(
- FileAccess::Read,
- moduleFileContents->getBufferPointer(),
- moduleFileContents->getBufferSize());
- SLANG_RETURN_NULL_ON_FAIL(RiffUtil::read(&readStream, riffContainer));
+ return nullptr;
}
- auto moduleChunkRef = ModuleChunkRef::find(&riffContainer);
- if (!moduleChunkRef)
+ auto moduleChunk = ModuleChunk::find(rootChunk);
+ if (!moduleChunk)
{
return nullptr;
}
@@ -4271,7 +4273,7 @@ RefPtr<Module> Linkage::loadBinaryModuleImpl(
SLANG_ASSERT(mostUniqueIdentity.getLength() > 0);
if (m_optionSet.getBoolOption(CompilerOptionName::UseUpToDateBinaryModule))
{
- if (!isBinaryModuleUpToDate(moduleFilePathInfo.foundPath, moduleChunkRef))
+ if (!isBinaryModuleUpToDate(moduleFilePathInfo.foundPath, moduleChunk))
{
return nullptr;
}
@@ -4280,8 +4282,13 @@ RefPtr<Module> Linkage::loadBinaryModuleImpl(
// If everything seems reasonable, then we will go ahead and load
// the module more completely from that serialized representation.
//
- RefPtr<Module> module =
- loadSerializedModule(moduleName, moduleFilePathInfo, moduleChunkRef, requestingLoc, sink);
+ RefPtr<Module> module = loadSerializedModule(
+ moduleName,
+ moduleFilePathInfo,
+ moduleChunk,
+ rootChunk,
+ requestingLoc,
+ sink);
return module;
}
@@ -4744,18 +4751,13 @@ SourceFile* Linkage::loadSourceFile(String pathFrom, String path)
}
// Check if a serialized module is up-to-date with current compiler options and source files.
-bool Linkage::isBinaryModuleUpToDate(String fromPath, RiffContainer* riffContainer)
+bool Linkage::isBinaryModuleUpToDate(String fromPath, RIFF::ListChunk const* baseChunk)
{
- auto moduleChunk = ModuleChunkRef::find(riffContainer);
+ auto moduleChunk = ModuleChunk::find(baseChunk);
if (!moduleChunk)
return false;
- return isBinaryModuleUpToDate(fromPath, moduleChunk);
-}
-
-bool Linkage::isBinaryModuleUpToDate(String fromPath, ModuleChunkRef moduleChunk)
-{
- SHA1::Digest existingDigest = moduleChunk.getDigest();
+ SHA1::Digest existingDigest = moduleChunk->getDigest();
DigestBuilder<SHA1> digestBuilder;
auto version = String(getBuildTagString());
@@ -4765,10 +4767,10 @@ bool Linkage::isBinaryModuleUpToDate(String fromPath, ModuleChunkRef moduleChunk
// Find the canonical path of the directory containing the module source file.
String moduleSrcPath = "";
- auto dependencyChunks = moduleChunk.getFileDependencies();
+ auto dependencyChunks = moduleChunk->getFileDependencies();
if (auto firstDependencyChunk = dependencyChunks.getFirst())
{
- moduleSrcPath = firstDependencyChunk.getValue();
+ moduleSrcPath = firstDependencyChunk->getValue();
IncludeSystem includeSystem(
&getSearchDirectories(),
@@ -4784,7 +4786,7 @@ bool Linkage::isBinaryModuleUpToDate(String fromPath, ModuleChunkRef moduleChunk
for (auto dependencyChunk : dependencyChunks)
{
- auto file = dependencyChunk.getValue();
+ auto file = dependencyChunk->getValue();
auto sourceFile = loadSourceFile(fromPath, file);
if (!sourceFile)
{
@@ -4803,14 +4805,10 @@ bool Linkage::isBinaryModuleUpToDate(String fromPath, ModuleChunkRef moduleChunk
SLANG_NO_THROW bool SLANG_MCALL
Linkage::isBinaryModuleUpToDate(const char* modulePath, slang::IBlob* binaryModuleBlob)
{
- RiffContainer container;
- MemoryStreamBase readStream(
- FileAccess::Read,
- binaryModuleBlob->getBufferPointer(),
- binaryModuleBlob->getBufferSize());
- if (SLANG_FAILED(RiffUtil::read(&readStream, container)))
+ auto rootChunk = RIFF::RootChunk::getFromBlob(binaryModuleBlob);
+ if (!rootChunk)
return false;
- return isBinaryModuleUpToDate(modulePath, &container);
+ return isBinaryModuleUpToDate(modulePath, rootChunk);
}
SourceFile* Linkage::findFile(Name* name, SourceLoc loc, IncludeSystem& outIncludeSystem)
@@ -6534,7 +6532,8 @@ void Linkage::setFileSystem(ISlangFileSystem* inFileSystem)
SlangResult Linkage::loadSerializedModuleContents(
Module* module,
const PathInfo& moduleFilePathInfo,
- ModuleChunkRef moduleChunk,
+ ModuleChunk const* moduleChunk,
+ RIFF::ListChunk const* containerChunk,
DiagnosticSink* sink)
{
// At this point we've dealt with basically all of
@@ -6542,19 +6541,49 @@ SlangResult Linkage::loadSerializedModuleContents(
// to the real work of decoding the information
// in the `moduleChunk`.
+ //
+ // TODO(tfoley): The fact that a separate `containerChunk` is getting
+ // passed in here is entirely byproduct of the support for "module libraries"
+ // that can (in principle) contain multiple serialized modules. When
+ // things are serialized in the "container" representation used for
+ // a module library, there is a single `DebugChunk` as a child of
+ // the container, with all of the `ModuleChunk`s sharing that debug info.
+ //
+ // In contrast, the more typical kind of serialized module that the compiler
+ // produces serializes a single `ModuleChunk`, and the `DebugChunk` is
+ // one of its direct children. Thus there are currently two different
+ // locations where debug information might be found.
+ //
+ // Prior to the change where we navigate the serialized RIFF hierarchy
+ // in memory without copying it, this issue was addressed by having
+ // the subroutine that looked for a `DebugChunk` start at the `ModuleChunk`
+ // and work its way up through the hierarchy using parent pointers that
+ // were created as part of RIFF loading. When navigating the RIFF in-place
+ // we don't have such parent pointers.
+ //
+ // As a short-term solution, we should deprecate and remove the support
+ // for "module libraries" so that the code doesn't have to handle two
+ // different layouts.
+ //
+ // In the longer term, we should be making some conscious design decisions
+ // around how we want to organize the top-level structure of our serialized
+ // intermediate/output formats, since there's quite a mix of different
+ // approaches currently in use.
+ //
+
auto sourceManager = getSourceManager();
RefPtr<SerialSourceLocReader> sourceLocReader;
- if (auto debugChunk = findDebugChunk(moduleChunk.ptr()))
+ if (auto debugChunk = DebugChunk::find(moduleChunk, containerChunk))
{
SLANG_RETURN_ON_FAIL(
readSourceLocationsFromDebugChunk(debugChunk, sourceManager, sourceLocReader));
}
- auto astChunk = moduleChunk.findAST();
+ auto astChunk = moduleChunk->findAST();
if (!astChunk)
return SLANG_FAIL;
- auto irChunk = moduleChunk.findIR();
+ auto irChunk = moduleChunk->findIR();
if (!irChunk)
return SLANG_FAIL;
@@ -6620,9 +6649,9 @@ SlangResult Linkage::loadSerializedModuleContents(
module->clearFileDependency();
String moduleSourcePath = moduleFilePathInfo.foundPath;
bool isFirst = true;
- for (auto depenencyFileChunk : moduleChunk.getFileDependencies())
+ for (auto depenencyFileChunk : moduleChunk->getFileDependencies())
{
- auto encodedDependencyFilePath = depenencyFileChunk.getValue();
+ auto encodedDependencyFilePath = depenencyFileChunk->getValue();
auto sourceFile = loadSourceFile(moduleFilePathInfo.foundPath, encodedDependencyFilePath);
if (isFirst)
@@ -6646,7 +6675,7 @@ SlangResult Linkage::loadSerializedModuleContents(
}
}
module->setPathInfo(moduleFilePathInfo);
- module->setDigest(moduleChunk.getDigest());
+ module->setDigest(moduleChunk->getDigest());
module->_collectShaderParams();
module->_discoverEntryPoints(sink, targets);
@@ -7159,8 +7188,8 @@ SlangResult _addLibraryReference(
SourceMap::getTypeGuid(),
ArtifactKeep::Yes,
castable.writeRef()));
- auto sourceMap = asBoxValue<SourceMap>(castable);
- SLANG_ASSERT(sourceMap);
+ auto sourceMapBox = asBoxValue<SourceMap>(castable);
+ SLANG_ASSERT(sourceMapBox);
// TODO(JS):
// There is perhaps (?) a risk here that we might copy the obfuscated map
@@ -7175,7 +7204,7 @@ SlangResult _addLibraryReference(
// unit(s).
for (auto module : library->m_modules)
{
- module->getIRModule()->setObfuscatedSourceMap(sourceMap);
+ module->getIRModule()->setObfuscatedSourceMap(sourceMapBox);
}
// Look up the source file
@@ -7185,8 +7214,26 @@ SlangResult _addLibraryReference(
if (name.getLength())
{
+ // Note(tfoley): There is a subtle requirement here, that any
+ // source file `name` that might be searched for here *must*
+ // have been added to the `sourceManager` already, as a
+ // byproduct of debug source location information getting
+ // deserialized as part of the call to `loadModuleLibrary()` above.
+ //
+ // The implicit dependency is frustrating, and could potentially
+ // break if somehow the debug info chunk was stripped from a binary,
+ // while the source map was left in (which should be valid, even if
+ // it is unlikely to be what a user wants).
+ //
+ // Ideally the source map would either be made an integral part of
+ // the debug source location chunk, so they are loaded together,
+ // or the `SourceManager` would be adapted so that it can store
+ // registered source maps independent of whether or not the
+ // corresponding source file(s) have been loaded.
+
auto sourceFile = sourceManager->findSourceFileByPathRecursively(name);
- sourceFile->setSourceMap(sourceMap, SourceMapKind::Obfuscated);
+ SLANG_ASSERT(sourceFile);
+ sourceFile->setSourceMap(sourceMapBox, SourceMapKind::Obfuscated);
}
}
}