summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2023-04-20 11:55:26 -0400
committerGitHub <noreply@github.com>2023-04-20 11:55:26 -0400
commit467fa3a5dcdd36e310b084747d6f4fcd6ca81249 (patch)
tree193104aad3da77fffddb4b9be3edad4bcfdf76ac /source
parent4d24f55226870055c8dcbb3409efc5355da134d7 (diff)
Improvements outputting containers (#2815)
* #include an absolute path didn't work - because paths were taken to always be relative. * Moved JSON source map writing logic to JSONSourceMapUtil. * Use ArtifactHandler to read/write SourceMaps. Use ObjectCastableAdapter to hold SourceMap Only serialize SourceMap <-> JSON on demand. * Make some types swappable. * BoxValue impl. * Added asBoxValue. * Remove const get funcs. * Fix typo in asBoxValue. * Fix another typo in asBoxValue. * Slightly simplify conversion to blob of SourceMap. * WIP Api improvements around sourcemap/artifact/line-directive. * Small fix for asBoxValue * WIP outputting container with multiple artifacts. * Added ArtifactContailerUtil::filter to produce an artifact hierarchy that only contains "signficant" and "blobable" artifacts. * Make emitting IR disjoint to using a container. Added -emit-ir option. Simplfiy output. * Fix typo in options parsing. * Add a test that ouputs with an emit source map. * Enable emitting our SlangIR module if no targets are specified. * Fix issues constructing container. * Extra checks getting obfuscated source map from a translation unit. * Fix typo.
Diffstat (limited to 'source')
-rw-r--r--source/compiler-core/slang-artifact-container-util.cpp100
-rw-r--r--source/compiler-core/slang-artifact-container-util.h8
-rw-r--r--source/compiler-core/slang-artifact-desc-util.cpp10
-rw-r--r--source/compiler-core/slang-artifact-util.cpp6
-rw-r--r--source/slang/slang-compiler.cpp257
-rwxr-xr-xsource/slang/slang-compiler.h22
-rw-r--r--source/slang/slang-emit-source-writer.cpp2
-rw-r--r--source/slang/slang-emit.cpp2
-rw-r--r--source/slang/slang-options.cpp84
-rw-r--r--source/slang/slang.cpp22
10 files changed, 343 insertions, 170 deletions
diff --git a/source/compiler-core/slang-artifact-container-util.cpp b/source/compiler-core/slang-artifact-container-util.cpp
index 6121df964..dfc385f9a 100644
--- a/source/compiler-core/slang-artifact-container-util.cpp
+++ b/source/compiler-core/slang-artifact-container-util.cpp
@@ -191,34 +191,24 @@ SlangResult ArtifactContainerWriter::getBaseName(IArtifact* artifact, String& ou
SlangResult ArtifactContainerWriter::writeInDirectory(IArtifact* artifact, const String& baseName)
{
-
// TODO(JS):
// We could now output information about the desc/artifact, say as some json.
// For now we assume the extension is good enough for most purposes.
+ // If it's an "arbitrary" container, we don't need to write it
+ if (artifact->getDesc().kind != ArtifactKind::Container)
{
// We can't write it without a blob
ComPtr<ISlangBlob> blob;
- const auto res = artifact->loadBlob(ArtifactKeep::No, blob.writeRef());
+ SLANG_RETURN_ON_FAIL(artifact->loadBlob(ArtifactKeep::No, blob.writeRef()));
- if (SLANG_FAILED(res))
- {
- // If it failed and it's significant the whole write fails
- if (ArtifactUtil::isSignificant(artifact))
- {
- return res;
- }
- }
-
- {
- // Get the name of the artifact
- StringBuilder artifactName;
- SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcNameForDesc(artifact->getDesc(), baseName.getUnownedSlice(), artifactName));
+ // Get the name of the artifact
+ StringBuilder artifactName;
+ SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcNameForDesc(artifact->getDesc(), baseName.getUnownedSlice(), artifactName));
- const auto combinedPath = Path::combine(m_entry.path, artifactName);
- // Write out the blob
- SLANG_RETURN_ON_FAIL(m_fileSystem->saveFileBlob(combinedPath.getBuffer(), blob));
- }
+ const auto combinedPath = Path::combine(m_entry.path, artifactName);
+ // Write out the blob
+ SLANG_RETURN_ON_FAIL(m_fileSystem->saveFileBlob(combinedPath.getBuffer(), blob));
}
{
@@ -837,4 +827,76 @@ SlangResult ArtifactContainerUtil::readContainer(IArtifact* artifact, ComPtr<IAr
return SLANG_OK;
}
+/* static */SlangResult ArtifactContainerUtil::filter(IArtifact* artifact, ComPtr<IArtifact>& outArtifact)
+{
+ outArtifact.setNull();
+
+ // Copy the artifact
+ auto dstArtifact = ArtifactUtil::createArtifact(artifact->getDesc(), artifact->getName());
+
+ ComPtr<ISlangBlob> blob;
+
+ if (artifact->getDesc().kind != ArtifactKind::Container)
+ {
+ // We can't write it without a blob
+ const auto res = artifact->loadBlob(ArtifactKeep::No, blob.writeRef());
+
+ if (SLANG_FAILED(res))
+ {
+ // If it failed and it's significant the whole write fails
+ if (ArtifactUtil::isSignificant(artifact))
+ {
+ return res;
+ }
+ }
+ else
+ {
+ // Add the blob to the destination
+ dstArtifact->addRepresentationUnknown(blob);
+ }
+ }
+
+ // Copy the children after filtering
+ {
+ for (IArtifact* child : artifact->getChildren())
+ {
+ ComPtr<IArtifact> dstChild;
+ SLANG_RETURN_ON_FAIL(filter(child, dstChild));
+
+ if (dstChild)
+ {
+ dstArtifact->addChild(dstChild);
+ }
+ }
+ }
+
+ // Copy the associated after filtering
+ {
+ for (IArtifact* assoc : artifact->getAssociated())
+ {
+ ComPtr<IArtifact> dstAssoc;
+ SLANG_RETURN_ON_FAIL(filter(assoc, dstAssoc));
+
+ if (dstAssoc)
+ {
+ dstArtifact->addAssociated(dstAssoc);
+ }
+ }
+ }
+
+ // We only return the artifact if any of the following are true
+ // 1) It has a blob representation
+ // 2) It contains children or associated artifacts
+
+ if (blob ||
+ dstArtifact->getChildren().count ||
+ dstArtifact->getAssociated().count)
+ {
+ outArtifact = dstArtifact;
+ }
+
+ // If we return an artifact or not, this was successful
+ return SLANG_OK;
+}
+
} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-container-util.h b/source/compiler-core/slang-artifact-container-util.h
index c6e836245..0ee99de26 100644
--- a/source/compiler-core/slang-artifact-container-util.h
+++ b/source/compiler-core/slang-artifact-container-util.h
@@ -36,6 +36,14 @@ struct ArtifactContainerUtil
/// Read an artifact that represents a container as an artifact hierarchy
static SlangResult readContainer(IArtifact* artifact, ComPtr<IArtifact>& outArtifact);
+
+ /// Creates a copy of artifact where
+ /// * All artifacts are blobs
+ /// * Any generic containers that are empty are dropped
+ /// * Any sub artifact that can't be blobed and isn't significant is ignored
+ ///
+ /// A future improvement would be to take a function to also control what makes it to the output
+ static SlangResult filter(IArtifact* artifact, ComPtr<IArtifact>& outArtifact);
};
} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-desc-util.cpp b/source/compiler-core/slang-artifact-desc-util.cpp
index 67501782a..e10ceee07 100644
--- a/source/compiler-core/slang-artifact-desc-util.cpp
+++ b/source/compiler-core/slang-artifact-desc-util.cpp
@@ -753,6 +753,16 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S
default: break;
}
+ if (ArtifactDescUtil::isGpuUsable(desc))
+ {
+ auto ext = _getPayloadExtension(desc.payload);
+ if (ext.getLength())
+ {
+ out << ext;
+ return SLANG_OK;
+ }
+ }
+
if (ArtifactDescUtil::isCpuLikeTarget(desc) && !isDerivedFrom(desc.payload, ArtifactPayload::Source))
{
return appendCpuExtensionForKind(desc.kind, out);
diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp
index 00884c96f..7420f6843 100644
--- a/source/compiler-core/slang-artifact-util.cpp
+++ b/source/compiler-core/slang-artifact-util.cpp
@@ -83,6 +83,12 @@ static bool _checkRecursive(ArtifactUtil::FindStyle findStyle)
return false;
}
+ /* We currently can't write out diagnostics, so for now we'll say they are insignificant */
+ if (isDerivedFrom(desc.payload, ArtifactPayload::Diagnostics))
+ {
+ return false;
+ }
+
return true;
}
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index b5fd27d55..825849b7f 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -1116,11 +1116,8 @@ namespace Slang
sourceLanguage = (SourceLanguage)TypeConvertUtil::getSourceLanguageFromTarget((SlangCompileTarget)sourceTarget);
}
- ComPtr<IArtifactPostEmitMetadata> metadata;
if (sourceArtifact)
{
- metadata = findAssociatedRepresentation<IArtifactPostEmitMetadata>(sourceArtifact);
-
// Set the source artifacts
options.sourceArtifacts = makeSlice(sourceArtifact.readRef(), 1);
}
@@ -1468,7 +1465,14 @@ namespace Slang
return SLANG_FAIL;
}
- ArtifactUtil::addAssociated(artifact, metadata);
+ // Copy over all of the information associated with the source into the output
+ if (sourceArtifact)
+ {
+ for (auto associatedArtifact : sourceArtifact->getAssociated())
+ {
+ artifact->addAssociated(associatedArtifact);
+ }
+ }
// Set the artifact
outArtifact.swap(artifact);
@@ -1613,24 +1617,18 @@ namespace Slang
ArtifactOutputUtil::maybeConvertAndWrite(session, artifact, sink, toSlice("stdout"), getWriter(WriterChannel::StdOutput));
}
- void EndToEndCompileRequest::writeWholeProgramResult(
- TargetRequest* targetReq)
+ String EndToEndCompileRequest::_getWholeProgramPath(TargetRequest* targetReq)
{
- auto program = getSpecializedGlobalAndEntryPointsComponentType();
- auto targetProgram = program->getTargetProgram(targetReq);
-
- IArtifact* artifact = targetProgram->getExistingWholeProgramResult();
-
- // Skip the case with no output
- if (artifact == nullptr)
- return;
-
- CodeGenContext::EntryPointIndices entryPointIndices;
- for (Index i = 0; i < program->getEntryPointCount(); ++i)
- entryPointIndices.add(i);
- CodeGenContext::Shared sharedCodeGenContext(targetProgram, entryPointIndices, getSink(), this);
- CodeGenContext codeGenContext(&sharedCodeGenContext);
+ RefPtr<EndToEndCompileRequest::TargetInfo> targetInfo;
+ if (m_targetInfos.TryGetValue(targetReq, targetInfo))
+ {
+ return targetInfo->wholeTargetOutputPath;
+ }
+ return String();
+ }
+ String EndToEndCompileRequest::_getEntryPointPath(TargetRequest* targetReq, Index entryPointIndex)
+ {
// It is possible that we are dynamically discovering entry
// points (using `[shader(...)]` attributes), so that there
// might be entry points added to the program that did not
@@ -1639,53 +1637,35 @@ namespace Slang
RefPtr<EndToEndCompileRequest::TargetInfo> targetInfo;
if (m_targetInfos.TryGetValue(targetReq, targetInfo))
{
- String outputPath = targetInfo->wholeTargetOutputPath;
- if (outputPath != "")
+ String outputPath;
+ if (targetInfo->entryPointOutputPaths.TryGetValue(entryPointIndex, outputPath))
{
- ArtifactOutputUtil::writeToFile(artifact, codeGenContext.getSink(), outputPath);
- return;
+ return outputPath;
}
}
- writeArtifactToStandardOutput(artifact, codeGenContext.getSink());
+
+ return String();
}
- void EndToEndCompileRequest::writeEntryPointResult(
- TargetRequest* targetReq,
- Int entryPointIndex)
+ SlangResult EndToEndCompileRequest::_maybeWriteArtifact(const String& path, IArtifact* artifact)
{
- auto program = getSpecializedGlobalAndEntryPointsComponentType();
- auto targetProgram = program->getTargetProgram(targetReq);
-
- IArtifact* artifact = targetProgram->getExistingEntryPointResult(entryPointIndex);
-
- // Skip the case with no output
- if (artifact == nullptr)
- return;
-
- CodeGenContext::EntryPointIndices entryPointIndices;
- entryPointIndices.add(entryPointIndex);
-
- CodeGenContext::Shared sharedCodeGenContext(targetProgram, entryPointIndices, getSink(), this);
- CodeGenContext codeGenContext(&sharedCodeGenContext);
-
- // It is possible that we are dynamically discovering entry
- // points (using `[shader(...)]` attributes), so that there
- // might be entry points added to the program that did not
- // get paths specified via command-line options.
- //
- RefPtr<EndToEndCompileRequest::TargetInfo> targetInfo;
- auto entryPoint = program->getEntryPoint(entryPointIndex);
- if(m_targetInfos.TryGetValue(targetReq, targetInfo))
+ // We don't have to do anything if there is no artifact
+ if (artifact)
{
- String outputPath;
- if(targetInfo->entryPointOutputPaths.TryGetValue(entryPointIndex, outputPath))
+ if (path.getLength())
{
- ArtifactOutputUtil::writeToFile(artifact, codeGenContext.getSink(), outputPath);
- return;
+ SLANG_RETURN_ON_FAIL(ArtifactOutputUtil::writeToFile(artifact, getSink(), path));
+ return SLANG_OK;
+ }
+
+ // If we aren't writing to a container and we didn't write to a file, we can output to
+ if (m_containerFormat == ContainerFormat::None)
+ {
+ writeArtifactToStandardOutput(artifact, getSink());
}
}
- writeArtifactToStandardOutput(artifact, codeGenContext.getSink());
+ return SLANG_OK;
}
IArtifact* TargetProgram::_createWholeProgramResult(
@@ -1860,11 +1840,54 @@ namespace Slang
return SLANG_OK;
}
- SlangResult EndToEndCompileRequest::_createContainer()
+ static IBoxValue<SourceMap>* _getObfuscatedSourceMap(TranslationUnitRequest* translationUnit)
{
- switch (m_containerFormat)
+ if (auto module = translationUnit->getModule())
+ {
+ if (auto irModule = module->getIRModule())
+ {
+ return irModule->getObfuscatedSourceMap();
+ }
+ }
+ return nullptr;
+ }
+
+ SlangResult EndToEndCompileRequest::maybeCreateContainer()
+ {
+ m_containerArtifact.setNull();
+
+ List<ComPtr<IArtifact>> artifacts;
+
+ auto linkage = getLinkage();
+
+ auto program = getSpecializedGlobalAndEntryPointsComponentType();
+
+ for (auto targetReq : linkage->targets)
{
- case ContainerFormat::SlangModule:
+ auto targetProgram = program->getTargetProgram(targetReq);
+
+ if (targetReq->isWholeProgramRequest())
+ {
+ if (auto artifact = targetProgram->getExistingWholeProgramResult())
+ {
+ artifacts.add(ComPtr<IArtifact>(artifact));
+ }
+ }
+ else
+ {
+ Index entryPointCount = program->getEntryPointCount();
+ for (Index ee = 0; ee < entryPointCount; ++ee)
+ {
+ if (auto artifact = targetProgram->getExistingEntryPointResult(ee))
+ {
+ artifacts.add(ComPtr<IArtifact>(artifact));
+ }
+ }
+ }
+ }
+
+ // If IR emitting is enabled, add IR to the artifacts
+ if (m_emitIr)
{
OwnedMemoryStream stream(FileAccess::Write);
SlangResult res = writeContainerToStream(&stream);
@@ -1880,78 +1903,74 @@ namespace Slang
auto containerBlob = ListBlob::moveCreate(blobData);
- m_containerArtifact = Artifact::create(ArtifactDesc::make(Artifact::Kind::CompileBinary, ArtifactPayload::SlangIR, ArtifactStyle::Unknown));
- m_containerArtifact->addRepresentationUnknown(containerBlob);
-
- return res;
- }
- default: break;
+ auto irArtifact = Artifact::create(ArtifactDesc::make(Artifact::Kind::CompileBinary, ArtifactPayload::SlangIR, ArtifactStyle::Unknown));
+ irArtifact->addRepresentationUnknown(containerBlob);
+
+ // Add the IR artifact
+ artifacts.add(irArtifact);
}
- return SLANG_OK;
- }
- SlangResult EndToEndCompileRequest::_completeContainer()
- {
- SLANG_ASSERT(m_containerArtifact);
- if (!m_containerArtifact)
+ // If there is only one artifact we can use that as the container
+ if (artifacts.getCount() == 1)
{
- return SLANG_FAIL;
+ m_containerArtifact = artifacts[0];
}
+ else
+ {
+ m_containerArtifact = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactKind::Container, ArtifactPayload::CompileResults));
- auto frontEndReq = getFrontEndReq();
+ for (IArtifact* childArtifact : artifacts)
+ {
+ m_containerArtifact->addChild(childArtifact);
+ }
+ }
- for (auto translationUnit : frontEndReq->translationUnits)
+ // Get all of the source obfuscated source maps and add those
+ if (m_containerArtifact)
{
- // Hmmm do I have to therefore add a map for all translation units(!)
- // I guess this is okay in so far as an association can always be looked up by name
-
- auto sourceMap = translationUnit->getModule()->getIRModule()->getObfuscatedSourceMap();
+ auto frontEndReq = getFrontEndReq();
- // If we have a source map *and* we want to generate them for output add to the container
- if (sourceMap && getLinkage()->m_generateSourceMap)
+ for (auto translationUnit : frontEndReq->translationUnits)
{
- auto artifactDesc = ArtifactDesc::make(ArtifactKind::Json, ArtifactPayload::SourceMap, ArtifactStyle::Obfuscated);
+ // Hmmm do I have to therefore add a map for all translation units(!)
+ // I guess this is okay in so far as an association can always be looked up by name
+ if (auto sourceMap = _getObfuscatedSourceMap(translationUnit))
+ {
+ auto artifactDesc = ArtifactDesc::make(ArtifactKind::Json, ArtifactPayload::SourceMap, ArtifactStyle::Obfuscated);
- // Create the source map artifact
- auto sourceMapArtifact = Artifact::create(artifactDesc, sourceMap->get().m_file.getUnownedSlice());
+ // Create the source map artifact
+ auto sourceMapArtifact = Artifact::create(artifactDesc, sourceMap->get().m_file.getUnownedSlice());
- // Add the repesentation
- sourceMapArtifact->addRepresentation(sourceMap);
+ // Add the repesentation
+ sourceMapArtifact->addRepresentation(sourceMap);
- // Associate with the container
- m_containerArtifact->addAssociated(sourceMapArtifact);
+ // Associate with the container
+ m_containerArtifact->addAssociated(sourceMapArtifact);
+ }
}
}
return SLANG_OK;
}
- SlangResult EndToEndCompileRequest::maybeCreateContainer()
+ SlangResult EndToEndCompileRequest::maybeWriteContainer(const String& fileName)
{
- m_containerArtifact.setNull();
-
- if (m_containerFormat == ContainerFormat::None)
+ // If there is no container, or filename, don't write anything
+ if (fileName.getLength() == 0 || !m_containerArtifact)
{
return SLANG_OK;
}
- // Create the container
- SLANG_RETURN_ON_FAIL(_createContainer());
+ // Filter the containerArtifact into things that can be written
+ ComPtr<IArtifact> writeArtifact;
+ SLANG_RETURN_ON_FAIL(ArtifactContainerUtil::filter(m_containerArtifact, writeArtifact));
- // Associate any other stuff with the container artifact
- SLANG_RETURN_ON_FAIL(_completeContainer());
-
- return SLANG_OK;
- }
-
- SlangResult EndToEndCompileRequest::maybeWriteContainer(const String& fileName)
- {
- // If there is no container, or filename, don't write anything
- if (fileName.getLength() == 0 || !m_containerArtifact)
+ // Only write if there is something to write
+ if (writeArtifact)
{
- return SLANG_OK;
+ SLANG_RETURN_ON_FAIL(ArtifactContainerUtil::writeContainer(writeArtifact, fileName));
}
- SLANG_RETURN_ON_FAIL(ArtifactContainerUtil::writeContainer(m_containerArtifact, fileName));
+
return SLANG_OK;
}
@@ -2109,26 +2128,38 @@ namespace Slang
{
auto linkage = getLinkage();
auto program = getSpecializedGlobalAndEntryPointsComponentType();
+
for (auto targetReq : linkage->targets)
{
+ auto targetProgram = program->getTargetProgram(targetReq);
+
if (targetReq->isWholeProgramRequest())
{
- writeWholeProgramResult(
- targetReq);
+ const auto path = _getWholeProgramPath(targetReq);
+ const auto artifact = targetProgram->getExistingWholeProgramResult();
+
+ _maybeWriteArtifact(path, artifact);
}
else
{
Index entryPointCount = program->getEntryPointCount();
for (Index ee = 0; ee < entryPointCount; ++ee)
- {
- writeEntryPointResult(
- targetReq,
- ee);
+ {
+ const auto path = _getEntryPointPath(targetReq, ee);
+ const auto artifact = targetProgram->getExistingEntryPointResult(ee);
+
+ _maybeWriteArtifact(path, artifact);
}
}
- }
+ }
+ }
- maybeCreateContainer();
+ // Maybe create the container
+ maybeCreateContainer();
+
+ // If it's a command line compile we may need to write the container to a file
+ if (m_isCommandLineCompile)
+ {
maybeWriteContainer(m_containerOutputPath);
_writeDependencyFile(this);
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index 0c366f485..d0827e2e6 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -104,6 +104,7 @@ namespace Slang
None = SLANG_LINE_DIRECTIVE_MODE_NONE,
Standard = SLANG_LINE_DIRECTIVE_MODE_STANDARD,
GLSL = SLANG_LINE_DIRECTIVE_MODE_GLSL,
+ SourceMap = SLANG_LINE_DIRECTIVE_MODE_SOURCE_MAP,
};
enum class ResultFormat
@@ -1771,8 +1772,7 @@ namespace Slang
SourceManager* m_sourceManager = nullptr;
bool m_obfuscateCode = false;
- bool m_generateSourceMap = false;
-
+
/// Holds any args that are destined for downstream compilers/tools etc
DownstreamArgs m_downstreamArgs;
@@ -2626,6 +2626,9 @@ namespace Slang
~EndToEndCompileRequest();
+ // If enabled will emit IR
+ bool m_emitIr = false;
+
// What container format are we being asked to generate?
// If it's set to a format, the container blob will be calculated during compile
ContainerFormat m_containerFormat = ContainerFormat::None;
@@ -2650,6 +2653,7 @@ namespace Slang
// Are we being driven by the command-line `slangc`, and should act accordingly?
bool m_isCommandLineCompile = false;
+
String m_diagnosticOutput;
@@ -2769,11 +2773,12 @@ namespace Slang
String m_dumpIntermediatePrefix;
private:
- void writeWholeProgramResult(
- TargetRequest* targetReq);
- void writeEntryPointResult(
- TargetRequest* targetReq,
- Int entryPointIndex);
+
+ String _getWholeProgramPath(TargetRequest* targetReq);
+ String _getEntryPointPath(TargetRequest* targetReq, Index entryPointIndex);
+
+ /// Maybe write the artifact to the path (if set), or stdout (if there is no container or path)
+ SlangResult _maybeWriteArtifact(const String& path, IArtifact* artifact);
ISlangUnknown* getInterface(const Guid& guid);
@@ -2782,9 +2787,6 @@ namespace Slang
void init();
- SlangResult _createContainer();
- SlangResult _completeContainer();
-
Session* m_session = nullptr;
RefPtr<Linkage> m_linkage;
DiagnosticSink m_sink;
diff --git a/source/slang/slang-emit-source-writer.cpp b/source/slang/slang-emit-source-writer.cpp
index 985d0a0bf..27cbd1932 100644
--- a/source/slang/slang-emit-source-writer.cpp
+++ b/source/slang/slang-emit-source-writer.cpp
@@ -391,6 +391,7 @@ void SourceWriter::_emitLineDirectiveIfNeeded(const HumaneSourceLoc& sourceLocat
auto mode = getLineDirectiveMode();
switch (mode)
{
+ case LineDirectiveMode::SourceMap:
case LineDirectiveMode::None:
return;
@@ -451,6 +452,7 @@ void SourceWriter::_emitLineDirective(const HumaneSourceLoc& sourceLocation)
switch (mode)
{
default:
+ case LineDirectiveMode::SourceMap:
case LineDirectiveMode::None:
SLANG_UNEXPECTED("should not be trying to emit '#line' directive");
return;
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index f9284d001..0b88bd057 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -972,7 +972,7 @@ SlangResult CodeGenContext::emitEntryPointsSourceFromIR(ComPtr<IArtifact>& outAr
ComPtr<IBoxValue<SourceMap>> sourceMap;
// If SourceMap is enabled, we create one and associate it with the sourceWriter
- if (targetRequest->getLinkage()->m_generateSourceMap)
+ if (lineDirectiveMode == LineDirectiveMode::SourceMap)
{
sourceMap = new BoxValue<SourceMap>;
}
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index b1e1b93d2..a8ac88f81 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -332,9 +332,24 @@ struct OptionsParser
String path = String(inPath);
String ext = Path::getPathExt(path);
- if (ext == "slang-module" || ext == "slang-lib" || ext == "dir" || ext == "zip")
+ if (ext == toSlice("slang-module") ||
+ ext == toSlice("slang-lib") ||
+ ext == toSlice("dir") ||
+ ext == toSlice("zip"))
{
- compileRequest->setOutputContainerFormat(SLANG_CONTAINER_FORMAT_SLANG_MODULE);
+ // These extensions don't indicate a artifact container, just that we want to emit IR
+ if (ext == toSlice("slang-module") ||
+ ext == toSlice("slang-lib"))
+ {
+ // We want to emit IR
+ requestImpl->m_emitIr = true;
+ }
+ else
+ {
+ // We want to write out in an artfact "container", that can hold multiple artifacts.
+ compileRequest->setOutputContainerFormat(SLANG_CONTAINER_FORMAT_SLANG_MODULE);
+ }
+
requestImpl->m_containerOutputPath = path;
}
else
@@ -591,6 +606,8 @@ struct OptionsParser
" -line-directive-mode <mode>: Sets how the `#line` directives should be\n"
" produced. Available options are:\n"
" none : Don't emit `#line` directives at all\n"
+ " source-map : Use source map to track line associations (doen't emit #line)\n"
+ " default : Default behavior\n"
" If not specified, default behavior is to use C-style `#line` directives\n"
" for HLSL and C/C++ output, and traditional GLSL-style `#line` directives\n"
" for GLSL output.\n"
@@ -890,6 +907,11 @@ struct OptionsParser
{
flags |= SLANG_COMPILE_FLAG_NO_MANGLING;
}
+ else if (argValue == toSlice("-emit-ir"))
+ {
+ // Enable emitting IR
+ requestImpl->m_emitIr = true;
+ }
else if (argValue == "-load-stdlib")
{
CommandLineArg fileName;
@@ -1178,10 +1200,6 @@ struct OptionsParser
{
getCurrentTarget()->targetFlags |= SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES;
}
- else if(argValue == "-source-map")
- {
- requestImpl->getLinkage()->m_generateSourceMap = true;
- }
else if (argValue == "-ir-compression")
{
CommandLineArg name;
@@ -1448,10 +1466,19 @@ struct OptionsParser
SLANG_RETURN_ON_FAIL(reader.expectArg(name));
SlangLineDirectiveMode mode = SLANG_LINE_DIRECTIVE_MODE_DEFAULT;
- if(name.value == "none")
+
+ if(name.value == toSlice("none"))
{
mode = SLANG_LINE_DIRECTIVE_MODE_NONE;
}
+ else if (name.value == toSlice("source-map"))
+ {
+ mode = SLANG_LINE_DIRECTIVE_MODE_SOURCE_MAP;
+ }
+ else if (name.value == toSlice("default"))
+ {
+ mode = SLANG_LINE_DIRECTIVE_MODE_DEFAULT;
+ }
else
{
sink->diagnose(name.loc, Diagnostics::unknownLineDirectiveMode, name.value);
@@ -1459,7 +1486,6 @@ struct OptionsParser
}
compileRequest->setLineDirectiveMode(mode);
-
}
else if( argValue == "-fp-mode" || argValue == "-floating-point-mode" )
{
@@ -1954,26 +1980,38 @@ struct OptionsParser
//
if(rawTargets.getCount() == 0)
{
- for(auto& rawOutput : rawOutputs)
+ // If there are no targets and no outputs
+ if (rawOutputs.getCount() == 0)
{
- // Some outputs don't imply a target format, and we shouldn't use those for inference.
- auto impliedFormat = rawOutput.impliedFormat;
- if( impliedFormat == CodeGenTarget::Unknown )
- continue;
-
- int targetIndex = 0;
- if( !mapFormatToTargetIndex.TryGetValue(impliedFormat, targetIndex) )
+ // And we have a container for output, then enable emitting SlangIR module
+ if (requestImpl->m_containerFormat != ContainerFormat::None)
+ {
+ requestImpl->m_emitIr = true;
+ }
+ }
+ else
+ {
+ for(auto& rawOutput : rawOutputs)
{
- targetIndex = (int) rawTargets.getCount();
+ // Some outputs don't imply a target format, and we shouldn't use those for inference.
+ auto impliedFormat = rawOutput.impliedFormat;
+ if( impliedFormat == CodeGenTarget::Unknown )
+ continue;
- RawTarget rawTarget;
- rawTarget.format = impliedFormat;
- rawTargets.add(rawTarget);
+ int targetIndex = 0;
+ if( !mapFormatToTargetIndex.TryGetValue(impliedFormat, targetIndex) )
+ {
+ targetIndex = (int) rawTargets.getCount();
- mapFormatToTargetIndex[impliedFormat] = targetIndex;
- }
+ RawTarget rawTarget;
+ rawTarget.format = impliedFormat;
+ rawTargets.add(rawTarget);
- rawOutput.targetIndex = targetIndex;
+ mapFormatToTargetIndex[impliedFormat] = targetIndex;
+ }
+
+ rawOutput.targetIndex = targetIndex;
+ }
}
}
else
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 6b2814ca7..637b22090 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -4887,8 +4887,16 @@ SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifac
auto sourceMap = asBoxValue<SourceMap>(castable);
SLANG_ASSERT(sourceMap);
- // I guess we add to all ir modules?
-
+ // TODO(JS):
+ // There is perhaps (?) a risk here that we might copy the obfuscated map
+ // into some output container. Currently that only happens for source maps
+ // that are from translation units.
+ //
+ // On the other hand using "import" is a way that such source maps *would* be
+ // copied into the output, and that is something that could be a vector
+ // for leaking.
+ //
+ // That isn't a risk from -r though because, it doesn't create a translation unit(s).
for (auto irModule : library->m_modules)
{
irModule->setObfuscatedSourceMap(sourceMap);
@@ -5316,9 +5324,15 @@ ISlangMutableFileSystem* EndToEndCompileRequest::getCompileRequestResultAsFileSy
if (m_containerArtifact)
{
ComPtr<ISlangMutableFileSystem> fileSystem(new MemoryFileSystem);
- if (SLANG_SUCCEEDED(ArtifactContainerUtil::writeContainer(m_containerArtifact, "", fileSystem)))
+
+ // Filter the containerArtifact into things that can be written
+ ComPtr<IArtifact> writeArtifact;
+ if (SLANG_SUCCEEDED(ArtifactContainerUtil::filter(m_containerArtifact, writeArtifact)))
{
- m_containerFileSystem.swap(fileSystem);
+ if (SLANG_SUCCEEDED(ArtifactContainerUtil::writeContainer(writeArtifact, "", fileSystem)))
+ {
+ m_containerFileSystem.swap(fileSystem);
+ }
}
}
}