diff options
Diffstat (limited to 'source')
35 files changed, 1410 insertions, 993 deletions
diff --git a/source/compiler-core/slang-artifact-associated-impl.cpp b/source/compiler-core/slang-artifact-associated-impl.cpp index 17ede975e..dcca24a7c 100644 --- a/source/compiler-core/slang-artifact-associated-impl.cpp +++ b/source/compiler-core/slang-artifact-associated-impl.cpp @@ -11,9 +11,9 @@ namespace Slang { -/* !!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDiagnostics !!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!! DiagnosticsImpl !!!!!!!!!!!!!!!!!!!!!!!!!!! */ -void* ArtifactDiagnostics::getInterface(const Guid& guid) +void* DiagnosticsImpl::getInterface(const Guid& guid) { if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || @@ -24,13 +24,13 @@ void* ArtifactDiagnostics::getInterface(const Guid& guid) return nullptr; } -void* ArtifactDiagnostics::getObject(const Guid& guid) +void* DiagnosticsImpl::getObject(const Guid& guid) { SLANG_UNUSED(guid); return nullptr; } -void* ArtifactDiagnostics::castAs(const Guid& guid) +void* DiagnosticsImpl::castAs(const Guid& guid) { if (auto intf = getInterface(guid)) { @@ -39,7 +39,16 @@ void* ArtifactDiagnostics::castAs(const Guid& guid) return getObject(guid); } -ZeroTerminatedCharSlice ArtifactDiagnostics::_allocateSlice(const Slice<char>& in) +void DiagnosticsImpl::reset() +{ + m_diagnostics.clear(); + m_raw = ZeroTerminatedCharSlice(); + m_result = SLANG_OK; + + m_arena.deallocateAll(); +} + +ZeroTerminatedCharSlice DiagnosticsImpl::_allocateSlice(const Slice<char>& in) { if (in.count == 0) { @@ -49,7 +58,7 @@ ZeroTerminatedCharSlice ArtifactDiagnostics::_allocateSlice(const Slice<char>& i return ZeroTerminatedCharSlice(dst, in.count); } -void ArtifactDiagnostics::add(const Diagnostic& inDiagnostic) +void DiagnosticsImpl::add(const Diagnostic& inDiagnostic) { Diagnostic diagnostic(inDiagnostic); @@ -60,9 +69,196 @@ void ArtifactDiagnostics::add(const Diagnostic& inDiagnostic) m_diagnostics.add(diagnostic); } -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PostEmitMetadata !!!!!!!!!!!!!!!!!!!!!!!!!!! */ +void DiagnosticsImpl::setRaw(const ZeroTerminatedCharSlice& slice) +{ + m_raw = _allocateSlice(slice); +} + +Count DiagnosticsImpl::getCountAtLeastSeverity(Severity severity) +{ + Index count = 0; + for (const auto& msg : m_diagnostics) + { + count += Index(Index(msg.severity) >= Index(severity)); + } + return count; +} + +Count DiagnosticsImpl::getCountBySeverity(Severity severity) +{ + Index count = 0; + for (const auto& msg : m_diagnostics) + { + count += Index(msg.severity == severity); + } + return count; +} + +bool DiagnosticsImpl::hasOfAtLeastSeverity(Severity severity) +{ + for (const auto& msg : m_diagnostics) + { + if (Index(msg.severity) >= Index(severity)) + { + return true; + } + } + return false; +} + +Count DiagnosticsImpl::getCountByStage(Stage stage, Count outCounts[Int(Severity::CountOf)]) +{ + Int count = 0; + ::memset(outCounts, 0, sizeof(Index) * Int(Severity::CountOf)); + for (const auto& diagnostic : m_diagnostics) + { + if (diagnostic.stage == stage) + { + count++; + outCounts[Index(diagnostic.severity)]++; + } + } + return count++; +} + +void DiagnosticsImpl::removeBySeverity(Severity severity) +{ + Index count = m_diagnostics.getCount(); + for (Index i = 0; i < count; ++i) + { + if (m_diagnostics[i].severity == severity) + { + m_diagnostics.removeAt(i); + i--; + count--; + } + } +} + +void DiagnosticsImpl::maybeAddNote(const ZeroTerminatedCharSlice& in) +{ + // Don't bother adding an empty line + if (UnownedStringSlice(in.begin(), in.end()).trim().getLength() == 0) + { + return; + } + + // If there's nothing previous, we'll ignore too, as note should be in addition to + // a pre-existing error/warning + if (m_diagnostics.getCount() == 0) + { + return; + } + + // Make it a note on the output + Diagnostic diagnostic; + + diagnostic.severity = Severity::Info; + diagnostic.text = _allocateSlice(in); + m_diagnostics.add(diagnostic); +} + +void DiagnosticsImpl::requireErrorDiagnostic() +{ + // If we find an error, we don't need to add a generic diagnostic + for (const auto& msg : m_diagnostics) + { + if (Index(msg.severity) >= Index(Severity::Error)) + { + return; + } + } + + Diagnostic diagnostic; + diagnostic.severity = Severity::Error; + diagnostic.text = m_raw; + + // Add the diagnostic + m_diagnostics.add(diagnostic); +} + +/* static */UnownedStringSlice _getSeverityText(IDiagnostics::Severity severity) +{ + typedef IDiagnostics::Severity Severity; + switch (severity) + { + default: return UnownedStringSlice::fromLiteral("Unknown"); + case Severity::Info: return UnownedStringSlice::fromLiteral("Info"); + case Severity::Warning: return UnownedStringSlice::fromLiteral("Warning"); + case Severity::Error: return UnownedStringSlice::fromLiteral("Error"); + } +} + +static void _appendCounts(const Index counts[Int(IDiagnostics::Severity::CountOf)], StringBuilder& out) +{ + typedef IDiagnostics::Severity Severity; + + for (Index i = 0; i < Int(Severity::CountOf); i++) + { + if (counts[i] > 0) + { + out << _getSeverityText(Severity(i)) << "(" << counts[i] << ") "; + } + } +} + +static void _appendSimplified(const Index counts[Int(IDiagnostics::Severity::CountOf)], StringBuilder& out) +{ + typedef IDiagnostics::Severity Severity; + for (Index i = 0; i < Int(Severity::CountOf); i++) + { + if (counts[i] > 0) + { + out << _getSeverityText(Severity(i)) << " "; + } + } +} + +void DiagnosticsImpl::appendSummary(ISlangBlob** outBlob) +{ + StringBuilder buf; + + Index counts[Int(Severity::CountOf)]; + if (getCountByStage(Stage::Compile, counts) > 0) + { + buf << "Compile: "; + _appendCounts(counts, buf); + buf << "\n"; + } + if (getCountByStage(Stage::Link, counts) > 0) + { + buf << "Link: "; + _appendCounts(counts, buf); + buf << "\n"; + } + + *outBlob = StringBlob::moveCreate(buf).detach(); +} + +void DiagnosticsImpl::appendSimplifiedSummary(ISlangBlob** outBlob) +{ + StringBuilder buf; + + Index counts[Int(Severity::CountOf)]; + if (getCountByStage(Stage::Compile, counts) > 0) + { + buf << "Compile: "; + _appendSimplified(counts, buf); + buf << "\n"; + } + if (getCountByStage(Stage::Link, counts) > 0) + { + buf << "Link: "; + _appendSimplified(counts, buf); + buf << "\n"; + } + + *outBlob = StringBlob::moveCreate(buf).detach(); +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PostEmitMetadataImpl !!!!!!!!!!!!!!!!!!!!!!!!!!! */ -void* PostEmitMetadata::getInterface(const Guid& guid) +void* PostEmitMetadataImpl::getInterface(const Guid& guid) { if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || @@ -73,7 +269,7 @@ void* PostEmitMetadata::getInterface(const Guid& guid) return nullptr; } -void* PostEmitMetadata::getObject(const Guid& uuid) +void* PostEmitMetadataImpl::getObject(const Guid& uuid) { if (uuid == getTypeGuid()) { @@ -82,7 +278,7 @@ void* PostEmitMetadata::getObject(const Guid& uuid) return nullptr; } -void* PostEmitMetadata::castAs(const Guid& guid) +void* PostEmitMetadataImpl::castAs(const Guid& guid) { if (auto ptr = getInterface(guid)) { @@ -91,7 +287,7 @@ void* PostEmitMetadata::castAs(const Guid& guid) return getObject(guid); } -Slice<ShaderBindingRange> PostEmitMetadata::getBindingRanges() +Slice<ShaderBindingRange> PostEmitMetadataImpl::getUsedBindingRanges() { return Slice<ShaderBindingRange>(m_usedBindings.getBuffer(), m_usedBindings.getCount()); } diff --git a/source/compiler-core/slang-artifact-associated-impl.h b/source/compiler-core/slang-artifact-associated-impl.h index dcd796c1e..eef965e3e 100644 --- a/source/compiler-core/slang-artifact-associated-impl.h +++ b/source/compiler-core/slang-artifact-associated-impl.h @@ -13,7 +13,7 @@ namespace Slang { -class ArtifactDiagnostics : public ComBaseObject, public IDiagnostics +class DiagnosticsImpl : public ComBaseObject, public IDiagnostics { public: SLANG_COM_BASE_IUNKNOWN_ALL @@ -27,8 +27,20 @@ public: SLANG_NO_THROW virtual void SLANG_MCALL removeAt(Index i) SLANG_OVERRIDE { m_diagnostics.removeAt(i); } SLANG_NO_THROW virtual SlangResult SLANG_MCALL getResult() SLANG_OVERRIDE { return m_result; } SLANG_NO_THROW virtual void SLANG_MCALL setResult(SlangResult res) SLANG_OVERRIDE { m_result = res; } - - ArtifactDiagnostics(): + SLANG_NO_THROW virtual void SLANG_MCALL setRaw(const ZeroTerminatedCharSlice& slice) SLANG_OVERRIDE; + SLANG_NO_THROW virtual ZeroTerminatedCharSlice SLANG_MCALL getRaw() SLANG_OVERRIDE { return m_raw; } + SLANG_NO_THROW virtual void SLANG_MCALL reset() SLANG_OVERRIDE; + SLANG_NO_THROW virtual Count SLANG_MCALL getCountAtLeastSeverity(Severity severity) SLANG_OVERRIDE; + SLANG_NO_THROW virtual Count SLANG_MCALL getCountBySeverity(Severity severity) SLANG_OVERRIDE; + SLANG_NO_THROW virtual bool SLANG_MCALL hasOfAtLeastSeverity(Severity severity) SLANG_OVERRIDE; + SLANG_NO_THROW virtual Count SLANG_MCALL getCountByStage(Stage stage, Count outCounts[Int(Severity::CountOf)]) SLANG_OVERRIDE; + SLANG_NO_THROW virtual void SLANG_MCALL removeBySeverity(Severity severity) SLANG_OVERRIDE; + SLANG_NO_THROW virtual void SLANG_MCALL maybeAddNote(const ZeroTerminatedCharSlice& in) SLANG_OVERRIDE; + SLANG_NO_THROW virtual void SLANG_MCALL requireErrorDiagnostic() SLANG_OVERRIDE; + SLANG_NO_THROW virtual void SLANG_MCALL appendSummary(ISlangBlob** outBlob) SLANG_OVERRIDE; + SLANG_NO_THROW virtual void SLANG_MCALL appendSimplifiedSummary(ISlangBlob** outBlob) SLANG_OVERRIDE; + + DiagnosticsImpl(): m_arena(1024) { } @@ -46,10 +58,11 @@ protected: List<Diagnostic> m_diagnostics; SlangResult m_result = SLANG_OK; + // Raw diagnostics ZeroTerminatedCharSlice m_raw; }; -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! PostEmitMetadata !!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! PostEmitMetadataImpl !!!!!!!!!!!!!!!!!!!!!!!!!! */ struct ShaderBindingRange { @@ -120,7 +133,7 @@ struct ShaderBindingRange } }; -class PostEmitMetadata : public ComBaseObject, public IPostEmitMetadata +class PostEmitMetadataImpl : public ComBaseObject, public IPostEmitMetadata { public: SLANG_CLASS_GUID(0x6f82509f, 0xe48b, 0x4b83, { 0xa3, 0x84, 0x5d, 0x70, 0x83, 0x19, 0x83, 0xcc }) @@ -131,7 +144,7 @@ public: SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; // IPostEmitMetadata - SLANG_NO_THROW virtual Slice<ShaderBindingRange> SLANG_MCALL getBindingRanges() SLANG_OVERRIDE; + SLANG_NO_THROW virtual Slice<ShaderBindingRange> SLANG_MCALL getUsedBindingRanges() SLANG_OVERRIDE; void* getInterface(const Guid& uuid); void* getObject(const Guid& uuid); diff --git a/source/compiler-core/slang-artifact-associated.h b/source/compiler-core/slang-artifact-associated.h index af47d2e59..e3dd83062 100644 --- a/source/compiler-core/slang-artifact-associated.h +++ b/source/compiler-core/slang-artifact-associated.h @@ -45,22 +45,53 @@ public: Location location; }; - /// Get the diagnostic at the index + /// Get the diagnostic at the index SLANG_NO_THROW virtual const Diagnostic* SLANG_MCALL getAt(Index i) = 0; - /// Get the amount of diangostics + /// Get the amount of diangostics SLANG_NO_THROW virtual Count SLANG_MCALL getCount() = 0; - /// Add a diagnostic + /// Add a diagnostic SLANG_NO_THROW virtual void SLANG_MCALL add(const Diagnostic& diagnostic) = 0; - /// Remove the diagnostic at the index + /// Remove the diagnostic at the index SLANG_NO_THROW virtual void SLANG_MCALL removeAt(Index i) = 0; - /// Get raw diagnostics information + /// Get raw diagnostics information SLANG_NO_THROW virtual ZeroTerminatedCharSlice SLANG_MCALL getRaw() = 0; + /// Set the raw diagnostic info + SLANG_NO_THROW virtual void SLANG_MCALL setRaw(const ZeroTerminatedCharSlice& slice) = 0; - /// Get the result for a compilation + /// Get the result for a compilation SLANG_NO_THROW virtual SlangResult SLANG_MCALL getResult() = 0; - /// Set the result + /// Set the result SLANG_NO_THROW virtual void SLANG_MCALL setResult(SlangResult res) = 0; + + /// Reset all state + SLANG_NO_THROW virtual void SLANG_MCALL reset() = 0; + + /// Count the number of diagnostics which have 'severity' or greater + SLANG_NO_THROW virtual Count SLANG_MCALL getCountAtLeastSeverity(Severity severity) = 0; + + /// Get the number of diagnostics by severity + SLANG_NO_THROW virtual Count SLANG_MCALL getCountBySeverity(Severity severity) = 0; + + /// True if there are any diagnostics of severity or worse + SLANG_NO_THROW virtual bool SLANG_MCALL hasOfAtLeastSeverity(Severity severity) = 0; + + /// Stores in outCounts, the amount of diagnostics for the stage of each severity + SLANG_NO_THROW virtual Count SLANG_MCALL getCountByStage(Stage stage, Count outCounts[Int(Severity::CountOf)]) = 0; + + /// Remove all diagnostics of the type + SLANG_NO_THROW virtual void SLANG_MCALL removeBySeverity(Severity severity) = 0; + + /// Add a note + SLANG_NO_THROW virtual void SLANG_MCALL maybeAddNote(const ZeroTerminatedCharSlice& in) = 0; + + /// If there are no error diagnostics, adds a generic error diagnostic + SLANG_NO_THROW virtual void SLANG_MCALL requireErrorDiagnostic() = 0; + + /// Append a summary to out + SLANG_NO_THROW virtual void SLANG_MCALL appendSummary(ISlangBlob** outBlob) = 0; + /// Appends a summary that just identifies if there is an error of a type (not a count) + SLANG_NO_THROW virtual void SLANG_MCALL appendSimplifiedSummary(ISlangBlob** outBlob) = 0; }; struct ShaderBindingRange; @@ -70,8 +101,8 @@ class IPostEmitMetadata : public ICastable public: SLANG_COM_INTERFACE(0x5d03bce9, 0xafb1, 0x4fc8, { 0xa4, 0x6f, 0x3c, 0xe0, 0x7b, 0x6, 0x1b, 0x1b }); - /// Get the binding ranges - SLANG_NO_THROW virtual Slice<ShaderBindingRange> SLANG_MCALL getBindingRanges() = 0; + /// Get the binding ranges + SLANG_NO_THROW virtual Slice<ShaderBindingRange> SLANG_MCALL getUsedBindingRanges() = 0; }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-handler-impl.cpp b/source/compiler-core/slang-artifact-handler-impl.cpp index f324a1d43..c342becec 100644 --- a/source/compiler-core/slang-artifact-handler-impl.cpp +++ b/source/compiler-core/slang-artifact-handler-impl.cpp @@ -15,78 +15,10 @@ #include "../core/slang-shared-library.h" // For workaround for DownstreamResult -#include "slang-downstream-compiler.h" +#include "slang-downstream-dep1.h" 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); -} - -/* Hack to take into account downstream compilers shared library interface might need an adapter */ -static SlangResult _getDownstreamSharedLibrary(DownstreamCompileResult* downstreamResult, ComPtr<ISlangSharedLibrary>& outSharedLibrary) -{ - ComPtr<ISlangSharedLibrary> lib; - SLANG_RETURN_ON_FAIL(downstreamResult->getHostCallableSharedLibrary(lib)); - - if (SLANG_SUCCEEDED(lib->queryInterface(ISlangSharedLibrary::getTypeGuid(), (void**)outSharedLibrary.writeRef()))) - { - return SLANG_OK; - } - - ComPtr<ISlangSharedLibrary_Dep1> libDep1; - if (SLANG_SUCCEEDED(lib->queryInterface(ISlangSharedLibrary_Dep1::getTypeGuid(), (void**)libDep1.writeRef()))) - { - // Okay, we need to adapt for now - outSharedLibrary = new SharedLibraryDep1Adapter(libDep1); - return SLANG_OK; - } - return SLANG_E_NOT_FOUND; -} - /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DefaultArtifactHandler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ /* static */DefaultArtifactHandler DefaultArtifactHandler::g_singleton; @@ -210,7 +142,7 @@ SlangResult DefaultArtifactHandler::getOrCreateRepresentation(IArtifact* artifac else if (guid == ISlangSharedLibrary::getTypeGuid()) { ComPtr<ISlangSharedLibrary> lib; - SLANG_RETURN_ON_FAIL(_getDownstreamSharedLibrary(downstreamResult, lib)); + SLANG_RETURN_ON_FAIL(DownstreamUtil_Dep1::getDownstreamSharedLibrary(downstreamResult, lib)); return _addRepresentation(artifact, keep, lib, outCastable); } } diff --git a/source/compiler-core/slang-downstream-compiler-set.cpp b/source/compiler-core/slang-downstream-compiler-set.cpp new file mode 100644 index 000000000..ee09b994c --- /dev/null +++ b/source/compiler-core/slang-downstream-compiler-set.cpp @@ -0,0 +1,97 @@ +// slang-downstream-compiler-set.cpp +#include "slang-downstream-compiler-set.h" + +namespace Slang +{ + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerSet !!!!!!!!!!!!!!!!!!!!!!*/ + +void DownstreamCompilerSet::getCompilerDescs(List<DownstreamCompilerDesc>& outCompilerDescs) const +{ + outCompilerDescs.clear(); + for (IDownstreamCompiler* compiler : m_compilers) + { + outCompilerDescs.add(compiler->getDesc()); + } +} + +Index DownstreamCompilerSet::_findIndex(const DownstreamCompilerDesc& desc) const +{ + const Index count = m_compilers.getCount(); + for (Index i = 0; i < count; ++i) + { + if (m_compilers[i]->getDesc() == desc) + { + return i; + } + } + return -1; +} + +IDownstreamCompiler* DownstreamCompilerSet::getCompiler(const DownstreamCompilerDesc& compilerDesc) const +{ + const Index index = _findIndex(compilerDesc); + return index >= 0 ? m_compilers[index] : nullptr; +} + +void DownstreamCompilerSet::getCompilers(List<IDownstreamCompiler*>& outCompilers) const +{ + outCompilers.clear(); + outCompilers.addRange((IDownstreamCompiler*const*)m_compilers.begin(), m_compilers.getCount()); +} + +bool DownstreamCompilerSet::hasSharedLibrary(ISlangSharedLibrary* lib) +{ + const Index foundIndex = m_sharedLibraries.findFirstIndex([lib](ISlangSharedLibrary* inLib) -> bool { return lib == inLib; }); + return(foundIndex >= 0); +} + +void DownstreamCompilerSet::addSharedLibrary(ISlangSharedLibrary* lib) +{ + SLANG_ASSERT(lib); + if (!hasSharedLibrary(lib)) + { + m_sharedLibraries.add(ComPtr<ISlangSharedLibrary>(lib)); + } +} + +bool DownstreamCompilerSet::hasCompiler(SlangPassThrough compilerType) const +{ + for (IDownstreamCompiler* compiler : m_compilers) + { + const auto& desc = compiler->getDesc(); + if (desc.type == compilerType) + { + return true; + } + } + return false; +} + +void DownstreamCompilerSet::remove(SlangPassThrough compilerType) +{ + for (Index i = 0; i < m_compilers.getCount(); ++i) + { + IDownstreamCompiler* compiler = m_compilers[i]; + if (compiler->getDesc().type == compilerType) + { + m_compilers.fastRemoveAt(i); + i--; + } + } +} + +void DownstreamCompilerSet::addCompiler(IDownstreamCompiler* compiler) +{ + const Index index = _findIndex(compiler->getDesc()); + if (index >= 0) + { + m_compilers[index] = compiler; + } + else + { + m_compilers.add(ComPtr<IDownstreamCompiler>(compiler)); + } +} + +} diff --git a/source/compiler-core/slang-downstream-compiler-set.h b/source/compiler-core/slang-downstream-compiler-set.h new file mode 100644 index 000000000..2a3d1ac01 --- /dev/null +++ b/source/compiler-core/slang-downstream-compiler-set.h @@ -0,0 +1,68 @@ +#ifndef SLANG_DOWNSTREAM_COMPILER_SET_H +#define SLANG_DOWNSTREAM_COMPILER_SET_H + +#include "slang-downstream-compiler.h" + +namespace Slang +{ + +class DownstreamCompilerSet : public RefObject +{ +public: + typedef RefObject Super; + + /// Find all the available compilers + void getCompilerDescs(List<IDownstreamCompiler::Desc>& outCompilerDescs) const; + /// Returns list of all compilers + void getCompilers(List<IDownstreamCompiler*>& outCompilers) const; + + /// Get a compiler + IDownstreamCompiler* getCompiler(const DownstreamCompilerDesc& compilerDesc) const; + + /// Will replace if there is one with same desc + void addCompiler(IDownstreamCompiler* compiler); + + /// Get a default compiler + IDownstreamCompiler* getDefaultCompiler(SlangSourceLanguage sourceLanguage) const { return m_defaultCompilers[int(sourceLanguage)]; } + /// Set the default compiler + void setDefaultCompiler(SlangSourceLanguage sourceLanguage, IDownstreamCompiler* compiler) { m_defaultCompilers[int(sourceLanguage)] = compiler; } + + /// True if has a compiler of the specified type + bool hasCompiler(SlangPassThrough compilerType) const; + + void remove(SlangPassThrough compilerType); + + void clear() { m_compilers.clear(); } + + bool hasSharedLibrary(ISlangSharedLibrary* lib); + void addSharedLibrary(ISlangSharedLibrary* lib); + + ~DownstreamCompilerSet() + { + // A compiler may be implemented in a shared library, so release all first. + m_compilers.clearAndDeallocate(); + for (auto& defaultCompiler : m_defaultCompilers) + { + defaultCompiler.setNull(); + } + + // Release any shared libraries + m_sharedLibraries.clearAndDeallocate(); + } + +protected: + + Index _findIndex(const DownstreamCompilerDesc& desc) const; + + + ComPtr<IDownstreamCompiler> m_defaultCompilers[int(SLANG_SOURCE_LANGUAGE_COUNT_OF)]; + // This could be a dictionary/map - but doing a linear search is going to be fine and it makes + // somethings easier. + List<ComPtr<IDownstreamCompiler>> m_compilers; + + List<ComPtr<ISlangSharedLibrary>> m_sharedLibraries; +}; + +} + +#endif diff --git a/source/compiler-core/slang-downstream-compiler-util.cpp b/source/compiler-core/slang-downstream-compiler-util.cpp new file mode 100644 index 000000000..9f6a96e43 --- /dev/null +++ b/source/compiler-core/slang-downstream-compiler-util.cpp @@ -0,0 +1,467 @@ +// slang-downstream-compiler.cpp +#include "slang-downstream-compiler-util.h" + +#include "../core/slang-common.h" +#include "../../slang-com-helper.h" +#include "../core/slang-string-util.h" + +#include "../core/slang-type-text-util.h" + +#include "../core/slang-io.h" +#include "../core/slang-shared-library.h" +#include "../core/slang-blob.h" +#include "../core/slang-char-util.h" + +#ifdef SLANG_VC +# include "windows/slang-win-visual-studio-util.h" +#endif + +#include "slang-visual-studio-compiler-util.h" +#include "slang-gcc-compiler-util.h" +#include "slang-nvrtc-compiler.h" +#include "slang-fxc-compiler.h" +#include "slang-dxc-compiler.h" +#include "slang-glslang-compiler.h" +#include "slang-llvm-compiler.h" + +namespace Slang +{ + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerInfos !!!!!!!!!!!!!!!!!!!!!!*/ + +struct DownstreamCompilerInfos +{ + DownstreamCompilerInfo infos[int(SLANG_PASS_THROUGH_COUNT_OF)]; + + static DownstreamCompilerInfos _calcInfos(); + static DownstreamCompilerInfos s_infos; +}; + +/* static */ DownstreamCompilerInfos DownstreamCompilerInfos::_calcInfos() +{ + typedef DownstreamCompilerInfo Info; + typedef Info::SourceLanguageFlag SourceLanguageFlag; + typedef Info::SourceLanguageFlags SourceLanguageFlags; + + DownstreamCompilerInfos infos; + + infos.infos[int(SLANG_PASS_THROUGH_CLANG)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); + infos.infos[int(SLANG_PASS_THROUGH_VISUAL_STUDIO)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); + infos.infos[int(SLANG_PASS_THROUGH_GCC)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); + infos.infos[int(SLANG_PASS_THROUGH_LLVM)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); + + infos.infos[int(SLANG_PASS_THROUGH_NVRTC)] = Info(SourceLanguageFlag::CUDA); + + infos.infos[int(SLANG_PASS_THROUGH_DXC)] = Info(SourceLanguageFlag::HLSL); + infos.infos[int(SLANG_PASS_THROUGH_FXC)] = Info(SourceLanguageFlag::HLSL); + infos.infos[int(SLANG_PASS_THROUGH_GLSLANG)] = Info(SourceLanguageFlag::GLSL); + + return infos; +} + +/* static */DownstreamCompilerInfos DownstreamCompilerInfos::s_infos = DownstreamCompilerInfos::_calcInfos(); + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerInfo !!!!!!!!!!!!!!!!!!!!!!*/ + +/* static */const DownstreamCompilerInfo& DownstreamCompilerInfo::getInfo(SlangPassThrough compiler) +{ + return DownstreamCompilerInfos::s_infos.infos[int(compiler)]; +} + +/* static */bool DownstreamCompilerInfo::canCompile(SlangPassThrough compiler, SlangSourceLanguage sourceLanguage) +{ + const auto& info = getInfo(compiler); + return (info.sourceLanguageFlags & (SourceLanguageFlags(1) << int(sourceLanguage))) != 0; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerUtil !!!!!!!!!!!!!!!!!!!!!!*/ + +static DownstreamCompilerMatchVersion _calcCompiledVersion() +{ + DownstreamCompilerMatchVersion matchVersion; + +#if SLANG_VC + matchVersion = WinVisualStudioUtil::getCompiledVersion(); +#elif SLANG_CLANG + matchVersion.type = SLANG_PASS_THROUGH_CLANG; + matchVersion.matchVersion.set(Index(__clang_major__), Index(__clang_minor__)); +#elif SLANG_GCC + matchVersion.type = SLANG_PASS_THROUGH_GCC; + matchVersion.matchVersion.set(Index(__GNUC__), Index(__GNUC_MINOR__)); +#else + // TODO(JS): Hmmm None is not quite the same as unknown. It works for now, but we might want to have a distinct enum for unknown. + matchVersion.type = SLANG_PASS_THROUGH_NONE; +#endif + + return matchVersion; +} + + +DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() +{ + static DownstreamCompilerMatchVersion s_version = _calcCompiledVersion(); + return s_version; +} + +/* static */IDownstreamCompiler* DownstreamCompilerUtil::findCompiler(const DownstreamCompilerSet* set, MatchType matchType, const DownstreamCompilerDesc& desc) +{ + List<IDownstreamCompiler*> compilers; + set->getCompilers(compilers); + return findCompiler(compilers, matchType, desc); +} + +/* static */IDownstreamCompiler* DownstreamCompilerUtil::findCompiler(const List<IDownstreamCompiler*>& compilers, MatchType matchType, const DownstreamCompilerDesc& desc) +{ + if (compilers.getCount() <= 0) + { + return nullptr; + } + + Int bestIndex = -1; + + const SlangPassThrough compilerType = desc.type; + + Int maxVersionValue = 0; + Int minVersionDiff = 0x7fffffff; + + Int descVersionValue = desc.getVersionValue(); + + // If we don't have version set, then anything 0 or above is good enough, and just take newest + if (descVersionValue == 0) + { + maxVersionValue = -1; + matchType = MatchType::Newest; + } + + for (Index i = 0; i < compilers.getCount(); ++i) + { + IDownstreamCompiler* compiler = compilers[i]; + auto compilerDesc = compiler->getDesc(); + + if (compilerType == compilerDesc.type) + { + const Int versionValue = compilerDesc.getVersionValue(); + switch (matchType) + { + case MatchType::MinGreaterEqual: + { + auto diff = descVersionValue - versionValue; + if (diff >= 0 && diff < minVersionDiff) + { + bestIndex = i; + minVersionDiff = diff; + } + break; + } + case MatchType::MinAbsolute: + { + auto diff = descVersionValue - versionValue; + diff = (diff >= 0) ? diff : -diff; + if (diff < minVersionDiff) + { + bestIndex = i; + minVersionDiff = diff; + } + break; + } + case MatchType::Newest: + { + if (versionValue > maxVersionValue) + { + maxVersionValue = versionValue; + bestIndex = i; + } + break; + } + } + } + } + + return (bestIndex >= 0) ? compilers[bestIndex] : nullptr; +} + +/* static */IDownstreamCompiler* DownstreamCompilerUtil::findCompiler(const List<IDownstreamCompiler*>& compilers, const DownstreamCompilerDesc& desc) +{ + for (auto compiler : compilers) + { + if (compiler->getDesc() == desc) + { + return compiler; + } + } + return nullptr; +} + +/* static */IDownstreamCompiler* DownstreamCompilerUtil::findCompiler(const List<IDownstreamCompiler*>& compilers, SlangPassThrough type, const SemanticVersion& version) +{ + DownstreamCompilerDesc desc; + desc.type = type; + desc.majorVersion = version.m_major; + desc.minorVersion = version.m_minor; + return findCompiler(compilers, desc); +} + +/* static */void DownstreamCompilerUtil::findVersions(const List<IDownstreamCompiler*>& compilers, SlangPassThrough type, List<SemanticVersion>& outVersions) +{ + for (auto compiler : compilers) + { + auto desc = compiler->getDesc(); + + if (desc.type == type) + { + outVersions.add(SemanticVersion(int(desc.majorVersion), int(desc.minorVersion), 0)); + } + } +} + +/* static */IDownstreamCompiler* DownstreamCompilerUtil::findClosestCompiler(const List<IDownstreamCompiler*>& compilers, const DownstreamCompilerMatchVersion& matchVersion) +{ + List<SemanticVersion> versions; + + findVersions(compilers, matchVersion.type, versions); + + if (versions.getCount() > 0) + { + if (versions.getCount() == 1) + { + // Must be that one + return findCompiler(compilers, matchVersion.type, versions[0]); + } + + // Okay lets find the best one + auto bestVersion = MatchSemanticVersion::findAnyBest(versions.getBuffer(), versions.getCount(), matchVersion.matchVersion); + + // If one is found use it + if (bestVersion.isSet()) + { + return findCompiler(compilers, matchVersion.type, bestVersion); + } + } + + { + // TODO(JS): + // NOTE! This may not really be appropriate, because LLVM is *not* interchangable with + // a 'normal' C++ compiler as cannot access standard libraries/headers. + // So `slang-llvm` can't be used for 'host' code. + + // These compilers should be usable interchangably. The order is important, as the first one that matches will + // be used, so LLVM is used before CLANG or GCC if appropriate + const SlangPassThrough compatiblePassThroughs[] = + { + SLANG_PASS_THROUGH_LLVM, + SLANG_PASS_THROUGH_CLANG, + SLANG_PASS_THROUGH_GCC, + }; + + // Check the version is one of the compatible types + if (makeConstArrayView(compatiblePassThroughs).indexOf(matchVersion.type) >= 0) + { + // Try each compatible type in turn + for (auto passThrough : compatiblePassThroughs) + { + versions.clear(); + findVersions(compilers, passThrough, versions); + + if (versions.getCount() > 0) + { + // Get the latest version (as we have no way to really compare) + auto latestVersion = SemanticVersion::getLatest(versions.getBuffer(), versions.getCount()); + return findCompiler(compilers, matchVersion.type, latestVersion); + } + } + } + } + + return nullptr; +} + +/* static */IDownstreamCompiler* DownstreamCompilerUtil::findClosestCompiler(const DownstreamCompilerSet* set, const DownstreamCompilerMatchVersion& matchVersion) +{ + List<IDownstreamCompiler*> compilers; + set->getCompilers(compilers); + return findClosestCompiler(compilers, matchVersion); +} + +/* static */void DownstreamCompilerUtil::updateDefault(DownstreamCompilerSet* set, SlangSourceLanguage sourceLanguage) +{ + IDownstreamCompiler* compiler = nullptr; + + switch (sourceLanguage) + { + case SLANG_SOURCE_LANGUAGE_CPP: + case SLANG_SOURCE_LANGUAGE_C: + { + // Find the compiler closest to the compiler this was compiled with + if (!compiler) + { + compiler = findClosestCompiler(set, getCompiledVersion()); + } + break; + } + case SLANG_SOURCE_LANGUAGE_CUDA: + { + DownstreamCompilerDesc desc; + desc.type = SLANG_PASS_THROUGH_NVRTC; + compiler = findCompiler(set, MatchType::Newest, desc); + break; + } + default: break; + } + + set->setDefaultCompiler(sourceLanguage, compiler); +} + +/* static */void DownstreamCompilerUtil::updateDefaults(DownstreamCompilerSet* set) +{ + for (Index i = 0; i < Index(SLANG_SOURCE_LANGUAGE_COUNT_OF); ++i) + { + updateDefault(set, SlangSourceLanguage(i)); + } +} + +/* static */void DownstreamCompilerUtil::setDefaultLocators(DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]) +{ + outFuncs[int(SLANG_PASS_THROUGH_VISUAL_STUDIO)] = &VisualStudioCompilerUtil::locateCompilers; + outFuncs[int(SLANG_PASS_THROUGH_CLANG)] = &GCCDownstreamCompilerUtil::locateClangCompilers; + outFuncs[int(SLANG_PASS_THROUGH_GCC)] = &GCCDownstreamCompilerUtil::locateGCCCompilers; + outFuncs[int(SLANG_PASS_THROUGH_NVRTC)] = &NVRTCDownstreamCompilerUtil::locateCompilers; + outFuncs[int(SLANG_PASS_THROUGH_DXC)] = &DXCDownstreamCompilerUtil::locateCompilers; + outFuncs[int(SLANG_PASS_THROUGH_FXC)] = &FXCDownstreamCompilerUtil::locateCompilers; + outFuncs[int(SLANG_PASS_THROUGH_GLSLANG)] = &GlslangDownstreamCompilerUtil::locateCompilers; + outFuncs[int(SLANG_PASS_THROUGH_LLVM)] = &LLVMDownstreamCompilerUtil::locateCompilers; +} + +static String _getParentPath(const String& path) +{ + // If we can get the canonical path, we'll do that before getting the parent + String canonicalPath; + if (SLANG_SUCCEEDED(Path::getCanonical(path, canonicalPath))) + { + return Path::getParentDirectory(canonicalPath); + } + else + { + return Path::getParentDirectory(path); + } +} + +static SlangResult _findPaths(const String& path, const char* libraryName, String& outParentPath, String& outLibraryPath) +{ + // Try to determine what the path is by looking up the path type + SlangPathType pathType; + if (SLANG_SUCCEEDED(Path::getPathType(path, &pathType))) + { + if (pathType == SLANG_PATH_TYPE_DIRECTORY) + { + outParentPath = path; + outLibraryPath = Path::combine(outParentPath, libraryName); + } + else + { + SLANG_ASSERT(pathType == SLANG_PATH_TYPE_FILE); + + outParentPath = _getParentPath(path); + outLibraryPath = path; + } + + return SLANG_OK; + } + + // If this failed the path could be to a shared library, but we may need to convert to the shared library filename first + const String sharedLibraryFilePath = SharedLibrary::calcPlatformPath(path.getUnownedSlice()); + if (SLANG_SUCCEEDED(Path::getPathType(sharedLibraryFilePath, &pathType)) && pathType == SLANG_PATH_TYPE_FILE) + { + // We pass in the shared library path, as canonical paths can sometimes only apply to pre-existing objects. + outParentPath = _getParentPath(sharedLibraryFilePath); + // The original path should work as is for the SharedLibrary load. Notably we don't use the sharedLibraryFilePath + // as this is the wrong name to do a SharedLibrary load with. + outLibraryPath = path; + + return SLANG_OK; + } + + return SLANG_FAIL; +} + +/* static */SlangResult DownstreamCompilerUtil::loadSharedLibrary(const String& path, ISlangSharedLibraryLoader* loader, const char*const* dependentNames, const char* inLibraryName, ComPtr<ISlangSharedLibrary>& outSharedLib) +{ + String parentPath; + String libraryPath; + + // If a path is passed in lets, try and determine what kind of path it is. + if (path.getLength()) + { + if (SLANG_FAILED(_findPaths(path, inLibraryName, parentPath, libraryPath))) + { + // We have a few scenarios here. + // 1) The path could be the shared library/dll filename, that will be found through some operating system mechanism + // 2) That the shared library is *NOT* on the filesystem directly (the loader does something different) + // 3) Permissions or some other mechanism stops the lookup from working + + // We should probably assume that the path means something, else why set it. + // It's probably less likely that it is a directory that we can't detect - as if it's a directory as part of an app + // it's permissions should allow detection, or be made to allow it. + + // All this being the case we should probably assume that it is the shared library name. + libraryPath = path; + + // Attempt to get a parent. If there isn't one this will be empty, which will mean it will be ignored, which is probably + // what we want if path is just a shared library name + parentPath = Path::getParentDirectory(libraryPath); + } + } + + // Keep all dependent libs in scope, before we load the library we want + List<ComPtr<ISlangSharedLibrary>> dependentLibs; + + // Try to load any dependent libs from the parent path + if (dependentNames) + { + for (const char*const* cur = dependentNames; *cur; ++cur) + { + const char* dependentName = *cur; + ComPtr<ISlangSharedLibrary> lib; + if (parentPath.getLength()) + { + String dependentPath = Path::combine(parentPath, dependentName); + loader->loadSharedLibrary(dependentPath.getBuffer(), lib.writeRef()); + } + else + { + loader->loadSharedLibrary(dependentName, lib.writeRef()); + } + + if (lib) + { + dependentLibs.add(lib); + } + } + } + + if (libraryPath.getLength()) + { + // If we hare a library path use that + return loader->loadSharedLibrary(libraryPath.getBuffer(), outSharedLib.writeRef()); + } + else + { + // Else just use the name that was passed in. + return loader->loadSharedLibrary(inLibraryName, outSharedLib.writeRef()); + } +} + +/* static */void DownstreamCompilerUtil::appendAsText(const DownstreamCompilerDesc& desc, StringBuilder& out) +{ + out << TypeTextUtil::getPassThroughAsHumanText(desc.type); + + // Append the version if there is a version + if (desc.majorVersion || desc.minorVersion) + { + out << " "; + out << desc.majorVersion; + out << "."; + out << desc.minorVersion; + } +} + +} diff --git a/source/compiler-core/slang-downstream-compiler-util.h b/source/compiler-core/slang-downstream-compiler-util.h new file mode 100644 index 000000000..9e595bb86 --- /dev/null +++ b/source/compiler-core/slang-downstream-compiler-util.h @@ -0,0 +1,104 @@ +#ifndef SLANG_DOWNSTREAM_COMPILER_UTIL_H +#define SLANG_DOWNSTREAM_COMPILER_UTIL_H + +#include "slang-downstream-compiler.h" +#include "slang-downstream-compiler-set.h" + +namespace Slang +{ + +typedef SlangResult (*DownstreamCompilerLocatorFunc)(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + +struct DownstreamCompilerInfo +{ + typedef DownstreamCompilerInfo This; + typedef uint32_t SourceLanguageFlags; + struct SourceLanguageFlag + { + enum Enum : SourceLanguageFlags + { + Unknown = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_UNKNOWN, + Slang = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_SLANG, + HLSL = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_HLSL, + GLSL = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_GLSL, + C = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_C, + CPP = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_CPP, + CUDA = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_CUDA, + }; + }; + + /// Get info for a compiler type + static const This& getInfo(SlangPassThrough compiler); + /// True if this compiler can compile the specified language + static bool canCompile(SlangPassThrough compiler, SlangSourceLanguage sourceLanguage); + + DownstreamCompilerInfo() : sourceLanguageFlags(0) {} + + DownstreamCompilerInfo(SourceLanguageFlags inSourceLanguageFlags) : + sourceLanguageFlags(inSourceLanguageFlags) + {} + SourceLanguageFlags sourceLanguageFlags; +}; + + +// Combination of a downstream compiler type (pass through) and +// a match version. +struct DownstreamCompilerMatchVersion +{ + DownstreamCompilerMatchVersion(SlangPassThrough inType, MatchSemanticVersion inMatchVersion) : + type(inType), + matchVersion(inMatchVersion) + {} + + DownstreamCompilerMatchVersion() :type(SLANG_PASS_THROUGH_NONE) {} + + SlangPassThrough type; ///< The type of the compiler + MatchSemanticVersion matchVersion; ///< The match version +}; + +struct DownstreamCompilerUtil: public DownstreamCompilerBaseUtil +{ + enum class MatchType + { + MinGreaterEqual, + MinAbsolute, + Newest, + }; + + /// Find a compiler + static IDownstreamCompiler* findCompiler(const DownstreamCompilerSet* set, MatchType matchType, const DownstreamCompilerDesc& desc); + static IDownstreamCompiler* findCompiler(const List<IDownstreamCompiler*>& compilers, MatchType matchType, const DownstreamCompilerDesc& desc); + + static IDownstreamCompiler* findCompiler(const List<IDownstreamCompiler*>& compilers, SlangPassThrough type, const SemanticVersion& version); + static IDownstreamCompiler* findCompiler(const List<IDownstreamCompiler*>& compilers, const DownstreamCompilerDesc& desc); + + /// Find all the compilers with the version + static void findVersions(const List<IDownstreamCompiler*>& compilers, SlangPassThrough compiler, List<SemanticVersion>& versions); + + + /// Find the compiler closest to the desc + static IDownstreamCompiler* findClosestCompiler(const List<IDownstreamCompiler*>& compilers, const DownstreamCompilerMatchVersion& version); + static IDownstreamCompiler* findClosestCompiler(const DownstreamCompilerSet* set, const DownstreamCompilerMatchVersion& version); + + /// Get the information on the compiler used to compile this source + static DownstreamCompilerMatchVersion getCompiledVersion(); + + static void updateDefault(DownstreamCompilerSet* set, SlangSourceLanguage sourceLanguage); + static void updateDefaults(DownstreamCompilerSet* set); + + static void setDefaultLocators(DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]); + + /// Attempts to determine what 'path' is and load appropriately. Is it a path to a shared library? Is it a directory holding the libraries? + /// Some downstream shared libraries need other shared libraries to be loaded before the main shared library, such that they are in the same directory + /// otherwise the shared library could come from some unwanted location. + /// dependentNames names shared libraries which should be attempted to be loaded in the path of the main shared library. + /// The list is optional (nullptr can be passed in), and the list is terminated by nullptr. + static SlangResult loadSharedLibrary(const String& path, ISlangSharedLibraryLoader* loader, const char*const* dependantNames, const char* libraryName, ComPtr<ISlangSharedLibrary>& outSharedLib); + + /// Append the desc as text + static void appendAsText(const DownstreamCompilerDesc& desc, StringBuilder& out); +}; + +} + +#endif diff --git a/source/compiler-core/slang-downstream-compiler.cpp b/source/compiler-core/slang-downstream-compiler.cpp index c492b6dd7..64ad7fbc9 100644 --- a/source/compiler-core/slang-downstream-compiler.cpp +++ b/source/compiler-core/slang-downstream-compiler.cpp @@ -12,61 +12,10 @@ #include "../core/slang-blob.h" #include "../core/slang-char-util.h" -#ifdef SLANG_VC -# include "windows/slang-win-visual-studio-util.h" -#endif - -#include "slang-visual-studio-compiler-util.h" -#include "slang-gcc-compiler-util.h" -#include "slang-nvrtc-compiler.h" -#include "slang-fxc-compiler.h" -#include "slang-dxc-compiler.h" -#include "slang-glslang-compiler.h" -#include "slang-llvm-compiler.h" namespace Slang { -static DownstreamCompiler::Infos _calcInfos() -{ - typedef DownstreamCompiler::Info Info; - typedef DownstreamCompiler::SourceLanguageFlag SourceLanguageFlag; - typedef DownstreamCompiler::SourceLanguageFlags SourceLanguageFlags; - - DownstreamCompiler::Infos infos; - - infos.infos[int(SLANG_PASS_THROUGH_CLANG)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); - infos.infos[int(SLANG_PASS_THROUGH_VISUAL_STUDIO)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); - infos.infos[int(SLANG_PASS_THROUGH_GCC)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); - infos.infos[int(SLANG_PASS_THROUGH_LLVM)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); - - infos.infos[int(SLANG_PASS_THROUGH_NVRTC)] = Info(SourceLanguageFlag::CUDA); - - infos.infos[int(SLANG_PASS_THROUGH_DXC)] = Info(SourceLanguageFlag::HLSL); - infos.infos[int(SLANG_PASS_THROUGH_FXC)] = Info(SourceLanguageFlag::HLSL); - infos.infos[int(SLANG_PASS_THROUGH_GLSLANG)] = Info(SourceLanguageFlag::GLSL); - - return infos; -} - -/* static */DownstreamCompiler::Infos DownstreamCompiler::s_infos = _calcInfos(); - -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompiler::Desc !!!!!!!!!!!!!!!!!!!!!!*/ - -void DownstreamCompiler::Desc::appendAsText(StringBuilder& out) const -{ - out << TypeTextUtil::getPassThroughAsHumanText(type); - - // Append the version if there is a version - if (majorVersion || minorVersion) - { - out << " "; - out << majorVersion; - out << "."; - out << minorVersion; - } -} - /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamDiagnostic !!!!!!!!!!!!!!!!!!!!!!!!*/ /* static */UnownedStringSlice DownstreamDiagnostic::getSeverityText(Severity severity) @@ -166,9 +115,9 @@ void DownstreamCompiler::Desc::appendAsText(StringBuilder& out) const return SLANG_OK; } -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompiler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerBase !!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ -SlangResult DownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) +SlangResult DownstreamCompilerBase::disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) { SLANG_UNUSED(sourceBlobTarget); SLANG_UNUSED(blob); @@ -178,11 +127,31 @@ SlangResult DownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarget, return SLANG_E_NOT_AVAILABLE; } +void* DownstreamCompilerBase::castAs(const Guid& guid) +{ + if (auto ptr = getInterface(guid)) + { + return ptr; + } + return getObject(guid); +} -/* static */bool DownstreamCompiler::canCompile(SlangPassThrough compiler, SlangSourceLanguage sourceLanguage) +void* DownstreamCompilerBase::getInterface(const Guid& guid) { - const auto& info = getInfo(compiler); - return (info.sourceLanguageFlags & (SourceLanguageFlags(1) << int(sourceLanguage))) != 0; + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == IDownstreamCompiler::getTypeGuid()) + { + return static_cast<IDownstreamCompiler*>(this); + } + + return nullptr; +} + +void* DownstreamCompilerBase::getObject(const Guid& guid) +{ + SLANG_UNUSED(guid); + return nullptr; } /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamDiagnostics !!!!!!!!!!!!!!!!!!!!!!*/ @@ -394,7 +363,7 @@ SlangResult CommandLineDownstreamCompileResult::getBinary(ComPtr<ISlangBlob>& ou /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CommandLineDownstreamCompiler !!!!!!!!!!!!!!!!!!!!!!*/ -static bool _isContentsInFile(const DownstreamCompiler::CompileOptions& options) +static bool _isContentsInFile(const DownstreamCompileOptions& options) { if (options.sourceContentsPath.getLength() <= 0) { @@ -500,7 +469,7 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio { List<String> paths; - SLANG_RETURN_ON_FAIL(calcCompileProducts(options, DownstreamCompiler::ProductFlag::All, paths)); + SLANG_RETURN_ON_FAIL(calcCompileProducts(options, DownstreamProductFlag::All, paths)); productFileSet->add(paths); } @@ -530,471 +499,4 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio return SLANG_OK; } -/* !!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompiler::Desc !!!!!!!!!!!!!!!!!!!!!!*/ - -static DownstreamCompilerMatchVersion _calcCompiledVersion() -{ - DownstreamCompilerMatchVersion matchVersion; - -#if SLANG_VC - matchVersion = WinVisualStudioUtil::getCompiledVersion(); -#elif SLANG_CLANG - matchVersion.type = SLANG_PASS_THROUGH_CLANG; - matchVersion.matchVersion.set(Index(__clang_major__), Index(__clang_minor__)); -#elif SLANG_GCC - matchVersion.type = SLANG_PASS_THROUGH_GCC; - matchVersion.matchVersion.set(Index(__GNUC__), Index(__GNUC_MINOR__)); -#else - // TODO(JS): Hmmm None is not quite the same as unknown. It works for now, but we might want to have a distinct enum for unknown. - matchVersion.type = SLANG_PASS_THROUGH_NONE; -#endif - - return matchVersion; -} - -/* !!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerUtil !!!!!!!!!!!!!!!!!!!!!!*/ - -DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() -{ - static DownstreamCompilerMatchVersion s_version = _calcCompiledVersion(); - return s_version; -} - -/* static */DownstreamCompiler* DownstreamCompilerUtil::findCompiler(const DownstreamCompilerSet* set, MatchType matchType, const DownstreamCompiler::Desc& desc) -{ - List<DownstreamCompiler*> compilers; - set->getCompilers(compilers); - return findCompiler(compilers, matchType, desc); -} - -/* static */DownstreamCompiler* DownstreamCompilerUtil::findCompiler(const List<DownstreamCompiler*>& compilers, MatchType matchType, const DownstreamCompiler::Desc& desc) -{ - if (compilers.getCount() <= 0) - { - return nullptr; - } - - Int bestIndex = -1; - - const SlangPassThrough compilerType = desc.type; - - Int maxVersionValue = 0; - Int minVersionDiff = 0x7fffffff; - - Int descVersionValue = desc.getVersionValue(); - - // If we don't have version set, then anything 0 or above is good enough, and just take newest - if (descVersionValue == 0) - { - maxVersionValue = -1; - matchType = MatchType::Newest; - } - - for (Index i = 0; i < compilers.getCount(); ++i) - { - DownstreamCompiler* compiler = compilers[i]; - auto compilerDesc = compiler->getDesc(); - - if (compilerType == compilerDesc.type) - { - const Int versionValue = compilerDesc.getVersionValue(); - switch (matchType) - { - case MatchType::MinGreaterEqual: - { - auto diff = descVersionValue - versionValue; - if (diff >= 0 && diff < minVersionDiff) - { - bestIndex = i; - minVersionDiff = diff; - } - break; - } - case MatchType::MinAbsolute: - { - auto diff = descVersionValue - versionValue; - diff = (diff >= 0) ? diff : -diff; - if (diff < minVersionDiff) - { - bestIndex = i; - minVersionDiff = diff; - } - break; - } - case MatchType::Newest: - { - if (versionValue > maxVersionValue) - { - maxVersionValue = versionValue; - bestIndex = i; - } - break; - } - } - } - } - - return (bestIndex >= 0) ? compilers[bestIndex] : nullptr; -} - -/* static */DownstreamCompiler* DownstreamCompilerUtil::findCompiler(const List<DownstreamCompiler*>& compilers, const DownstreamCompiler::Desc& desc) -{ - for (auto compiler : compilers) - { - if (compiler->getDesc() == desc) - { - return compiler; - } - } - return nullptr; -} - -/* static */DownstreamCompiler* DownstreamCompilerUtil::findCompiler(const List<DownstreamCompiler*>& compilers, SlangPassThrough type, const SemanticVersion& version) -{ - DownstreamCompiler::Desc desc; - desc.type = type; - desc.majorVersion = version.m_major; - desc.minorVersion = version.m_minor; - return findCompiler(compilers, desc); -} - -/* static */void DownstreamCompilerUtil::findVersions(const List<DownstreamCompiler*>& compilers, SlangPassThrough type, List<SemanticVersion>& outVersions) -{ - for (auto compiler : compilers) - { - auto desc = compiler->getDesc(); - - if (desc.type == type) - { - outVersions.add(SemanticVersion(int(desc.majorVersion), int(desc.minorVersion), 0)); - } - } -} - -/* static */DownstreamCompiler* DownstreamCompilerUtil::findClosestCompiler(const List<DownstreamCompiler*>& compilers, const DownstreamCompilerMatchVersion& matchVersion) -{ - List<SemanticVersion> versions; - - findVersions(compilers, matchVersion.type, versions); - - if (versions.getCount() > 0) - { - if (versions.getCount() == 1) - { - // Must be that one - return findCompiler(compilers, matchVersion.type, versions[0]); - } - - // Okay lets find the best one - auto bestVersion = MatchSemanticVersion::findAnyBest(versions.getBuffer(), versions.getCount(), matchVersion.matchVersion); - - // If one is found use it - if (bestVersion.isSet()) - { - return findCompiler(compilers, matchVersion.type, bestVersion); - } - } - - { - // TODO(JS): - // NOTE! This may not really be appropriate, because LLVM is *not* interchangable with - // a 'normal' C++ compiler as cannot access standard libraries/headers. - // So `slang-llvm` can't be used for 'host' code. - - // These compilers should be usable interchangably. The order is important, as the first one that matches will - // be used, so LLVM is used before CLANG or GCC if appropriate - const SlangPassThrough compatiblePassThroughs[] = - { - SLANG_PASS_THROUGH_LLVM, - SLANG_PASS_THROUGH_CLANG, - SLANG_PASS_THROUGH_GCC, - }; - - // Check the version is one of the compatible types - if (makeConstArrayView(compatiblePassThroughs).indexOf(matchVersion.type) >= 0) - { - // Try each compatible type in turn - for (auto passThrough : compatiblePassThroughs) - { - versions.clear(); - findVersions(compilers, passThrough, versions); - - if (versions.getCount() > 0) - { - // Get the latest version (as we have no way to really compare) - auto latestVersion = SemanticVersion::getLatest(versions.getBuffer(), versions.getCount()); - return findCompiler(compilers, matchVersion.type, latestVersion); - } - } - } - } - - return nullptr; -} - -/* static */DownstreamCompiler* DownstreamCompilerUtil::findClosestCompiler(const DownstreamCompilerSet* set, const DownstreamCompilerMatchVersion& matchVersion) -{ - List<DownstreamCompiler*> compilers; - set->getCompilers(compilers); - return findClosestCompiler(compilers, matchVersion); -} - -/* static */void DownstreamCompilerUtil::updateDefault(DownstreamCompilerSet* set, SlangSourceLanguage sourceLanguage) -{ - DownstreamCompiler* compiler = nullptr; - - switch (sourceLanguage) - { - case SLANG_SOURCE_LANGUAGE_CPP: - case SLANG_SOURCE_LANGUAGE_C: - { - // Find the compiler closest to the compiler this was compiled with - if (!compiler) - { - compiler = findClosestCompiler(set, getCompiledVersion()); - } - break; - } - case SLANG_SOURCE_LANGUAGE_CUDA: - { - DownstreamCompiler::Desc desc; - desc.type = SLANG_PASS_THROUGH_NVRTC; - compiler = findCompiler(set, MatchType::Newest, desc); - break; - } - default: break; - } - - set->setDefaultCompiler(sourceLanguage, compiler); -} - -/* static */void DownstreamCompilerUtil::updateDefaults(DownstreamCompilerSet* set) -{ - for (Index i = 0; i < Index(SLANG_SOURCE_LANGUAGE_COUNT_OF); ++i) - { - updateDefault(set, SlangSourceLanguage(i)); - } -} - -/* static */void DownstreamCompilerUtil::setDefaultLocators(DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]) -{ - outFuncs[int(SLANG_PASS_THROUGH_VISUAL_STUDIO)] = &VisualStudioCompilerUtil::locateCompilers; - outFuncs[int(SLANG_PASS_THROUGH_CLANG)] = &GCCDownstreamCompilerUtil::locateClangCompilers; - outFuncs[int(SLANG_PASS_THROUGH_GCC)] = &GCCDownstreamCompilerUtil::locateGCCCompilers; - outFuncs[int(SLANG_PASS_THROUGH_NVRTC)] = &NVRTCDownstreamCompilerUtil::locateCompilers; - outFuncs[int(SLANG_PASS_THROUGH_DXC)] = &DXCDownstreamCompilerUtil::locateCompilers; - outFuncs[int(SLANG_PASS_THROUGH_FXC)] = &FXCDownstreamCompilerUtil::locateCompilers; - outFuncs[int(SLANG_PASS_THROUGH_GLSLANG)] = &GlslangDownstreamCompilerUtil::locateCompilers; - outFuncs[int(SLANG_PASS_THROUGH_LLVM)] = &LLVMDownstreamCompilerUtil::locateCompilers; -} - -static String _getParentPath(const String& path) -{ - // If we can get the canonical path, we'll do that before getting the parent - String canonicalPath; - if (SLANG_SUCCEEDED(Path::getCanonical(path, canonicalPath))) - { - return Path::getParentDirectory(canonicalPath); - } - else - { - return Path::getParentDirectory(path); - } -} - -static SlangResult _findPaths(const String& path, const char* libraryName, String& outParentPath, String& outLibraryPath) -{ - // Try to determine what the path is by looking up the path type - SlangPathType pathType; - if (SLANG_SUCCEEDED(Path::getPathType(path, &pathType))) - { - if (pathType == SLANG_PATH_TYPE_DIRECTORY) - { - outParentPath = path; - outLibraryPath = Path::combine(outParentPath, libraryName); - } - else - { - SLANG_ASSERT(pathType == SLANG_PATH_TYPE_FILE); - - outParentPath = _getParentPath(path); - outLibraryPath = path; - } - - return SLANG_OK; - } - - // If this failed the path could be to a shared library, but we may need to convert to the shared library filename first - const String sharedLibraryFilePath = SharedLibrary::calcPlatformPath(path.getUnownedSlice()); - if (SLANG_SUCCEEDED(Path::getPathType(sharedLibraryFilePath, &pathType)) && pathType == SLANG_PATH_TYPE_FILE) - { - // We pass in the shared library path, as canonical paths can sometimes only apply to pre-existing objects. - outParentPath = _getParentPath(sharedLibraryFilePath); - // The original path should work as is for the SharedLibrary load. Notably we don't use the sharedLibraryFilePath - // as this is the wrong name to do a SharedLibrary load with. - outLibraryPath = path; - - return SLANG_OK; - } - - return SLANG_FAIL; -} - -/* static */SlangResult DownstreamCompilerUtil::loadSharedLibrary(const String& path, ISlangSharedLibraryLoader* loader, const char*const* dependentNames, const char* inLibraryName, ComPtr<ISlangSharedLibrary>& outSharedLib) -{ - String parentPath; - String libraryPath; - - // If a path is passed in lets, try and determine what kind of path it is. - if (path.getLength()) - { - if (SLANG_FAILED(_findPaths(path, inLibraryName, parentPath, libraryPath))) - { - // We have a few scenarios here. - // 1) The path could be the shared library/dll filename, that will be found through some operating system mechanism - // 2) That the shared library is *NOT* on the filesystem directly (the loader does something different) - // 3) Permissions or some other mechanism stops the lookup from working - - // We should probably assume that the path means something, else why set it. - // It's probably less likely that it is a directory that we can't detect - as if it's a directory as part of an app - // it's permissions should allow detection, or be made to allow it. - - // All this being the case we should probably assume that it is the shared library name. - libraryPath = path; - - // Attempt to get a parent. If there isn't one this will be empty, which will mean it will be ignored, which is probably - // what we want if path is just a shared library name - parentPath = Path::getParentDirectory(libraryPath); - } - } - - // Keep all dependent libs in scope, before we load the library we want - List<ComPtr<ISlangSharedLibrary>> dependentLibs; - - // Try to load any dependent libs from the parent path - if (dependentNames) - { - for (const char*const* cur = dependentNames; *cur; ++cur) - { - const char* dependentName = *cur; - ComPtr<ISlangSharedLibrary> lib; - if (parentPath.getLength()) - { - String dependentPath = Path::combine(parentPath, dependentName); - loader->loadSharedLibrary(dependentPath.getBuffer(), lib.writeRef()); - } - else - { - loader->loadSharedLibrary(dependentName, lib.writeRef()); - } - - if (lib) - { - dependentLibs.add(lib); - } - } - } - - if (libraryPath.getLength()) - { - // If we hare a library path use that - return loader->loadSharedLibrary(libraryPath.getBuffer(), outSharedLib.writeRef()); - } - else - { - // Else just use the name that was passed in. - return loader->loadSharedLibrary(inLibraryName, outSharedLib.writeRef()); - } -} - -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerSet !!!!!!!!!!!!!!!!!!!!!!*/ - -void DownstreamCompilerSet::getCompilerDescs(List<DownstreamCompiler::Desc>& outCompilerDescs) const -{ - outCompilerDescs.clear(); - for (DownstreamCompiler* compiler : m_compilers) - { - outCompilerDescs.add(compiler->getDesc()); - } -} - -Index DownstreamCompilerSet::_findIndex(const DownstreamCompiler::Desc& desc) const -{ - const Index count = m_compilers.getCount(); - for (Index i = 0; i < count; ++i) - { - if (m_compilers[i]->getDesc() == desc) - { - return i; - } - } - return -1; -} - -DownstreamCompiler* DownstreamCompilerSet::getCompiler(const DownstreamCompiler::Desc& compilerDesc) const -{ - const Index index = _findIndex(compilerDesc); - return index >= 0 ? m_compilers[index] : nullptr; -} - -void DownstreamCompilerSet::getCompilers(List<DownstreamCompiler*>& outCompilers) const -{ - outCompilers.clear(); - outCompilers.addRange((DownstreamCompiler*const*)m_compilers.begin(), m_compilers.getCount()); -} - -bool DownstreamCompilerSet::hasSharedLibrary(ISlangSharedLibrary* lib) -{ - const Index foundIndex = m_sharedLibraries.findFirstIndex([lib](ISlangSharedLibrary* inLib) -> bool { return lib == inLib; }); - return(foundIndex >= 0); -} - -void DownstreamCompilerSet::addSharedLibrary(ISlangSharedLibrary* lib) -{ - SLANG_ASSERT(lib); - if (!hasSharedLibrary(lib)) - { - m_sharedLibraries.add(ComPtr<ISlangSharedLibrary>(lib)); - } -} - -bool DownstreamCompilerSet::hasCompiler(SlangPassThrough compilerType) const -{ - for (DownstreamCompiler* compiler : m_compilers) - { - const auto& desc = compiler->getDesc(); - if (desc.type == compilerType) - { - return true; - } - } - return false; -} - -void DownstreamCompilerSet::remove(SlangPassThrough compilerType) -{ - for (Index i = 0; i < m_compilers.getCount(); ++i) - { - DownstreamCompiler* compiler = m_compilers[i]; - if (compiler->getDesc().type == compilerType) - { - m_compilers.fastRemoveAt(i); - i--; - } - } -} - -void DownstreamCompilerSet::addCompiler(DownstreamCompiler* compiler) -{ - const Index index = _findIndex(compiler->getDesc()); - if (index >= 0) - { - m_compilers[index] = compiler; - } - else - { - m_compilers.add(compiler); - } -} - } diff --git a/source/compiler-core/slang-downstream-compiler.h b/source/compiler-core/slang-downstream-compiler.h index 666ca5568..ece6c1c51 100644 --- a/source/compiler-core/slang-downstream-compiler.h +++ b/source/compiler-core/slang-downstream-compiler.h @@ -155,88 +155,48 @@ protected: ComPtr<ISlangBlob> m_blob; }; -// Combination of a downstream compiler type (pass through) and -// a match version. -struct DownstreamCompilerMatchVersion +// Compiler description +struct DownstreamCompilerDesc { - DownstreamCompilerMatchVersion(SlangPassThrough inType, MatchSemanticVersion inMatchVersion): - type(inType), - matchVersion(inMatchVersion) - {} + typedef DownstreamCompilerDesc ThisType; - DownstreamCompilerMatchVersion():type(SLANG_PASS_THROUGH_NONE) {} + HashCode getHashCode() const { return combineHash(HashCode(type), combineHash(HashCode(majorVersion), HashCode(minorVersion))); } + bool operator==(const ThisType& rhs) const { return type == rhs.type && majorVersion == rhs.majorVersion && minorVersion == rhs.minorVersion; } + bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - SlangPassThrough type; ///< The type of the compiler - MatchSemanticVersion matchVersion; ///< The match version -}; + /// Get the version as a value + Int getVersionValue() const { return majorVersion * 100 + minorVersion; } -class DownstreamCompiler: public RefObject -{ -public: - typedef RefObject Super; + /// true if has a version set + bool hasVersion() const { return majorVersion || minorVersion; } - typedef DownstreamCompileResult CompileResult; + /// Ctor + explicit DownstreamCompilerDesc(SlangPassThrough inType = SLANG_PASS_THROUGH_NONE, Int inMajorVersion = 0, Int inMinorVersion = 0) :type(inType), majorVersion(inMajorVersion), minorVersion(inMinorVersion) {} - typedef uint32_t SourceLanguageFlags; - struct SourceLanguageFlag - { - enum Enum : SourceLanguageFlags - { - Unknown = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_UNKNOWN, - Slang = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_SLANG, - HLSL = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_HLSL, - GLSL = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_GLSL, - C = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_C, - CPP = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_CPP, - CUDA = SourceLanguageFlags(1) << SLANG_SOURCE_LANGUAGE_CUDA, - }; - }; + explicit DownstreamCompilerDesc(SlangPassThrough inType, const SemanticVersion& version) :type(inType), majorVersion(version.m_major), minorVersion(version.m_minor) {} - struct Info - { - Info():sourceLanguageFlags(0) {} + SlangPassThrough type; ///< The type of the compiler - Info(SourceLanguageFlags inSourceLanguageFlags): - sourceLanguageFlags(inSourceLanguageFlags) - {} - SourceLanguageFlags sourceLanguageFlags; - }; - struct Infos - { - Info infos[int(SLANG_PASS_THROUGH_COUNT_OF)]; - }; + /// TODO(JS): Would probably be better if changed to SemanticVersion, but not trivial to change + // because this type is part of the DownstreamCompiler interface, which is used with `slang-llvm`. + Int majorVersion; ///< Major version (interpretation is type specific) + Int minorVersion; ///< Minor version (interpretation is type specific) +}; - - // Compiler description - struct Desc +struct DownstreamCompileOptions +{ + typedef uint32_t Flags; + struct Flag { - typedef Desc ThisType; - - HashCode getHashCode() const { return combineHash(HashCode(type), combineHash(HashCode(majorVersion), HashCode(minorVersion))); } - bool operator==(const ThisType& rhs) const { return type == rhs.type && majorVersion == rhs.majorVersion && minorVersion == rhs.minorVersion; } - bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - - /// Get the version as a value - Int getVersionValue() const { return majorVersion * 100 + minorVersion; } - - void appendAsText(StringBuilder& out) const; - /// true if has a version set - bool hasVersion() const { return majorVersion || minorVersion; } - - /// Ctor - explicit Desc(SlangPassThrough inType = SLANG_PASS_THROUGH_NONE, Int inMajorVersion = 0, Int inMinorVersion = 0):type(inType), majorVersion(inMajorVersion), minorVersion(inMinorVersion) {} - - explicit Desc(SlangPassThrough inType, const SemanticVersion& version):type(inType), majorVersion(version.m_major), minorVersion(version.m_minor) {} - - SlangPassThrough type; ///< The type of the compiler - - /// TODO(JS): Would probably be better if changed to SemanticVersion, but not trivial to change - // because this type is part of the DownstreamCompiler interface, which is used with `slang-llvm`. - Int majorVersion; ///< Major version (interpretation is type specific) - Int minorVersion; ///< Minor version (interpretation is type specific) + enum Enum : Flags + { + EnableExceptionHandling = 0x01, ///< Enables exception handling support (say as optionally supported by C++) + Verbose = 0x02, ///< Give more verbose diagnostics + EnableSecurityChecks = 0x04, ///< Enable runtime security checks (such as for buffer overruns) - enabling typically decreases performance + EnableFloat16 = 0x08, ///< If set compiles with support for float16/half + }; }; - enum class OptimizationLevel { None, ///< Don't optimize at all. @@ -254,7 +214,7 @@ public: }; enum class FloatingPointMode { - Default, + Default, Fast, Precise, }; @@ -284,119 +244,122 @@ public: SemanticVersion version; }; - struct CompileOptions - { - typedef uint32_t Flags; - struct Flag - { - enum Enum : Flags - { - EnableExceptionHandling = 0x01, ///< Enables exception handling support (say as optionally supported by C++) - Verbose = 0x02, ///< Give more verbose diagnostics - EnableSecurityChecks = 0x04, ///< Enable runtime security checks (such as for buffer overruns) - enabling typically decreases performance - EnableFloat16 = 0x08, ///< If set compiles with support for float16/half - }; - }; - - OptimizationLevel optimizationLevel = OptimizationLevel::Default; - DebugInfoType debugInfoType = DebugInfoType::Standard; - SlangCompileTarget targetType = SLANG_HOST_EXECUTABLE; - SlangSourceLanguage sourceLanguage = SLANG_SOURCE_LANGUAGE_CPP; - FloatingPointMode floatingPointMode = FloatingPointMode::Default; - PipelineType pipelineType = PipelineType::Unknown; - SlangMatrixLayoutMode matrixLayout = SLANG_MATRIX_LAYOUT_MODE_UNKNOWN; + OptimizationLevel optimizationLevel = OptimizationLevel::Default; + DebugInfoType debugInfoType = DebugInfoType::Standard; + SlangCompileTarget targetType = SLANG_HOST_EXECUTABLE; + SlangSourceLanguage sourceLanguage = SLANG_SOURCE_LANGUAGE_CPP; + FloatingPointMode floatingPointMode = FloatingPointMode::Default; + PipelineType pipelineType = PipelineType::Unknown; + SlangMatrixLayoutMode matrixLayout = SLANG_MATRIX_LAYOUT_MODE_UNKNOWN; - Flags flags = Flag::EnableExceptionHandling; + Flags flags = Flag::EnableExceptionHandling; - PlatformKind platform = PlatformKind::Unknown; + PlatformKind platform = PlatformKind::Unknown; - /// The path/name of the output module. Should not have the extension, as that will be added for each of the target types. - /// If not set a module path will be internally generated internally on a command line based compiler - String modulePath; + /// The path/name of the output module. Should not have the extension, as that will be added for each of the target types. + /// If not set a module path will be internally generated internally on a command line based compiler + String modulePath; - List<Define> defines; + List<Define> defines; - /// The contents of the source to compile. This can be empty is sourceFiles is set. - /// If the compiler is a commandLine file this source will be written to a temporary file. - String sourceContents; - /// 'Path' that the contents originated from. NOTE! This is for reporting only and doesn't have to exist on file system - String sourceContentsPath; + /// The contents of the source to compile. This can be empty is sourceFiles is set. + /// If the compiler is a commandLine file this source will be written to a temporary file. + String sourceContents; + /// 'Path' that the contents originated from. NOTE! This is for reporting only and doesn't have to exist on file system + String sourceContentsPath; - /// The names/paths of source to compile. This can be empty if sourceContents is set. - List<String> sourceFiles; + /// The names/paths of source to compile. This can be empty if sourceContents is set. + List<String> sourceFiles; - List<String> includePaths; - List<String> libraryPaths; + List<String> includePaths; + List<String> libraryPaths; - /// Libraries to link against. - List<ComPtr<IArtifact>> libraries; + /// Libraries to link against. + List<ComPtr<IArtifact>> libraries; - List<CapabilityVersion> requiredCapabilityVersions; + List<CapabilityVersion> requiredCapabilityVersions; - /// For compilers/compiles that require an entry point name, else can be empty - String entryPointName; - /// Profile name to use, only required for compiles that need to compile against a a specific profiles. - /// Profile names are tied to compilers and targets. - String profileName; + /// For compilers/compiles that require an entry point name, else can be empty + String entryPointName; + /// Profile name to use, only required for compiles that need to compile against a a specific profiles. + /// Profile names are tied to compilers and targets. + String profileName; - /// The stage being compiled for - SlangStage stage = SLANG_STAGE_NONE; + /// The stage being compiled for + SlangStage stage = SLANG_STAGE_NONE; - /// Arguments that are specific to a particular compiler implementation. - List<String> compilerSpecificArguments; + /// Arguments that are specific to a particular compiler implementation. + List<String> compilerSpecificArguments; - /// NOTE! Not all downstream compilers can use the fileSystemExt/sourceManager. This option will be ignored in those scenarios. - ISlangFileSystemExt* fileSystemExt = nullptr; - SourceManager* sourceManager = nullptr; - }; + /// NOTE! Not all downstream compilers can use the fileSystemExt/sourceManager. This option will be ignored in those scenarios. + ISlangFileSystemExt* fileSystemExt = nullptr; + SourceManager* sourceManager = nullptr; +}; - typedef uint32_t ProductFlags; - struct ProductFlag +/* Used to indicate what kind of products are expected to be produced for a compilation. */ +typedef uint32_t DownstreamProductFlags; +struct DownstreamProductFlag +{ + enum Enum : DownstreamProductFlags { - enum Enum : ProductFlags - { - Debug = 0x1, ///< Used by debugger during execution - Execution = 0x2, ///< Required for execution - Compile = 0x4, ///< A product *required* for compilation - Miscellaneous = 0x8, ///< Anything else - }; - enum Mask : ProductFlags - { - All = 0xf, ///< All the flags - }; + Debug = 0x1, ///< Used by debugger during execution + Execution = 0x2, ///< Required for execution + Compile = 0x4, ///< A product *required* for compilation + Miscellaneous = 0x8, ///< Anything else }; - - enum class Product + enum Mask : DownstreamProductFlags { - DebugRun, - Run, - CompileTemporary, - All, + All = 0xf, ///< All the flags }; +}; + +class IDownstreamCompiler : public ICastable +{ +public: + SLANG_COM_INTERFACE(0x167b8ba7, 0xbd41, 0x469a, { 0x92, 0x28, 0xb8, 0x53, 0xc8, 0xea, 0x56, 0x6d }) + + typedef DownstreamCompilerDesc Desc; + typedef DownstreamCompileOptions CompileOptions; + typedef DownstreamCompileResult CompileResult; + + typedef CompileOptions::OptimizationLevel OptimizationLevel; + typedef CompileOptions::DebugInfoType DebugInfoType; + typedef CompileOptions::FloatingPointMode FloatingPointMode; + typedef CompileOptions::PipelineType PipelineType; + typedef CompileOptions::Define Define; + typedef CompileOptions::CapabilityVersion CapabilityVersion; /// Get the desc of this compiler - const Desc& getDesc() const { return m_desc; } + virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() = 0; /// Compile using the specified options. The result is in resOut - virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) = 0; /// Some compilers have support converting a binary blob into disassembly. Output disassembly is held in the output blob - virtual SlangResult disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out); + virtual SLANG_NO_THROW SlangResult SLANG_MCALL disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) = 0; /// True if underlying compiler uses file system to communicate source - virtual bool isFileBased() = 0; + virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() = 0; +}; - /// Get info for a compiler type - static const Info& getInfo(SlangPassThrough compiler) { return s_infos.infos[int(compiler)]; } - /// True if this compiler can compile the specified language - static bool canCompile(SlangPassThrough compiler, SlangSourceLanguage sourceLanguage); +class DownstreamCompilerBase : public ComBaseObject, public IDownstreamCompiler +{ +public: + SLANG_COM_BASE_IUNKNOWN_ALL - -protected: - static Infos s_infos; + // ICastable + virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // IDownstreamCompiler + virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() SLANG_OVERRIDE { return m_desc; } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE; - DownstreamCompiler(const Desc& desc) : + DownstreamCompilerBase(const Desc& desc): m_desc(desc) - {} - DownstreamCompiler() {} + { + } + DownstreamCompilerBase() {} + + void* getInterface(const Guid& guid); + void* getObject(const Guid& guid); Desc m_desc; }; @@ -421,20 +384,20 @@ public: protected: String m_moduleFilePath; - DownstreamCompiler::CompileOptions m_options; + DownstreamCompileOptions m_options; ComPtr<ISlangBlob> m_binaryBlob; /// Cache of the shared library if appropriate ComPtr<ISlangSharedLibrary> m_hostCallableSharedLibrary; }; -class CommandLineDownstreamCompiler : public DownstreamCompiler +class CommandLineDownstreamCompiler : public DownstreamCompilerBase { public: - typedef DownstreamCompiler Super; + typedef DownstreamCompilerBase Super; - // DownstreamCompiler - virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; - virtual bool isFileBased() SLANG_OVERRIDE { return true; } + // IDownstreamCompiler + virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return true; } // Functions to be implemented for a specific CommandLine @@ -443,7 +406,7 @@ public: /// Given options determines the paths to products produced (including the 'moduleFilePath'). /// Note that does *not* guarentee all products were or should be produced. Just aims to include all that could /// be produced, such that can be removed on completion. - virtual SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, List<String>& outPaths) = 0; + virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags flags, List<String>& outPaths) = 0; virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) = 0; virtual SlangResult parseOutput(const ExecuteResult& exeResult, DownstreamDiagnostics& output) = 0; @@ -464,118 +427,20 @@ public: CommandLine m_cmdLine; }; -class DownstreamCompilerSet : public RefObject -{ -public: - typedef RefObject Super; - - /// Find all the available compilers - void getCompilerDescs(List<DownstreamCompiler::Desc>& outCompilerDescs) const; - /// Returns list of all compilers - void getCompilers(List<DownstreamCompiler*>& outCompilers) const; - - /// Get a compiler - DownstreamCompiler* getCompiler(const DownstreamCompiler::Desc& compilerDesc) const; - - /// Will replace if there is one with same desc - void addCompiler(DownstreamCompiler* compiler); - - /// Get a default compiler - DownstreamCompiler* getDefaultCompiler(SlangSourceLanguage sourceLanguage) const { return m_defaultCompilers[int(sourceLanguage)]; } - /// Set the default compiler - void setDefaultCompiler(SlangSourceLanguage sourceLanguage, DownstreamCompiler* compiler) { m_defaultCompilers[int(sourceLanguage)] = compiler; } - - /// True if has a compiler of the specified type - bool hasCompiler(SlangPassThrough compilerType) const; - - void remove(SlangPassThrough compilerType); - - void clear() { m_compilers.clear(); } - - bool hasSharedLibrary(ISlangSharedLibrary* lib); - void addSharedLibrary(ISlangSharedLibrary* lib); - - ~DownstreamCompilerSet() - { - // A compiler may be implemented in a shared library, so release all first. - m_compilers.clearAndDeallocate(); - for (auto& defaultCompiler : m_defaultCompilers) - { - defaultCompiler.setNull(); - } - - // Release any shared libraries - m_sharedLibraries.clearAndDeallocate(); - } - -protected: - - Index _findIndex(const DownstreamCompiler::Desc& desc) const; - - - RefPtr<DownstreamCompiler> m_defaultCompilers[int(SLANG_SOURCE_LANGUAGE_COUNT_OF)]; - // This could be a dictionary/map - but doing a linear search is going to be fine and it makes - // somethings easier. - List<RefPtr<DownstreamCompiler>> m_compilers; - - List<ComPtr<ISlangSharedLibrary>> m_sharedLibraries; -}; - -typedef SlangResult (*DownstreamCompilerLocatorFunc)(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); - /* Only purpose of having base-class here is to make all the DownstreamCompiler types available directly in derived Utils */ struct DownstreamCompilerBaseUtil { - typedef DownstreamCompiler::CompileOptions CompileOptions; - typedef DownstreamCompiler::OptimizationLevel OptimizationLevel; - typedef DownstreamCompiler::DebugInfoType DebugInfoType; - - typedef DownstreamDiagnostics::Diagnostic Diagnostic; + typedef DownstreamCompileOptions CompileOptions; - typedef DownstreamCompiler::FloatingPointMode FloatingPointMode; - typedef DownstreamCompiler::ProductFlag ProductFlag; - typedef DownstreamCompiler::ProductFlags ProductFlags; -}; + typedef CompileOptions::OptimizationLevel OptimizationLevel; + typedef CompileOptions::DebugInfoType DebugInfoType; -struct DownstreamCompilerUtil: public DownstreamCompilerBaseUtil -{ - enum class MatchType - { - MinGreaterEqual, - MinAbsolute, - Newest, - }; - - /// Find a compiler - static DownstreamCompiler* findCompiler(const DownstreamCompilerSet* set, MatchType matchType, const DownstreamCompiler::Desc& desc); - static DownstreamCompiler* findCompiler(const List<DownstreamCompiler*>& compilers, MatchType matchType, const DownstreamCompiler::Desc& desc); + typedef CompileOptions::FloatingPointMode FloatingPointMode; - static DownstreamCompiler* findCompiler(const List<DownstreamCompiler*>& compilers, SlangPassThrough type, const SemanticVersion& version); - static DownstreamCompiler* findCompiler(const List<DownstreamCompiler*>& compilers, const DownstreamCompiler::Desc& desc); - - /// Find all the compilers with the version - static void findVersions(const List<DownstreamCompiler*>& compilers, SlangPassThrough compiler, List<SemanticVersion>& versions); - - - /// Find the compiler closest to the desc - static DownstreamCompiler* findClosestCompiler(const List<DownstreamCompiler*>& compilers, const DownstreamCompilerMatchVersion& version); - static DownstreamCompiler* findClosestCompiler(const DownstreamCompilerSet* set, const DownstreamCompilerMatchVersion& version); - - /// Get the information on the compiler used to compile this source - static DownstreamCompilerMatchVersion getCompiledVersion(); - - static void updateDefault(DownstreamCompilerSet* set, SlangSourceLanguage sourceLanguage); - static void updateDefaults(DownstreamCompilerSet* set); - - static void setDefaultLocators(DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]); - - /// Attempts to determine what 'path' is and load appropriately. Is it a path to a shared library? Is it a directory holding the libraries? - /// Some downstream shared libraries need other shared libraries to be loaded before the main shared library, such that they are in the same directory - /// otherwise the shared library could come from some unwanted location. - /// dependentNames names shared libraries which should be attempted to be loaded in the path of the main shared library. - /// The list is optional (nullptr can be passed in), and the list is terminated by nullptr. - static SlangResult loadSharedLibrary(const String& path, ISlangSharedLibraryLoader* loader, const char*const* dependantNames, const char* libraryName, ComPtr<ISlangSharedLibrary>& outSharedLib); + typedef DownstreamProductFlag ProductFlag; + typedef DownstreamProductFlags ProductFlags; + typedef DownstreamDiagnostic Diagnostic; }; } diff --git a/source/compiler-core/slang-downstream-dep1.cpp b/source/compiler-core/slang-downstream-dep1.cpp new file mode 100644 index 000000000..e5eb4ac24 --- /dev/null +++ b/source/compiler-core/slang-downstream-dep1.cpp @@ -0,0 +1,75 @@ +// slang-downstream-dep1.cpp +#include "slang-downstream-dep1.h" + + +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); +} + +/* Hack to take into account downstream compilers shared library interface might need an adapter */ +/* static */SlangResult DownstreamUtil_Dep1::getDownstreamSharedLibrary(DownstreamCompileResult* downstreamResult, ComPtr<ISlangSharedLibrary>& outSharedLibrary) +{ + ComPtr<ISlangSharedLibrary> lib; + SLANG_RETURN_ON_FAIL(downstreamResult->getHostCallableSharedLibrary(lib)); + + if (SLANG_SUCCEEDED(lib->queryInterface(ISlangSharedLibrary::getTypeGuid(), (void**)outSharedLibrary.writeRef()))) + { + return SLANG_OK; + } + + ComPtr<ISlangSharedLibrary_Dep1> libDep1; + if (SLANG_SUCCEEDED(lib->queryInterface(ISlangSharedLibrary_Dep1::getTypeGuid(), (void**)libDep1.writeRef()))) + { + // Okay, we need to adapt for now + outSharedLibrary = new SharedLibraryDep1Adapter(libDep1); + return SLANG_OK; + } + return SLANG_E_NOT_FOUND; +} + +} diff --git a/source/compiler-core/slang-downstream-dep1.h b/source/compiler-core/slang-downstream-dep1.h new file mode 100644 index 000000000..fd0efd1e9 --- /dev/null +++ b/source/compiler-core/slang-downstream-dep1.h @@ -0,0 +1,56 @@ +#ifndef SLANG_DOWNSTREAM_DEP1_H +#define SLANG_DOWNSTREAM_DEP1_H + + +#include "slang-downstream-compiler.h" + +namespace Slang +{ + +// (DEPRECIATED) +class DownstreamCompiler_Dep1: public RefObject +{ +public: + typedef RefObject Super; + + /// Get the desc of this compiler + const DownstreamCompilerDesc& getDesc() const { return m_desc; } + /// Compile using the specified options. The result is in resOut + virtual SlangResult compile(const DownstreamCompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) = 0; + /// Some compilers have support converting a binary blob into disassembly. Output disassembly is held in the output blob + virtual SlangResult disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out); + + /// True if underlying compiler uses file system to communicate source + virtual bool isFileBased() = 0; + +protected: + + DownstreamCompilerDesc m_desc; +}; + +class DownstreamCompilerAdapter_Dep1 : public DownstreamCompilerBase +{ +public: + // IDownstreamCompiler + virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() SLANG_OVERRIDE { return m_dep->getDesc(); } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE { return m_dep->compile(options, outResult); } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE { return m_dep->disassemble(sourceBlobTarget, blob, blobSize, out); } + virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return m_dep->isFileBased(); } + + DownstreamCompilerAdapter_Dep1(DownstreamCompiler_Dep1* dep) : + m_dep(dep) + { + } + +protected: + RefPtr<DownstreamCompiler_Dep1> m_dep; +}; + +struct DownstreamUtil_Dep1 +{ + static SlangResult getDownstreamSharedLibrary(DownstreamCompileResult* downstreamResult, ComPtr<ISlangSharedLibrary>& outSharedLibrary); +}; + +} + +#endif diff --git a/source/compiler-core/slang-dxc-compiler.cpp b/source/compiler-core/slang-dxc-compiler.cpp index 771aa870a..5126e53cc 100644 --- a/source/compiler-core/slang-dxc-compiler.cpp +++ b/source/compiler-core/slang-dxc-compiler.cpp @@ -155,15 +155,15 @@ protected: IncludeSystem m_system; }; -class DXCDownstreamCompiler : public DownstreamCompiler +class DXCDownstreamCompiler : public DownstreamCompilerBase { public: - typedef DownstreamCompiler Super; + typedef DownstreamCompilerBase Super; - // DownstreamCompiler - virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; - virtual SlangResult disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE; - virtual bool isFileBased() SLANG_OVERRIDE { return false; } + // IDownstreamCompiler + virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } /// Must be called before use SlangResult init(ISlangSharedLibrary* library); @@ -174,7 +174,6 @@ protected: DxcCreateInstanceProc m_createInstance = nullptr; - ComPtr<ISlangSharedLibrary> m_sharedLibrary; }; @@ -560,10 +559,11 @@ SlangResult DXCDownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarg return SLANG_FAIL; } - RefPtr<DXCDownstreamCompiler> compiler(new DXCDownstreamCompiler); + auto compiler = new DXCDownstreamCompiler; + ComPtr<IDownstreamCompiler> compilerIntf(compiler); SLANG_RETURN_ON_FAIL(compiler->init(library)); - set->addCompiler(compiler); + set->addCompiler(compilerIntf); return SLANG_OK; } diff --git a/source/compiler-core/slang-dxc-compiler.h b/source/compiler-core/slang-dxc-compiler.h index a4e8eb4d7..4c915fb19 100644 --- a/source/compiler-core/slang-dxc-compiler.h +++ b/source/compiler-core/slang-dxc-compiler.h @@ -1,7 +1,7 @@ #ifndef SLANG_DXC_COMPILER_UTIL_H #define SLANG_DXC_COMPILER_UTIL_H -#include "slang-downstream-compiler.h" +#include "slang-downstream-compiler-util.h" #include "../core/slang-platform.h" diff --git a/source/compiler-core/slang-fxc-compiler.cpp b/source/compiler-core/slang-fxc-compiler.cpp index 2e78f8aa4..d9d506221 100644 --- a/source/compiler-core/slang-fxc-compiler.cpp +++ b/source/compiler-core/slang-fxc-compiler.cpp @@ -107,15 +107,15 @@ struct FxcIncludeHandler : ID3DInclude IncludeSystem m_system; }; -class FXCDownstreamCompiler : public DownstreamCompiler +class FXCDownstreamCompiler : public DownstreamCompilerBase { public: - typedef DownstreamCompiler Super; + typedef DownstreamCompilerBase Super; - // DownstreamCompiler - virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; - virtual SlangResult disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE; - virtual bool isFileBased() SLANG_OVERRIDE { return false; } + // IDownstreamCompiler + virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } /// Must be called before use SlangResult init(ISlangSharedLibrary* library); @@ -340,10 +340,12 @@ SlangResult FXCDownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarg return SLANG_FAIL; } - RefPtr<FXCDownstreamCompiler> compiler(new FXCDownstreamCompiler); + auto compiler = new FXCDownstreamCompiler; + ComPtr<IDownstreamCompiler> compilerInft(compiler); + SLANG_RETURN_ON_FAIL(compiler->init(library)); - set->addCompiler(compiler); + set->addCompiler(compilerInft); return SLANG_OK; } diff --git a/source/compiler-core/slang-fxc-compiler.h b/source/compiler-core/slang-fxc-compiler.h index 0718f6db4..856d2fc0e 100644 --- a/source/compiler-core/slang-fxc-compiler.h +++ b/source/compiler-core/slang-fxc-compiler.h @@ -1,7 +1,7 @@ #ifndef SLANG_FXC_COMPILER_UTIL_H #define SLANG_FXC_COMPILER_UTIL_H -#include "slang-downstream-compiler.h" +#include "slang-downstream-compiler-util.h" #include "../core/slang-platform.h" diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp index c1e6e8fbc..61cf5640a 100644 --- a/source/compiler-core/slang-gcc-compiler-util.cpp +++ b/source/compiler-core/slang-gcc-compiler-util.cpp @@ -42,7 +42,7 @@ static Index _findVersionEnd(const UnownedStringSlice& in) return len; } -/* static */SlangResult GCCDownstreamCompilerUtil::parseVersion(const UnownedStringSlice& text, const UnownedStringSlice& prefix, DownstreamCompiler::Desc& outDesc) +/* static */SlangResult GCCDownstreamCompilerUtil::parseVersion(const UnownedStringSlice& text, const UnownedStringSlice& prefix, DownstreamCompilerDesc& outDesc) { List<UnownedStringSlice> lines; StringUtil::calcLines(text, lines); @@ -90,7 +90,7 @@ static Index _findVersionEnd(const UnownedStringSlice& in) return SLANG_FAIL; } -SlangResult GCCDownstreamCompilerUtil::calcVersion(const ExecutableLocation& exe, DownstreamCompiler::Desc& outDesc) +SlangResult GCCDownstreamCompilerUtil::calcVersion(const ExecutableLocation& exe, DownstreamCompilerDesc& outDesc) { CommandLine cmdLine; cmdLine.setExecutableLocation(exe); @@ -675,15 +675,16 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::createCompiler(const ExecutableLocation& exe, RefPtr<DownstreamCompiler>& outCompiler) +/* static */SlangResult GCCDownstreamCompilerUtil::createCompiler(const ExecutableLocation& exe, ComPtr<IDownstreamCompiler>& outCompiler) { - DownstreamCompiler::Desc desc; + DownstreamCompilerDesc desc; SLANG_RETURN_ON_FAIL(GCCDownstreamCompilerUtil::calcVersion(exe, desc)); - RefPtr<CommandLineDownstreamCompiler> compiler(new GCCDownstreamCompiler(desc)); + auto compiler = new GCCDownstreamCompiler(desc); + ComPtr<IDownstreamCompiler> compilerIntf(compiler); compiler->m_cmdLine.setExecutableLocation(exe); - outCompiler = compiler; + outCompiler.swap(compilerIntf); return SLANG_OK; } @@ -691,7 +692,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse { SLANG_UNUSED(loader); - RefPtr<DownstreamCompiler> compiler; + ComPtr<IDownstreamCompiler> compiler; if (SLANG_SUCCEEDED(createCompiler(ExecutableLocation(path, "g++"), compiler))) { // A downstream compiler for Slang must currently support C++14 - such that @@ -719,7 +720,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse { SLANG_UNUSED(loader); - RefPtr<DownstreamCompiler> compiler; + ComPtr<IDownstreamCompiler> compiler; if (SLANG_SUCCEEDED(createCompiler(ExecutableLocation(path, "clang"), compiler))) { set->addCompiler(compiler); diff --git a/source/compiler-core/slang-gcc-compiler-util.h b/source/compiler-core/slang-gcc-compiler-util.h index b1ff791b0..ec8b21e03 100644 --- a/source/compiler-core/slang-gcc-compiler-util.h +++ b/source/compiler-core/slang-gcc-compiler-util.h @@ -1,7 +1,7 @@ #ifndef SLANG_GCC_COMPILER_UTIL_H #define SLANG_GCC_COMPILER_UTIL_H -#include "slang-downstream-compiler.h" +#include "slang-downstream-compiler-util.h" namespace Slang { @@ -10,10 +10,10 @@ namespace Slang struct GCCDownstreamCompilerUtil : public DownstreamCompilerBaseUtil { /// Extracts version number into desc from text (assumes gcc/clang -v layout with a line with version) - static SlangResult parseVersion(const UnownedStringSlice& text, const UnownedStringSlice& prefix, DownstreamCompiler::Desc& outDesc); + static SlangResult parseVersion(const UnownedStringSlice& text, const UnownedStringSlice& prefix, DownstreamCompilerDesc& outDesc); /// Runs the exe, and extracts the version info into outDesc - static SlangResult calcVersion(const ExecutableLocation& exe, DownstreamCompiler::Desc& outDesc); + static SlangResult calcVersion(const ExecutableLocation& exe, DownstreamCompilerDesc& outDesc); /// Calculate gcc family compilers (including clang) cmdLine arguments from options static SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine); @@ -29,7 +29,7 @@ struct GCCDownstreamCompilerUtil : public DownstreamCompilerBaseUtil /// Given the exe location, creates a DownstreamCompiler. /// Note! Invoke/s the compiler to determine the compiler version number. - static SlangResult createCompiler(const ExecutableLocation& exe, RefPtr<DownstreamCompiler>& outCompiler); + static SlangResult createCompiler(const ExecutableLocation& exe, ComPtr<IDownstreamCompiler>& outCompiler); /// Finds GCC compiler/s and adds them to the set static SlangResult locateGCCCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); @@ -48,7 +48,7 @@ public: virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE { return Util::calcArgs(options, cmdLine); } virtual SlangResult parseOutput(const ExecuteResult& exeResult, DownstreamDiagnostics& output) SLANG_OVERRIDE { return Util::parseOutput(exeResult, output); } virtual SlangResult calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath) SLANG_OVERRIDE { return Util::calcModuleFilePath(options, outPath); } - virtual SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, List<String>& outPaths) SLANG_OVERRIDE { return Util::calcCompileProducts(options, flags, outPaths); } + virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags flags, List<String>& outPaths) SLANG_OVERRIDE { return Util::calcCompileProducts(options, flags, outPaths); } GCCDownstreamCompiler(const Desc& desc):Super(desc) {} }; diff --git a/source/compiler-core/slang-glslang-compiler.cpp b/source/compiler-core/slang-glslang-compiler.cpp index 70743f9d9..b4e3d915d 100644 --- a/source/compiler-core/slang-glslang-compiler.cpp +++ b/source/compiler-core/slang-glslang-compiler.cpp @@ -34,15 +34,15 @@ namespace Slang #if SLANG_ENABLE_GLSLANG_SUPPORT -class GlslangDownstreamCompiler : public DownstreamCompiler +class GlslangDownstreamCompiler : public DownstreamCompilerBase { public: - typedef DownstreamCompiler Super; + typedef DownstreamCompilerBase Super; - // DownstreamCompiler - virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; - virtual SlangResult disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE; - virtual bool isFileBased() SLANG_OVERRIDE { return false; } + // IDownstreamCompiler + virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } /// Must be called before use SlangResult init(ISlangSharedLibrary* library); @@ -163,7 +163,7 @@ SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& options, Re SemanticVersion spirvVersion; for (const auto& capabilityVersion : options.requiredCapabilityVersions) { - if (capabilityVersion.kind == DownstreamCompiler::CapabilityVersion::Kind::SPIRV) + if (capabilityVersion.kind == DownstreamCompileOptions::CapabilityVersion::Kind::SPIRV) { if (capabilityVersion.version > spirvVersion) { @@ -275,10 +275,11 @@ SlangResult GlslangDownstreamCompiler::disassemble(SlangCompileTarget sourceBlob return SLANG_FAIL; } - RefPtr<GlslangDownstreamCompiler> compiler(new GlslangDownstreamCompiler); + auto compiler = new GlslangDownstreamCompiler; + ComPtr<IDownstreamCompiler> compilerIntf(compiler); SLANG_RETURN_ON_FAIL(compiler->init(library)); - set->addCompiler(compiler); + set->addCompiler(compilerIntf); return SLANG_OK; } diff --git a/source/compiler-core/slang-glslang-compiler.h b/source/compiler-core/slang-glslang-compiler.h index 917315af8..ea4352a0b 100644 --- a/source/compiler-core/slang-glslang-compiler.h +++ b/source/compiler-core/slang-glslang-compiler.h @@ -1,7 +1,7 @@ #ifndef SLANG_GLSLANG_COMPILER_UTIL_H #define SLANG_GLSLANG_COMPILER_UTIL_H -#include "slang-downstream-compiler.h" +#include "slang-downstream-compiler-util.h" #include "../core/slang-platform.h" diff --git a/source/compiler-core/slang-llvm-compiler.cpp b/source/compiler-core/slang-llvm-compiler.cpp index 9b301ffab..e143500c0 100644 --- a/source/compiler-core/slang-llvm-compiler.cpp +++ b/source/compiler-core/slang-llvm-compiler.cpp @@ -1,6 +1,8 @@ // slang-llvm-compiler.cpp #include "slang-llvm-compiler.h" +#include "slang-downstream-dep1.h" + #include "../core/slang-common.h" #include "../../slang-com-helper.h" @@ -34,17 +36,19 @@ namespace Slang return SLANG_FAIL; } - typedef SlangResult(*CreateDownstreamCompilerFunc)(RefPtr<DownstreamCompiler>& out); + typedef SlangResult(*CreateDownstreamCompilerFunc_Dep1)(RefPtr<DownstreamCompiler_Dep1>& out); - auto fn = (CreateDownstreamCompilerFunc)library->findFuncByName("createLLVMDownstreamCompiler"); + auto fn = (CreateDownstreamCompilerFunc_Dep1)library->findFuncByName("createLLVMDownstreamCompiler"); if (!fn) { return SLANG_FAIL; } - RefPtr<DownstreamCompiler> downstreamCompiler; + RefPtr<DownstreamCompiler_Dep1> downstreamCompilerDep1; + + SLANG_RETURN_ON_FAIL(fn(downstreamCompilerDep1)); - SLANG_RETURN_ON_FAIL(fn(downstreamCompiler)); + ComPtr<IDownstreamCompiler> downstreamCompiler(new DownstreamCompilerAdapter_Dep1(downstreamCompilerDep1)); set->addSharedLibrary(library); set->addCompiler(downstreamCompiler); diff --git a/source/compiler-core/slang-llvm-compiler.h b/source/compiler-core/slang-llvm-compiler.h index 4044aef0f..a05e1fed9 100644 --- a/source/compiler-core/slang-llvm-compiler.h +++ b/source/compiler-core/slang-llvm-compiler.h @@ -1,7 +1,7 @@ #ifndef SLANG_LLVM_COMPILER_UTIL_H #define SLANG_LLVM_COMPILER_UTIL_H -#include "slang-downstream-compiler.h" +#include "slang-downstream-compiler-util.h" #include "../core/slang-platform.h" diff --git a/source/compiler-core/slang-nvrtc-compiler.cpp b/source/compiler-core/slang-nvrtc-compiler.cpp index 3f285ada2..0cc208854 100644 --- a/source/compiler-core/slang-nvrtc-compiler.cpp +++ b/source/compiler-core/slang-nvrtc-compiler.cpp @@ -92,14 +92,14 @@ static SlangResult _asResult(nvrtcResult res) } } -class NVRTCDownstreamCompiler : public DownstreamCompiler +class NVRTCDownstreamCompiler : public DownstreamCompilerBase { public: - typedef DownstreamCompiler Super; + typedef DownstreamCompilerBase Super; - // DownstreamCompiler - virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; - virtual bool isFileBased() SLANG_OVERRIDE { return false; } + // IDownstreamCompiler + virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } /// Must be called before use SlangResult init(ISlangSharedLibrary* library); @@ -593,9 +593,9 @@ SlangResult NVRTCDownstreamCompiler::_findIncludePath(String& outPath) return SLANG_E_NOT_FOUND; } -SlangResult NVRTCDownstreamCompiler::_maybeAddHalfSupport(const CompileOptions& options, CommandLine& ioCmdLine) +SlangResult NVRTCDownstreamCompiler::_maybeAddHalfSupport(const DownstreamCompileOptions& options, CommandLine& ioCmdLine) { - if ((options.flags & CompileOptions::Flag::EnableFloat16) == 0) + if ((options.flags & DownstreamCompileOptions::Flag::EnableFloat16) == 0) { return SLANG_OK; } @@ -637,7 +637,7 @@ SlangResult NVRTCDownstreamCompiler::_maybeAddHalfSupport(const CompileOptions& return SLANG_OK; } -SlangResult NVRTCDownstreamCompiler::compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) +SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) { // This compiler doesn't read files, they should be read externally and stored in sourceContents/sourceContentsPath if (options.sourceFiles.getCount() > 0) @@ -742,7 +742,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const CompileOptions& options, RefP // for (const auto& capabilityVersion : options.requiredCapabilityVersions) { - if (capabilityVersion.kind == DownstreamCompiler::CapabilityVersion::Kind::CUDASM) + if (capabilityVersion.kind == DownstreamCompileOptions::CapabilityVersion::Kind::CUDASM) { if (capabilityVersion.version > version) { @@ -967,10 +967,11 @@ static SlangResult _findAndLoadNVRTC(ISlangSharedLibraryLoader* loader, ComPtr<I return SLANG_FAIL; } - RefPtr<NVRTCDownstreamCompiler> compiler(new NVRTCDownstreamCompiler); + auto compiler = new NVRTCDownstreamCompiler; + ComPtr<IDownstreamCompiler> compilerIntf(compiler); SLANG_RETURN_ON_FAIL(compiler->init(library)); - set->addCompiler(compiler); + set->addCompiler(compilerIntf); return SLANG_OK; } diff --git a/source/compiler-core/slang-nvrtc-compiler.h b/source/compiler-core/slang-nvrtc-compiler.h index 48c6d4da6..215fc4c23 100644 --- a/source/compiler-core/slang-nvrtc-compiler.h +++ b/source/compiler-core/slang-nvrtc-compiler.h @@ -1,7 +1,7 @@ #ifndef SLANG_NVRTC_COMPILER_UTIL_H #define SLANG_NVRTC_COMPILER_UTIL_H -#include "slang-downstream-compiler.h" +#include "slang-downstream-compiler-util.h" #include "../core/slang-platform.h" diff --git a/source/compiler-core/slang-visual-studio-compiler-util.h b/source/compiler-core/slang-visual-studio-compiler-util.h index 018dde212..6c3011e7c 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.h +++ b/source/compiler-core/slang-visual-studio-compiler-util.h @@ -1,7 +1,7 @@ #ifndef SLANG_VISUAL_STUDIO_COMPILER_UTIL_H #define SLANG_VISUAL_STUDIO_COMPILER_UTIL_H -#include "slang-downstream-compiler.h" +#include "slang-downstream-compiler-util.h" namespace Slang { @@ -31,7 +31,7 @@ public: virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE { return Util::calcArgs(options, cmdLine); } virtual SlangResult parseOutput(const ExecuteResult& exeResult, DownstreamDiagnostics& output) SLANG_OVERRIDE { return Util::parseOutput(exeResult, output); } virtual SlangResult calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath) SLANG_OVERRIDE { return Util::calcModuleFilePath(options, outPath); } - virtual SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags productFlags, List<String>& outPaths) SLANG_OVERRIDE { return Util::calcCompileProducts(options, productFlags, outPaths); } + virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags productFlags, List<String>& outPaths) SLANG_OVERRIDE { return Util::calcCompileProducts(options, productFlags, outPaths); } VisualStudioDownstreamCompiler(const Desc& desc):Super(desc) {} }; diff --git a/source/compiler-core/windows/slang-win-visual-studio-util.cpp b/source/compiler-core/windows/slang-win-visual-studio-util.cpp index b0b634d72..d4c72e100 100644 --- a/source/compiler-core/windows/slang-win-visual-studio-util.cpp +++ b/source/compiler-core/windows/slang-win-visual-studio-util.cpp @@ -454,14 +454,15 @@ static SlangResult _findVersionsWithRegistery(List<WinVisualStudioUtil::VersionP for (const auto& versionPath : versionPaths) { // Turn into a desc - const DownstreamCompiler::Desc desc(SLANG_PASS_THROUGH_VISUAL_STUDIO, versionPath.version); + const DownstreamCompilerDesc desc(SLANG_PASS_THROUGH_VISUAL_STUDIO, versionPath.version); // If not in set add it if (!set->getCompiler(desc)) { - RefPtr<CommandLineDownstreamCompiler> compiler = new VisualStudioDownstreamCompiler(desc); + auto compiler = new VisualStudioDownstreamCompiler(desc); + ComPtr<IDownstreamCompiler> compilerIntf(compiler); calcExecuteCompilerArgs(versionPath, compiler->m_cmdLine); - set->addCompiler(compiler); + set->addCompiler(compilerIntf); } } diff --git a/source/compiler-core/windows/slang-win-visual-studio-util.h b/source/compiler-core/windows/slang-win-visual-studio-util.h index 4dfac8f34..d69325f02 100644 --- a/source/compiler-core/windows/slang-win-visual-studio-util.h +++ b/source/compiler-core/windows/slang-win-visual-studio-util.h @@ -6,7 +6,7 @@ #include "../../core/slang-process-util.h" -#include "../slang-downstream-compiler.h" +#include "../slang-downstream-compiler-util.h" namespace Slang { diff --git a/source/slang/slang-artifact-output-util.cpp b/source/slang/slang-artifact-output-util.cpp index 2694fcb10..ccf49ed30 100644 --- a/source/slang/slang-artifact-output-util.cpp +++ b/source/slang/slang-artifact-output-util.cpp @@ -51,7 +51,7 @@ static CodeGenTarget _getDisassemblyCodeGenTarget(const ArtifactDesc& desc) auto downstreamCompiler = getDownstreamCompilerRequiredForTarget(target); // Get the required downstream compiler - DownstreamCompiler* compiler = session->getOrLoadDownstreamCompiler(downstreamCompiler, sink); + IDownstreamCompiler* compiler = session->getOrLoadDownstreamCompiler(downstreamCompiler, sink); if (!compiler) { diff --git a/source/slang/slang-check.cpp b/source/slang/slang-check.cpp index 633dec215..bcc74a6d0 100644 --- a/source/slang/slang-check.cpp +++ b/source/slang/slang-check.cpp @@ -83,7 +83,7 @@ namespace Slang m_downstreamCompilers[int(type)].setNull(); } - DownstreamCompiler* Session::getOrLoadDownstreamCompiler(PassThroughMode type, DiagnosticSink* sink) + IDownstreamCompiler* Session::getOrLoadDownstreamCompiler(PassThroughMode type, DiagnosticSink* sink) { if (m_downstreamCompilerInitialized & (1 << int(type))) { @@ -144,7 +144,7 @@ namespace Slang DownstreamCompilerUtil::updateDefaults(m_downstreamCompilerSet); } - DownstreamCompiler* compiler = nullptr; + IDownstreamCompiler* compiler = nullptr; if (type == PassThroughMode::GenericCCpp) { @@ -152,7 +152,7 @@ namespace Slang } else { - DownstreamCompiler::Desc desc; + DownstreamCompilerDesc desc; desc.type = SlangPassThrough(type); compiler = DownstreamCompilerUtil::findCompiler(m_downstreamCompilerSet, DownstreamCompilerUtil::MatchType::Newest, desc); } diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 02d312b61..d175277c8 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -828,7 +828,7 @@ namespace Slang /// and generally there will not be a match with emitted source. /// /// This test is only used for pass through mode. - static bool _useEmittedSource(DownstreamCompiler* compiler, TranslationUnitRequest* translationUnit) + static bool _useEmittedSource(IDownstreamCompiler* compiler, TranslationUnitRequest* translationUnit) { // We only bother if it's a file based compiler. if (compiler->isFileBased()) @@ -952,7 +952,7 @@ namespace Slang SLANG_ASSERT(compilerType != PassThroughMode::None); // Get the required downstream compiler - DownstreamCompiler* compiler = session->getOrLoadDownstreamCompiler(compilerType, sink); + IDownstreamCompiler* compiler = session->getOrLoadDownstreamCompiler(compilerType, sink); if (!compiler) { auto compilerName = TypeTextUtil::getPassThroughAsHumanText((SlangPassThrough)compilerType); @@ -963,7 +963,7 @@ namespace Slang Dictionary<String, String> preprocessorDefinitions; List<String> includePaths; - typedef DownstreamCompiler::CompileOptions CompileOptions; + typedef DownstreamCompileOptions CompileOptions; CompileOptions options; // Set compiler specific args @@ -1115,8 +1115,8 @@ namespace Slang if (cudaTracker->m_smVersion.isSet()) { - DownstreamCompiler::CapabilityVersion version; - version.kind = DownstreamCompiler::CapabilityVersion::Kind::CUDASM; + DownstreamCompileOptions::CapabilityVersion version; + version.kind = DownstreamCompileOptions::CapabilityVersion::Kind::CUDASM; version.version = cudaTracker->m_smVersion; options.requiredCapabilityVersions.add(version); @@ -1129,8 +1129,8 @@ namespace Slang } else if (GLSLExtensionTracker* glslTracker = as<GLSLExtensionTracker>(extensionTracker)) { - DownstreamCompiler::CapabilityVersion version; - version.kind = DownstreamCompiler::CapabilityVersion::Kind::SPIRV; + DownstreamCompileOptions::CapabilityVersion version; + version.kind = DownstreamCompileOptions::CapabilityVersion::Kind::SPIRV; version.version = glslTracker->getSPIRVVersion(); options.requiredCapabilityVersions.add(version); @@ -1260,28 +1260,28 @@ namespace Slang switch (linkage->optimizationLevel) { - case OptimizationLevel::None: options.optimizationLevel = DownstreamCompiler::OptimizationLevel::None; break; - case OptimizationLevel::Default: options.optimizationLevel = DownstreamCompiler::OptimizationLevel::Default; break; - case OptimizationLevel::High: options.optimizationLevel = DownstreamCompiler::OptimizationLevel::High; break; - case OptimizationLevel::Maximal: options.optimizationLevel = DownstreamCompiler::OptimizationLevel::Maximal; break; + case OptimizationLevel::None: options.optimizationLevel = DownstreamCompileOptions::OptimizationLevel::None; break; + case OptimizationLevel::Default: options.optimizationLevel = DownstreamCompileOptions::OptimizationLevel::Default; break; + case OptimizationLevel::High: options.optimizationLevel = DownstreamCompileOptions::OptimizationLevel::High; break; + case OptimizationLevel::Maximal: options.optimizationLevel = DownstreamCompileOptions::OptimizationLevel::Maximal; break; default: SLANG_ASSERT(!"Unhandled optimization level"); break; } switch (linkage->debugInfoLevel) { - case DebugInfoLevel::None: options.debugInfoType = DownstreamCompiler::DebugInfoType::None; break; - case DebugInfoLevel::Minimal: options.debugInfoType = DownstreamCompiler::DebugInfoType::Minimal; break; + case DebugInfoLevel::None: options.debugInfoType = DownstreamCompileOptions::DebugInfoType::None; break; + case DebugInfoLevel::Minimal: options.debugInfoType = DownstreamCompileOptions::DebugInfoType::Minimal; break; - case DebugInfoLevel::Standard: options.debugInfoType = DownstreamCompiler::DebugInfoType::Standard; break; - case DebugInfoLevel::Maximal: options.debugInfoType = DownstreamCompiler::DebugInfoType::Maximal; break; + case DebugInfoLevel::Standard: options.debugInfoType = DownstreamCompileOptions::DebugInfoType::Standard; break; + case DebugInfoLevel::Maximal: options.debugInfoType = DownstreamCompileOptions::DebugInfoType::Maximal; break; default: SLANG_ASSERT(!"Unhandled debug level"); break; } switch( getTargetReq()->getFloatingPointMode()) { - case FloatingPointMode::Default: options.floatingPointMode = DownstreamCompiler::FloatingPointMode::Default; break; - case FloatingPointMode::Precise: options.floatingPointMode = DownstreamCompiler::FloatingPointMode::Precise; break; - case FloatingPointMode::Fast: options.floatingPointMode = DownstreamCompiler::FloatingPointMode::Fast; break; + case FloatingPointMode::Default: options.floatingPointMode = DownstreamCompileOptions::FloatingPointMode::Default; break; + case FloatingPointMode::Precise: options.floatingPointMode = DownstreamCompileOptions::FloatingPointMode::Precise; break; + case FloatingPointMode::Fast: options.floatingPointMode = DownstreamCompileOptions::FloatingPointMode::Fast; break; default: SLANG_ASSERT(!"Unhandled floating point mode"); } @@ -1311,7 +1311,7 @@ namespace Slang break; case Stage::Compute: - options.pipelineType = DownstreamCompiler::PipelineType::Compute; + options.pipelineType = DownstreamCompileOptions::PipelineType::Compute; break; case Stage::Vertex: @@ -1319,7 +1319,7 @@ namespace Slang case Stage::Domain: case Stage::Geometry: case Stage::Fragment: - options.pipelineType = DownstreamCompiler::PipelineType::Rasterization; + options.pipelineType = DownstreamCompileOptions::PipelineType::Rasterization; break; case Stage::RayGeneration: @@ -1328,7 +1328,7 @@ namespace Slang case Stage::ClosestHit: case Stage::Miss: case Stage::Callable: - options.pipelineType = DownstreamCompiler::PipelineType::RayTracing; + options.pipelineType = DownstreamCompileOptions::PipelineType::RayTracing; break; } } @@ -1341,7 +1341,7 @@ namespace Slang { for(auto& def : preprocessorDefinitions) { - DownstreamCompiler::Define define; + DownstreamCompileOptions::Define define; define.nameWithSig = def.Key; define.value = def.Value; @@ -1366,7 +1366,7 @@ namespace Slang if (diagnostics.diagnostics.getCount()) { StringBuilder compilerText; - compiler->getDesc().appendAsText(compilerText); + DownstreamCompilerUtil::appendAsText(compiler->getDesc(), compilerText); StringBuilder builder; diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 6b79b2679..97111f540 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -7,6 +7,8 @@ #include "../core/slang-file-system.h" #include "../compiler-core/slang-downstream-compiler.h" +#include "../compiler-core/slang-downstream-compiler-util.h" + #include "../compiler-core/slang-name.h" #include "../compiler-core/slang-include-system.h" #include "../compiler-core/slang-command-line-args.h" @@ -2802,7 +2804,7 @@ namespace Slang } /// Get the downstream compiler for a transition - DownstreamCompiler* getDownstreamCompiler(CodeGenTarget source, CodeGenTarget target); + IDownstreamCompiler* getDownstreamCompiler(CodeGenTarget source, CodeGenTarget target); Scope* baseLanguageScope = nullptr; Scope* coreLanguageScope = nullptr; @@ -2856,7 +2858,7 @@ namespace Slang void _setSharedLibraryLoader(ISlangSharedLibraryLoader* loader); /// Will try to load the library by specified name (using the set loader), if not one already available. - DownstreamCompiler* getOrLoadDownstreamCompiler(PassThroughMode type, DiagnosticSink* sink); + IDownstreamCompiler* getOrLoadDownstreamCompiler(PassThroughMode type, DiagnosticSink* sink); /// Will unload the specified shared library if it's currently loaded void resetDownstreamCompiler(PassThroughMode type); @@ -2883,7 +2885,7 @@ namespace Slang int m_downstreamCompilerInitialized = 0; RefPtr<DownstreamCompilerSet> m_downstreamCompilerSet; ///< Information about all available downstream compilers. - RefPtr<DownstreamCompiler> m_downstreamCompilers[int(PassThroughMode::CountOf)]; ///< A downstream compiler for a pass through + ComPtr<IDownstreamCompiler> m_downstreamCompilers[int(PassThroughMode::CountOf)]; ///< A downstream compiler for a pass through DownstreamCompilerLocatorFunc m_downstreamCompilerLocators[int(PassThroughMode::CountOf)]; Name* m_completionTokenName = nullptr; ///< The name of a completion request token. diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index 2a1b78833..4cbfa97ab 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -837,7 +837,7 @@ Result linkAndOptimizeIR( #endif validateIRModuleIfEnabled(codeGenContext, irModule); - auto metadata = new PostEmitMetadata; + auto metadata = new PostEmitMetadataImpl; outLinkedIR.metadata = metadata; collectMetadata(irModule, *metadata); diff --git a/source/slang/slang-ir-metadata.cpp b/source/slang/slang-ir-metadata.cpp index 7d4694ec5..b6ab2b922 100644 --- a/source/slang/slang-ir-metadata.cpp +++ b/source/slang/slang-ir-metadata.cpp @@ -39,7 +39,7 @@ static void _insertBinding(List<ShaderBindingRange>& ranges, LayoutResourceKind } // Collects the metadata from the provided IR module, saves it in outMetadata. -void collectMetadata(const IRModule* irModule, PostEmitMetadata& outMetadata) +void collectMetadata(const IRModule* irModule, PostEmitMetadataImpl& outMetadata) { // Scan the instructions looking for global resource declarations for (const auto& inst : irModule->getGlobalInsts()) diff --git a/source/slang/slang-ir-metadata.h b/source/slang/slang-ir-metadata.h index e72e10a94..f5e3229ae 100644 --- a/source/slang/slang-ir-metadata.h +++ b/source/slang/slang-ir-metadata.h @@ -4,9 +4,9 @@ namespace Slang { -class PostEmitMetadata; +class PostEmitMetadataImpl; struct IRModule; -void collectMetadata(const IRModule* irModule, PostEmitMetadata& outMetadata); +void collectMetadata(const IRModule* irModule, PostEmitMetadataImpl& outMetadata); } diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 710cc0b45..b86617f1f 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -695,7 +695,7 @@ SLANG_NO_THROW const char* SLANG_MCALL Session::getBuildTagString() SLANG_NO_THROW SlangResult SLANG_MCALL Session::setDefaultDownstreamCompiler(SlangSourceLanguage sourceLanguage, SlangPassThrough defaultCompiler) { - if (DownstreamCompiler::canCompile(defaultCompiler, sourceLanguage)) + if (DownstreamCompilerInfo::canCompile(defaultCompiler, sourceLanguage)) { m_defaultDownstreamCompilers[int(sourceLanguage)] = PassThroughMode(defaultCompiler); return SLANG_OK; @@ -740,8 +740,7 @@ SlangPassThrough Session::getDownstreamCompilerForTransition(SlangCompileTarget (source == CodeGenTarget::CSource || source == CodeGenTarget::CPPSource)) { // We prefer LLVM if it's available - DownstreamCompiler* llvm = getOrLoadDownstreamCompiler(PassThroughMode::LLVM, nullptr); - if (llvm) + if (auto llvm = getOrLoadDownstreamCompiler(PassThroughMode::LLVM, nullptr)) { return SLANG_PASS_THROUGH_LLVM; } @@ -760,7 +759,7 @@ SlangPassThrough Session::getDownstreamCompilerForTransition(SlangCompileTarget return SLANG_PASS_THROUGH_NONE; } -DownstreamCompiler* Session::getDownstreamCompiler(CodeGenTarget source, CodeGenTarget target) +IDownstreamCompiler* Session::getDownstreamCompiler(CodeGenTarget source, CodeGenTarget target) { PassThroughMode compilerType = (PassThroughMode)getDownstreamCompilerForTransition(SlangCompileTarget(source), SlangCompileTarget(target)); return getOrLoadDownstreamCompiler(compilerType, nullptr); @@ -5054,7 +5053,7 @@ SlangResult EndToEndCompileRequest::isParameterLocationUsed(Int entryPointIndex, // TODO: optimize this with a binary search through a sorted list - for (const auto& range : metadata->getBindingRanges()) + for (const auto& range : metadata->getUsedBindingRanges()) { if (range.containsBinding((slang::ParameterCategory)category, spaceIndex, registerIndex)) { |
