diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/core/slang-riff.cpp | 13 | ||||
| -rw-r--r-- | source/core/slang-riff.h | 3 | ||||
| -rw-r--r-- | source/slang/slang-compiler.cpp | 69 | ||||
| -rw-r--r-- | source/slang/slang-compiler.h | 4 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-ir-link.cpp | 23 | ||||
| -rw-r--r-- | source/slang/slang-ir-serialize.cpp | 73 | ||||
| -rw-r--r-- | source/slang/slang-ir-serialize.h | 47 | ||||
| -rw-r--r-- | source/slang/slang-options.cpp | 21 |
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()); |
