diff options
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/slang-compiler.cpp | 513 | ||||
| -rwxr-xr-x | source/slang/slang-compiler.h | 46 | ||||
| -rw-r--r-- | source/slang/slang-emit.cpp | 57 | ||||
| -rw-r--r-- | source/slang/slang-ir-link.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir-metadata.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 135 |
6 files changed, 400 insertions, 355 deletions
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 80015440a..e49b67af2 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -18,6 +18,7 @@ #include "../compiler-core/slang-artifact-desc-util.h" #include "../compiler-core/slang-artifact-representation-impl.h" #include "../compiler-core/slang-artifact-impl.h" +#include "../compiler-core/slang-artifact-util.h" #include "slang-lower-to-ir.h" #include "slang-mangle.h" @@ -55,52 +56,7 @@ namespace Slang { - // A temporary class that adapts `ISlangSharedLibrary_Dep1` to ISlangSharedLibrary - class SharedLibraryDep1Adapter : public ComBaseObject, public ISlangSharedLibrary - { - public: - SLANG_COM_BASE_IUNKNOWN_ALL - - // ICastable - virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const SlangUUID& guid) SLANG_OVERRIDE; - - // ISlangSharedLibrary - virtual SLANG_NO_THROW void* SLANG_MCALL findSymbolAddressByName(char const* name) SLANG_OVERRIDE { return m_contained->findSymbolAddressByName(name); } - - SharedLibraryDep1Adapter(ISlangSharedLibrary_Dep1* dep1): - m_contained(dep1) - { - } - - protected: - void* getInterface(const Guid& guid) - { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || - guid == ISlangSharedLibrary::getTypeGuid()) - { - return static_cast<ISlangSharedLibrary*>(this); - } - return nullptr; - } - void* getObject(const Guid& guid) - { - SLANG_UNUSED(guid); - return nullptr; - } - - ComPtr<ISlangSharedLibrary_Dep1> m_contained; - }; - - void* SharedLibraryDep1Adapter::castAs(const SlangUUID& guid) - { - if (auto intf = getInterface(guid)) - { - return intf; - } - return getObject(guid); - } // !!!!!!!!!!!!!!!!!!!!!! free functions for DiagnosicSink !!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -123,6 +79,7 @@ namespace Slang // !!!!!!!!!!!!!!!!!!!!!!!!!!!! CompileResult !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +#if 0 SlangResult CompileResult::getSharedLibrary(ComPtr<ISlangSharedLibrary>& outSharedLibrary) { if (downstreamResult) @@ -188,27 +145,8 @@ namespace Slang return SLANG_OK; } - SlangResult CompileResult::isParameterLocationUsed(SlangParameterCategory category, UInt spaceIndex, UInt registerIndex, bool& outUsed) - { - if (!postEmitMetadata) - return SLANG_E_NOT_AVAILABLE; - - if (!ShaderBindingRange::isUsageTracked((slang::ParameterCategory)category)) - return SLANG_E_NOT_AVAILABLE; - // TODO: optimize this with a binary search through a sorted list - for (const auto& range : postEmitMetadata->usedBindings) - { - if (range.containsBinding((slang::ParameterCategory)category, spaceIndex, registerIndex)) - { - outUsed = true; - return SLANG_OK; - } - } - - outUsed = false; - return SLANG_OK; - } +#endif // // FrontEndEntryPointRequest @@ -729,13 +667,20 @@ namespace Slang } } - SlangResult CodeGenContext::emitEntryPointsSource( - String& outSource, - RefPtr<PostEmitMetadata>& outMetadata) +#if SLANG_VC +// TODO(JS): This is a workaround +// In debug VS builds there is a warning on line about it being unreachable. +// for (auto entryPointIndex : getEntryPointIndices()) +// It's not clear how that could possibly be unreachable +# pragma warning(push) +# pragma warning(disable:4702) +#endif + SlangResult CodeGenContext::emitEntryPointsSource(ComPtr<IArtifact>& outArtifact) { - outSource = String(); + outArtifact.setNull(); - if(auto endToEndReq = isPassThroughEnabled()) + auto endToEndReq = isPassThroughEnabled(); + if(endToEndReq) { for (auto entryPointIndex : getEntryPointIndices()) { @@ -776,16 +721,22 @@ namespace Slang } } - outSource = codeBuilder.ProduceString(); + auto artifact = ArtifactUtil::createArtifactForCompileTarget(asExternal(getTargetFormat())); + artifact->addRepresentationUnknown(StringBlob::moveCreate(codeBuilder)); + + outArtifact.swap(artifact); + return SLANG_OK; } return SLANG_OK; } else { - return emitEntryPointsSourceFromIR( - outSource, outMetadata); + return emitEntryPointsSourceFromIR(outArtifact); } } +#if SLANG_VC +# pragma warning(pop) +#endif String GetHLSLProfileName(Profile profile) { @@ -1052,11 +1003,9 @@ namespace Slang return desc.style == ArtifactStyle::Host; } - SlangResult CodeGenContext::emitWithDownstreamForEntryPoints( - RefPtr<DownstreamCompileResult>& outResult, - RefPtr<PostEmitMetadata>& outMetadata) + SlangResult CodeGenContext::emitWithDownstreamForEntryPoints(ComPtr<IArtifact>& outArtifact) { - outResult.setNull(); + outArtifact.setNull(); auto sink = getSink(); auto session = getSession(); @@ -1123,6 +1072,8 @@ namespace Slang } } + ComPtr<IArtifact> sourceContainerArtifact; + /* This is more convoluted than the other scenarios, because when we invoke C/C++ compiler we would ideally like to use the original file. We want to do this because we want includes relative to the source file to work, and for that to work most easily we want to use the original file, if there is one */ @@ -1189,7 +1140,10 @@ namespace Slang options.sourceContentsPath = calcSourcePathForEntryPoints(); CodeGenContext sourceCodeGenContext(this, sourceTarget, extensionTracker); - SLANG_RETURN_ON_FAIL(sourceCodeGenContext.emitEntryPointsSource(options.sourceContents, outMetadata)); + + SLANG_RETURN_ON_FAIL(sourceCodeGenContext.emitEntryPointsSource(sourceContainerArtifact)); + + sourceCodeGenContext.maybeDumpIntermediate(sourceContainerArtifact); } else { @@ -1206,12 +1160,32 @@ namespace Slang else { CodeGenContext sourceCodeGenContext(this, sourceTarget, extensionTracker); - SLANG_RETURN_ON_FAIL(sourceCodeGenContext.emitEntryPointsSource(options.sourceContents, outMetadata)); - sourceCodeGenContext.maybeDumpIntermediate(options.sourceContents.getBuffer()); + + SLANG_RETURN_ON_FAIL(sourceCodeGenContext.emitEntryPointsSource(sourceContainerArtifact)); + sourceCodeGenContext.maybeDumpIntermediate(sourceContainerArtifact); sourceLanguage = (SourceLanguage)TypeConvertUtil::getSourceLanguageFromTarget((SlangCompileTarget)sourceTarget); } + ComPtr<IArtifact> metadata; + if (sourceContainerArtifact) + { + auto sourceArtifact = sourceContainerArtifact->findArtifactByDerivedDesc(IArtifact::FindStyle::SelfOrChildren, + ArtifactDesc::make(ArtifactKind::Source, ArtifactPayload::Base, ArtifactStyle::Base)); + if (!sourceArtifact) + { + return SLANG_FAIL; + } + + metadata = sourceContainerArtifact->findArtifactByDerivedDesc(IArtifact::FindStyle::SelfOrChildren, + ArtifactDesc::make(ArtifactKind::Base, ArtifactPayload::PostEmitMetadata, ArtifactStyle::Base)); + + ComPtr<ISlangBlob> blob; + SLANG_RETURN_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::No, blob.writeRef())); + + options.sourceContents = StringUtil::getString(blob); + } + // Add any preprocessor definitions associated with the linkage { // TODO(JS): This is somewhat arguable - should defines passed to Slang really be @@ -1539,7 +1513,22 @@ namespace Slang return SLANG_FAIL; } - outResult = downstreamCompileResult; + auto artifactContainer = ArtifactUtil::createResultsContainer(); + + if (metadata) + { + artifactContainer->addChild(metadata); + } + + // Create the artifact that encapsulates the result + auto artifact = ArtifactUtil::createArtifactForCompileTarget(asExternal(target)); + + // Wrap the downstream compile result + auto objRep = new ObjectArtifactRepresentation(DownstreamCompileResult::getTypeGuid(), downstreamCompileResult); + artifact->addRepresentation(objRep); + + // Set the artifact + outArtifact.swap(artifact); return SLANG_OK; } @@ -1588,8 +1577,7 @@ namespace Slang SlangResult emitSPIRVForEntryPointsDirectly( CodeGenContext* codeGenContext, - List<uint8_t>& spirvOut, - RefPtr<PostEmitMetadata>& outMetadata); + ComPtr<IArtifact>& outArtifact); static CodeGenTarget _getIntermediateTarget(CodeGenTarget target) { @@ -1603,9 +1591,7 @@ namespace Slang } /// Function to simplify the logic around emitting, and dissassembling - SlangResult CodeGenContext::_emitEntryPoints( - RefPtr<DownstreamCompileResult>& outDownstreamResult, - RefPtr<PostEmitMetadata>& outMetadata) + SlangResult CodeGenContext::_emitEntryPoints(ComPtr<IArtifact>& outArtifact) { auto target = getTargetFormat(); switch (target) @@ -1618,25 +1604,37 @@ namespace Slang const CodeGenTarget intermediateTarget = _getIntermediateTarget(target); CodeGenContext intermediateContext(this, intermediateTarget); - RefPtr<DownstreamCompileResult> code; - SLANG_RETURN_ON_FAIL(intermediateContext._emitEntryPoints(code, outMetadata)); - intermediateContext.maybeDumpIntermediate(code); + ComPtr<IArtifact> intermediateArtifact; + + SLANG_RETURN_ON_FAIL(intermediateContext._emitEntryPoints(intermediateArtifact)); + intermediateContext.maybeDumpIntermediate(intermediateArtifact); + + IArtifact* binaryArtifact = intermediateArtifact->findArtifactByDerivedDesc(IArtifact::FindStyle::SelfOrChildren, + ArtifactDesc::make(ArtifactKind::BinaryLike, ArtifactPayload::Base, ArtifactStyle::Base)); + if (!binaryArtifact) + { + return SLANG_FAIL; + } + + ComPtr<ISlangBlob> binaryBlob; + SLANG_RETURN_ON_FAIL(binaryArtifact->loadBlob(ArtifactKeep::No, binaryBlob.writeRef())); // Then disassemble the intermediate binary result to get the desired output // Output the disassembly ComPtr<ISlangBlob> disassemblyBlob; - SLANG_RETURN_ON_FAIL(intermediateContext.dissassembleWithDownstream(code, disassemblyBlob.writeRef())); + SLANG_RETURN_ON_FAIL(intermediateContext.dissassembleWithDownstream(binaryBlob->getBufferPointer(), binaryBlob->getBufferSize(), disassemblyBlob.writeRef())); + + auto artifact = ArtifactUtil::createArtifactForCompileTarget(asExternal(target)); + artifact->addRepresentationUnknown(disassemblyBlob); + + outArtifact.swap(artifact); - outDownstreamResult = new BlobDownstreamCompileResult(DownstreamDiagnostics(), disassemblyBlob); return SLANG_OK; } case CodeGenTarget::SPIRV: if (getTargetReq()->shouldEmitSPIRVDirectly()) { - List<uint8_t> spirv; - SLANG_RETURN_ON_FAIL(emitSPIRVForEntryPointsDirectly(this, spirv, outMetadata)); - auto spirvBlob = ListBlob::moveCreate(spirv); - outDownstreamResult = new BlobDownstreamCompileResult(DownstreamDiagnostics(), spirvBlob); + SLANG_RETURN_ON_FAIL(emitSPIRVForEntryPointsDirectly(this, outArtifact)); return SLANG_OK; } /* fall through to: */ @@ -1647,7 +1645,7 @@ namespace Slang case CodeGenTarget::ShaderSharedLibrary: case CodeGenTarget::HostExecutable: case CodeGenTarget::HostHostCallable: - SLANG_RETURN_ON_FAIL(emitWithDownstreamForEntryPoints(outDownstreamResult, outMetadata)); + SLANG_RETURN_ON_FAIL(emitWithDownstreamForEntryPoints(outArtifact)); return SLANG_OK; default: break; @@ -1657,10 +1655,8 @@ namespace Slang } // Do emit logic for a zero or more entry points - CompileResult CodeGenContext::emitEntryPoints() + SlangResult CodeGenContext::emitEntryPoints(ComPtr<IArtifact>& outArtifact) { - CompileResult result; - auto target = getTargetFormat(); switch (target) @@ -1677,14 +1673,10 @@ namespace Slang case CodeGenTarget::ShaderSharedLibrary: case CodeGenTarget::HostExecutable: { - RefPtr<DownstreamCompileResult> downstreamResult; - RefPtr<PostEmitMetadata> metadata; + SLANG_RETURN_ON_FAIL(_emitEntryPoints(outArtifact)); - if (SLANG_SUCCEEDED(_emitEntryPoints(downstreamResult, metadata))) - { - maybeDumpIntermediate(downstreamResult); - result = CompileResult(downstreamResult, metadata); - } + maybeDumpIntermediate(outArtifact); + return SLANG_OK; } break; case CodeGenTarget::GLSL: @@ -1695,35 +1687,31 @@ namespace Slang case CodeGenTarget::CSource: { RefPtr<ExtensionTracker> extensionTracker = _newExtensionTracker(target); - RefPtr<PostEmitMetadata> metadata; - + CodeGenContext subContext(this, target, extensionTracker); - String code; - if (SLANG_FAILED(subContext.emitEntryPointsSource(code, metadata))) - { - return result; - } + ComPtr<IArtifact> sourceArtifact; + + SLANG_RETURN_ON_FAIL(subContext.emitEntryPointsSource(sourceArtifact)); - subContext.maybeDumpIntermediate(code.getBuffer()); - result = CompileResult(code, metadata); + subContext.maybeDumpIntermediate(sourceArtifact); + outArtifact = sourceArtifact; + return SLANG_OK; } break; case CodeGenTarget::None: // The user requested no output - break; + return SLANG_OK; // Note(tfoley): We currently hit this case when compiling the stdlib case CodeGenTarget::Unknown: - break; + return SLANG_OK; default: SLANG_UNEXPECTED("unhandled code generation target"); break; } - - return result; } enum class OutputFileKind @@ -1792,42 +1780,31 @@ namespace Slang static void writeCompileResultToFile( CodeGenContext* context, String const& outputPath, - CompileResult const& result) + IArtifact* inArtifact) { - switch (result.format) + // The artifact can contain multiple things, we want to find something like 'source' or binary like + IArtifact* artifact = ArtifactUtil::findSignificant(inArtifact); + if (!artifact) { - case ResultFormat::Text: - { - auto text = result.outputString; - writeOutputFile(context, - outputPath, - text.begin(), - text.end() - text.begin(), - OutputFileKind::Text); - } - break; - - case ResultFormat::Binary: - { - ComPtr<ISlangBlob> blob; - if (SLANG_FAILED(result.getBlob(blob))) - { - SLANG_UNEXPECTED("No blob to emit"); - return; - } - writeOutputFile(context, - outputPath, - blob->getBufferPointer(), - blob->getBufferSize(), - OutputFileKind::Binary); - } - break; + return; + } - default: - SLANG_UNEXPECTED("unhandled output format"); - break; + ComPtr<ISlangBlob> blob; + if (SLANG_FAILED(artifact->loadBlob(ArtifactKeep::No, blob.writeRef()))) + { + // Unable to get blob + return; } + const auto outputKind = ArtifactDescUtil::isText(artifact->getDesc()) ? + OutputFileKind::Text : + OutputFileKind::Binary; + + writeOutputFile(context, + outputPath, + (const char*)blob->getBufferPointer(), + blob->getBufferSize(), + outputKind); } static void writeOutputToConsole( @@ -1840,99 +1817,65 @@ namespace Slang static void writeCompileResultToStandardOutput( CodeGenContext* codeGenContext, EndToEndCompileRequest* endToEndReq, - CompileResult const& result) + IArtifact* inArtifact) { - auto targetReq = codeGenContext->getTargetReq(); ISlangWriter* writer = endToEndReq->getWriter(WriterChannel::StdOutput); - switch (result.format) + // The artifact can contain multiple things, we want to find something like 'source' or binary like + IArtifact* artifact = ArtifactUtil::findSignificant(inArtifact); + if (!artifact) { - case ResultFormat::Text: - writeOutputToConsole(writer, result.outputString); - break; - - case ResultFormat::Binary: - { - ComPtr<ISlangBlob> blob; - if (SLANG_FAILED(result.getBlob(blob))) - { - if (ArtifactDescUtil::makeDescFromCompileTarget(asExternal(targetReq->getTarget())).kind == ArtifactKind::HostCallable) - { - // Some HostCallable are not directly representable as a 'binary'. - // So here, we just ignore if that appears the case, and don't output an unexpected error. - return; - } + return; + } - SLANG_UNEXPECTED("No blob to emit"); - return; - } + ComPtr<ISlangBlob> blob; + if (SLANG_FAILED(artifact->loadBlob(ArtifactKeep::No, blob.writeRef()))) + { + // Unable to get blob + return; + } - const void* blobData = blob->getBufferPointer(); - size_t blobSize = blob->getBufferSize(); + // If is text, we can just output + if (ArtifactDescUtil::isText(artifact->getDesc())) + { + writer->write((const char*)blob->getBufferPointer(), blob->getBufferSize()); + return; + } - if (writer->isConsole()) + if (writer->isConsole()) + { + switch (artifact->getDesc().payload) + { + case ArtifactPayload::SPIRV: + case ArtifactPayload::DXIL: + case ArtifactPayload::DXBC: { - // Writing to console, so we need to generate text output. + ComPtr<ISlangBlob> disassemblyBlob; - switch (targetReq->getTarget()) + if (SLANG_SUCCEEDED(codeGenContext->dissassembleWithDownstream(blob->getBufferPointer(), blob->getBufferSize(), disassemblyBlob.writeRef()))) { - case CodeGenTarget::SPIRVAssembly: - case CodeGenTarget::DXBytecodeAssembly: - case CodeGenTarget::DXILAssembly: - { - const UnownedStringSlice disassembly = StringUtil::getSlice(blob); - writeOutputToConsole(writer, disassembly); - } - break; - case CodeGenTarget::SPIRV: - case CodeGenTarget::DXIL: - case CodeGenTarget::DXBytecode: - { - ComPtr<ISlangBlob> disassemblyBlob; - - if (SLANG_SUCCEEDED(codeGenContext->dissassembleWithDownstream(blobData, blobSize, disassemblyBlob.writeRef()))) - { - const UnownedStringSlice disassembly = StringUtil::getSlice(disassemblyBlob); - writeOutputToConsole(writer, disassembly); - } - } - break; - case CodeGenTarget::PTX: - // For now we just dump PTX out as hex - - case CodeGenTarget::HostHostCallable: - case CodeGenTarget::ShaderHostCallable: - case CodeGenTarget::ShaderSharedLibrary: - case CodeGenTarget::HostExecutable: - HexDumpUtil::dumpWithMarkers((const uint8_t*)blobData, blobSize, 24, writer); - break; - - - default: - SLANG_UNEXPECTED("unhandled output format"); - return; - } + const UnownedStringSlice disassembly = StringUtil::getSlice(disassemblyBlob); + writeOutputToConsole(writer, disassembly); + } + return; } - else - { - // Redirecting stdout to a file, so do the usual thing - writer->setMode(SLANG_WRITER_MODE_BINARY); - - writeOutputFile( - codeGenContext, - writer, - "stdout", - blobData, - blobSize); } - } - break; - default: - SLANG_UNEXPECTED("unhandled output format"); - break; + // Else just dump as text + HexDumpUtil::dumpWithMarkers((const uint8_t*)blob->getBufferPointer(), blob->getBufferSize(), 24, writer); } + else + { + // Redirecting stdout to a file, so do the usual thing + writer->setMode(SLANG_WRITER_MODE_BINARY); + writeOutputFile( + codeGenContext, + writer, + "stdout", + blob->getBufferPointer(), + blob->getBufferSize()); + } } void EndToEndCompileRequest::writeWholeProgramResult( @@ -1941,10 +1884,10 @@ namespace Slang auto program = getSpecializedGlobalAndEntryPointsComponentType(); auto targetProgram = program->getTargetProgram(targetReq); - auto& result = targetProgram->getExistingWholeProgramResult(); + IArtifact* artifact = targetProgram->getExistingWholeProgramResult(); // Skip the case with no output - if (result.format == ResultFormat::None) + if (artifact == nullptr) return; CodeGenContext::EntryPointIndices entryPointIndices; @@ -1964,12 +1907,12 @@ namespace Slang String outputPath = targetInfo->wholeTargetOutputPath; if (outputPath != "") { - writeCompileResultToFile(&codeGenContext, outputPath, result); + writeCompileResultToFile(&codeGenContext, outputPath, artifact); return; } } - writeCompileResultToStandardOutput(&codeGenContext, this, result); + writeCompileResultToStandardOutput(&codeGenContext, this, artifact); } void EndToEndCompileRequest::writeEntryPointResult( @@ -1979,10 +1922,10 @@ namespace Slang auto program = getSpecializedGlobalAndEntryPointsComponentType(); auto targetProgram = program->getTargetProgram(targetReq); - auto& result = targetProgram->getExistingEntryPointResult(entryPointIndex); + IArtifact* artifact = targetProgram->getExistingEntryPointResult(entryPointIndex); // Skip the case with no output - if (result.format == ResultFormat::None) + if (artifact == nullptr) return; CodeGenContext::EntryPointIndices entryPointIndices; @@ -2003,15 +1946,15 @@ namespace Slang String outputPath; if(targetInfo->entryPointOutputPaths.TryGetValue(entryPointIndex, outputPath)) { - writeCompileResultToFile(&codeGenContext, outputPath, result); + writeCompileResultToFile(&codeGenContext, outputPath, artifact); return; } } - writeCompileResultToStandardOutput(&codeGenContext, this, result); + writeCompileResultToStandardOutput(&codeGenContext, this, artifact); } - CompileResult& TargetProgram::_createWholeProgramResult( + IArtifact* TargetProgram::_createWholeProgramResult( DiagnosticSink* sink, EndToEndCompileRequest* endToEndReq) { @@ -2026,17 +1969,18 @@ namespace Slang for (Index i = 0; i < entryPointIndices.getCount(); i++) entryPointIndices[i] = i; - auto& result = m_wholeProgramResult; - CodeGenContext::Shared sharedCodeGenContext(this, entryPointIndices, sink, endToEndReq); CodeGenContext codeGenContext(&sharedCodeGenContext); - result = codeGenContext.emitEntryPoints(); - - return result; + if (SLANG_FAILED(codeGenContext.emitEntryPoints(m_wholeProgramResult))) + { + return nullptr; + } + + return m_wholeProgramResult; } - CompileResult& TargetProgram::_createEntryPointResult( + IArtifact* TargetProgram::_createEntryPointResult( Int entryPointIndex, DiagnosticSink* sink, EndToEndCompileRequest* endToEndReq) @@ -2050,26 +1994,25 @@ namespace Slang // this problem. // if(entryPointIndex >= m_entryPointResults.getCount()) - m_entryPointResults.setCount(entryPointIndex+1); - - auto& result = m_entryPointResults[entryPointIndex]; + m_entryPointResults.setCount(entryPointIndex + 1); + CodeGenContext::EntryPointIndices entryPointIndices; entryPointIndices.add(entryPointIndex); CodeGenContext::Shared sharedCodeGenContext(this, entryPointIndices, sink, endToEndReq); CodeGenContext codeGenContext(&sharedCodeGenContext); - result = codeGenContext.emitEntryPoints(); - return result; + codeGenContext.emitEntryPoints(m_entryPointResults[entryPointIndex]); + + return m_entryPointResults[entryPointIndex]; } - CompileResult& TargetProgram::getOrCreateWholeProgramResult( + IArtifact* TargetProgram::getOrCreateWholeProgramResult( DiagnosticSink* sink) { - auto& result = m_wholeProgramResult; - if (result.format != ResultFormat::None) - return result; + if (m_wholeProgramResult) + return m_wholeProgramResult; // If we haven't yet computed a layout for this target // program, we need to make sure that is done before @@ -2077,22 +2020,21 @@ namespace Slang // if (!getOrCreateIRModuleForLayout(sink)) { - return result; + return nullptr; } return _createWholeProgramResult(sink); } - CompileResult& TargetProgram::getOrCreateEntryPointResult( + IArtifact* TargetProgram::getOrCreateEntryPointResult( Int entryPointIndex, DiagnosticSink* sink) { if(entryPointIndex >= m_entryPointResults.getCount()) - m_entryPointResults.setCount(entryPointIndex+1); + m_entryPointResults.setCount(entryPointIndex + 1); - auto& result = m_entryPointResults[entryPointIndex]; - if( result.format != ResultFormat::None ) - return result; + if(IArtifact* artifact = m_entryPointResults[entryPointIndex]) + return artifact; // If we haven't yet computed a layout for this target // program, we need to make sure that is done before @@ -2100,7 +2042,7 @@ namespace Slang // if( !getOrCreateIRModuleForLayout(sink) ) { - return result; + return nullptr; } return _createEntryPointResult( @@ -2492,6 +2434,59 @@ namespace Slang return nullptr; } + void CodeGenContext::maybeDumpIntermediate(IArtifact* inArtifact) + { + if (!shouldDumpIntermediates()) + return; + + IArtifact* artifact = ArtifactUtil::findSignificant(inArtifact); + if (!artifact) + { + return; + } + + ComPtr<ISlangBlob> blob; + if (SLANG_FAILED(artifact->loadBlob(ArtifactKeep::No, blob.writeRef()))) + { + return; + } + + const auto desc = artifact->getDesc(); + String ext = ArtifactDescUtil::getDefaultExtension(desc); + + + if (ArtifactDescUtil::isText(artifact->getDesc())) + { + dumpIntermediateText(blob->getBufferPointer(), blob->getBufferSize(), ext.getBuffer()); + } + else + { + switch (artifact->getDesc().payload) + { + case ArtifactPayload::SPIRV: + case ArtifactPayload::DXIL: + case ArtifactPayload::DXBC: + { + ComPtr<ISlangBlob> disassemblyBlob; + + if (SLANG_SUCCEEDED(dissassembleWithDownstream(blob->getBufferPointer(), blob->getBufferSize(), disassemblyBlob.writeRef()))) + { + ArtifactDesc assemblyDesc(desc); + assemblyDesc.kind = ArtifactKind::Assembly; + + ext = ArtifactDescUtil::getDefaultExtension(assemblyDesc); + + dumpIntermediateText(disassemblyBlob->getBufferPointer(), disassemblyBlob->getBufferSize(), ext.getBuffer()); + return; + } + } + default: break; + } + + dumpIntermediateBinary(blob->getBufferPointer(), blob->getBufferSize(), ext.getBuffer()); + } + } + void CodeGenContext::maybeDumpIntermediate( void const* data, size_t size) diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 56e161483..9f75d94d3 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -144,11 +144,7 @@ namespace Slang class Module; class TranslationUnitRequest; - struct PostEmitMetadata : public RefObject - { - List<ShaderBindingRange> usedBindings; - }; - +#if 0 // Result of compiling an entry point. // Should only ever be string, binary or shared library class CompileResult @@ -187,6 +183,7 @@ namespace Slang RefPtr<PostEmitMetadata> postEmitMetadata; }; +#endif /// Information collected about global or entry-point shader parameters struct ShaderParamInfo @@ -2171,11 +2168,10 @@ namespace Slang /// been requested, report any errors that arise during /// code generation to the given `sink`. /// - CompileResult& getOrCreateEntryPointResult(Int entryPointIndex, DiagnosticSink* sink); - CompileResult& getOrCreateWholeProgramResult(DiagnosticSink* sink); + IArtifact* getOrCreateEntryPointResult(Int entryPointIndex, DiagnosticSink* sink); + IArtifact* getOrCreateWholeProgramResult(DiagnosticSink* sink); - - CompileResult& getExistingWholeProgramResult() + IArtifact* getExistingWholeProgramResult() { return m_wholeProgramResult; } @@ -2184,12 +2180,12 @@ namespace Slang /// This routine assumes that `getOrCreateEntryPointResult` /// has already been called previously. /// - CompileResult& getExistingEntryPointResult(Int entryPointIndex) + IArtifact* getExistingEntryPointResult(Int entryPointIndex) { return m_entryPointResults[entryPointIndex]; } - CompileResult& _createWholeProgramResult( + IArtifact* _createWholeProgramResult( DiagnosticSink* sink, EndToEndCompileRequest* endToEndReq = nullptr); @@ -2200,7 +2196,7 @@ namespace Slang /// /// Shouldn't be called directly by most code. /// - CompileResult& _createEntryPointResult( + IArtifact* _createEntryPointResult( Int entryPointIndex, DiagnosticSink* sink, EndToEndCompileRequest* endToEndReq = nullptr); @@ -2227,8 +2223,8 @@ namespace Slang // Generated compile results for each entry point // in the parent `Program` (indexing matches // the order they are given in the `Program`) - CompileResult m_wholeProgramResult; - List<CompileResult> m_entryPointResults; + ComPtr<IArtifact> m_wholeProgramResult; + List<ComPtr<IArtifact>> m_entryPointResults; RefPtr<IRModule> m_irModuleForLayout; }; @@ -2416,7 +2412,7 @@ namespace Slang // - CompileResult emitEntryPoints(); + SlangResult emitEntryPoints(ComPtr<IArtifact>& outArtifact); SlangResult dissassembleWithDownstream( const void* data, @@ -2431,6 +2427,8 @@ namespace Slang CodeGenTarget m_targetFormat = CodeGenTarget::Unknown; ExtensionTracker* m_extensionTracker = nullptr; + void maybeDumpIntermediate(IArtifact* artifact); + // Helper to dump intermediate output when debugging void maybeDumpIntermediate( void const* data, @@ -2459,17 +2457,11 @@ namespace Slang /* Emits entry point source taking into account if a pass-through or not. Uses 'targetFormat' to determine the target (not targetReq) */ - SlangResult emitEntryPointsSource( - String& outSource, - RefPtr<PostEmitMetadata>& outMetadata); - - SlangResult emitEntryPointsSourceFromIR( - String& outSource, - RefPtr<PostEmitMetadata>& outMetadata); + SlangResult emitEntryPointsSource(ComPtr<IArtifact>& outArtifact); - SlangResult emitWithDownstreamForEntryPoints( - RefPtr<DownstreamCompileResult>& outResult, - RefPtr<PostEmitMetadata>& outMetadata); + SlangResult emitEntryPointsSourceFromIR(ComPtr<IArtifact>& outArtifact); + + SlangResult emitWithDownstreamForEntryPoints(ComPtr<IArtifact>& outArtifact); /* Determines a suitable filename to identify the input for a given entry point being compiled. If the end-to-end compile is a pass-through case, will attempt to find the (unique) source file @@ -2484,9 +2476,7 @@ namespace Slang Int entryPointIndex); - SlangResult _emitEntryPoints( - RefPtr<DownstreamCompileResult>& outDownstreamResult, - RefPtr<PostEmitMetadata>& outMetadata); + SlangResult _emitEntryPoints(ComPtr<IArtifact>& outArtifact); private: Shared* m_shared = nullptr; diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index f3e78e48f..43f9da3df 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -69,6 +69,8 @@ #include "slang-emit-cuda.h" #include "../compiler-core/slang-artifact-desc-util.h" +#include "../compiler-core/slang-artifact-util.h" +#include "../compiler-core/slang-artifact-impl.h" #include <assert.h> @@ -834,17 +836,20 @@ Result linkAndOptimizeIR( #endif validateIRModuleIfEnabled(codeGenContext, irModule); - outLinkedIR.metadata = new PostEmitMetadata(); - collectMetadata(irModule, *outLinkedIR.metadata); + auto metadata = Artifact::create(ArtifactDesc::make(ArtifactKind::Instance, ArtifactPayload::PostEmitMetadata, artifactDesc.style)); + auto postEmitMetaRep = new PostEmitMetadataArtifactRepresentation; + metadata->addRepresentation(postEmitMetaRep); + + collectMetadata(irModule, postEmitMetaRep->m_metadata); + + outLinkedIR.metadata = metadata; return SLANG_OK; } -SlangResult CodeGenContext::emitEntryPointsSourceFromIR( - String& outSource, - RefPtr<PostEmitMetadata>& outMetadata) +SlangResult CodeGenContext::emitEntryPointsSourceFromIR(ComPtr<IArtifact>& outArtifact) { - outSource = String(); + outArtifact.setNull(); auto session = getSession(); auto sink = getSink(); @@ -852,6 +857,8 @@ SlangResult CodeGenContext::emitEntryPointsSourceFromIR( auto target = getTargetFormat(); auto targetRequest = getTargetReq(); + auto artifactContainer = ArtifactUtil::createResultsContainer(); + auto lineDirectiveMode = targetRequest->getLineDirectiveMode(); // To try to make the default behavior reasonable, we will // always use C-style line directives (to give the user @@ -923,6 +930,7 @@ SlangResult CodeGenContext::emitEntryPointsSourceFromIR( SLANG_RETURN_ON_FAIL(sourceEmitter->init()); + { LinkingAndOptimizationOptions linkingAndOptimizationOptions; @@ -947,8 +955,11 @@ SlangResult CodeGenContext::emitEntryPointsSourceFromIR( auto irModule = linkedIR.module; - outMetadata = linkedIR.metadata; - + if (linkedIR.metadata) + { + artifactContainer->addChild(linkedIR.metadata); + } + // After all of the required optimization and legalization // passes have been performed, we can emit target code from // the IR module. @@ -1017,7 +1028,13 @@ SlangResult CodeGenContext::emitEntryPointsSourceFromIR( finalResult.append(code); // Write out the result - outSource = finalResult; + + auto targetArtifact = ArtifactUtil::createArtifactForCompileTarget(asExternal(target)); + targetArtifact->addRepresentationUnknown(StringBlob::moveCreate(finalResult)); + + artifactContainer->addChild(targetArtifact); + + outArtifact = artifactContainer; return SLANG_OK; } @@ -1029,9 +1046,10 @@ SlangResult emitSPIRVFromIR( SlangResult emitSPIRVForEntryPointsDirectly( CodeGenContext* codeGenContext, - List<uint8_t>& spirvOut, - RefPtr<PostEmitMetadata>& outMetadata) + ComPtr<IArtifact>& outArtifact) { + auto artifactContainer = ArtifactUtil::createResultsContainer(); + // Outside because we want to keep IR in scope whilst we are processing emits LinkedIR linkedIR; LinkingAndOptimizationOptions linkingAndOptimizationOptions; @@ -1043,13 +1061,22 @@ SlangResult emitSPIRVForEntryPointsDirectly( auto irModule = linkedIR.module; auto irEntryPoints = linkedIR.entryPoints; - emitSPIRVFromIR(codeGenContext, irModule, irEntryPoints, spirvOut); + List<uint8_t> spirv; + emitSPIRVFromIR(codeGenContext, irModule, irEntryPoints, spirv); - outMetadata = linkedIR.metadata; + auto targetArtifact = ArtifactUtil::createArtifactForCompileTarget(asExternal(codeGenContext->getTargetFormat())); + targetArtifact->addRepresentationUnknown(ListBlob::moveCreate(spirv)); - return SLANG_OK; -} + artifactContainer->addChild(targetArtifact); + if (linkedIR.metadata) + { + artifactContainer->addChild(linkedIR.metadata); + } + + outArtifact = artifactContainer; + return SLANG_OK; +} } // namespace Slang diff --git a/source/slang/slang-ir-link.h b/source/slang/slang-ir-link.h index 798013a8d..dcfb642da 100644 --- a/source/slang/slang-ir-link.h +++ b/source/slang/slang-ir-link.h @@ -12,7 +12,7 @@ namespace Slang RefPtr<IRModule> module; IRVarLayout* globalScopeVarLayout; List<IRFunc*> entryPoints; - RefPtr<PostEmitMetadata> metadata; + ComPtr<IArtifact> metadata; }; diff --git a/source/slang/slang-ir-metadata.cpp b/source/slang/slang-ir-metadata.cpp index cc5922e93..396c40837 100644 --- a/source/slang/slang-ir-metadata.cpp +++ b/source/slang/slang-ir-metadata.cpp @@ -4,6 +4,8 @@ #include "slang-ir.h" #include "slang-ir-insts.h" +#include "../compiler-core/slang-artifact-representation-impl.h" + namespace Slang { diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index c0c7c4f5a..6515dc35d 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -10,6 +10,7 @@ // Artifact #include "../compiler-core/slang-artifact-impl.h" #include "../compiler-core/slang-artifact-desc-util.h" +#include "../compiler-core/slang-artifact-util.h" #include "slang-module-library.h" @@ -3151,16 +3152,20 @@ SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getEntryPointCode( auto targetProgram = getTargetProgram(target); DiagnosticSink sink(linkage->getSourceManager(), Lexer::sourceLocationLexer); - auto& entryPointResult = targetProgram->getOrCreateEntryPointResult(entryPointIndex, &sink); + + IArtifact* entryPointResult = targetProgram->getOrCreateEntryPointResult(entryPointIndex, &sink); sink.getBlobIfNeeded(outDiagnostics); - if(entryPointResult.format == ResultFormat::None ) + if(entryPointResult == nullptr) return SLANG_FAIL; - ComPtr<ISlangBlob> blob; - SLANG_RETURN_ON_FAIL(entryPointResult.getBlob(blob)); - *outCode = blob.detach(); - return SLANG_OK; + IArtifact* significantBlob = ArtifactUtil::findSignificant(entryPointResult); + if (!significantBlob) + { + return SLANG_FAIL; + } + + return significantBlob->loadBlob(ArtifactKeep::Yes, outCode); } SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getEntryPointHostCallable( @@ -3177,17 +3182,13 @@ SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getEntryPointHostCallable( auto targetProgram = getTargetProgram(target); DiagnosticSink sink(linkage->getSourceManager(), Lexer::sourceLocationLexer); - auto& entryPointResult = targetProgram->getOrCreateEntryPointResult(entryPointIndex, &sink); + IArtifact* artifact = targetProgram->getOrCreateEntryPointResult(entryPointIndex, &sink); sink.getBlobIfNeeded(outDiagnostics); - if(entryPointResult.format == ResultFormat::None ) + if(artifact == nullptr) return SLANG_FAIL; - ComPtr<ISlangSharedLibrary> sharedLibrary; - SLANG_RETURN_ON_FAIL(entryPointResult.getSharedLibrary(sharedLibrary)); - - *outSharedLibrary = sharedLibrary.detach(); - return SLANG_OK; + return artifact->loadSharedLibrary(ArtifactKeep::Yes, outSharedLibrary); } RefPtr<ComponentType> ComponentType::specialize( @@ -4757,10 +4758,14 @@ void const* EndToEndCompileRequest::getEntryPointCode(int entryPointIndex, size_ auto targetProgram = program->getTargetProgram(targetReq); if (!targetProgram) return nullptr; - CompileResult& result = targetProgram->getExistingEntryPointResult(entryPointIndex); + IArtifact* artifact = targetProgram->getExistingEntryPointResult(entryPointIndex); + if (!artifact) + { + return nullptr; + } ComPtr<ISlangBlob> blob; - SLANG_RETURN_NULL_ON_FAIL(result.getBlob(blob)); + SLANG_RETURN_NULL_ON_FAIL(artifact->loadBlob(ArtifactKeep::Yes, blob.writeRef())); if (outSize) { @@ -4774,7 +4779,7 @@ static SlangResult _getEntryPointResult( EndToEndCompileRequest* req, int entryPointIndex, int targetIndex, - Slang::CompileResult** outCompileResult) + ComPtr<IArtifact>& outArtifact) { auto linkage = req->getLinkage(); auto program = req->getSpecializedGlobalAndEntryPointsComponentType(); @@ -4793,18 +4798,18 @@ static SlangResult _getEntryPointResult( } auto entryPointReq = program->getEntryPoint(entryPointIndex); - auto targetProgram = program->getTargetProgram(targetReq); if (!targetProgram) return SLANG_FAIL; - *outCompileResult = &targetProgram->getExistingEntryPointResult(entryPointIndex); + + outArtifact = targetProgram->getExistingEntryPointResult(entryPointIndex); return SLANG_OK; } static SlangResult _getWholeProgramResult( EndToEndCompileRequest* req, int targetIndex, - Slang::CompileResult** outCompileResult) + ComPtr<IArtifact>& outArtifact) { auto linkage = req->getLinkage(); auto program = req->getSpecializedGlobalAndEntryPointsComponentType(); @@ -4824,34 +4829,34 @@ static SlangResult _getWholeProgramResult( auto targetProgram = program->getTargetProgram(targetReq); if (!targetProgram) return SLANG_FAIL; - *outCompileResult = &targetProgram->getExistingWholeProgramResult(); + outArtifact = targetProgram->getExistingWholeProgramResult(); return SLANG_OK; } SlangResult EndToEndCompileRequest::getEntryPointCodeBlob(int entryPointIndex, int targetIndex, ISlangBlob** outBlob) { if (!outBlob) return SLANG_E_INVALID_ARG; - - CompileResult* compileResult = nullptr; - SLANG_RETURN_ON_FAIL(_getEntryPointResult(this, entryPointIndex, targetIndex, &compileResult)); - - ComPtr<ISlangBlob> blob; - SLANG_RETURN_ON_FAIL(compileResult->getBlob(blob)); - *outBlob = blob.detach(); - return SLANG_OK; + ComPtr<IArtifact> artifact; + SLANG_RETURN_ON_FAIL(_getEntryPointResult(this, entryPointIndex, targetIndex, artifact)); + if (auto significant = ArtifactUtil::findSignificant(artifact)) + { + SLANG_RETURN_ON_FAIL(significant->loadBlob(ArtifactKeep::Yes, outBlob)); + return SLANG_OK; + } + return SLANG_E_NOT_AVAILABLE; } SlangResult EndToEndCompileRequest::getEntryPointHostCallable(int entryPointIndex, int targetIndex, ISlangSharedLibrary** outSharedLibrary) { if (!outSharedLibrary) return SLANG_E_INVALID_ARG; - - CompileResult* compileResult = nullptr; - SLANG_RETURN_ON_FAIL(_getEntryPointResult(this, entryPointIndex, targetIndex, &compileResult)); - - ComPtr<ISlangSharedLibrary> sharedLibrary; - SLANG_RETURN_ON_FAIL(compileResult->getSharedLibrary(sharedLibrary)); - *outSharedLibrary = sharedLibrary.detach(); - return SLANG_OK; + ComPtr<IArtifact> artifact; + SLANG_RETURN_ON_FAIL(_getEntryPointResult(this, entryPointIndex, targetIndex, artifact)); + if (auto significant = ArtifactUtil::findSignificant(artifact)) + { + SLANG_RETURN_ON_FAIL(significant->loadSharedLibrary(ArtifactKeep::Yes, outSharedLibrary)); + return SLANG_OK; + } + return SLANG_E_NOT_AVAILABLE; } SlangResult EndToEndCompileRequest::getTargetCodeBlob(int targetIndex, ISlangBlob** outBlob) @@ -4859,13 +4864,15 @@ SlangResult EndToEndCompileRequest::getTargetCodeBlob(int targetIndex, ISlangBlo if (!outBlob) return SLANG_E_INVALID_ARG; - CompileResult* compileResult = nullptr; - SLANG_RETURN_ON_FAIL(_getWholeProgramResult(this, targetIndex, &compileResult)); + ComPtr<IArtifact> artifact; + SLANG_RETURN_ON_FAIL(_getWholeProgramResult(this, targetIndex, artifact)); - ComPtr<ISlangBlob> blob; - SLANG_RETURN_ON_FAIL(compileResult->getBlob(blob)); - *outBlob = blob.detach(); - return SLANG_OK; + if (auto significant = ArtifactUtil::findSignificant(artifact)) + { + SLANG_RETURN_ON_FAIL(significant->loadBlob(ArtifactKeep::Yes, outBlob)); + return SLANG_OK; + } + return SLANG_E_NOT_AVAILABLE; } SlangResult EndToEndCompileRequest::getTargetHostCallable(int targetIndex,ISlangSharedLibrary** outSharedLibrary) @@ -4873,12 +4880,9 @@ SlangResult EndToEndCompileRequest::getTargetHostCallable(int targetIndex,ISlang if (!outSharedLibrary) return SLANG_E_INVALID_ARG; - CompileResult* compileResult = nullptr; - SLANG_RETURN_ON_FAIL(_getWholeProgramResult(this, targetIndex, &compileResult)); - - ComPtr<ISlangSharedLibrary> sharedLibrary; - SLANG_RETURN_ON_FAIL(compileResult->getSharedLibrary(sharedLibrary)); - *outSharedLibrary = sharedLibrary.detach(); + ComPtr<IArtifact> artifact; + SLANG_RETURN_ON_FAIL(_getWholeProgramResult(this, targetIndex, artifact)); + SLANG_RETURN_ON_FAIL(artifact->loadSharedLibrary(ArtifactKeep::Yes, outSharedLibrary)); return SLANG_OK; } @@ -5019,12 +5023,39 @@ SlangResult EndToEndCompileRequest::getEntryPoint(SlangInt entryPointIndex, slan SlangResult EndToEndCompileRequest::isParameterLocationUsed(Int entryPointIndex, Int targetIndex, SlangParameterCategory category, UInt spaceIndex, UInt registerIndex, bool& outUsed) { - CompileResult* compileResult = nullptr; - if (_getEntryPointResult(this, static_cast<int>(entryPointIndex), static_cast<int>(targetIndex), &compileResult) != SLANG_OK) + if (!ShaderBindingRange::isUsageTracked((slang::ParameterCategory)category)) + return SLANG_E_NOT_AVAILABLE; + + ComPtr<IArtifact> artifact; + if (SLANG_FAILED(_getEntryPointResult(this, static_cast<int>(entryPointIndex), static_cast<int>(targetIndex), artifact))) return SLANG_E_INVALID_ARG; - return compileResult->isParameterLocationUsed(category, spaceIndex, registerIndex, outUsed); -} + // We need to find the meta data + IArtifact* metadataArtifact = artifact->findArtifactByDerivedDesc(IArtifact::FindStyle::SelfOrChildren, + ArtifactDesc::make(ArtifactKind::Base, ArtifactPayload::PostEmitMetadata, ArtifactStyle::Base)); + if (!metadataArtifact) + { + return SLANG_E_NOT_AVAILABLE; + } + + // Find a rep + auto metadataRep = findRepresentation<IPostEmitMetadataArtifactRepresentation>(metadataArtifact); + if (!metadataRep) + return SLANG_E_NOT_AVAILABLE; + + // TODO: optimize this with a binary search through a sorted list + for (const auto& range : metadataRep->getBindingRanges()) + { + if (range.containsBinding((slang::ParameterCategory)category, spaceIndex, registerIndex)) + { + outUsed = true; + return SLANG_OK; + } + } + + outUsed = false; + return SLANG_OK; +} } // namespace Slang |
