diff options
Diffstat (limited to 'source/compiler-core/slang-downstream-compiler.cpp')
| -rw-r--r-- | source/compiler-core/slang-downstream-compiler.cpp | 552 |
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); - } -} - } |
