summaryrefslogtreecommitdiffstats
path: root/source/compiler-core/slang-downstream-compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/compiler-core/slang-downstream-compiler.cpp')
-rw-r--r--source/compiler-core/slang-downstream-compiler.cpp552
1 files changed, 27 insertions, 525 deletions
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);
- }
-}
-
}