summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/core/slang-riff.cpp13
-rw-r--r--source/core/slang-riff.h3
-rw-r--r--source/slang/slang-compiler.cpp69
-rw-r--r--source/slang/slang-compiler.h4
-rw-r--r--source/slang/slang-diagnostic-defs.h1
-rw-r--r--source/slang/slang-ir-link.cpp23
-rw-r--r--source/slang/slang-ir-serialize.cpp73
-rw-r--r--source/slang/slang-ir-serialize.h47
-rw-r--r--source/slang/slang-options.cpp21
9 files changed, 194 insertions, 60 deletions
diff --git a/source/core/slang-riff.cpp b/source/core/slang-riff.cpp
index 3a3722bb8..2e633f2e7 100644
--- a/source/core/slang-riff.cpp
+++ b/source/core/slang-riff.cpp
@@ -535,6 +535,19 @@ RiffContainer::Chunk* RiffContainer::ListChunk::findContained(FourCC fourCC) con
return nullptr;
}
+void RiffContainer::ListChunk::findContained(FourCC type, List<ListChunk*>& out)
+{
+ Chunk* chunk = m_containedChunks;
+ while (chunk)
+ {
+ if (chunk->m_fourCC == type && chunk->m_kind == Chunk::Kind::List)
+ {
+ out.add(static_cast<ListChunk*>(chunk));
+ }
+ chunk = chunk->m_next;
+ }
+}
+
RiffContainer::Data* RiffContainer::ListChunk::findContainedData(FourCC type) const
{
Chunk* found = findContained(type);
diff --git a/source/core/slang-riff.h b/source/core/slang-riff.h
index 4d23e45c1..99d078625 100644
--- a/source/core/slang-riff.h
+++ b/source/core/slang-riff.h
@@ -245,6 +245,9 @@ public:
template <typename T>
T* findContainedData(FourCC type) const { return (T*)findContainedData(type, sizeof(T)); }
+ /// Find all contained that match the type
+ void findContained(FourCC type, List<ListChunk*>& out);
+
/// Find the list (including self) that matches subtype recursively
ListChunk* findListRec(FourCC subType);
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index 87a5e01a8..705b4ed59 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -5,6 +5,7 @@
#include "../core/slang-io.h"
#include "../core/slang-string-util.h"
#include "../core/slang-hex-dump-util.h"
+#include "../core/slang-riff.h"
#include "slang-check.h"
#include "slang-compiler.h"
@@ -18,6 +19,8 @@
#include "slang-reflection.h"
#include "slang-emit.h"
+#include "slang-ir-serialize.h"
+
// Enable calling through to `fxc` or `dxc` to
// generate code on Windows.
#ifdef _WIN32
@@ -2187,38 +2190,64 @@ SlangResult dissassembleDXILUsingDXC(
EndToEndCompileRequest* endToEndReq,
Stream* stream)
{
- SLANG_UNUSED(stream);
+ RiffContainer container;
- auto linkage = endToEndReq->getLinkage();
- auto sink = endToEndReq->getSink();
- auto frontEndReq = endToEndReq->getFrontEndReq();
+ // TODO(JS): We may want a switch to control is we use compression and/or we may just want compressed by default.
+ // For now uncompressed is fine.
+ const auto compressionType = IRSerialBinary::CompressionType::None;
- for (auto translationUnit : frontEndReq->translationUnits)
{
- auto module = translationUnit->module;
- auto irModule = module->getIRModule();
+ // Module list
+ RiffContainer::ScopeChunk listScope(&container, RiffContainer::Chunk::Kind::List, IRSerialBinary::kSlangModuleListFourCc);
- SLANG_UNUSED(irModule);
+ auto linkage = endToEndReq->getLinkage();
+ auto sink = endToEndReq->getSink();
+ auto frontEndReq = endToEndReq->getFrontEndReq();
- // Okay, we need to serialize this module to our container file,
- // including both its name and generated IR code.
- }
+ IRSerialWriter::OptionFlags optionFlags = 0;
- auto program = endToEndReq->getSpecializedGlobalAndEntryPointsComponentType();
+ if (linkage->debugInfoLevel != DebugInfoLevel::None)
+ {
+ optionFlags |= IRSerialWriter::OptionFlag::DebugInfo;
+ }
-
+ SourceManager* sourceManager = frontEndReq->getSourceManager();
- // TODO: in the case where we have specialization, we might need
- // to serialize IR related to `program`...
+ for (auto translationUnit : frontEndReq->translationUnits)
+ {
+ auto module = translationUnit->module;
+ auto irModule = module->getIRModule();
- for (auto target : linkage->targets)
- {
- auto targetProgram = program->getTargetProgram(target);
- auto irModule = targetProgram->getOrCreateIRModuleForLayout(sink);
+ // Okay, we need to serialize this module to our container file.
+ // We currently don't serialize it's name..., but support for that could be added.
- // Okay, we need to serialize this target program and its IR too...
+ IRSerialData serialData;
+ IRSerialWriter writer;
+ SLANG_RETURN_ON_FAIL(writer.write(irModule, sourceManager, optionFlags, &serialData));
+ SLANG_RETURN_ON_FAIL(IRSerialWriter::writeContainer(serialData, compressionType, &container));
+ }
+
+ auto program = endToEndReq->getSpecializedGlobalAndEntryPointsComponentType();
+
+ // TODO: in the case where we have specialization, we might need
+ // to serialize IR related to `program`...
+
+ for (auto target : linkage->targets)
+ {
+ auto targetProgram = program->getTargetProgram(target);
+ auto irModule = targetProgram->getOrCreateIRModuleForLayout(sink);
+
+ // Okay, we need to serialize this target program and its IR too...
+ IRSerialData serialData;
+ IRSerialWriter writer;
+ SLANG_RETURN_ON_FAIL(writer.write(irModule, sourceManager, optionFlags, &serialData));
+ SLANG_RETURN_ON_FAIL(IRSerialWriter::writeContainer(serialData, compressionType, &container));
+ }
}
+ // We now write the RiffContainer to the stream
+ SLANG_RETURN_ON_FAIL(RiffUtil::write(container.getRoot(), true, stream));
+
return SLANG_OK;
}
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index a527d3a31..cd99c4079 100644
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -1260,6 +1260,9 @@ namespace Slang
bool m_requireCacheFileSystem = false;
bool m_useFalcorCustomSharedKeywordSemantics = false;
+ // Modules that have been read in with the -r option
+ List<RefPtr<IRModule>> m_libModules;
+
private:
Session* m_session = nullptr;
@@ -1299,6 +1302,7 @@ namespace Slang
bool isBeingImported(Module* module);
List<RefPtr<Type>> m_specializedTypes;
+
};
/// Shared functionality between front- and back-end compile requests.
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 6623b7195..405590111 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -111,6 +111,7 @@ DIAGNOSTIC( 80, Error, duplicateOutputPathsForEntryPointAndTarget, "multiple
DIAGNOSTIC( 81, Error, parametersAfterLoadReproIgnored, "parameters after -load-repro [file] are ignored")
DIAGNOSTIC( 82, Error, unableToWriteReproFile, "unable to write repro file '%0'");
DIAGNOSTIC( 83, Error, unableToWriteModuleContainer, "unable to write module container '%0'");
+DIAGNOSTIC( 84, Error, unableToReadModuleContainer, "unable to read module container '%0'");
//
// 1xxxx - Lexical anaylsis
diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp
index 1cdc2cfc9..1102ecb3e 100644
--- a/source/slang/slang-ir-link.cpp
+++ b/source/slang/slang-ir-link.cpp
@@ -1339,15 +1339,26 @@ LinkedIR linkIR(
state->irModule = sharedContext->module;
+ auto linkage = compileRequest->getLinkage();
+
// We need to be able to look up IR definitions for any symbols in
// modules that the program depends on (transitively). To
// accelerate lookup, we will create a symbol table for looking
// up IR definitions by their mangled name.
//
+
+ List<IRModule*> irModules;
program->enumerateIRModules([&](IRModule* irModule)
{
- insertGlobalValueSymbols(sharedContext, irModule);
+ irModules.add(irModule);
});
+ irModules.addRange(linkage->m_libModules.getBuffer()->readRef(), linkage->m_libModules.getCount());
+
+ // Add any modules that were loaded as libraries
+ for (IRModule* irModule : irModules)
+ {
+ insertGlobalValueSymbols(sharedContext, irModule);
+ }
// We will also insert the IR global symbols from the IR module
// attached to the `TargetProgram`, since this module is
@@ -1374,7 +1385,6 @@ LinkedIR linkIR(
cloneGlobalValue(context, (IRWitnessTable*)sym.Value->irGlobalValue);
}
-
// Next, we make sure to clone the global value for
// the entry point function itself, and rely on
// this step to recursively copy over anything else
@@ -1401,17 +1411,18 @@ LinkedIR linkIR(
// In the long run we do not want to *ever* iterate over all the
// instructions in all the input modules.
//
- program->enumerateIRModules([&](IRModule* irModule)
+
+ for (IRModule* irModule : irModules)
{
- for(auto inst : irModule->getGlobalInsts())
+ for (auto inst : irModule->getGlobalInsts())
{
auto bindInst = as<IRBindGlobalGenericParam>(inst);
- if(!bindInst)
+ if (!bindInst)
continue;
cloneValue(context, bindInst);
}
- });
+ }
// TODO: *technically* we should consider the case where
// we have global variables with initializers, since
diff --git a/source/slang/slang-ir-serialize.cpp b/source/slang/slang-ir-serialize.cpp
index 97b070f9c..5c16f70f3 100644
--- a/source/slang/slang-ir-serialize.cpp
+++ b/source/slang/slang-ir-serialize.cpp
@@ -809,7 +809,7 @@ static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType,
{
ScopeChunk scope(container, Chunk::Kind::Data, chunkId);
Bin::ArrayHeader header;
- header.m_numEntries = uint32_t(numEntries);
+ header.numEntries = uint32_t(numEntries);
container->write(&header, sizeof(header));
container->write(data, typeSize * numEntries);
@@ -823,8 +823,8 @@ static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType,
ByteEncodeUtil::encodeLiteUInt32((const uint32_t*)data, numCompressedEntries, compressedPayload);
Bin::CompressedArrayHeader header;
- header.m_numEntries = uint32_t(numEntries);
- header.m_numCompressedEntries = uint32_t(numCompressedEntries);
+ header.numEntries = uint32_t(numEntries);
+ header.numCompressedEntries = uint32_t(numCompressedEntries);
container->write(&header, sizeof(header));
@@ -961,8 +961,8 @@ Result _writeInstArrayChunk(IRSerialBinary::CompressionType compressionType, uin
ScopeChunk scope(container, Chunk::Kind::Data, SLANG_MAKE_COMPRESSED_FOUR_CC(chunkId));
Bin::CompressedArrayHeader header;
- header.m_numEntries = uint32_t(array.getCount());
- header.m_numCompressedEntries = 0;
+ header.numEntries = uint32_t(array.getCount());
+ header.numCompressedEntries = 0;
container->write(&header, sizeof(header));
@@ -986,7 +986,7 @@ Result _writeInstArrayChunk(IRSerialBinary::CompressionType compressionType, uin
// Write the header
{
Bin::ModuleHeader moduleHeader;
- moduleHeader.m_compressionType = uint32_t(Bin::CompressionType::VariableByteLite);
+ moduleHeader.compressionType = uint32_t(Bin::CompressionType::VariableByteLite);
ScopeChunk scopeHeader(container, Chunk::Kind::Data, Bin::kSlangModuleHeaderFourCc);
container->write(&moduleHeader, sizeof(moduleHeader));
}
@@ -1065,11 +1065,11 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, R
Bin::CompressedArrayHeader header;
SLANG_RETURN_ON_FAIL(read.read(header));
- void* dst = listOut.setSize(header.m_numEntries);
- SLANG_ASSERT(header.m_numCompressedEntries == uint32_t((header.m_numEntries * typeSize) / sizeof(uint32_t)));
+ void* dst = listOut.setSize(header.numEntries);
+ SLANG_ASSERT(header.numCompressedEntries == uint32_t((header.numEntries * typeSize) / sizeof(uint32_t)));
// Decode..
- ByteEncodeUtil::decodeLiteUInt32(read.getData(), header.m_numCompressedEntries, (uint32_t*)dst);
+ ByteEncodeUtil::decodeLiteUInt32(read.getData(), header.numCompressedEntries, (uint32_t*)dst);
break;
}
case Bin::CompressionType::None:
@@ -1077,9 +1077,9 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, R
// Read uncompressed
Bin::ArrayHeader header;
SLANG_RETURN_ON_FAIL(read.read(header));
- const size_t payloadSize = header.m_numEntries * typeSize;
+ const size_t payloadSize = header.numEntries * typeSize;
SLANG_ASSERT(payloadSize == read.getRemainingSize());
- void* dst = listOut.setSize(header.m_numEntries);
+ void* dst = listOut.setSize(header.numEntries);
::memcpy(dst, read.getData(), payloadSize);
break;
}
@@ -1097,7 +1097,7 @@ static Result _readArrayChunk(const IRSerialBinary::ModuleHeader* header, RiffCo
if (dataChunk->m_fourCC == SLANG_MAKE_COMPRESSED_FOUR_CC(dataChunk->m_fourCC))
{
// If it has compression, use the compression type set in the header
- compressionType = Bin::CompressionType(header->m_compressionType);
+ compressionType = Bin::CompressionType(header->compressionType);
}
ListResizerForType<T> resizer(arrayOut);
return _readArrayChunk(compressionType, dataChunk, resizer);
@@ -1191,7 +1191,7 @@ static Result _readInstArrayChunk(const IRSerialBinary::ModuleHeader* moduleHead
Bin::CompressionType compressionType = Bin::CompressionType::None;
if (chunk->m_fourCC == SLANG_MAKE_COMPRESSED_FOUR_CC(chunk->m_fourCC))
{
- compressionType = Bin::CompressionType(moduleHeader->m_compressionType);
+ compressionType = Bin::CompressionType(moduleHeader->compressionType);
}
switch (compressionType)
@@ -1208,7 +1208,7 @@ static Result _readInstArrayChunk(const IRSerialBinary::ModuleHeader* moduleHead
Bin::CompressedArrayHeader header;
SLANG_RETURN_ON_FAIL(read.read(header));
- arrayOut.setCount(header.m_numEntries);
+ arrayOut.setCount(header.numEntries);
SLANG_RETURN_ON_FAIL(_decodeInsts(compressionType, read.getData(), read.getRemainingSize(), arrayOut));
break;
@@ -1357,6 +1357,51 @@ static int _calcFixSourceLoc(const IRSerialData::DebugSourceInfo& info, SourceVi
return int(sourceView->getRange().begin.getRaw()) - int(info.m_startSourceLoc);
}
+/* static */Result IRSerialReader::readStreamModules(Stream* stream, Session* session, SourceManager* sourceManager, List<RefPtr<IRModule>>& outModules)
+{
+ // Load up the module
+ RiffContainer container;
+ SLANG_RETURN_ON_FAIL(RiffUtil::read(stream, container));
+
+ List<RiffContainer::ListChunk*> moduleChunks;
+ // First try to find a list
+ {
+ RiffContainer::ListChunk* listChunk = container.getRoot()->findListRec(IRSerialBinary::kSlangModuleListFourCc);
+ if (listChunk)
+ {
+ listChunk->findContained(IRSerialBinary::kSlangModuleFourCc, moduleChunks);
+ }
+ else
+ {
+ // Maybe its just a single module
+ RiffContainer::ListChunk* moduleChunk = container.getRoot()->findListRec(IRSerialBinary::kSlangModuleFourCc);
+ if (!moduleChunk)
+ {
+ // Couldn't find any modules
+ return SLANG_FAIL;
+ }
+ moduleChunks.add(moduleChunk);
+ }
+ }
+
+ // Okay, we need to decode into ir modules
+ for (auto moduleChunk : moduleChunks)
+ {
+ IRSerialData serialData;
+
+ SLANG_RETURN_ON_FAIL(IRSerialReader::readContainer(moduleChunk, &serialData));
+
+ // Construct into a module
+ RefPtr<IRModule> irModule;
+ IRSerialReader reader;
+ SLANG_RETURN_ON_FAIL(reader.read(serialData, session, sourceManager, irModule));
+
+ outModules.add(irModule);
+ }
+
+ return SLANG_OK;
+}
+
/* static */Result IRSerialReader::read(const IRSerialData& data, Session* session, SourceManager* sourceManager, RefPtr<IRModule>& moduleOut)
{
typedef Ser::Inst::PayloadType PayloadType;
diff --git a/source/slang/slang-ir-serialize.h b/source/slang/slang-ir-serialize.h
index ed9441874..d1f78d5f8 100644
--- a/source/slang/slang-ir-serialize.h
+++ b/source/slang/slang-ir-serialize.h
@@ -357,42 +357,44 @@ struct IRSerialBinary
VariableByteLite,
};
- static const uint32_t kRiffFourCc = RiffFourCC::kRiff;
+ static const FourCC kRiffFourCc = RiffFourCC::kRiff;
- static const uint32_t kSlangModuleFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'd'); ///< Holds all the slang specific chunks
+ static const FourCC kSlangModuleListFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'l');
- static const uint32_t kSlangModuleHeaderFourCc = SLANG_FOUR_CC('S', 'L', 'h', 'd');
+ static const FourCC kSlangModuleFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'd'); ///< Holds all the slang specific chunks
- static const uint32_t kInstFourCc = SLANG_FOUR_CC('S', 'L', 'i', 'n');
- static const uint32_t kChildRunFourCc = SLANG_FOUR_CC('S', 'L', 'c', 'r');
- static const uint32_t kExternalOperandsFourCc = SLANG_FOUR_CC('S', 'L', 'e', 'o');
+ static const FourCC kSlangModuleHeaderFourCc = SLANG_FOUR_CC('S', 'L', 'h', 'd');
- static const uint32_t kCompressedInstFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kInstFourCc);
- static const uint32_t kCompressedChildRunFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kChildRunFourCc);
- static const uint32_t kCompressedExternalOperandsFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kExternalOperandsFourCc);
+ static const FourCC kInstFourCc = SLANG_FOUR_CC('S', 'L', 'i', 'n');
+ static const FourCC kChildRunFourCc = SLANG_FOUR_CC('S', 'L', 'c', 'r');
+ static const FourCC kExternalOperandsFourCc = SLANG_FOUR_CC('S', 'L', 'e', 'o');
- static const uint32_t kStringFourCc = SLANG_FOUR_CC('S', 'L', 's', 't');
+ static const FourCC kCompressedInstFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kInstFourCc);
+ static const FourCC kCompressedChildRunFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kChildRunFourCc);
+ static const FourCC kCompressedExternalOperandsFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kExternalOperandsFourCc);
- static const uint32_t kUInt32SourceLocFourCc = SLANG_FOUR_CC('S', 'r', 's', '4');
+ static const FourCC kStringFourCc = SLANG_FOUR_CC('S', 'L', 's', 't');
- static const uint32_t kDebugStringFourCc = SLANG_FOUR_CC('S', 'd', 's', 't');
- static const uint32_t kDebugLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'l', 'n');
- static const uint32_t kDebugAdjustedLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'a', 'l');
- static const uint32_t kDebugSourceInfoFourCc = SLANG_FOUR_CC('S', 'd', 's', 'o');
- static const uint32_t kDebugSourceLocRunFourCc = SLANG_FOUR_CC('S', 'd', 's', 'r');
+ static const FourCC kUInt32SourceLocFourCc = SLANG_FOUR_CC('S', 'r', 's', '4');
+
+ static const FourCC kDebugStringFourCc = SLANG_FOUR_CC('S', 'd', 's', 't');
+ static const FourCC kDebugLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'l', 'n');
+ static const FourCC kDebugAdjustedLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'a', 'l');
+ static const FourCC kDebugSourceInfoFourCc = SLANG_FOUR_CC('S', 'd', 's', 'o');
+ static const FourCC kDebugSourceLocRunFourCc = SLANG_FOUR_CC('S', 'd', 's', 'r');
struct ModuleHeader
{
- uint32_t m_compressionType; ///< Holds the compression type used (if used at all)
+ uint32_t compressionType; ///< Holds the compression type used (if used at all)
};
struct ArrayHeader
{
- uint32_t m_numEntries;
+ uint32_t numEntries;
};
struct CompressedArrayHeader
{
- uint32_t m_numEntries; ///< The number of entries
- uint32_t m_numCompressedEntries; ///< The amount of compressed entries
+ uint32_t numEntries; ///< The number of entries
+ uint32_t numCompressedEntries; ///< The amount of compressed entries
};
};
@@ -501,12 +503,17 @@ struct IRSerialReader
/// Read a stream to fill in dataOut IRSerialData
static Result readStream(Stream* stream, IRSerialData* dataOut);
+ /// Read potentially multiple modules from a stream
+ static Result readStreamModules(Stream* stream, Session* session, SourceManager* manager, List<RefPtr<IRModule>>& outModules);
+
/// Read a stream to fill in dataOut IRSerialData
static Result readContainer(RiffContainer::ListChunk* module, IRSerialData* outData);
/// Read a module from serial data
Result read(const IRSerialData& data, Session* session, SourceManager* sourceManager, RefPtr<IRModule>& moduleOut);
+
+
/// Get the representation cache
StringRepresentationCache& getStringRepresentationCache() { return m_stringRepresentationCache; }
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index e9a8e7e04..76ebcca52 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -11,6 +11,7 @@
#include "slang-file-system.h"
#include "slang-state-serialize.h"
+#include "slang-ir-serialize.h"
#include <assert.h>
@@ -857,6 +858,26 @@ struct OptionsParser
return SLANG_FAIL;
}
}
+ else if (argStr == "-r")
+ {
+ String moduleName;
+ SLANG_RETURN_ON_FAIL(tryReadCommandLineArgument(sink, arg, &argCursor, argEnd, moduleName));
+
+ // We need to deserialize and add the modules
+ FileStream fileStream(moduleName, FileMode::Open, FileAccess::Read, FileShare::ReadWrite);
+
+ List<RefPtr<IRModule>> irModules;
+ if (SLANG_FAILED(IRSerialReader::readStreamModules(&fileStream, asInternal(session), requestImpl->getFrontEndReq()->getSourceManager(), irModules)))
+ {
+ sink->diagnose(SourceLoc(), Diagnostics::unableToReadModuleContainer, moduleName);
+ return SLANG_FAIL;
+ }
+
+ // TODO(JS): May be better to have a ITypeComponent that encapsulates a collection of modules
+ // For now just add to the linkage
+ auto linkage = requestImpl->getLinkage();
+ linkage->m_libModules.addRange(irModules.getBuffer(), irModules.getCount());
+ }
else if (argStr == "-v")
{
sink->diagnoseRaw(Severity::Note, session->getBuildTagString());