From 181fd1f3c9c4b047c1947096e7b3f8e5bc2314c3 Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Tue, 18 Apr 2023 12:36:06 -0400 Subject: On demand SourceMap JSON serialization (#2811) * #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. --- .../compiler-core/slang-artifact-handler-impl.cpp | 49 +++++++++++++++++++- .../compiler-core/slang-json-source-map-util.cpp | 43 ++++++++++++++++++ source/compiler-core/slang-json-source-map-util.h | 6 +++ source/compiler-core/slang-source-map.h | 2 + source/core/slang-castable.cpp | 31 +++++++++++++ source/core/slang-castable.h | 53 ++++++++++++++++++++++ source/slang/slang-compiler.cpp | 28 ++---------- source/slang/slang-emit.cpp | 26 ++--------- source/slang/slang.cpp | 11 ++--- 9 files changed, 194 insertions(+), 55 deletions(-) (limited to 'source') diff --git a/source/compiler-core/slang-artifact-handler-impl.cpp b/source/compiler-core/slang-artifact-handler-impl.cpp index 985aa2337..1a8e8374d 100644 --- a/source/compiler-core/slang-artifact-handler-impl.cpp +++ b/source/compiler-core/slang-artifact-handler-impl.cpp @@ -17,6 +17,10 @@ #include "../core/slang-io.h" #include "../core/slang-shared-library.h" +#include "slang-source-map.h" + +#include "slang-json-source-map-util.h" + namespace Slang { /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DefaultArtifactHandler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -126,6 +130,25 @@ SlangResult DefaultArtifactHandler::expandChildren(IArtifact* container) return SLANG_OK; } +static SlangResult _loadSourceMap(IArtifact* artifact, ArtifactKeep intermediateKeep, RefPtr& outSourceMap) +{ + const auto desc = artifact->getDesc(); + if (isDerivedFrom(desc.kind, ArtifactKind::Json) && + isDerivedFrom(desc.payload, ArtifactPayload::SourceMap)) + { + ComPtr blob; + SLANG_RETURN_ON_FAIL(artifact->loadBlob(intermediateKeep, blob.writeRef())); + + RefPtr sourceMap; + SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::read(blob, sourceMap)); + + outSourceMap = sourceMap; + return SLANG_OK; + } + + return SLANG_FAIL; +} + SlangResult DefaultArtifactHandler::getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) { const auto reps = artifact->getRepresentations(); @@ -156,8 +179,16 @@ SlangResult DefaultArtifactHandler::getOrCreateRepresentation(IArtifact* artifac } } - // Special case shared library - if (guid == ISlangSharedLibrary::getTypeGuid()) + // Special cases + if (guid == SourceMap::getTypeGuid()) + { + // Blob -> SourceMap + RefPtr sourceMap; + SLANG_RETURN_ON_FAIL(_loadSourceMap(artifact, getIntermediateKeep(keep), sourceMap)); + ComPtr castable(new ObjectCastableAdapter(sourceMap)); + return _addRepresentation(artifact, keep, castable, outCastable); + } + else if (guid == ISlangSharedLibrary::getTypeGuid()) { ComPtr sharedLib; SLANG_RETURN_ON_FAIL(_loadSharedLibrary(artifact, sharedLib.writeRef())); @@ -169,6 +200,20 @@ SlangResult DefaultArtifactHandler::getOrCreateRepresentation(IArtifact* artifac SLANG_RETURN_ON_FAIL(_createOSFile(artifact, getIntermediateKeep(keep), fileRep.writeRef())); return _addRepresentation(artifact, keep, fileRep, outCastable); } + else if (guid == ISlangBlob::getTypeGuid()) + { + for (ICastable* rep : reps) + { + if (SourceMap* sourceMap = as(rep)) + { + // SourceMap -> Blob + ComPtr blob; + SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::write(sourceMap, blob)); + // Add the rep + return _addRepresentation(artifact, keep, blob, outCastable); + } + } + } return SLANG_E_NOT_AVAILABLE; } diff --git a/source/compiler-core/slang-json-source-map-util.cpp b/source/compiler-core/slang-json-source-map-util.cpp index 3929a3387..4ef6ee3d6 100644 --- a/source/compiler-core/slang-json-source-map-util.cpp +++ b/source/compiler-core/slang-json-source-map-util.cpp @@ -3,6 +3,7 @@ #include "../../slang-com-helper.h" #include "../core/slang-string-util.h" +#include "../core/slang-blob.h" #include "slang-json-native.h" @@ -454,6 +455,11 @@ SlangResult JSONSourceMapUtil::encode(SourceMap* sourceMap, JSONContainer* conta return SLANG_OK; } +/* static */SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, RefPtr& outSourceMap) +{ + return read(blob, nullptr, outSourceMap); +} + SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, DiagnosticSink* parentSink, RefPtr& outSourceMap) { SourceManager sourceManager; @@ -489,4 +495,41 @@ SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, DiagnosticSink* parentSink return SLANG_OK; } + +/* static */SlangResult JSONSourceMapUtil::write(SourceMap* sourceMap, ComPtr& outBlob) +{ + SourceManager sourceMapSourceManager; + sourceMapSourceManager.initialize(nullptr, nullptr); + + // Create a sink + DiagnosticSink sourceMapSink(&sourceMapSourceManager, nullptr); + + SLANG_RETURN_ON_FAIL(write(sourceMap, &sourceMapSink, outBlob)); + return SLANG_OK; +} + +/* static */ SlangResult JSONSourceMapUtil::write(SourceMap* sourceMap, DiagnosticSink* sink, ComPtr& outBlob) +{ + auto sourceManager = sink->getSourceManager(); + + // Write it out + String json; + { + RefPtr jsonContainer(new JSONContainer(sourceManager)); + + JSONValue jsonValue; + + SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::encode(sourceMap, jsonContainer, sink, jsonValue)); + + // Convert into a string + JSONWriter writer(JSONWriter::IndentationStyle::Allman); + jsonContainer->traverseRecursively(jsonValue, &writer); + + json = writer.getBuilder(); + } + + outBlob = StringBlob::moveCreate(json); + return SLANG_OK; +} + } // namespace Slang diff --git a/source/compiler-core/slang-json-source-map-util.h b/source/compiler-core/slang-json-source-map-util.h index ba417dd7c..8d5071d4e 100644 --- a/source/compiler-core/slang-json-source-map-util.h +++ b/source/compiler-core/slang-json-source-map-util.h @@ -18,6 +18,12 @@ struct JSONSourceMapUtil /// Read the blob (encoded as JSON) as a source map. /// Sink is optional, and can be passed as nullptr static SlangResult read(ISlangBlob* blob, DiagnosticSink* sink, RefPtr& outSourceMap); + static SlangResult read(ISlangBlob* blob, RefPtr& outSourceMap); + + /// Write source map to outBlob JSON + static SlangResult write(SourceMap* sourceMap, ComPtr& outBlob); + /// Write out the source map into a blob + static SlangResult write(SourceMap* sourceMap, DiagnosticSink* sink, ComPtr& outBlob); }; } // namespace Slang diff --git a/source/compiler-core/slang-source-map.h b/source/compiler-core/slang-source-map.h index 1ccc87e90..f1338508f 100644 --- a/source/compiler-core/slang-source-map.h +++ b/source/compiler-core/slang-source-map.h @@ -13,6 +13,8 @@ namespace Slang { class SourceMap : public RefObject { public: + SLANG_CLASS_GUID(0x731383ea, 0xe516, 0x4cc3, { 0xa6, 0xcf, 0x37, 0xd2, 0x8c, 0x24, 0x5c, 0x5e }); + struct Entry { void init() diff --git a/source/core/slang-castable.cpp b/source/core/slang-castable.cpp index f3c6541dd..6b7644bf2 100644 --- a/source/core/slang-castable.cpp +++ b/source/core/slang-castable.cpp @@ -20,6 +20,37 @@ namespace Slang { return castable; } +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ObjectCastableAdapter !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* ObjectCastableAdapter::castAs(const Guid& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + return getObject(guid); +} + +void* ObjectCastableAdapter::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == IObjectCastableAdapter::getTypeGuid()) + { + return static_cast(this); + } + return nullptr; +} + +void* ObjectCastableAdapter::getObject(const Guid& guid) +{ + if (guid == m_containedGuid) + { + return m_contained; + } + return nullptr; +} + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! UnknownCastableAdapter !!!!!!!!!!!!!!!!!!!!!!!!!!! */ void* UnknownCastableAdapter::castAs(const Guid& guid) diff --git a/source/core/slang-castable.h b/source/core/slang-castable.h index a72822f05..4f4fdc940 100644 --- a/source/core/slang-castable.h +++ b/source/core/slang-castable.h @@ -35,6 +35,58 @@ SLANG_FORCE_INLINE T* as(ICastable* castable) return nullptr; } +/* Adapter interface to make non castable ref counted object usable as ICastable */ +class IObjectCastableAdapter : public ICastable +{ + SLANG_COM_INTERFACE(0x8b4aad81, 0x4934, 0x4a67, { 0xb2, 0xe2, 0xe9, 0x17, 0xfc, 0x29, 0x12, 0x54 }); + + /// Get the contained object + virtual SLANG_NO_THROW RefObject* SLANG_MCALL getContained() = 0; + /// Get the guid that represents the contained ref object + virtual SLANG_NO_THROW SlangUUID getContainedGuid() = 0; +}; + +class ObjectCastableAdapter : public ComBaseObject, public IObjectCastableAdapter +{ +public: + SLANG_COM_BASE_IUNKNOWN_ALL + + // ICastable + SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // IObjectCastableAdapter + virtual SLANG_NO_THROW RefObject* SLANG_MCALL getContained() SLANG_OVERRIDE { return m_contained; } + virtual SlangUUID getContainedGuid() SLANG_OVERRIDE { return m_containedGuid; } + + template + explicit ObjectCastableAdapter(T* ptr) + { + m_containedGuid = T::getTypeGuid(); + m_contained = ptr; + } + template + explicit ObjectCastableAdapter(const RefPtr& ptr) + { + m_containedGuid = T::getTypeGuid(); + m_contained = ptr; + } + + ObjectCastableAdapter(RefObject* obj, const Guid& containedGuid) : + m_contained(obj), + m_containedGuid(containedGuid) + { + SLANG_ASSERT(obj); + } + +protected: + void* getInterface(const Guid& guid); + void* getObject(const Guid& guid); + + RefPtr m_contained; + SlangUUID m_containedGuid; +}; + + /* Adapter interface to make a non castable types work as ICastable */ class IUnknownCastableAdapter : public ICastable { @@ -44,6 +96,7 @@ class IUnknownCastableAdapter : public ICastable virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getContained() = 0; }; + /* An adapter such that types which aren't derived from ICastable, can be used as such. With the following caveats. diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index becd65596..907f39f48 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -15,8 +15,6 @@ #include "../compiler-core/slang-lexer.h" -#include "../compiler-core/slang-json-source-map-util.h" - // Artifact #include "../compiler-core/slang-artifact-desc-util.h" #include "../compiler-core/slang-artifact-representation-impl.h" @@ -1902,9 +1900,6 @@ namespace Slang auto frontEndReq = getFrontEndReq(); - auto sourceManager = frontEndReq->getSourceManager(); - auto sink = getSink(); - for (auto translationUnit : frontEndReq->translationUnits) { // Hmmm do I have to therefore add a map for all translation units(!) @@ -1915,29 +1910,14 @@ namespace Slang // If we have a source map *and* we want to generate them for output add to the container if (sourceMap && getLinkage()->m_generateSourceMap) { - // Write it out - String json; - { - RefPtr jsonContainer(new JSONContainer(sourceManager)); - - JSONValue jsonValue; - - SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::encode(sourceMap, jsonContainer, sink, jsonValue)); - - // Convert into a string - JSONWriter writer(JSONWriter::IndentationStyle::Allman); - jsonContainer->traverseRecursively(jsonValue, &writer); - - json = writer.getBuilder(); - } - - auto jsonSourceMapBlob = StringBlob::moveCreate(json); - auto artifactDesc = ArtifactDesc::make(ArtifactKind::Json, ArtifactPayload::SourceMap, ArtifactStyle::Obfuscated); // Create the source map artifact auto sourceMapArtifact = Artifact::create(artifactDesc, sourceMap->m_file.getUnownedSlice()); - sourceMapArtifact->addRepresentationUnknown(jsonSourceMapBlob); + + // Add the repesentation + ComPtr castableAdapter(new ObjectCastableAdapter(sourceMap)); + sourceMapArtifact->addRepresentation(castableAdapter); // Associate with the container m_containerArtifact->addAssociated(sourceMapArtifact); diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index e2948561c..67a4c4610 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -82,7 +82,7 @@ #include "../compiler-core/slang-artifact-impl.h" #include "../compiler-core/slang-artifact-associated-impl.h" -#include "../compiler-core/slang-json-source-map-util.h" +#include "../core/slang-castable.h" #include @@ -1152,28 +1152,10 @@ SlangResult CodeGenContext::emitEntryPointsSourceFromIR(ComPtr& outAr if (sourceMap) { - SourceManager sourceMapSourceManager; - sourceMapSourceManager.initialize(nullptr, nullptr); - - // Create a sink - DiagnosticSink sourceMapSink(&sourceMapSourceManager, nullptr); - - // Turn into JSON - RefPtr jsonContainer(new JSONContainer(&sourceMapSourceManager)); - - JSONValue jsonValue; - SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::encode(sourceMap, jsonContainer, &sourceMapSink, jsonValue)); - - // Okay now convert this into a text file and then a blob - - // Convert into a string - JSONWriter writer(JSONWriter::IndentationStyle::KNR); - jsonContainer->traverseRecursively(jsonValue, &writer); - - auto sourceMapBlob = StringBlob::moveCreate(writer.getBuilder()); - auto sourceMapArtifact = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactKind::Json, ArtifactPayload::SourceMap, ArtifactStyle::None)); - sourceMapArtifact->addRepresentationUnknown(sourceMapBlob); + + ComPtr castableAdapter(new ObjectCastableAdapter(sourceMap)); + sourceMapArtifact->addRepresentation(castableAdapter); artifact->addAssociated(sourceMapArtifact); } diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index c8cda0dca..bedfb1161 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -15,8 +15,6 @@ #include "../compiler-core/slang-artifact-associated-impl.h" #include "../compiler-core/slang-artifact-container-util.h" -#include "../compiler-core/slang-json-source-map-util.h" - #include "../core/slang-memory-file-system.h" #include "slang-module-library.h" @@ -4884,12 +4882,11 @@ SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifac isDerivedFrom(assocDesc.payload, ArtifactPayload::SourceMap) && isDerivedFrom(assocDesc.style, ArtifactStyle::Obfuscated)) { - ComPtr sourceMapBlob; - SLANG_RETURN_ON_FAIL(associated->loadBlob(ArtifactKeep::No, sourceMapBlob.writeRef())); + ComPtr castable; + SLANG_RETURN_ON_FAIL(associated->getOrCreateRepresentation(SourceMap::getTypeGuid(), ArtifactKeep::Yes, castable.writeRef())); + + auto sourceMap = as(castable); - RefPtr sourceMap; - SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::read(sourceMapBlob, nullptr, sourceMap)); - // I guess we add to all ir modules? for (auto irModule : library->m_modules) -- cgit v1.2.3