diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2019-12-10 10:02:19 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-12-10 10:02:19 -0500 |
| commit | 79ec0cfdb5f3461c763e0bf712cf42eb87fccb90 (patch) | |
| tree | cf0c3c0b6e7f10d3a29930cd3aeef586298d4234 /source | |
| parent | 2e52217cb870b4101c1639fed78224f89bf119b3 (diff) | |
DownstreamCompiler abstraction (#1149)
* CPPCompiler -> DownstreamCompiler
* Added DownstreamCompileResult to start abstraction such that we don't need files.
* * Split out slang-blob.cpp
* Made CompileResult hold a DownstreamCompileResult - for access to binary or ISlangSharedLibrary
* Keep temporary files in scope.
* Add a hash to the hex dump stream.
* Move all file tracking into DownstreamCompiler.
Diffstat (limited to 'source')
27 files changed, 1421 insertions, 1284 deletions
diff --git a/source/core/core.vcxproj b/source/core/core.vcxproj index e0cc33569..b0f33f2a2 100644 --- a/source/core/core.vcxproj +++ b/source/core/core.vcxproj @@ -174,10 +174,11 @@ <ClInclude Include="slang-array-view.h" /> <ClInclude Include="slang-array.h" /> <ClInclude Include="slang-basic.h" /> + <ClInclude Include="slang-blob.h" /> <ClInclude Include="slang-byte-encode-util.h" /> <ClInclude Include="slang-common.h" /> - <ClInclude Include="slang-cpp-compiler.h" /> <ClInclude Include="slang-dictionary.h" /> + <ClInclude Include="slang-downstream-compiler.h" /> <ClInclude Include="slang-exception.h" /> <ClInclude Include="slang-free-list.h" /> <ClInclude Include="slang-gcc-compiler-util.h" /> @@ -212,8 +213,9 @@ <ClInclude Include="windows\slang-win-visual-studio-util.h" /> </ItemGroup> <ItemGroup> + <ClCompile Include="slang-blob.cpp" /> <ClCompile Include="slang-byte-encode-util.cpp" /> - <ClCompile Include="slang-cpp-compiler.cpp" /> + <ClCompile Include="slang-downstream-compiler.cpp" /> <ClCompile Include="slang-free-list.cpp" /> <ClCompile Include="slang-gcc-compiler-util.cpp" /> <ClCompile Include="slang-hex-dump-util.cpp" /> diff --git a/source/core/core.vcxproj.filters b/source/core/core.vcxproj.filters index 6042a1c22..44d199771 100644 --- a/source/core/core.vcxproj.filters +++ b/source/core/core.vcxproj.filters @@ -21,16 +21,19 @@ <ClInclude Include="slang-basic.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="slang-blob.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="slang-byte-encode-util.h"> <Filter>Header Files</Filter> </ClInclude> <ClInclude Include="slang-common.h"> <Filter>Header Files</Filter> </ClInclude> - <ClInclude Include="slang-cpp-compiler.h"> + <ClInclude Include="slang-dictionary.h"> <Filter>Header Files</Filter> </ClInclude> - <ClInclude Include="slang-dictionary.h"> + <ClInclude Include="slang-downstream-compiler.h"> <Filter>Header Files</Filter> </ClInclude> <ClInclude Include="slang-exception.h"> @@ -131,10 +134,13 @@ </ClInclude> </ItemGroup> <ItemGroup> + <ClCompile Include="slang-blob.cpp"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="slang-byte-encode-util.cpp"> <Filter>Source Files</Filter> </ClCompile> - <ClCompile Include="slang-cpp-compiler.cpp"> + <ClCompile Include="slang-downstream-compiler.cpp"> <Filter>Source Files</Filter> </ClCompile> <ClCompile Include="slang-free-list.cpp"> diff --git a/source/core/slang-blob.cpp b/source/core/slang-blob.cpp new file mode 100644 index 000000000..4421db09a --- /dev/null +++ b/source/core/slang-blob.cpp @@ -0,0 +1,14 @@ +#include "slang-blob.h" + +namespace Slang { + +// Allocate static const storage for the various interface IDs that the Slang API needs to expose +static const Guid IID_ISlangUnknown = SLANG_UUID_ISlangUnknown; +static const Guid IID_ISlangBlob = SLANG_UUID_ISlangBlob; + +ISlangUnknown* BlobBase::getInterface(const Guid& guid) +{ + return (guid == IID_ISlangUnknown || guid == IID_ISlangBlob) ? static_cast<ISlangBlob*>(this) : nullptr; +} + +} // namespace Slang diff --git a/source/core/slang-blob.h b/source/core/slang-blob.h new file mode 100644 index 000000000..aab131a36 --- /dev/null +++ b/source/core/slang-blob.h @@ -0,0 +1,126 @@ +#ifndef SLANG_CORE_BLOB_H +#define SLANG_CORE_BLOB_H + +#include "../../slang.h" + +#include "slang-string.h" +#include "slang-list.h" + +#include <stdarg.h> + +#include "../../slang-com-helper.h" +#include "../../slang-com-ptr.h" + +namespace Slang { + +/** Base class for simple blobs. +*/ +class BlobBase : public ISlangBlob, public RefObject +{ +public: + // ISlangUnknown + SLANG_REF_OBJECT_IUNKNOWN_ALL + +protected: + ISlangUnknown* getInterface(const Guid& guid); +}; + +/** A blob that uses a `String` for its storage. +*/ +class StringBlob : public BlobBase +{ +public: + // ISlangBlob + SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_string.getBuffer(); } + SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_string.getLength(); } + + /// Get the contained string + SLANG_FORCE_INLINE const String& getString() const { return m_string; } + + explicit StringBlob(String const& string) + : m_string(string) + {} + +protected: + String m_string; +}; + +class ListBlob : public BlobBase +{ +public: + typedef BlobBase Super; + typedef ListBlob ThisType; + + // ISlangBlob + SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_data.getBuffer(); } + SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_data.getCount(); } + + ListBlob() {} + + ListBlob(const List<uint8_t>& data): m_data(data) {} + // Move ctor + ListBlob(List<uint8_t>&& data): m_data(data) {} + + static RefPtr<ListBlob> moveCreate(List<uint8_t>& data) { return new ListBlob(_Move(data)); } + + List<uint8_t> m_data; + +protected: + void operator=(const ThisType& rhs) = delete; +}; + +/** A blob that manages some raw data that it owns. +*/ +class RawBlob : public BlobBase +{ +public: + // ISlangBlob + SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_data; } + SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_size; } + + // Ctor + RawBlob(const void* data, size_t size) : + m_size(size) + { + m_data = malloc(size); + memcpy(m_data, data, size); + } + ~RawBlob() + { + free(m_data); + } + +protected: + void* m_data; + size_t m_size; +}; + +/// Create a blob that will retain (a copy of) raw data. +/// +inline ComPtr<ISlangBlob> createRawBlob(void const* inData, size_t size) +{ + return ComPtr<ISlangBlob>(new RawBlob(inData, size)); +} + +class ScopeRefObjectBlob : public BlobBase +{ +public: + // ISlangBlob + SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_blob->getBufferPointer(); } + SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_blob->getBufferSize(); } + + // Ctor + ScopeRefObjectBlob(ISlangBlob* blob, RefObject* scope) : + m_blob(blob), + m_scope(scope) + { + } + +protected: + RefPtr<RefObject> m_scope; + ComPtr<ISlangBlob> m_blob; +}; + +} // namespace Slang + +#endif // SLANG_CORE_BLOB_H diff --git a/source/core/slang-cpp-compiler.cpp b/source/core/slang-cpp-compiler.cpp deleted file mode 100644 index 7ae474fe7..000000000 --- a/source/core/slang-cpp-compiler.cpp +++ /dev/null @@ -1,436 +0,0 @@ -// slang-cpp-compiler.cpp -#include "slang-cpp-compiler.h" - -#include "slang-common.h" -#include "../../slang-com-helper.h" -#include "slang-string-util.h" - -#include "slang-io.h" -#include "slang-shared-library.h" - -// if Visual Studio import the visual studio platform specific header -#if SLANG_VC -# include "windows/slang-win-visual-studio-util.h" -#endif - -#include "slang-visual-studio-compiler-util.h" -#include "slang-gcc-compiler-util.h" - -namespace Slang -{ - -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CPPCompiler::Desc !!!!!!!!!!!!!!!!!!!!!!*/ - -void CPPCompiler::Desc::appendAsText(StringBuilder& out) const -{ - out << getCompilerTypeAsText(type); - out << " "; - out << majorVersion; - out << "."; - out << minorVersion; -} - -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CPPCompiler::OutputMessage !!!!!!!!!!!!!!!!!!!!!!*/ - -/* static */UnownedStringSlice CPPCompiler::Diagnostic::getTypeText(Diagnostic::Type type) -{ - typedef Diagnostic::Type Type; - switch (type) - { - default: return UnownedStringSlice::fromLiteral("Unknown"); - case Type::Info: return UnownedStringSlice::fromLiteral("Info"); - case Type::Warning: return UnownedStringSlice::fromLiteral("Warning"); - case Type::Error: return UnownedStringSlice::fromLiteral("Error"); - } -} - -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CPPCompiler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ - -/* static */UnownedStringSlice CPPCompiler::getCompilerTypeAsText(CompilerType type) -{ - switch (type) - { - default: - case CompilerType::Unknown: return UnownedStringSlice::fromLiteral("Unknown"); - case CompilerType::VisualStudio:return UnownedStringSlice::fromLiteral("Visual Studio"); - case CompilerType::GCC: return UnownedStringSlice::fromLiteral("GCC"); - case CompilerType::Clang: return UnownedStringSlice::fromLiteral("Clang"); - case CompilerType::SNC: return UnownedStringSlice::fromLiteral("SNC"); - case CompilerType::GHS: return UnownedStringSlice::fromLiteral("GHS"); - } -} - -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CPPCompiler::Output !!!!!!!!!!!!!!!!!!!!!!*/ - -Index CPPCompiler::Output::getCountByType(Diagnostic::Type type) const -{ - Index count = 0; - for (const auto& msg : diagnostics) - { - count += Index(msg.type == type); - } - return count; -} - -Int CPPCompiler::Output::countByStage(Diagnostic::Stage stage, Index counts[Int(Diagnostic::Type::CountOf)]) const -{ - Int count = 0; - ::memset(counts, 0, sizeof(Index) * Int(Diagnostic::Type::CountOf)); - for (const auto& diagnostic : diagnostics) - { - if (diagnostic.stage == stage) - { - count++; - counts[Index(diagnostic.type)]++; - } - } - return count++; -} - -static void _appendCounts(const Index counts[Int(CPPCompiler::Diagnostic::Type::CountOf)], StringBuilder& out) -{ - typedef CPPCompiler::Diagnostic::Type Type; - - for (Index i = 0; i < Int(Type::CountOf); i++) - { - if (counts[i] > 0) - { - out << CPPCompiler::Diagnostic::getTypeText(Type(i)) << "(" << counts[i] << ") "; - } - } -} - -static void _appendSimplified(const Index counts[Int(CPPCompiler::Diagnostic::Type::CountOf)], StringBuilder& out) -{ - typedef CPPCompiler::Diagnostic::Type Type; - for (Index i = 0; i < Int(Type::CountOf); i++) - { - if (counts[i] > 0) - { - out << CPPCompiler::Diagnostic::getTypeText(Type(i)) << " "; - } - } -} - -void CPPCompiler::Output::appendSummary(StringBuilder& out) const -{ - Index counts[Int(Diagnostic::Type::CountOf)]; - if (countByStage(Diagnostic::Stage::Compile, counts) > 0) - { - out << "Compile: "; - _appendCounts(counts, out); - out << "\n"; - } - if (countByStage(Diagnostic::Stage::Link, counts) > 0) - { - out << "Link: "; - _appendCounts(counts, out); - out << "\n"; - } -} - -void CPPCompiler::Output::appendSimplifiedSummary(StringBuilder& out) const -{ - Index counts[Int(Diagnostic::Type::CountOf)]; - if (countByStage(Diagnostic::Stage::Compile, counts) > 0) - { - out << "Compile: "; - _appendSimplified(counts, out); - out << "\n"; - } - if (countByStage(Diagnostic::Stage::Link, counts) > 0) - { - out << "Link: "; - _appendSimplified(counts, out); - out << "\n"; - } -} - -void CPPCompiler::Output::removeByType(Diagnostic::Type type) -{ - Index count = diagnostics.getCount(); - for (Index i = 0; i < count; ++i) - { - if (diagnostics[i].type == type) - { - diagnostics.removeAt(i); - i--; - count--; - } - } -} - -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CommandLineCPPCompiler !!!!!!!!!!!!!!!!!!!!!!*/ - -SlangResult CommandLineCPPCompiler::compile(const CompileOptions& options, Output& outOutput) -{ - outOutput.reset(); - - // Copy the command line options - CommandLine cmdLine(m_cmdLine); - - // Append command line args to the end of cmdLine using the target specific function for the specified options - SLANG_RETURN_ON_FAIL(calcArgs(options, cmdLine)); - - ExecuteResult exeRes; - -#if 0 - // Test - { - String line = ProcessUtil::getCommandLineString(cmdLine); - printf("%s", line.getBuffer()); - } -#endif - - SLANG_RETURN_ON_FAIL(ProcessUtil::execute(cmdLine, exeRes)); - -#if 0 - { - printf("stdout=\"%s\"\nstderr=\"%s\"\nret=%d\n", exeRes.standardOutput.getBuffer(), exeRes.standardError.getBuffer(), int(exeRes.resultCode)); - } -#endif - - return parseOutput(exeRes, outOutput); -} - -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CPPCompilerUtil !!!!!!!!!!!!!!!!!!!!!!*/ - -static CPPCompiler::Desc _calcCompiledWithDesc() -{ - CPPCompiler::Desc desc = {}; - -#if SLANG_VC - desc = WinVisualStudioUtil::getDesc(WinVisualStudioUtil::getCompiledVersion()); -#elif SLANG_CLANG - desc.type = CPPCompiler::CompilerType::Clang; - desc.majorVersion = Int(__clang_major__); - desc.minorVersion = Int(__clang_minor__); -#elif SLANG_SNC - desc.type = CPPCompiler::CompilerType::SNC; -#elif SLANG_GHS - desc.type = CPPCompiler::CompilerType::GHS; -#elif SLANG_GCC - desc.type = CPPCompiler::CompilerType::GCC; - desc.majorVersion = Int(__GNUC__); - desc.minorVersion = Int(__GNUC_MINOR__); -#else - desc.type = CPPCompiler::CompilerType::Unknown; -#endif - - return desc; -} - -const CPPCompiler::Desc& CPPCompilerUtil::getCompiledWithDesc() -{ - static CPPCompiler::Desc s_desc = _calcCompiledWithDesc(); - return s_desc; -} - -/* static */CPPCompiler* CPPCompilerUtil::findCompiler(const CPPCompilerSet* set, MatchType matchType, const CPPCompiler::Desc& desc) -{ - List<CPPCompiler*> compilers; - set->getCompilers(compilers); - return findCompiler(compilers, matchType, desc); -} - -/* static */CPPCompiler* CPPCompilerUtil::findCompiler(const List<CPPCompiler*>& compilers, MatchType matchType, const CPPCompiler::Desc& desc) -{ - Int bestIndex = -1; - - const CPPCompiler::CompilerType type = desc.type; - - Int maxVersionValue = 0; - Int minVersionDiff = 0x7fffffff; - - const auto descVersionValue = desc.getVersionValue(); - - for (Index i = 0; i < compilers.getCount(); ++i) - { - CPPCompiler* compiler = compilers[i]; - auto compilerDesc = compiler->getDesc(); - - if (type == 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 */CPPCompiler* CPPCompilerUtil::findClosestCompiler(const List<CPPCompiler*>& compilers, const CPPCompiler::Desc& desc) -{ - CPPCompiler* compiler; - - compiler = findCompiler(compilers, MatchType::MinGreaterEqual, desc); - if (compiler) - { - return compiler; - } - compiler = findCompiler(compilers, MatchType::MinAbsolute, desc); - if (compiler) - { - return compiler; - } - - // If we are gcc, we can try clang and vice versa - if (desc.type == CPPCompiler::CompilerType::GCC || desc.type == CPPCompiler::CompilerType::Clang) - { - CPPCompiler::Desc compatible = desc; - compatible.type = (compatible.type == CPPCompiler::CompilerType::Clang) ? CPPCompiler::CompilerType::GCC : CPPCompiler::CompilerType::Clang; - - compiler = findCompiler(compilers, MatchType::MinGreaterEqual, compatible); - if (compiler) - { - return compiler; - } - compiler = findCompiler(compilers, MatchType::MinAbsolute, compatible); - if (compiler) - { - return compiler; - } - } - - return nullptr; -} - -static void _addGCCFamilyCompiler(const String& path, const String& inExeName, CPPCompilerSet* compilerSet) -{ - String exeName(inExeName); - if (path.getLength() > 0) - { - exeName = Path::combine(path, inExeName); - } - - CPPCompiler::Desc desc; - if (SLANG_SUCCEEDED(GCCCompilerUtil::calcVersion(exeName, desc))) - { - RefPtr<CommandLineCPPCompiler> compiler(new GCCCPPCompiler(desc)); - compiler->m_cmdLine.setExecutableFilename(exeName); - compilerSet->addCompiler(compiler); - } -} - -/* static */CPPCompiler* CPPCompilerUtil::findClosestCompiler(const CPPCompilerSet* set, const CPPCompiler::Desc& desc) -{ - CPPCompiler* compiler = set->getCompiler(desc); - if (compiler) - { - return compiler; - } - List<CPPCompiler*> compilers; - set->getCompilers(compilers); - return findClosestCompiler(compilers, desc); -} - -/* static */SlangResult CPPCompilerUtil::initializeSet(const InitializeSetDesc& desc, CPPCompilerSet* set) -{ -#if SLANG_WINDOWS_FAMILY - WinVisualStudioUtil::find(set); -#endif - - _addGCCFamilyCompiler(desc.getPath(CompilerType::Clang), "clang", set); - _addGCCFamilyCompiler(desc.getPath(CompilerType::GCC), "g++", set); - - // Set the default to the compiler closest to how this source was compiled - set->setDefaultCompiler(findClosestCompiler(set, getCompiledWithDesc())); - return SLANG_OK; -} - -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CPPCompilerFactory !!!!!!!!!!!!!!!!!!!!!!*/ - - -void CPPCompilerSet::getCompilerDescs(List<CPPCompiler::Desc>& outCompilerDescs) const -{ - outCompilerDescs.clear(); - for (CPPCompiler* compiler : m_compilers) - { - outCompilerDescs.add(compiler->getDesc()); - } -} - -Index CPPCompilerSet::_findIndex(const CPPCompiler::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; -} - -CPPCompiler* CPPCompilerSet::getCompiler(const CPPCompiler::Desc& compilerDesc) const -{ - const Index index = _findIndex(compilerDesc); - return index >= 0 ? m_compilers[index] : nullptr; -} - -void CPPCompilerSet::getCompilers(List<CPPCompiler*>& outCompilers) const -{ - outCompilers.clear(); - outCompilers.addRange((CPPCompiler*const*)m_compilers.begin(), m_compilers.getCount()); -} - -bool CPPCompilerSet::hasCompiler(CPPCompiler::CompilerType compilerType) const -{ - for (CPPCompiler* compiler : m_compilers) - { - const auto& desc = compiler->getDesc(); - if (desc.type == compilerType) - { - return true; - } - } - return false; -} - -void CPPCompilerSet::addCompiler(CPPCompiler* compiler) -{ - const Index index = _findIndex(compiler->getDesc()); - if (index >= 0) - { - m_compilers[index] = compiler; - } - else - { - m_compilers.add(compiler); - } -} - -} diff --git a/source/core/slang-cpp-compiler.h b/source/core/slang-cpp-compiler.h deleted file mode 100644 index f1592d240..000000000 --- a/source/core/slang-cpp-compiler.h +++ /dev/null @@ -1,343 +0,0 @@ -#ifndef SLANG_CPP_COMPILER_H -#define SLANG_CPP_COMPILER_H - -#include "slang-common.h" -#include "slang-string.h" - -#include "slang-process-util.h" - -#include "slang-platform.h" - -namespace Slang -{ - -class CPPCompiler: public RefObject -{ -public: - typedef RefObject Super; - enum class CompilerType - { - Unknown, - VisualStudio, - GCC, - Clang, - SNC, - GHS, - CountOf, - }; - enum class SourceType - { - C, ///< C source - CPP, ///< C++ source - }; - - struct Desc - { - typedef Desc ThisType; - - UInt GetHashCode() const { return combineHash(int(type), combineHash(int(majorVersion), int(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; - - /// Ctor - Desc(CompilerType inType = CompilerType::Unknown, Int inMajorVersion = 0, Int inMinorVersion = 0):type(inType), majorVersion(inMajorVersion), minorVersion(inMinorVersion) {} - - CompilerType type; ///< The type of the compiler - Int majorVersion; ///< Major version (interpretation is type specific) - Int minorVersion; ///< Minor version - }; - - enum class OptimizationLevel - { - None, ///< Don't optimize at all. - Default, ///< Default optimization level: balance code quality and compilation time. - High, ///< Optimize aggressively. - Maximal, ///< Include optimizations that may take a very long time, or may involve severe space-vs-speed tradeoffs - }; - - enum class DebugInfoType - { - None, ///< Don't emit debug information at all. - Minimal, ///< Emit as little debug information as possible, while still supporting stack traces. - Standard, ///< Emit whatever is the standard level of debug information for each target. - Maximal, ///< Emit as much debug information as possible for each target. - }; - enum class FloatingPointMode - { - Default, - Fast, - Precise, - }; - - enum TargetType - { - Executable, ///< Produce an executable - SharedLibrary, ///< Produce a shared library object/dll - Object, ///< Produce an object file - }; - - struct Define - { - String nameWithSig; ///< If macro takes parameters include in brackets - String value; - }; - - struct CompileOptions - { - typedef uint32_t Flags; - struct Flag - { - enum Enum : Flags - { - EnableExceptionHandling = 0x01, - Verbose = 0x02, - EnableSecurityChecks = 0x04, - }; - }; - - OptimizationLevel optimizationLevel = OptimizationLevel::Default; - DebugInfoType debugInfoType = DebugInfoType::Standard; - TargetType targetType = TargetType::Executable; - SourceType sourceType = SourceType::CPP; - FloatingPointMode floatingPointMode = FloatingPointMode::Default; - - Flags flags = Flag::EnableExceptionHandling; - - PlatformKind platform = PlatformKind::Unknown; - - 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 - - List<Define> defines; - - List<String> sourceFiles; - - List<String> includePaths; - List<String> libraryPaths; - }; - - struct Diagnostic - { - enum class Type - { - Unknown, - Info, - Warning, - Error, - CountOf, - }; - enum class Stage - { - Compile, - Link, - }; - - void reset() - { - type = Type::Unknown; - stage = Stage::Compile; - fileLine = 0; - } - static UnownedStringSlice getTypeText(Diagnostic::Type type); - - - Type type; ///< The type of error - Stage stage; ///< The stage the error came from - String text; ///< The text of the error - String code; ///< The compiler specific error code - String filePath; ///< The path the error originated from - Int fileLine; ///< The line number the error came from - }; - - typedef uint32_t ProductFlags; - struct ProductFlag - { - 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 - }; - }; - - enum class Product - { - DebugRun, - Run, - CompileTemporary, - All, - }; - - struct Output - { - /// Reset to an initial empty state - void reset() { diagnostics.clear(); rawDiagnostics = String(); result = SLANG_OK; } - - /// Get the number of diagnostics by type - Index getCountByType(Diagnostic::Type type) const; - /// True if there are any diagnostics of the type - bool has(Diagnostic::Type type) const { return getCountByType(type) > 0; } - - /// Stores in outCounts, the amount of diagnostics for the stage of each type - Int countByStage(Diagnostic::Stage stage, Index outCounts[Int(Diagnostic::Type::CountOf)]) const; - - /// Append a summary to out - void appendSummary(StringBuilder& out) const; - /// Appends a summary that just identifies if there is an error of a type (not a count) - void appendSimplifiedSummary(StringBuilder& out) const; - - /// Remove all diagnostics of the type - void removeByType(Diagnostic::Type type); - - String rawDiagnostics; - - SlangResult result; - List<Diagnostic> diagnostics; - }; - - /// Get the desc of this compiler - const Desc& getDesc() const { return m_desc; } - /// Compile using the specified options. The result is in resOut - virtual SlangResult compile(const CompileOptions& options, Output& outOutput) = 0; - /// Given the compilation options and the module name, determines the actual file name used for output - virtual SlangResult calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath) = 0; - /// 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; - - /// Return the compiler type as name - static UnownedStringSlice getCompilerTypeAsText(CompilerType type); - -protected: - - CPPCompiler(const Desc& desc) : - m_desc(desc) - {} - - Desc m_desc; -}; - -class CommandLineCPPCompiler : public CPPCompiler -{ -public: - typedef CPPCompiler Super; - - // CPPCompiler - virtual SlangResult compile(const CompileOptions& options, Output& outOutput) SLANG_OVERRIDE; - - // Functions to be implemented for a specific CommandLine - virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) = 0; - virtual SlangResult parseOutput(const ExecuteResult& exeResult, Output& output) = 0; - - CommandLineCPPCompiler(const Desc& desc, const String& exeName) : - Super(desc) - { - m_cmdLine.setExecutableFilename(exeName); - } - - CommandLineCPPCompiler(const Desc& desc, const CommandLine& cmdLine) : - Super(desc), - m_cmdLine(cmdLine) - {} - - CommandLineCPPCompiler(const Desc& desc):Super(desc) {} - - CommandLine m_cmdLine; -}; - -class CPPCompilerSet : public RefObject -{ -public: - typedef RefObject Super; - - - /// Find all the available compilers - void getCompilerDescs(List<CPPCompiler::Desc>& outCompilerDescs) const; - /// Returns list of all compilers - void getCompilers(List<CPPCompiler*>& outCompilers) const; - - /// Get a compiler - CPPCompiler* getCompiler(const CPPCompiler::Desc& compilerDesc) const; - - /// Will replace if there is one with same desc - void addCompiler(CPPCompiler* compiler); - - /// Get a default compiler - CPPCompiler* getDefaultCompiler() const { return m_defaultCompiler; } - /// Set the default compiler - void setDefaultCompiler(CPPCompiler* compiler) { m_defaultCompiler = compiler; } - - /// True if has a compiler of the specified type - bool hasCompiler(CPPCompiler::CompilerType compilerType) const; - -protected: - - Index _findIndex(const CPPCompiler::Desc& desc) const; - - RefPtr<CPPCompiler> m_defaultCompiler; - // This could be a dictionary/map - but doing a linear search is going to be fine and it makes - // somethings easier. - List<RefPtr<CPPCompiler>> m_compilers; -}; - -/* Only purpose of having base-class here is to make all the CPPCompiler types available directly in derived Utils */ -struct CPPCompilerBaseUtil -{ - typedef CPPCompiler::CompileOptions CompileOptions; - typedef CPPCompiler::OptimizationLevel OptimizationLevel; - typedef CPPCompiler::TargetType TargetType; - typedef CPPCompiler::DebugInfoType DebugInfoType; - typedef CPPCompiler::SourceType SourceType; - typedef CPPCompiler::CompilerType CompilerType; - - typedef CPPCompiler::Diagnostic Diagnostic; - typedef CPPCompiler::FloatingPointMode FloatingPointMode; - typedef CPPCompiler::ProductFlag ProductFlag; - typedef CPPCompiler::ProductFlags ProductFlags; -}; - -struct CPPCompilerUtil: public CPPCompilerBaseUtil -{ - enum class MatchType - { - MinGreaterEqual, - MinAbsolute, - Newest, - }; - - struct InitializeSetDesc - { - const String& getPath(CompilerType type) const { return paths[int(type)]; } - void setPath(CompilerType type, const String& path) { paths[int(type)] = path; } - - String paths[int(CPPCompiler::CompilerType::CountOf)]; - }; - - /// Find a compiler - static CPPCompiler* findCompiler(const CPPCompilerSet* set, MatchType matchType, const CPPCompiler::Desc& desc); - static CPPCompiler* findCompiler(const List<CPPCompiler*>& compilers, MatchType matchType, const CPPCompiler::Desc& desc); - - /// Find the compiler closest to the desc - static CPPCompiler* findClosestCompiler(const List<CPPCompiler*>& compilers, const CPPCompiler::Desc& desc); - static CPPCompiler* findClosestCompiler(const CPPCompilerSet* set, const CPPCompiler::Desc& desc); - - /// Get the information on the compiler used to compile this source - static const CPPCompiler::Desc& getCompiledWithDesc(); - - /// Given a set, registers compilers found through standard means and determines a reasonable default compiler if possible - static SlangResult initializeSet(const InitializeSetDesc& desc, CPPCompilerSet* set); -}; - -} - -#endif diff --git a/source/core/slang-downstream-compiler.cpp b/source/core/slang-downstream-compiler.cpp new file mode 100644 index 000000000..52ec2fcd7 --- /dev/null +++ b/source/core/slang-downstream-compiler.cpp @@ -0,0 +1,558 @@ +// slang-downstream-compiler.cpp +#include "slang-downstream-compiler.h" + +#include "slang-common.h" +#include "../../slang-com-helper.h" +#include "slang-string-util.h" + +#include "slang-io.h" +#include "slang-shared-library.h" +#include "slang-blob.h" + +// if Visual Studio import the visual studio platform specific header +#if SLANG_VC +# include "windows/slang-win-visual-studio-util.h" +#endif + +#include "slang-visual-studio-compiler-util.h" +#include "slang-gcc-compiler-util.h" + +namespace Slang +{ + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompiler::Desc !!!!!!!!!!!!!!!!!!!!!!*/ + +void DownstreamCompiler::Desc::appendAsText(StringBuilder& out) const +{ + out << getCompilerTypeAsText(type); + out << " "; + out << majorVersion; + out << "."; + out << minorVersion; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamDiagnostic !!!!!!!!!!!!!!!!!!!!!!!!*/ + +/* static */UnownedStringSlice DownstreamDiagnostic::getTypeText(Type type) +{ + switch (type) + { + default: return UnownedStringSlice::fromLiteral("Unknown"); + case Type::Info: return UnownedStringSlice::fromLiteral("Info"); + case Type::Warning: return UnownedStringSlice::fromLiteral("Warning"); + case Type::Error: return UnownedStringSlice::fromLiteral("Error"); + } +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompiler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ + +/* static */UnownedStringSlice DownstreamCompiler::getCompilerTypeAsText(CompilerType type) +{ + switch (type) + { + default: + case CompilerType::Unknown: return UnownedStringSlice::fromLiteral("Unknown"); + case CompilerType::VisualStudio:return UnownedStringSlice::fromLiteral("Visual Studio"); + case CompilerType::GCC: return UnownedStringSlice::fromLiteral("GCC"); + case CompilerType::Clang: return UnownedStringSlice::fromLiteral("Clang"); + case CompilerType::SNC: return UnownedStringSlice::fromLiteral("SNC"); + case CompilerType::GHS: return UnownedStringSlice::fromLiteral("GHS"); + } +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamDiagnostics !!!!!!!!!!!!!!!!!!!!!!*/ + +Index DownstreamDiagnostics::getCountByType(Diagnostic::Type type) const +{ + Index count = 0; + for (const auto& msg : diagnostics) + { + count += Index(msg.type == type); + } + return count; +} + +Int DownstreamDiagnostics::countByStage(Diagnostic::Stage stage, Index counts[Int(Diagnostic::Type::CountOf)]) const +{ + Int count = 0; + ::memset(counts, 0, sizeof(Index) * Int(Diagnostic::Type::CountOf)); + for (const auto& diagnostic : diagnostics) + { + if (diagnostic.stage == stage) + { + count++; + counts[Index(diagnostic.type)]++; + } + } + return count++; +} + +static void _appendCounts(const Index counts[Int(DownstreamDiagnostic::Type::CountOf)], StringBuilder& out) +{ + typedef DownstreamDiagnostic::Type Type; + + for (Index i = 0; i < Int(Type::CountOf); i++) + { + if (counts[i] > 0) + { + out << DownstreamDiagnostic::getTypeText(Type(i)) << "(" << counts[i] << ") "; + } + } +} + +static void _appendSimplified(const Index counts[Int(DownstreamDiagnostic::Type::CountOf)], StringBuilder& out) +{ + typedef DownstreamDiagnostic::Type Type; + for (Index i = 0; i < Int(Type::CountOf); i++) + { + if (counts[i] > 0) + { + out << DownstreamDiagnostic::getTypeText(Type(i)) << " "; + } + } +} + +void DownstreamDiagnostics::appendSummary(StringBuilder& out) const +{ + Index counts[Int(Diagnostic::Type::CountOf)]; + if (countByStage(Diagnostic::Stage::Compile, counts) > 0) + { + out << "Compile: "; + _appendCounts(counts, out); + out << "\n"; + } + if (countByStage(Diagnostic::Stage::Link, counts) > 0) + { + out << "Link: "; + _appendCounts(counts, out); + out << "\n"; + } +} + +void DownstreamDiagnostics::appendSimplifiedSummary(StringBuilder& out) const +{ + Index counts[Int(Diagnostic::Type::CountOf)]; + if (countByStage(Diagnostic::Stage::Compile, counts) > 0) + { + out << "Compile: "; + _appendSimplified(counts, out); + out << "\n"; + } + if (countByStage(Diagnostic::Stage::Link, counts) > 0) + { + out << "Link: "; + _appendSimplified(counts, out); + out << "\n"; + } +} + +void DownstreamDiagnostics::removeByType(Diagnostic::Type type) +{ + Index count = diagnostics.getCount(); + for (Index i = 0; i < count; ++i) + { + if (diagnostics[i].type == type) + { + diagnostics.removeAt(i); + i--; + count--; + } + } +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CommandLineDownstreamCompileResult !!!!!!!!!!!!!!!!!!!!!!*/ + +SlangResult CommandLineDownstreamCompileResult::getHostCallableSharedLibrary(ComPtr<ISlangSharedLibrary>& outLibrary) +{ + if (m_hostCallableSharedLibrary) + { + outLibrary = m_hostCallableSharedLibrary; + return SLANG_OK; + } + + // Okay we want to load + // Try loading the shared library + SharedLibrary::Handle handle; + if (SLANG_FAILED(SharedLibrary::loadWithPlatformPath(m_moduleFilePath.getBuffer(), handle))) + { + return SLANG_FAIL; + } + // The shared library needs to keep temp files in scope + RefPtr<TemporarySharedLibrary> sharedLib(new TemporarySharedLibrary(handle, m_moduleFilePath)); + sharedLib->m_temporaryFileSet = m_temporaryFiles; + + m_hostCallableSharedLibrary = sharedLib; + outLibrary = m_hostCallableSharedLibrary; + return SLANG_OK; +} + +SlangResult CommandLineDownstreamCompileResult::getBinary(ComPtr<ISlangBlob>& outBlob) +{ + if (m_binaryBlob) + { + outBlob = m_binaryBlob; + return SLANG_OK; + } + + // Read the binary + try + { + // Read the contents of the binary + List<uint8_t> contents = File::readAllBytes(m_moduleFilePath); + + m_binaryBlob = new ScopeRefObjectBlob(ListBlob::moveCreate(contents), m_temporaryFiles); + outBlob = m_binaryBlob; + return SLANG_OK; + } + catch (const Slang::IOException&) + { + return SLANG_FAIL; + } +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CommandLineDownstreamCompiler !!!!!!!!!!!!!!!!!!!!!!*/ + +SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptions, RefPtr<DownstreamCompileResult>& out) +{ + // Copy the command line options + CommandLine cmdLine(m_cmdLine); + + CompileOptions options(inOptions); + + // Find all the files that will be produced + RefPtr<TemporaryFileSet> productFileSet(new TemporaryFileSet); + + if (options.modulePath.getLength() == 0 || options.sourceContents.getLength() != 0) + { + String modulePath = options.modulePath; + + // If there is no module path, generate one. + if (modulePath.getLength() == 0) + { + SLANG_RETURN_ON_FAIL(File::generateTemporary(UnownedStringSlice::fromLiteral("slang-generated"), modulePath)); + options.modulePath = modulePath; + } + + if (options.sourceContents.getLength() != 0) + { + String compileSourcePath = modulePath; + + // NOTE: Strictly speaking producing filenames by modifying the generateTemporary path that may introduce a temp filename clash, but in practice is extraordinary unlikely + compileSourcePath.append("-src"); + + // Make the temporary filename have the appropriate extension. + if (options.sourceType == DownstreamCompiler::SourceType::C) + { + compileSourcePath.append(".c"); + } + else + { + compileSourcePath.append(".cpp"); + } + + // Write it out + try + { + productFileSet->add(compileSourcePath); + + File::writeAllText(compileSourcePath, options.sourceContents); + } + catch (...) + { + return SLANG_FAIL; + } + + // Add it as a source file + options.sourceFiles.add(compileSourcePath); + + // There is no source contents + options.sourceContents = String(); + } + } + + // Append command line args to the end of cmdLine using the target specific function for the specified options + SLANG_RETURN_ON_FAIL(calcArgs(options, cmdLine)); + + String moduleFilePath; + + { + StringBuilder builder; + SLANG_RETURN_ON_FAIL(calcModuleFilePath(options, builder)); + moduleFilePath = builder.ProduceString(); + } + + { + List<String> paths; + SLANG_RETURN_ON_FAIL(calcCompileProducts(options, DownstreamCompiler::ProductFlag::All, paths)); + productFileSet->add(paths); + } + + ExecuteResult exeRes; + +#if 0 + // Test + { + String line = ProcessUtil::getCommandLineString(cmdLine); + printf("%s", line.getBuffer()); + } +#endif + + SLANG_RETURN_ON_FAIL(ProcessUtil::execute(cmdLine, exeRes)); + +#if 0 + { + printf("stdout=\"%s\"\nstderr=\"%s\"\nret=%d\n", exeRes.standardOutput.getBuffer(), exeRes.standardError.getBuffer(), int(exeRes.resultCode)); + } +#endif + + DownstreamDiagnostics diagnostics; + SLANG_RETURN_ON_FAIL(parseOutput(exeRes, diagnostics)); + + + out = new CommandLineDownstreamCompileResult(diagnostics, moduleFilePath, productFileSet); + + return SLANG_OK; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompiler::Desc !!!!!!!!!!!!!!!!!!!!!!*/ + +static DownstreamCompiler::Desc _calcCompiledWithDesc() +{ + DownstreamCompiler::Desc desc = {}; + +#if SLANG_VC + desc = WinVisualStudioUtil::getDesc(WinVisualStudioUtil::getCompiledVersion()); +#elif SLANG_CLANG + desc.type = DownstreamCompiler::CompilerType::Clang; + desc.majorVersion = Int(__clang_major__); + desc.minorVersion = Int(__clang_minor__); +#elif SLANG_SNC + desc.type = DownstreamCompiler::CompilerType::SNC; +#elif SLANG_GHS + desc.type = DownstreamCompiler::CompilerType::GHS; +#elif SLANG_GCC + desc.type = DownstreamCompiler::CompilerType::GCC; + desc.majorVersion = Int(__GNUC__); + desc.minorVersion = Int(__GNUC_MINOR__); +#else + desc.type = DownstreamCompiler::CompilerType::Unknown; +#endif + + return desc; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerUtil !!!!!!!!!!!!!!!!!!!!!!*/ + +const DownstreamCompiler::Desc& DownstreamCompilerUtil::getCompiledWithDesc() +{ + static DownstreamCompiler::Desc s_desc = _calcCompiledWithDesc(); + return s_desc; +} + +/* 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) +{ + Int bestIndex = -1; + + const DownstreamCompiler::CompilerType type = desc.type; + + Int maxVersionValue = 0; + Int minVersionDiff = 0x7fffffff; + + const auto descVersionValue = desc.getVersionValue(); + + for (Index i = 0; i < compilers.getCount(); ++i) + { + DownstreamCompiler* compiler = compilers[i]; + auto compilerDesc = compiler->getDesc(); + + if (type == 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::findClosestCompiler(const List<DownstreamCompiler*>& compilers, const DownstreamCompiler::Desc& desc) +{ + DownstreamCompiler* compiler; + + compiler = findCompiler(compilers, MatchType::MinGreaterEqual, desc); + if (compiler) + { + return compiler; + } + compiler = findCompiler(compilers, MatchType::MinAbsolute, desc); + if (compiler) + { + return compiler; + } + + // If we are gcc, we can try clang and vice versa + if (desc.type == DownstreamCompiler::CompilerType::GCC || desc.type == DownstreamCompiler::CompilerType::Clang) + { + DownstreamCompiler::Desc compatible = desc; + compatible.type = (compatible.type == DownstreamCompiler::CompilerType::Clang) ? DownstreamCompiler::CompilerType::GCC : DownstreamCompiler::CompilerType::Clang; + + compiler = findCompiler(compilers, MatchType::MinGreaterEqual, compatible); + if (compiler) + { + return compiler; + } + compiler = findCompiler(compilers, MatchType::MinAbsolute, compatible); + if (compiler) + { + return compiler; + } + } + + return nullptr; +} + +static void _addGCCFamilyCompiler(const String& path, const String& inExeName, DownstreamCompilerSet* compilerSet) +{ + String exeName(inExeName); + if (path.getLength() > 0) + { + exeName = Path::combine(path, inExeName); + } + + DownstreamCompiler::Desc desc; + if (SLANG_SUCCEEDED(GCCDownstreamCompilerUtil::calcVersion(exeName, desc))) + { + RefPtr<CommandLineDownstreamCompiler> compiler(new GCCDownstreamCompiler(desc)); + compiler->m_cmdLine.setExecutableFilename(exeName); + compilerSet->addCompiler(compiler); + } +} + +/* static */DownstreamCompiler* DownstreamCompilerUtil::findClosestCompiler(const DownstreamCompilerSet* set, const DownstreamCompiler::Desc& desc) +{ + DownstreamCompiler* compiler = set->getCompiler(desc); + if (compiler) + { + return compiler; + } + List<DownstreamCompiler*> compilers; + set->getCompilers(compilers); + return findClosestCompiler(compilers, desc); +} + +/* static */SlangResult DownstreamCompilerUtil::initializeSet(const InitializeSetDesc& desc, DownstreamCompilerSet* set) +{ +#if SLANG_WINDOWS_FAMILY + WinVisualStudioUtil::find(set); +#endif + + _addGCCFamilyCompiler(desc.getPath(CompilerType::Clang), "clang", set); + _addGCCFamilyCompiler(desc.getPath(CompilerType::GCC), "g++", set); + + // Set the default to the compiler closest to how this source was compiled + set->setDefaultCompiler(findClosestCompiler(set, getCompiledWithDesc())); + return SLANG_OK; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 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::hasCompiler(DownstreamCompiler::CompilerType compilerType) const +{ + for (DownstreamCompiler* compiler : m_compilers) + { + const auto& desc = compiler->getDesc(); + if (desc.type == compilerType) + { + return true; + } + } + return false; +} + +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/core/slang-downstream-compiler.h b/source/core/slang-downstream-compiler.h new file mode 100644 index 000000000..12cf54a91 --- /dev/null +++ b/source/core/slang-downstream-compiler.h @@ -0,0 +1,403 @@ +#ifndef SLANG_DOWNSTREAM_COMPILER_H +#define SLANG_DOWNSTREAM_COMPILER_H + +#include "slang-common.h" +#include "slang-string.h" + +#include "slang-process-util.h" + +#include "slang-platform.h" + +#include "slang-io.h" + +#include "../../slang-com-ptr.h" + +namespace Slang +{ + +struct DownstreamDiagnostic +{ + enum class Type + { + Unknown, + Info, + Warning, + Error, + CountOf, + }; + enum class Stage + { + Compile, + Link, + }; + + void reset() + { + type = Type::Unknown; + stage = Stage::Compile; + fileLine = 0; + } + static UnownedStringSlice getTypeText(Type type); + + Type type; ///< The type of error + Stage stage; ///< The stage the error came from + String text; ///< The text of the error + String code; ///< The compiler specific error code + String filePath; ///< The path the error originated from + Int fileLine; ///< The line number the error came from +}; + +struct DownstreamDiagnostics +{ + typedef DownstreamDiagnostic Diagnostic; + + /// Reset to an initial empty state + void reset() { diagnostics.clear(); rawDiagnostics = String(); result = SLANG_OK; } + + /// Get the number of diagnostics by type + Index getCountByType(Diagnostic::Type type) const; + /// True if there are any diagnostics of the type + bool has(Diagnostic::Type type) const { return getCountByType(type) > 0; } + + /// Stores in outCounts, the amount of diagnostics for the stage of each type + Int countByStage(Diagnostic::Stage stage, Index outCounts[Int(Diagnostic::Type::CountOf)]) const; + + /// Append a summary to out + void appendSummary(StringBuilder& out) const; + /// Appends a summary that just identifies if there is an error of a type (not a count) + void appendSimplifiedSummary(StringBuilder& out) const; + + /// Remove all diagnostics of the type + void removeByType(Diagnostic::Type type); + + String rawDiagnostics; + + SlangResult result; + List<Diagnostic> diagnostics; +}; + +class DownstreamCompileResult : public RefObject +{ +public: + + virtual SlangResult getHostCallableSharedLibrary(ComPtr<ISlangSharedLibrary>& outLibrary) = 0; + virtual SlangResult getBinary(ComPtr<ISlangBlob>& outBlob) = 0; + + const DownstreamDiagnostics& getDiagnostics() const { return m_diagnostics; } + + /// Ctor + DownstreamCompileResult(const DownstreamDiagnostics& diagnostics): + m_diagnostics(diagnostics) + {} + +protected: + DownstreamDiagnostics m_diagnostics; +}; + +class DownstreamCompiler: public RefObject +{ +public: + typedef RefObject Super; + + typedef DownstreamCompileResult CompileResult; + + enum class CompilerType + { + Unknown, + VisualStudio, + GCC, + Clang, + SNC, + GHS, + CountOf, + }; + enum class SourceType + { + C, ///< C source + CPP, ///< C++ source + }; + + struct Desc + { + typedef Desc ThisType; + + UInt GetHashCode() const { return combineHash(int(type), combineHash(int(majorVersion), int(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; + + /// Ctor + Desc(CompilerType inType = CompilerType::Unknown, Int inMajorVersion = 0, Int inMinorVersion = 0):type(inType), majorVersion(inMajorVersion), minorVersion(inMinorVersion) {} + + CompilerType type; ///< The type of the compiler + Int majorVersion; ///< Major version (interpretation is type specific) + Int minorVersion; ///< Minor version + }; + + enum class OptimizationLevel + { + None, ///< Don't optimize at all. + Default, ///< Default optimization level: balance code quality and compilation time. + High, ///< Optimize aggressively. + Maximal, ///< Include optimizations that may take a very long time, or may involve severe space-vs-speed tradeoffs + }; + + enum class DebugInfoType + { + None, ///< Don't emit debug information at all. + Minimal, ///< Emit as little debug information as possible, while still supporting stack traces. + Standard, ///< Emit whatever is the standard level of debug information for each target. + Maximal, ///< Emit as much debug information as possible for each target. + }; + enum class FloatingPointMode + { + Default, + Fast, + Precise, + }; + + enum TargetType + { + Executable, ///< Produce an executable + SharedLibrary, ///< Produce a shared library object/dll + Object, ///< Produce an object file + }; + + struct Define + { + String nameWithSig; ///< If macro takes parameters include in brackets + String value; + }; + + struct CompileOptions + { + typedef uint32_t Flags; + struct Flag + { + enum Enum : Flags + { + EnableExceptionHandling = 0x01, + Verbose = 0x02, + EnableSecurityChecks = 0x04, + }; + }; + + OptimizationLevel optimizationLevel = OptimizationLevel::Default; + DebugInfoType debugInfoType = DebugInfoType::Standard; + TargetType targetType = TargetType::Executable; + SourceType sourceType = SourceType::CPP; + FloatingPointMode floatingPointMode = FloatingPointMode::Default; + + Flags flags = Flag::EnableExceptionHandling; + + 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; + + 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; + /// The names/paths of source to compile. This can be empty if sourceContents is set. + List<String> sourceFiles; + + List<String> includePaths; + List<String> libraryPaths; + }; + + typedef uint32_t ProductFlags; + struct ProductFlag + { + 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 + }; + }; + + enum class Product + { + DebugRun, + Run, + CompileTemporary, + All, + }; + + /// Get the desc of this compiler + const Desc& getDesc() const { return m_desc; } + /// Compile using the specified options. The result is in resOut + virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) = 0; + + /// Return the compiler type as name + static UnownedStringSlice getCompilerTypeAsText(CompilerType type); + +protected: + + DownstreamCompiler(const Desc& desc) : + m_desc(desc) + {} + + Desc m_desc; +}; + +class CommandLineDownstreamCompileResult : public DownstreamCompileResult +{ +public: + typedef DownstreamCompileResult Super; + + virtual SlangResult getHostCallableSharedLibrary(ComPtr<ISlangSharedLibrary>& outLibrary) SLANG_OVERRIDE; + virtual SlangResult getBinary(ComPtr<ISlangBlob>& outBlob) SLANG_OVERRIDE; + + CommandLineDownstreamCompileResult(const DownstreamDiagnostics& diagnostics, const String& moduleFilePath, TemporaryFileSet* temporaryFileSet) : + Super(diagnostics), + m_moduleFilePath(moduleFilePath), + m_temporaryFiles(temporaryFileSet) + { + } + + RefPtr<TemporaryFileSet> m_temporaryFiles; + +protected: + + String m_moduleFilePath; + DownstreamCompiler::CompileOptions m_options; + ComPtr<ISlangBlob> m_binaryBlob; + /// Cache of the shared library if appropriate + ComPtr<ISlangSharedLibrary> m_hostCallableSharedLibrary; +}; + +class CommandLineDownstreamCompiler : public DownstreamCompiler +{ +public: + typedef DownstreamCompiler Super; + + // DownstreamCompiler + virtual SlangResult compile(const CompileOptions& options, RefPtr<DownstreamCompileResult>& outResult) SLANG_OVERRIDE; + + // Functions to be implemented for a specific CommandLine + + /// Given the compilation options and the module name, determines the actual file name used for output + virtual SlangResult calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath) = 0; + /// 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 calcArgs(const CompileOptions& options, CommandLine& cmdLine) = 0; + virtual SlangResult parseOutput(const ExecuteResult& exeResult, DownstreamDiagnostics& output) = 0; + + CommandLineDownstreamCompiler(const Desc& desc, const String& exeName) : + Super(desc) + { + m_cmdLine.setExecutableFilename(exeName); + } + + CommandLineDownstreamCompiler(const Desc& desc, const CommandLine& cmdLine) : + Super(desc), + m_cmdLine(cmdLine) + {} + + CommandLineDownstreamCompiler(const Desc& desc):Super(desc) {} + + 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() const { return m_defaultCompiler; } + /// Set the default compiler + void setDefaultCompiler(DownstreamCompiler* compiler) { m_defaultCompiler = compiler; } + + /// True if has a compiler of the specified type + bool hasCompiler(DownstreamCompiler::CompilerType compilerType) const; + +protected: + + Index _findIndex(const DownstreamCompiler::Desc& desc) const; + + RefPtr<DownstreamCompiler> m_defaultCompiler; + // 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; +}; + +/* 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::TargetType TargetType; + typedef DownstreamCompiler::DebugInfoType DebugInfoType; + typedef DownstreamCompiler::SourceType SourceType; + typedef DownstreamCompiler::CompilerType CompilerType; + + typedef DownstreamDiagnostics::Diagnostic Diagnostic; + + typedef DownstreamCompiler::FloatingPointMode FloatingPointMode; + typedef DownstreamCompiler::ProductFlag ProductFlag; + typedef DownstreamCompiler::ProductFlags ProductFlags; +}; + +struct DownstreamCompilerUtil: public DownstreamCompilerBaseUtil +{ + enum class MatchType + { + MinGreaterEqual, + MinAbsolute, + Newest, + }; + + struct InitializeSetDesc + { + const String& getPath(CompilerType type) const { return paths[int(type)]; } + void setPath(CompilerType type, const String& path) { paths[int(type)] = path; } + + String paths[int(DownstreamCompiler::CompilerType::CountOf)]; + }; + + /// 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); + + /// Find the compiler closest to the desc + static DownstreamCompiler* findClosestCompiler(const List<DownstreamCompiler*>& compilers, const DownstreamCompiler::Desc& desc); + static DownstreamCompiler* findClosestCompiler(const DownstreamCompilerSet* set, const DownstreamCompiler::Desc& desc); + + /// Get the information on the compiler used to compile this source + static const DownstreamCompiler::Desc& getCompiledWithDesc(); + + /// Given a set, registers compilers found through standard means and determines a reasonable default compiler if possible + static SlangResult initializeSet(const InitializeSetDesc& desc, DownstreamCompilerSet* set); +}; + +} + +#endif diff --git a/source/core/slang-gcc-compiler-util.cpp b/source/core/slang-gcc-compiler-util.cpp index 7838ca25b..ba077e0c5 100644 --- a/source/core/slang-gcc-compiler-util.cpp +++ b/source/core/slang-gcc-compiler-util.cpp @@ -11,7 +11,7 @@ namespace Slang { -/* static */SlangResult GCCCompilerUtil::parseVersion(const UnownedStringSlice& text, const UnownedStringSlice& prefix, CPPCompiler::Desc& outDesc) +/* static */SlangResult GCCDownstreamCompilerUtil::parseVersion(const UnownedStringSlice& text, const UnownedStringSlice& prefix, DownstreamCompiler::Desc& outDesc) { List<UnownedStringSlice> lines; StringUtil::calcLines(text, lines); @@ -55,7 +55,7 @@ namespace Slang return SLANG_FAIL; } -SlangResult GCCCompilerUtil::calcVersion(const String& exeName, CPPCompiler::Desc& outDesc) +SlangResult GCCDownstreamCompilerUtil::calcVersion(const String& exeName, DownstreamCompiler::Desc& outDesc) { CommandLine cmdLine; cmdLine.setExecutableFilename(exeName); @@ -70,11 +70,11 @@ SlangResult GCCCompilerUtil::calcVersion(const String& exeName, CPPCompiler::Des UnownedStringSlice::fromLiteral("gcc version"), UnownedStringSlice::fromLiteral("Apple LLVM version"), }; - const CPPCompiler::CompilerType types[] = + const DownstreamCompiler::CompilerType types[] = { - CPPCompiler::CompilerType::Clang, - CPPCompiler::CompilerType::GCC, - CPPCompiler::CompilerType::Clang, + DownstreamCompiler::CompilerType::Clang, + DownstreamCompiler::CompilerType::GCC, + DownstreamCompiler::CompilerType::Clang, }; SLANG_COMPILE_TIME_ASSERT(SLANG_COUNT_OF(prefixes) == SLANG_COUNT_OF(types)); @@ -92,9 +92,9 @@ SlangResult GCCCompilerUtil::calcVersion(const String& exeName, CPPCompiler::Des return SLANG_FAIL; } -static SlangResult _parseErrorType(const UnownedStringSlice& in, CPPCompiler::Diagnostic::Type& outType) +static SlangResult _parseErrorType(const UnownedStringSlice& in, DownstreamDiagnostic::Type& outType) { - typedef CPPCompiler::Diagnostic::Type Type; + typedef DownstreamDiagnostic::Type Type; if (in == "error" || in == "fatal error") { @@ -127,9 +127,9 @@ enum class LineParseResult } // anonymous -static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParseResult& outLineParseResult, CPPCompiler::Diagnostic& outDiagnostic) +static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParseResult& outLineParseResult, DownstreamDiagnostic& outDiagnostic) { - typedef CPPCompiler::Diagnostic Diagnostic; + typedef DownstreamDiagnostic Diagnostic; typedef Diagnostic::Type Type; // Set to default case @@ -231,7 +231,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse } else if (text.startsWith("ld returned")) { - outDiagnostic.stage = CPPCompiler::Diagnostic::Stage::Link; + outDiagnostic.stage = DownstreamDiagnostic::Stage::Link; SLANG_RETURN_ON_FAIL(_parseErrorType(split[1].trim(), outDiagnostic.type)); outDiagnostic.text = line; outLineParseResult = LineParseResult::Single; @@ -285,7 +285,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse return SLANG_OK; } -/* static */SlangResult GCCCompilerUtil::parseOutput(const ExecuteResult& exeRes, CPPCompiler::Output& outOutput) +/* static */SlangResult GCCDownstreamCompilerUtil::parseOutput(const ExecuteResult& exeRes, DownstreamDiagnostics& outOutput) { LineParseResult prevLineResult = LineParseResult::Ignore; @@ -294,7 +294,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse for (auto line : LineParser(exeRes.standardError.getUnownedSlice())) { - CPPCompiler::Diagnostic diagnostic; + Diagnostic diagnostic; diagnostic.reset(); LineParseResult lineRes; @@ -341,7 +341,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse } } - if (outOutput.has(CPPCompiler::Diagnostic::Type::Error) || exeRes.resultCode != 0) + if (outOutput.has(Diagnostic::Type::Error) || exeRes.resultCode != 0) { outOutput.result = SLANG_FAIL; } @@ -349,8 +349,10 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse return SLANG_OK; } -/* static */ SlangResult GCCCompilerUtil::calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath) +/* static */ SlangResult GCCDownstreamCompilerUtil::calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath) { + SLANG_ASSERT(options.modulePath.getLength()); + outPath.Clear(); switch (options.targetType) @@ -381,8 +383,10 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse return SLANG_FAIL; } -/* static */SlangResult GCCCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, List<String>& outPaths) +/* static */SlangResult GCCDownstreamCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, List<String>& outPaths) { + SLANG_ASSERT(options.modulePath.getLength()); + outPaths.clear(); if (flags & ProductFlag::Execution) @@ -395,8 +399,11 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse return SLANG_OK; } -/* static */SlangResult GCCCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine) +/* static */SlangResult GCCDownstreamCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine) { + SLANG_ASSERT(options.sourceContents.getLength() == 0); + SLANG_ASSERT(options.modulePath.getLength()); + PlatformKind platformKind = (options.platform == PlatformKind::Unknown) ? PlatformUtil::getPlatformKind() : options.platform; if (options.sourceType == SourceType::CPP) diff --git a/source/core/slang-gcc-compiler-util.h b/source/core/slang-gcc-compiler-util.h index df3cb8a4b..ead527e0d 100644 --- a/source/core/slang-gcc-compiler-util.h +++ b/source/core/slang-gcc-compiler-util.h @@ -1,25 +1,25 @@ #ifndef SLANG_GCC_COMPILER_UTIL_H #define SLANG_GCC_COMPILER_UTIL_H -#include "slang-cpp-compiler.h" +#include "slang-downstream-compiler.h" namespace Slang { /* Utility for processing input and output of gcc-like compilers, including clang */ -struct GCCCompilerUtil : public CPPCompilerBaseUtil +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, CPPCompiler::Desc& outDesc); + static SlangResult parseVersion(const UnownedStringSlice& text, const UnownedStringSlice& prefix, DownstreamCompiler::Desc& outDesc); /// Runs the exeName, and extracts the version info into outDesc - static SlangResult calcVersion(const String& exeName, CPPCompiler::Desc& outDesc); + static SlangResult calcVersion(const String& exeName, DownstreamCompiler::Desc& outDesc); /// Calculate gcc family compilers (including clang) cmdLine arguments from options static SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine); /// Parse ExecuteResult into Output - static SlangResult parseOutput(const ExecuteResult& exeRes, CPPCompiler::Output& outOutput); + static SlangResult parseOutput(const ExecuteResult& exeRes, DownstreamDiagnostics& outOutput); /// Calculate the output module filename static SlangResult calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath); @@ -28,19 +28,19 @@ struct GCCCompilerUtil : public CPPCompilerBaseUtil static SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, List<String>& outPaths); }; -class GCCCPPCompiler : public CommandLineCPPCompiler +class GCCDownstreamCompiler : public CommandLineDownstreamCompiler { public: - typedef CommandLineCPPCompiler Super; - typedef GCCCompilerUtil Util; + typedef CommandLineDownstreamCompiler Super; + typedef GCCDownstreamCompilerUtil Util; // CommandLineCPPCompiler impl - just forwards to the Util virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE { return Util::calcArgs(options, cmdLine); } - virtual SlangResult parseOutput(const ExecuteResult& exeResult, Output& output) SLANG_OVERRIDE { return Util::parseOutput(exeResult, output); } + 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); } - GCCCPPCompiler(const Desc& desc):Super(desc) {} + GCCDownstreamCompiler(const Desc& desc):Super(desc) {} }; } diff --git a/source/core/slang-hex-dump-util.cpp b/source/core/slang-hex-dump-util.cpp index 4a3d4ce06..1583d8461 100644 --- a/source/core/slang-hex-dump-util.cpp +++ b/source/core/slang-hex-dump-util.cpp @@ -6,6 +6,7 @@ #include "slang-writer.h" #include "../../slang-com-helper.h" +#include "slang-hash.h" namespace Slang { @@ -16,11 +17,19 @@ static const char s_hex[] = "0123456789abcdef"; /* static */SlangResult HexDumpUtil::dumpWithMarkers(const List<uint8_t>& data, int maxBytesPerLine, ISlangWriter* writer) { + return dumpWithMarkers(data.getBuffer(), data.getCount(), maxBytesPerLine, writer); +} + +/* static */SlangResult HexDumpUtil::dumpWithMarkers(const uint8_t* data, size_t dataCount, int maxBytesPerLine, ISlangWriter* writer) +{ WriterHelper helper(writer); SLANG_RETURN_ON_FAIL(helper.write(s_start.begin(), s_start.size())); - SLANG_RETURN_ON_FAIL(helper.print(" (%zu)\n", size_t(data.getCount()))); + SLANG_RETURN_ON_FAIL(helper.print(" %zu", dataCount)); - SLANG_RETURN_ON_FAIL(dump(data, maxBytesPerLine, writer)); + const int hash = GetHashCode((const char*)data, dataCount); + SLANG_RETURN_ON_FAIL(helper.print(" %d\n", hash )); + + SLANG_RETURN_ON_FAIL(dump(data, dataCount, maxBytesPerLine, writer)); SLANG_RETURN_ON_FAIL(helper.write(s_end.begin(), s_end.size())); SLANG_RETURN_ON_FAIL(helper.put("\n")); @@ -38,14 +47,19 @@ static const char s_hex[] = "0123456789abcdef"; writer->write(c, 8); } + /* static */SlangResult HexDumpUtil::dump(const List<uint8_t>& data, int maxBytesPerLine, ISlangWriter* writer) { - int maxCharsPerLine = 2 * maxBytesPerLine + 1 + maxBytesPerLine + 1; + return dump(data.getBuffer(), data.getCount(), maxBytesPerLine, writer); +} - const uint8_t* cur = data.begin(); - const uint8_t* end = data.end(); +/* static */SlangResult HexDumpUtil::dump(const uint8_t* data, size_t dataCount, int maxBytesPerLine, ISlangWriter* writer) +{ + int maxCharsPerLine = 2 * maxBytesPerLine + 1 + maxBytesPerLine + 1; - + const uint8_t* cur = data; + const uint8_t* end = data + dataCount; + while (cur < end) { size_t count = size_t(end - cur); @@ -112,34 +126,16 @@ static int _parseHexDigit(char c) { outBytes.clear(); - bool inHex = false; - LineParser lineParser(lines); for (const auto& line : lineParser) { - if (!inHex) - { - if (line.startsWith(s_start)) - { - inHex = true; - continue; - } - } - else - { - if (line.startsWith(s_end)) - { - break; - } - } - const char* cur = line.begin(); const char* end = line.end(); while(cur + 2 <= end) { const char c = cur[0]; - if (c == ' ' || c== '\n' || c == '\r' || c == '\t') + if (c == ' ' || c == '\n' || c == '\r' || c == '\t') { // Skip to next line break; @@ -160,35 +156,59 @@ static int _parseHexDigit(char c) return SLANG_OK; } +static SlangResult _findLine(const UnownedStringSlice& find, UnownedStringSlice& ioRemaining, UnownedStringSlice& outLine) +{ + // Find the start line + UnownedStringSlice line; + while (StringUtil::extractLine(ioRemaining, line)) + { + if (line.startsWith(find)) + { + outLine = line; + return SLANG_OK; + } + } + return SLANG_FAIL; +} + +/* static */SlangResult HexDumpUtil::findStartAndEndLines(const UnownedStringSlice& lines, UnownedStringSlice& outStart, UnownedStringSlice& outEnd) +{ + UnownedStringSlice remaining(lines); + SLANG_RETURN_ON_FAIL(_findLine(s_start, remaining, outStart)); + SLANG_RETURN_ON_FAIL(_findLine(s_end, remaining, outEnd)); + return SLANG_OK; +} + /* static */SlangResult HexDumpUtil::parseWithMarkers(const UnownedStringSlice& lines, List<uint8_t>& outBytes) { - UnownedStringSlice remaining(lines), line; + UnownedStringSlice startLine, endLine; + SLANG_RETURN_ON_FAIL(findStartAndEndLines(lines, startLine, endLine)); - while(StringUtil::extractLine(remaining, line)) + int hash; + size_t size; { - if (line.startsWith(s_start)) + // Get the size and the hash + List<UnownedStringSlice> slices; + StringUtil::split(startLine, ' ', slices); + if (slices.getCount() != 3) { - // Extract next line - if (!StringUtil::extractLine(remaining, line)) - { - return SLANG_FAIL; - } - // It's the start line - UnownedStringSlice startLine = line; - - // Look for the ending line - do - { - if (line.startsWith(s_end)) - { - return parse(UnownedStringSlice(startLine.begin(), line.begin()), outBytes); - } - } - while ( StringUtil::extractLine(remaining, line)); + return SLANG_FAIL; } + // Extract the size + size = StringToInt(String(slices[1])); + hash = int(StringToInt(String(slices[2]))); } - return SLANG_FAIL; + SLANG_RETURN_ON_FAIL(parse(UnownedStringSlice(startLine.end(), endLine.begin()), outBytes)); + + // Calc the hash + const int readHash = GetHashCode((const char*)outBytes.begin(), outBytes.getCount()); + + if (readHash != hash || size_t(outBytes.getCount()) != size) + { + return SLANG_FAIL; + } + return SLANG_OK; } } diff --git a/source/core/slang-hex-dump-util.h b/source/core/slang-hex-dump-util.h index fefe84a17..f38bfde78 100644 --- a/source/core/slang-hex-dump-util.h +++ b/source/core/slang-hex-dump-util.h @@ -15,15 +15,21 @@ struct HexDumpUtil /// Dump data to writer, with lines starting with hex data static SlangResult dump(const List<uint8_t>& data, int numBytesPerLine, ISlangWriter* writer); + static SlangResult dump(const uint8_t* data, size_t dataCount, int numBytesPerLine, ISlangWriter* writer); + /// Dump a single value static void dump(uint32_t value, ISlangWriter* writer); static SlangResult dumpWithMarkers(const List<uint8_t>& data, int numBytesPerLine, ISlangWriter* writer); + static SlangResult dumpWithMarkers(const uint8_t* data, size_t dataSize, int numBytesPerLine, ISlangWriter* writer); + /// Parses lines formatted by dump, back into bytes static SlangResult parse(const UnownedStringSlice& lines, List<uint8_t>& outBytes); static SlangResult parseWithMarkers(const UnownedStringSlice& lines, List<uint8_t>& outBytes); + + static SlangResult findStartAndEndLines(const UnownedStringSlice& lines, UnownedStringSlice& outStart, UnownedStringSlice& outEnd); }; } diff --git a/source/core/slang-io.h b/source/core/slang-io.h index 758a05edb..a42a6991b 100644 --- a/source/core/slang-io.h +++ b/source/core/slang-io.h @@ -91,8 +91,12 @@ namespace Slang }; // Helper class to clean up temporary files on dtor - struct TemporaryFileSet + class TemporaryFileSet: public RefObject { + public: + typedef RefObject Super; + typedef TemporaryFileSet ThisType; + void remove(const String& path) { if (const Index index = m_paths.indexOf(path) >= 0) @@ -119,6 +123,12 @@ namespace Slang { m_paths.clear(); } + + void swapWith(ThisType& rhs) + { + m_paths.swapWith(rhs.m_paths); + } + ~TemporaryFileSet() { for (const auto& path : m_paths) @@ -126,7 +136,15 @@ namespace Slang File::remove(path); } } + /// Default Ctor + TemporaryFileSet() {} + List<String> m_paths; + + private: + // Disable ctor/assignment + TemporaryFileSet(const ThisType& rhs) = delete; + void operator=(const ThisType& rhs) = delete; }; } diff --git a/source/core/slang-shared-library.h b/source/core/slang-shared-library.h index 675ee5cae..517292908 100644 --- a/source/core/slang-shared-library.h +++ b/source/core/slang-shared-library.h @@ -103,7 +103,7 @@ public: virtual ~TemporarySharedLibrary(); /// Any files specified in this set will be deleted on exit - TemporaryFileSet m_temporaryFileSet; + RefPtr<TemporaryFileSet> m_temporaryFileSet; protected: String m_path; diff --git a/source/core/slang-string-util.cpp b/source/core/slang-string-util.cpp index 4295a2c52..cd79ffce7 100644 --- a/source/core/slang-string-util.cpp +++ b/source/core/slang-string-util.cpp @@ -1,17 +1,8 @@ #include "slang-string-util.h" -namespace Slang { - -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! StringBlob !!!!!!!!!!!!!!!!!!!!!!!!!!! - -// Allocate static const storage for the various interface IDs that the Slang API needs to expose -static const Guid IID_ISlangUnknown = SLANG_UUID_ISlangUnknown; -static const Guid IID_ISlangBlob = SLANG_UUID_ISlangBlob; +#include "slang-blob.h" -/* static */ISlangUnknown* StringBlob::getInterface(const Guid& guid) -{ - return (guid == IID_ISlangUnknown || guid == IID_ISlangBlob) ? static_cast<ISlangBlob*>(this) : nullptr; -} +namespace Slang { // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! StringUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/source/core/slang-string-util.h b/source/core/slang-string-util.h index 77b7ca2a3..16588bd35 100644 --- a/source/core/slang-string-util.h +++ b/source/core/slang-string-util.h @@ -11,30 +11,6 @@ namespace Slang { -/** A blob that uses a `String` for its storage. -*/ -class StringBlob : public ISlangBlob, public RefObject -{ -public: - // ISlangUnknown - SLANG_REF_OBJECT_IUNKNOWN_ALL - - // ISlangBlob - SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_string.getBuffer(); } - SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_string.getLength(); } - - /// Get the contained string - SLANG_FORCE_INLINE const String& getString() const { return m_string; } - - explicit StringBlob(String const& string) - : m_string(string) - {} - -protected: - ISlangUnknown* getInterface(const Guid& guid); - String m_string; -}; - struct StringUtil { /// Split in, by specified splitChar into slices out diff --git a/source/core/slang-visual-studio-compiler-util.cpp b/source/core/slang-visual-studio-compiler-util.cpp index 8b4598b43..8797c3384 100644 --- a/source/core/slang-visual-studio-compiler-util.cpp +++ b/source/core/slang-visual-studio-compiler-util.cpp @@ -12,6 +12,8 @@ namespace Slang /* static */ SlangResult VisualStudioCompilerUtil::calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath) { + SLANG_ASSERT(options.modulePath.getLength()); + outPath.Clear(); switch (options.targetType) @@ -39,6 +41,8 @@ namespace Slang /* static */SlangResult VisualStudioCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, List<String>& outPaths) { + SLANG_ASSERT(options.modulePath.getLength()); + outPaths.clear(); if (flags & ProductFlag::Execution) @@ -72,6 +76,9 @@ namespace Slang /* static */SlangResult VisualStudioCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine) { + SLANG_ASSERT(options.sourceContents.getLength() == 0); + SLANG_ASSERT(options.modulePath.getLength()); + // https://docs.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-alphabetically?view=vs-2019 cmdLine.addArg("/nologo"); @@ -242,9 +249,9 @@ namespace Slang return SLANG_OK; } -static SlangResult _parseErrorType(const UnownedStringSlice& in, CPPCompiler::Diagnostic::Type& outType) +static SlangResult _parseErrorType(const UnownedStringSlice& in, DownstreamDiagnostics::Diagnostic::Type& outType) { - typedef CPPCompiler::Diagnostic::Type Type; + typedef DownstreamDiagnostics::Diagnostic::Type Type; if (in == "error" || in == "fatal error") { @@ -265,9 +272,9 @@ static SlangResult _parseErrorType(const UnownedStringSlice& in, CPPCompiler::Di return SLANG_OK; } -static SlangResult _parseVisualStudioLine(const UnownedStringSlice& line, CPPCompiler::Diagnostic& outDiagnostic) +static SlangResult _parseVisualStudioLine(const UnownedStringSlice& line, DownstreamDiagnostics::Diagnostic& outDiagnostic) { - typedef CPPCompiler::Diagnostic Diagnostic; + typedef DownstreamDiagnostics::Diagnostic Diagnostic; UnownedStringSlice linkPrefix = UnownedStringSlice::fromLiteral("LINK :"); if (line.startsWith(linkPrefix)) @@ -389,11 +396,11 @@ static SlangResult _parseVisualStudioLine(const UnownedStringSlice& line, CPPCom return SLANG_OK; } -/* static */SlangResult VisualStudioCompilerUtil::parseOutput(const ExecuteResult& exeRes, CPPCompiler::Output& outOutput) +/* static */SlangResult VisualStudioCompilerUtil::parseOutput(const ExecuteResult& exeRes, DownstreamDiagnostics& outDiagnostics) { - outOutput.reset(); + outDiagnostics.reset(); - outOutput.rawDiagnostics = exeRes.standardOutput; + outDiagnostics.rawDiagnostics = exeRes.standardOutput; for (auto line : LineParser(exeRes.standardOutput.getUnownedSlice())) { @@ -402,17 +409,17 @@ static SlangResult _parseVisualStudioLine(const UnownedStringSlice& line, CPPCom fprintf(stdout, "\n"); #endif - CPPCompiler::Diagnostic diagnostic; + Diagnostic diagnostic; if (SLANG_SUCCEEDED(_parseVisualStudioLine(line, diagnostic))) { - outOutput.diagnostics.add(diagnostic); + outDiagnostics.diagnostics.add(diagnostic); } } // if it has a compilation error.. set on output - if (outOutput.has(CPPCompiler::Diagnostic::Type::Error)) + if (outDiagnostics.has(Diagnostic::Type::Error)) { - outOutput.result = SLANG_FAIL; + outDiagnostics.result = SLANG_FAIL; } return SLANG_OK; diff --git a/source/core/slang-visual-studio-compiler-util.h b/source/core/slang-visual-studio-compiler-util.h index 1e2fbb318..3571f4b42 100644 --- a/source/core/slang-visual-studio-compiler-util.h +++ b/source/core/slang-visual-studio-compiler-util.h @@ -1,37 +1,37 @@ #ifndef SLANG_VISUAL_STUDIO_COMPILER_UTIL_H #define SLANG_VISUAL_STUDIO_COMPILER_UTIL_H -#include "slang-cpp-compiler.h" +#include "slang-downstream-compiler.h" namespace Slang { -struct VisualStudioCompilerUtil : public CPPCompilerBaseUtil +struct VisualStudioCompilerUtil : public DownstreamCompilerBaseUtil { /// Calculate Visual Studio family compilers cmdLine arguments from options static SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine); /// Parse Visual Studio exeRes into CPPCompiler::Output - static SlangResult parseOutput(const ExecuteResult& exeRes, CPPCompiler::Output& outOutput); + static SlangResult parseOutput(const ExecuteResult& exeRes, DownstreamDiagnostics& outOutput); static SlangResult calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath); static SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, List<String>& outPaths); }; -class VisualStudioCPPCompiler : public CommandLineCPPCompiler +class VisualStudioDownstreamCompiler : public CommandLineDownstreamCompiler { public: - typedef CommandLineCPPCompiler Super; + typedef CommandLineDownstreamCompiler Super; typedef VisualStudioCompilerUtil Util; - // CommandLineCPPCompiler impl - just forwards to the Util + // CommandLineDownstreamCompiler impl - just forwards to the Util virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE { return Util::calcArgs(options, cmdLine); } - virtual SlangResult parseOutput(const ExecuteResult& exeResult, Output& output) SLANG_OVERRIDE { return Util::parseOutput(exeResult, output); } + 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); } - VisualStudioCPPCompiler(const Desc& desc):Super(desc) {} + VisualStudioDownstreamCompiler(const Desc& desc):Super(desc) {} }; diff --git a/source/core/windows/slang-win-visual-studio-util.cpp b/source/core/windows/slang-win-visual-studio-util.cpp index 260f3f56f..078406d99 100644 --- a/source/core/windows/slang-win-visual-studio-util.cpp +++ b/source/core/windows/slang-win-visual-studio-util.cpp @@ -278,7 +278,7 @@ static SlangResult _find(int versionIndex, WinVisualStudioUtil::VersionPath& out return SLANG_FAIL; } -/* static */SlangResult WinVisualStudioUtil::find(CPPCompilerSet* set) +/* static */SlangResult WinVisualStudioUtil::find(DownstreamCompilerSet* set) { const int versionCount = SLANG_COUNT_OF(s_versionInfos); @@ -290,7 +290,7 @@ static SlangResult _find(int versionIndex, WinVisualStudioUtil::VersionPath& out VersionPath versionPath; if (!set->getCompiler(desc) && SLANG_SUCCEEDED(_find(i, versionPath))) { - RefPtr<CommandLineCPPCompiler> compiler = new VisualStudioCPPCompiler(desc); + RefPtr<CommandLineDownstreamCompiler> compiler = new VisualStudioDownstreamCompiler(desc); calcExecuteCompilerArgs(versionPath, compiler->m_cmdLine); set->addCompiler(compiler); } diff --git a/source/core/windows/slang-win-visual-studio-util.h b/source/core/windows/slang-win-visual-studio-util.h index 34be8473d..1122fccb7 100644 --- a/source/core/windows/slang-win-visual-studio-util.h +++ b/source/core/windows/slang-win-visual-studio-util.h @@ -6,7 +6,7 @@ #include "../slang-process-util.h" -#include "../slang-cpp-compiler.h" +#include "../slang-downstream-compiler.h" namespace Slang { @@ -31,7 +31,7 @@ struct WinVisualStudioUtil static SlangResult find(Version version, VersionPath& outPath); /// Find and add to the set (if not already there) - static SlangResult find(CPPCompilerSet* set); + static SlangResult find(DownstreamCompilerSet* set); /// Create the cmdLine to start compiler for specified path static void calcExecuteCompilerArgs(const VersionPath& versionPath, CommandLine& outCmdLine); @@ -52,10 +52,10 @@ struct WinVisualStudioUtil static void append(Version version, StringBuilder& outBuilder); /// Get version as desc - static CPPCompiler::Desc getDesc(Version version) + static DownstreamCompiler::Desc getDesc(Version version) { - CPPCompiler::Desc desc; - desc.type = CPPCompiler::CompilerType::VisualStudio; + DownstreamCompiler::Desc desc; + desc.type = DownstreamCompiler::CompilerType::VisualStudio; desc.majorVersion = Int(version) / 10; desc.minorVersion = Int(version) % 10; return desc; diff --git a/source/slang/slang-check.cpp b/source/slang/slang-check.cpp index 704d37d01..3586fcf25 100644 --- a/source/slang/slang-check.cpp +++ b/source/slang/slang-check.cpp @@ -121,20 +121,20 @@ namespace Slang return func; } - CPPCompilerSet* Session::requireCPPCompilerSet() + DownstreamCompilerSet* Session::requireCPPCompilerSet() { if (cppCompilerSet == nullptr) { - cppCompilerSet = new CPPCompilerSet; + cppCompilerSet = new DownstreamCompilerSet; - typedef CPPCompiler::CompilerType CompilerType; - CPPCompilerUtil::InitializeSetDesc desc; + typedef DownstreamCompiler::CompilerType CompilerType; + DownstreamCompilerUtil::InitializeSetDesc desc; desc.paths[int(CompilerType::GCC)] = m_downstreamCompilerPaths[int(PassThroughMode::Gcc)]; desc.paths[int(CompilerType::Clang)] = m_downstreamCompilerPaths[int(PassThroughMode::Clang)]; desc.paths[int(CompilerType::VisualStudio)] = m_downstreamCompilerPaths[int(PassThroughMode::VisualStudio)]; - CPPCompilerUtil::initializeSet(desc, cppCompilerSet); + DownstreamCompilerUtil::initializeSet(desc, cppCompilerSet); } SLANG_ASSERT(cppCompilerSet); return cppCompilerSet; diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 6cb3603b9..9ac49f60c 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -130,48 +130,16 @@ namespace Slang return StringUtil::getAtInSplit(s_codeGenTargetInfos[int(target)].names, ',', 0); } - // CompileResult - - void CompileResult::append(CompileResult const& result) - { - // Find which to append to - ResultFormat appendTo = ResultFormat::None; - - if (format == ResultFormat::None) - { - format = result.format; - appendTo = result.format; - } - else if (format == result.format) - { - appendTo = format; - } - - if (appendTo == ResultFormat::Text) - { - outputString.append(result.outputString.getBuffer()); - } - else if (appendTo == ResultFormat::Binary) - { - outputBinary.addRange(result.outputBinary.getBuffer(), result.outputBinary.getCount()); - } - else if (appendTo == ResultFormat::SharedLibrary) - { - SLANG_ASSERT(!"Trying to append to a shared library"); - } - } - SlangResult CompileResult::getSharedLibrary(ComPtr<ISlangSharedLibrary>& outSharedLibrary) { - if (format == ResultFormat::SharedLibrary && sharedLibrary) + if (downstreamResult) { - outSharedLibrary = sharedLibrary; - return SLANG_OK; + return downstreamResult->getHostCallableSharedLibrary(outSharedLibrary); } return SLANG_FAIL; } - SlangResult CompileResult::getBlob(ComPtr<ISlangBlob>& outBlob) + SlangResult CompileResult::getBlob(ComPtr<ISlangBlob>& outBlob) const { if(!blob) { @@ -184,28 +152,12 @@ namespace Slang case ResultFormat::Text: blob = StringUtil::createStringBlob(outputString); break; - case ResultFormat::Binary: - blob = createRawBlob(outputBinary.getBuffer(), outputBinary.getCount()); - break; - case ResultFormat::SharedLibrary: { - // TODO(JS): Could do something more sophisticated to check this cast is safe (like have an interface to get the path), but this - // is simple and works with current impl - TemporarySharedLibrary* tempLibrary = static_cast<TemporarySharedLibrary*>(sharedLibrary.get()); - - SLANG_ASSERT(sharedLibrary); - List<uint8_t> contents; - try + if (downstreamResult) { - // We can read it from the shared library... - contents = File::readAllBytes(tempLibrary->getPath()); + SLANG_RETURN_ON_FAIL(downstreamResult->getBinary(blob)); } - catch (const Slang::IOException&) - { - return SLANG_E_CANNOT_OPEN; - } - blob = createRawBlob(contents.getBuffer(), contents.getCount()); break; } } @@ -520,19 +472,19 @@ namespace Slang } case PassThroughMode::Clang: { - return session->requireCPPCompilerSet()->hasCompiler(CPPCompiler::CompilerType::Clang) ? SLANG_OK: SLANG_E_NOT_FOUND; + return session->requireCPPCompilerSet()->hasCompiler(DownstreamCompiler::CompilerType::Clang) ? SLANG_OK: SLANG_E_NOT_FOUND; } case PassThroughMode::VisualStudio: { - return session->requireCPPCompilerSet()->hasCompiler(CPPCompiler::CompilerType::VisualStudio) ? SLANG_OK: SLANG_E_NOT_FOUND; + return session->requireCPPCompilerSet()->hasCompiler(DownstreamCompiler::CompilerType::VisualStudio) ? SLANG_OK: SLANG_E_NOT_FOUND; } case PassThroughMode::Gcc: { - return session->requireCPPCompilerSet()->hasCompiler(CPPCompiler::CompilerType::GCC) ? SLANG_OK: SLANG_E_NOT_FOUND; + return session->requireCPPCompilerSet()->hasCompiler(DownstreamCompiler::CompilerType::GCC) ? SLANG_OK: SLANG_E_NOT_FOUND; } case PassThroughMode::GenericCCpp: { - List<CPPCompiler::Desc> descs; + List<DownstreamCompiler::Desc> descs; session->requireCPPCompilerSet()->getCompilerDescs(descs); return descs.getCount() ? SLANG_OK: SLANG_E_NOT_FOUND; @@ -597,9 +549,9 @@ namespace Slang return PassThroughMode::None; } - PassThroughMode getPassThroughModeForCPPCompiler(CPPCompiler::CompilerType type) + PassThroughMode getPassThroughModeForCPPCompiler(DownstreamCompiler::CompilerType type) { - typedef CPPCompiler::CompilerType CompilerType; + typedef DownstreamCompiler::CompilerType CompilerType; switch (type) { @@ -1330,8 +1282,7 @@ SlangResult dissassembleDXILUsingDXC( Int entryPointIndex, TargetRequest* targetReq, EndToEndCompileRequest* endToEndReq, - ComPtr<ISlangSharedLibrary>& outSharedLib, - List<uint8_t>& outBin) + RefPtr<DownstreamCompileResult>& outResult) { auto sink = slangRequest->getSink(); @@ -1339,9 +1290,8 @@ SlangResult dissassembleDXILUsingDXC( const String originalSourcePath = calcSourcePathForEntryPoint(endToEndReq, entryPointIndex); - outBin.clear(); - outSharedLib.setNull(); - + outResult.setNull(); + PassThroughMode downstreamCompiler = endToEndReq->passThrough; // If we are not in pass through, lookup the default compiler for the emitted source type @@ -1351,7 +1301,7 @@ SlangResult dissassembleDXILUsingDXC( } // Get the required downstream CPP compiler - CPPCompiler* compiler = session->getCPPCompiler(downstreamCompiler); + DownstreamCompiler* compiler = session->getDownstreamCompiler(downstreamCompiler); if (!compiler) { @@ -1367,19 +1317,14 @@ SlangResult dissassembleDXILUsingDXC( return SLANG_FAIL; } - TemporaryFileSet temporaryFileSet; - - bool useOriginalFile = false; - - String compileSourcePath; - - String rawSource; - SourceLanguage rawSourceLanguage = SourceLanguage::Unknown; Dictionary<String, String> preprocessorDefinitions; List<String> includePaths; + typedef DownstreamCompiler::CompileOptions CompileOptions; + CompileOptions options; + /* This is more convoluted than the other scenarios, because when we invoke C/C++ compiler we would ideally like to use the original file. We want to do this because we want includes relative to the source file to work, and for that to work most easily we want to use the original file, if there is one */ @@ -1437,7 +1382,7 @@ SlangResult dissassembleDXILUsingDXC( const PathInfo& pathInfo = sourceFile->getPathInfo(); if (pathInfo.type == PathInfo::Type::FoundPath || pathInfo.type == PathInfo::Type::Normal) { - compileSourcePath = pathInfo.foundPath; + String compileSourcePath = pathInfo.foundPath; // We can see if we can load it if (File::exists(compileSourcePath)) { @@ -1454,7 +1399,11 @@ SlangResult dissassembleDXILUsingDXC( { String readContents = File::readAllText(compileSourcePath); // We should see if they are the same - useOriginalFile = (sourceFile->getContent() == readContents.getUnownedSlice()); + if ((sourceFile->getContent() == readContents.getUnownedSlice())) + { + // We just say use this file + options.sourceFiles.add(compileSourcePath); + } } catch (const Slang::IOException&) { @@ -1463,114 +1412,53 @@ SlangResult dissassembleDXILUsingDXC( } } - if (!useOriginalFile) + // If can't just use file, concat together and make + if (options.sourceFiles.getCount() == 0) { StringBuilder codeBuilder; for (auto sourceFile : translationUnit->getSourceFiles()) { _appendCodeWithPath(sourceFile->getPathInfo().foundPath.getUnownedSlice(), sourceFile->getContent(), codeBuilder); } - rawSource = codeBuilder.ProduceString(); + options.sourceContents = codeBuilder.ProduceString(); } } else { - rawSource = emitCPPForEntryPoint( + options.sourceContents = emitCPPForEntryPoint( slangRequest, entryPointIndex, targetReq, endToEndReq); - maybeDumpIntermediate(slangRequest, rawSource.getBuffer(), CodeGenTarget::CPPSource); + maybeDumpIntermediate(slangRequest, options.sourceContents.getBuffer(), CodeGenTarget::CPPSource); rawSourceLanguage = SourceLanguage::CPP; } - // Generate a path a temporary filename for output module - String modulePath; - SLANG_RETURN_ON_FAIL(File::generateTemporary(UnownedStringSlice::fromLiteral("slang-generated"), modulePath)); - - if (!useOriginalFile) - { - // We need to create a new file which has the source. We'll use the module generated name as the basis - compileSourcePath = modulePath; - - // NOTE: Strictly speaking producing filenames by modifying the generateTemporary path that may introduce a temp filename clash, but in practice is extraordinary unlikely - - compileSourcePath.append("-src"); - - // Make the temporary filename have the appropriate extension. - if (rawSourceLanguage == SourceLanguage::C) - { - compileSourcePath.append(".c"); - } - else - { - compileSourcePath.append(".cpp"); - } - - // Delete this path at end of execution - temporaryFileSet.add(compileSourcePath); - - try - { - File::writeAllText(compileSourcePath, rawSource); - } - catch (...) - { - sink->diagnose(SourceLoc(), Diagnostics::unableToWriteFile, compileSourcePath); - return SLANG_FAIL; - } - } - - typedef CPPCompiler::CompileOptions CompileOptions; - CompileOptions options; - // Set the source type - options.sourceType = (rawSourceLanguage == SourceLanguage::C) ? CPPCompiler::SourceType::C : CPPCompiler::SourceType::CPP; + options.sourceType = (rawSourceLanguage == SourceLanguage::C) ? DownstreamCompiler::SourceType::C : DownstreamCompiler::SourceType::CPP; // Disable exceptions and security checks options.flags &= ~(CompileOptions::Flag::EnableExceptionHandling | CompileOptions::Flag::EnableSecurityChecks); - // Remove the temporary path/file when done - temporaryFileSet.add(modulePath); - - options.modulePath = modulePath; - options.sourceFiles.add(compileSourcePath); - // Set what kind of target we should build switch (targetReq->target) { case CodeGenTarget::HostCallable: case CodeGenTarget::SharedLibrary: { - options.targetType = CPPCompiler::TargetType::SharedLibrary; + options.targetType = DownstreamCompiler::TargetType::SharedLibrary; break; } case CodeGenTarget::Executable: { - options.targetType = CPPCompiler::TargetType::Executable; + options.targetType = DownstreamCompiler::TargetType::Executable; break; } default: break; } - String moduleFilePath; - - { - StringBuilder builder; - SLANG_RETURN_ON_FAIL(compiler->calcModuleFilePath(options, builder)); - moduleFilePath = builder.ProduceString(); - } - - // Find all the files that will be produced - TemporaryFileSet productFileSet; - { - List<String> paths; - SLANG_RETURN_ON_FAIL(compiler->calcCompileProducts(options, CPPCompiler::ProductFlag::All, paths)); - productFileSet.add(paths); - } - // Need to configure for the compilation { @@ -1578,28 +1466,28 @@ SlangResult dissassembleDXILUsingDXC( switch (linkage->optimizationLevel) { - case OptimizationLevel::None: options.optimizationLevel = CPPCompiler::OptimizationLevel::None; break; - case OptimizationLevel::Default: options.optimizationLevel = CPPCompiler::OptimizationLevel::Default; break; - case OptimizationLevel::High: options.optimizationLevel = CPPCompiler::OptimizationLevel::High; break; - case OptimizationLevel::Maximal: options.optimizationLevel = CPPCompiler::OptimizationLevel::Maximal; break; + 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; default: SLANG_ASSERT(!"Unhandled optimization level"); break; } switch (linkage->debugInfoLevel) { - case DebugInfoLevel::None: options.debugInfoType = CPPCompiler::DebugInfoType::None; break; - case DebugInfoLevel::Minimal: options.debugInfoType = CPPCompiler::DebugInfoType::Minimal; break; + case DebugInfoLevel::None: options.debugInfoType = DownstreamCompiler::DebugInfoType::None; break; + case DebugInfoLevel::Minimal: options.debugInfoType = DownstreamCompiler::DebugInfoType::Minimal; break; - case DebugInfoLevel::Standard: options.debugInfoType = CPPCompiler::DebugInfoType::Standard; break; - case DebugInfoLevel::Maximal: options.debugInfoType = CPPCompiler::DebugInfoType::Maximal; break; + case DebugInfoLevel::Standard: options.debugInfoType = DownstreamCompiler::DebugInfoType::Standard; break; + case DebugInfoLevel::Maximal: options.debugInfoType = DownstreamCompiler::DebugInfoType::Maximal; break; default: SLANG_ASSERT(!"Unhandled debug level"); break; } switch( targetReq->floatingPointMode ) { - case FloatingPointMode::Default: options.floatingPointMode = CPPCompiler::FloatingPointMode::Default; break; - case FloatingPointMode::Precise: options.floatingPointMode = CPPCompiler::FloatingPointMode::Precise; break; - case FloatingPointMode::Fast: options.floatingPointMode = CPPCompiler::FloatingPointMode::Fast; break; + 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; default: SLANG_ASSERT(!"Unhanlde floating point mode"); } @@ -1610,7 +1498,7 @@ SlangResult dissassembleDXILUsingDXC( { for(auto& def : preprocessorDefinitions) { - CPPCompiler::Define define; + DownstreamCompiler::Define define; define.nameWithSig = def.Key; define.value = def.Value; @@ -1620,8 +1508,10 @@ SlangResult dissassembleDXILUsingDXC( } // Compile - CPPCompiler::Output output; - SLANG_RETURN_ON_FAIL(compiler->compile(options, output)); + RefPtr<DownstreamCompileResult> downstreamCompileResult; + SLANG_RETURN_ON_FAIL(compiler->compile(options, downstreamCompileResult)); + + const auto& diagnostics = downstreamCompileResult->getDiagnostics(); { StringBuilder compilerText; @@ -1629,9 +1519,9 @@ SlangResult dissassembleDXILUsingDXC( StringBuilder builder; - typedef CPPCompiler::Diagnostic Diagnostic; + typedef DownstreamDiagnostic Diagnostic; - for (const auto& diagnostic : output.diagnostics) + for (const auto& diagnostic : diagnostics.diagnostics) { builder.Clear(); @@ -1676,63 +1566,12 @@ SlangResult dissassembleDXILUsingDXC( } // If any errors are emitted, then we are done - if (output.has(CPPCompiler::Diagnostic::Type::Error)) + if (diagnostics.has(DownstreamDiagnostic::Type::Error)) { return SLANG_FAIL; } - // If callable we need to load the shared library - if (targetReq->target == CodeGenTarget::HostCallable) - { - // Try loading the shared library - SharedLibrary::Handle handle; - if (SLANG_FAILED(SharedLibrary::loadWithPlatformPath(moduleFilePath.getBuffer(), handle))) - { - sink->diagnose(SourceLoc(), Diagnostics::unableToReadFile, moduleFilePath); - return SLANG_FAIL; - } - RefPtr<TemporarySharedLibrary> sharedLib(new TemporarySharedLibrary(handle, moduleFilePath)); - sharedLib->m_temporaryFileSet = productFileSet; - productFileSet.clear(); - - // Copy the paths in the temporary file set - // We particularly want to do this to keep the source - sharedLib->m_temporaryFileSet.add(temporaryFileSet.m_paths); - temporaryFileSet.clear(); - - // Output the shared library - outSharedLib = sharedLib; - } - else - { - // Read the binary - try - { - // TODO(JS): We have a problem here.. productFileSet will clear up all temporaries - // and although we return the binary here (through outBin), we don't return debug info - // which is separate (say with a pdb). To work around this we reevaluate productFileSet, - // so we don't include debug info. The executable will presumably be reconstructed from - // outBin - // The problem is that these files have no specific lifetime (unlike with HostCallable). - - CPPCompiler::ProductFlags flags = CPPCompiler::ProductFlag::All; - flags &= ~CPPCompiler::ProductFlag::Debug; - - List<String> paths; - SLANG_RETURN_ON_FAIL(compiler->calcCompileProducts(options, flags, paths)); - productFileSet.clear(); - productFileSet.add(paths); - - // Read the contents of the binary - outBin = File::readAllBytes(moduleFilePath); - } - catch (const Slang::IOException&) - { - sink->diagnose(SourceLoc(), Diagnostics::unableToReadFile, moduleFilePath); - return SLANG_FAIL; - } - } - + outResult = downstreamCompileResult; return SLANG_OK; } @@ -1851,26 +1690,18 @@ SlangResult dissassembleDXILUsingDXC( case CodeGenTarget::SharedLibrary: case CodeGenTarget::Executable: { - ComPtr<ISlangSharedLibrary> sharedLibrary; + RefPtr<DownstreamCompileResult> downstreamResult; - List<uint8_t> code; if (SLANG_SUCCEEDED(emitCPUBinaryForEntryPoint( compileRequest, entryPointIndex, targetReq, endToEndReq, - sharedLibrary, - code))) + downstreamResult))) { - if (target == CodeGenTarget::HostCallable) - { - result = CompileResult(sharedLibrary); - } - else - { - maybeDumpIntermediate(compileRequest, code.getBuffer(), code.getCount(), target); - result = CompileResult(code); - } + maybeDumpIntermediate(compileRequest, downstreamResult, target); + + result = CompileResult(downstreamResult); } } break; @@ -1901,11 +1732,13 @@ SlangResult dissassembleDXILUsingDXC( case CodeGenTarget::CPPSource: case CodeGenTarget::CSource: { - return emitEntryPointSource( + String code = emitEntryPointSource( compileRequest, entryPointIndex, target, targetReq); + maybeDumpIntermediate(compileRequest, code.getBuffer(), target); + result = CompileResult(code); } break; @@ -1922,7 +1755,8 @@ SlangResult dissassembleDXILUsingDXC( code))) { maybeDumpIntermediate(compileRequest, code.getBuffer(), code.getCount(), target); - result = CompileResult(code); + + result = CompileResult(ListBlob::moveCreate(code)); } } break; @@ -1958,7 +1792,7 @@ SlangResult dissassembleDXILUsingDXC( code))) { maybeDumpIntermediate(compileRequest, code.getBuffer(), code.getCount(), target); - result = CompileResult(code); + result = CompileResult(ListBlob::moveCreate(code)); } } break; @@ -1983,7 +1817,8 @@ SlangResult dissassembleDXILUsingDXC( maybeDumpIntermediate(compileRequest, assembly.getBuffer(), target); - result = CompileResult(assembly); + // Write as text, even if stored in uint8_t array + result = CompileResult(UnownedStringSlice((const char*)code.getBuffer(), code.getCount())); } } break; @@ -2001,7 +1836,7 @@ SlangResult dissassembleDXILUsingDXC( code))) { maybeDumpIntermediate(compileRequest, code.getBuffer(), code.getCount(), target); - result = CompileResult(code); + result = CompileResult(ListBlob::moveCreate(code)); } } break; @@ -2125,11 +1960,12 @@ SlangResult dissassembleDXILUsingDXC( case ResultFormat::Binary: { - auto& data = result.outputBinary; + ComPtr<ISlangBlob> blob; + result.getBlob(blob); writeOutputFile(compileRequest, outputPath, - data.begin(), - data.end() - data.begin(), + blob->getBufferPointer(), + blob->getBufferSize(), OutputFileKind::Binary); } break; @@ -2165,13 +2001,18 @@ SlangResult dissassembleDXILUsingDXC( writeOutputToConsole(writer, result.outputString); break; - case ResultFormat::SharedLibrary: - break; - case ResultFormat::Binary: { - auto& data = result.outputBinary; - + ComPtr<ISlangBlob> blob; + if (SLANG_FAILED(result.getBlob(blob))) + { + return; + } + + const void* blobData = blob->getBufferPointer(); + size_t blobSize = blob->getBufferSize(); + + if (writer->isConsole()) { // Writing to console, so we need to generate text output. @@ -2182,9 +2023,7 @@ SlangResult dissassembleDXILUsingDXC( case CodeGenTarget::DXBytecode: { String assembly; - dissassembleDXBC(backEndReq, - data.begin(), - data.end() - data.begin(), assembly); + dissassembleDXBC(backEndReq, blobData, blobSize, assembly); writeOutputToConsole(writer, assembly); } break; @@ -2194,10 +2033,7 @@ SlangResult dissassembleDXILUsingDXC( case CodeGenTarget::DXIL: { String assembly; - dissassembleDXILUsingDXC(backEndReq, - data.begin(), - data.end() - data.begin(), - assembly); + dissassembleDXILUsingDXC(backEndReq, blobData, blobSize, assembly); writeOutputToConsole(writer, assembly); } break; @@ -2206,16 +2042,15 @@ SlangResult dissassembleDXILUsingDXC( case CodeGenTarget::SPIRV: { String assembly; - dissassembleSPIRV(backEndReq, - data.begin(), - data.end() - data.begin(), assembly); + dissassembleSPIRV(backEndReq, blobData, blobSize, assembly); writeOutputToConsole(writer, assembly); } break; + case CodeGenTarget::HostCallable: case CodeGenTarget::SharedLibrary: case CodeGenTarget::Executable: - HexDumpUtil::dumpWithMarkers(data, 24, writer); + HexDumpUtil::dumpWithMarkers((const uint8_t*)blobData, blobSize, 24, writer); break; default: @@ -2232,8 +2067,8 @@ SlangResult dissassembleDXILUsingDXC( backEndReq, writer, "stdout", - data.begin(), - data.end() - data.begin()); + blobData, + blobSize); } } break; @@ -2627,6 +2462,21 @@ SlangResult dissassembleDXILUsingDXC( void maybeDumpIntermediate( BackEndCompileRequest* compileRequest, + DownstreamCompileResult* compileResult, + CodeGenTarget target) + { + if (!compileRequest->shouldDumpIntermediates) + return; + + ComPtr<ISlangBlob> blob; + if (SLANG_SUCCEEDED(compileResult->getBinary(blob))) + { + maybeDumpIntermediate(compileRequest, blob->getBufferPointer(), blob->getBufferSize(), target); + } + } + + void maybeDumpIntermediate( + BackEndCompileRequest* compileRequest, void const* data, size_t size, CodeGenTarget target) diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 9950764e4..c33b2cf28 100644 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -4,7 +4,7 @@ #include "../core/slang-basic.h" #include "../core/slang-shared-library.h" -#include "../core/slang-cpp-compiler.h" +#include "../core/slang-downstream-compiler.h" #include "../../slang-com-ptr.h" @@ -92,7 +92,6 @@ namespace Slang None, Text, Binary, - SharedLibrary, }; // When storing the layout for a matrix-type @@ -135,21 +134,20 @@ namespace Slang { public: CompileResult() = default; - CompileResult(String const& str) : format(ResultFormat::Text), outputString(str) {} - CompileResult(List<uint8_t> const& buffer) : format(ResultFormat::Binary), outputBinary(buffer) {} - CompileResult(ISlangSharedLibrary* inSharedLibrary) : format(ResultFormat::SharedLibrary), sharedLibrary(inSharedLibrary) {} + explicit CompileResult(String const& str) : format(ResultFormat::Text), outputString(str) {} + explicit CompileResult(ISlangBlob* inBlob) : format(ResultFormat::Binary), blob(inBlob) {} + explicit CompileResult(DownstreamCompileResult* inDownstreamResult): format(ResultFormat::Binary), downstreamResult(inDownstreamResult) {} + explicit CompileResult(const UnownedStringSlice& slice ) : format(ResultFormat::Text), outputString(slice) {} - void append(CompileResult const& result); - - SlangResult getBlob(ComPtr<ISlangBlob>& outBlob); + SlangResult getBlob(ComPtr<ISlangBlob>& outBlob) const; SlangResult getSharedLibrary(ComPtr<ISlangSharedLibrary>& outSharedLibrary); ResultFormat format = ResultFormat::None; - String outputString; - List<uint8_t> outputBinary; + String outputString; ///< Only set if result type is ResultFormat::Text + + mutable ComPtr<ISlangBlob> blob; - ComPtr<ISlangSharedLibrary> sharedLibrary; - ComPtr<ISlangBlob> blob; + RefPtr<DownstreamCompileResult> downstreamResult; }; /// Information collected about global or entry-point shader parameters @@ -1073,15 +1071,10 @@ namespace Slang List<SearchDirectory> searchDirectories; }; - /// Create a blob that will retain (a copy of) raw data. - /// - ComPtr<ISlangBlob> createRawBlob(void const* data, size_t size); - - /// Given a target returns the required downstream compiler PassThroughMode getDownstreamCompilerRequiredForTarget(CodeGenTarget target); - PassThroughMode getPassThroughModeForCPPCompiler(CPPCompiler::CompilerType type); + PassThroughMode getPassThroughModeForCPPCompiler(DownstreamCompiler::CompilerType type); /// A context for loading and re-using code modules. @@ -1777,6 +1770,11 @@ namespace Slang char const* text, CodeGenTarget target); + void maybeDumpIntermediate( + BackEndCompileRequest* compileRequest, + DownstreamCompileResult* compileResult, + CodeGenTarget target); + /* Returns SLANG_OK if a codeGen target is available. */ SlangResult checkCompileTargetSupport(Session* session, CodeGenTarget target); /* Returns SLANG_OK if pass through support is available */ @@ -1836,9 +1834,9 @@ namespace Slang SLANG_NO_THROW SlangPassThrough SLANG_MCALL getDefaultDownstreamCompiler(SlangSourceLanguage sourceLanguage) override; /// Get the specified compiler - CPPCompiler* getCPPCompiler(PassThroughMode downstreamCompiler); + DownstreamCompiler* getDownstreamCompiler(PassThroughMode downstreamCompiler); /// Get the default cpp compiler for a language - CPPCompiler* getDefaultCPPCompiler(SourceLanguage sourceLanguage); + DownstreamCompiler* getDefaultCPPCompiler(SourceLanguage sourceLanguage); enum class SharedLibraryFuncType { @@ -1894,7 +1892,7 @@ namespace Slang RefPtr<Type> stringType; RefPtr<Type> enumTypeType; - RefPtr<CPPCompilerSet> cppCompilerSet; ///< Information about available C/C++ compilers. null unless information is requested (because slow) + RefPtr<DownstreamCompilerSet> cppCompilerSet; ///< Information about available C/C++ compilers. null unless information is requested (because slow) ComPtr<ISlangSharedLibraryLoader> sharedLibraryLoader; ///< The shared library loader (never null) ComPtr<ISlangSharedLibrary> sharedLibraries[int(SharedLibraryType::CountOf)]; ///< The loaded shared libraries @@ -1976,7 +1974,7 @@ namespace Slang const String& getDownstreamCompilerPrelude(PassThroughMode mode) { return m_downstreamCompilerPreludes[int(mode)]; } /// Finds out what compilers are present and caches the result - CPPCompilerSet* requireCPPCompilerSet(); + DownstreamCompilerSet* requireCPPCompilerSet(); Session(); @@ -2095,20 +2093,7 @@ SLANG_FORCE_INLINE EndToEndCompileRequest* asInternal(SlangCompileRequest* reque return reinterpret_cast<EndToEndCompileRequest*>(request); } -class ListBlob : public ISlangBlob, public RefObject -{ -public: - SLANG_REF_OBJECT_IUNKNOWN_ALL - - // ISlangBlob - SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_data.getBuffer(); } - SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_data.getCount(); } - - List<uint8_t> m_data; -protected: - ISlangUnknown* getInterface(const Guid& guid); -}; } diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index 710c1731f..755a005d1 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -583,7 +583,7 @@ String emitEntryPointSource( { const SourceLanguage sourceLanguage = (sourceStyle == SourceStyle::C) ? SourceLanguage::C : SourceLanguage::CPP; // Get the compiler used for the language - CPPCompiler* compiler = session->getDefaultCPPCompiler(sourceLanguage); + DownstreamCompiler* compiler = session->getDefaultCPPCompiler(sourceLanguage); if (compiler) { passThru = getPassThroughModeForCPPCompiler(compiler->getDesc().type); diff --git a/source/slang/slang-file-system.h b/source/slang/slang-file-system.h index 3d2bfe3c1..199cafe24 100644 --- a/source/slang/slang-file-system.h +++ b/source/slang/slang-file-system.h @@ -5,6 +5,8 @@ #include "../../slang-com-helper.h" #include "../../slang-com-ptr.h" +#include "../core/slang-blob.h" + #include "../core/slang-string-util.h" #include "../core/slang-dictionary.h" diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 339ace54f..faf748098 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -278,23 +278,23 @@ SlangPassThrough SLANG_MCALL Session::getDefaultDownstreamCompiler(SlangSourceLa return SlangPassThrough(m_defaultDownstreamCompilers[int(sourceLanguage)]); } -CPPCompiler* Session::getCPPCompiler(PassThroughMode compiler) +DownstreamCompiler* Session::getDownstreamCompiler(PassThroughMode compiler) { - CPPCompilerSet* compilerSet = requireCPPCompilerSet(); + DownstreamCompilerSet* compilerSet = requireCPPCompilerSet(); switch (compiler) { case PassThroughMode::GenericCCpp: return compilerSet->getDefaultCompiler(); - case PassThroughMode::Clang: return CPPCompilerUtil::findCompiler(compilerSet, CPPCompilerUtil::MatchType::Newest, CPPCompiler::Desc(CPPCompiler::CompilerType::Clang)); - case PassThroughMode::VisualStudio: return CPPCompilerUtil::findCompiler(compilerSet, CPPCompilerUtil::MatchType::Newest, CPPCompiler::Desc(CPPCompiler::CompilerType::VisualStudio)); - case PassThroughMode::Gcc: return CPPCompilerUtil::findCompiler(compilerSet, CPPCompilerUtil::MatchType::Newest, CPPCompiler::Desc(CPPCompiler::CompilerType::GCC)); + case PassThroughMode::Clang: return DownstreamCompilerUtil::findCompiler(compilerSet, DownstreamCompilerUtil::MatchType::Newest, DownstreamCompiler::Desc(DownstreamCompiler::CompilerType::Clang)); + case PassThroughMode::VisualStudio: return DownstreamCompilerUtil::findCompiler(compilerSet, DownstreamCompilerUtil::MatchType::Newest, DownstreamCompiler::Desc(DownstreamCompiler::CompilerType::VisualStudio)); + case PassThroughMode::Gcc: return DownstreamCompilerUtil::findCompiler(compilerSet, DownstreamCompilerUtil::MatchType::Newest, DownstreamCompiler::Desc(DownstreamCompiler::CompilerType::GCC)); default: break; } return nullptr; } -CPPCompiler* Session::getDefaultCPPCompiler(SourceLanguage sourceLanguage) +DownstreamCompiler* Session::getDefaultCPPCompiler(SourceLanguage sourceLanguage) { - return getCPPCompiler(m_defaultDownstreamCompilers[int(sourceLanguage)]); + return getDownstreamCompiler(m_defaultDownstreamCompilers[int(sourceLanguage)]); } ISlangFileSystemExt* IncludeHandlerImpl::_getFileSystemExt() @@ -689,56 +689,7 @@ SlangResult Linkage::setMatrixLayoutMode( return SLANG_OK; } -/** Base class for simple blobs. -*/ -class BlobBase : public ISlangBlob, public RefObject -{ -public: - // ISlangUnknown - SLANG_REF_OBJECT_IUNKNOWN_ALL - -protected: - SLANG_FORCE_INLINE ISlangUnknown* getInterface(const Guid& guid) - { - return (guid == IID_ISlangUnknown || guid == IID_ISlangBlob) ? static_cast<ISlangBlob*>(this) : nullptr; - } -}; -/** A blob that manages some raw data that it owns. -*/ -class RawBlob : public BlobBase -{ -public: - // ISlangBlob - SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_data; } - SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_size; } - - // Ctor - RawBlob(const void* data, size_t size): - m_size(size) - { - m_data = malloc(size); - memcpy(m_data, data, size); - } - ~RawBlob() - { - free(m_data); - } - -protected: - void* m_data; - size_t m_size; -}; - -ComPtr<ISlangBlob> createRawBlob(void const* inData, size_t size) -{ - return ComPtr<ISlangBlob>(new RawBlob(inData, size)); -} - -ISlangUnknown* ListBlob::getInterface(const Guid& guid) -{ - return (guid == IID_ISlangUnknown || guid == IID_ISlangBlob) ? static_cast<ISlangBlob*>(this) : nullptr; -} // // TargetRequest // @@ -3387,24 +3338,18 @@ SLANG_API void const* spGetEntryPointCode( void const* data = nullptr; size_t size = 0; - switch (result.format) + ComPtr<ISlangBlob> blob; + if (SLANG_SUCCEEDED(result.getBlob(blob))) { - case ResultFormat::None: - default: - break; - - case ResultFormat::Binary: - data = result.outputBinary.getBuffer(); - size = result.outputBinary.getCount(); - break; + data = blob->getBufferPointer(); + size = blob->getBufferSize(); + } - case ResultFormat::Text: - data = result.outputString.getBuffer(); - size = result.outputString.getLength(); - break; + if (outSize) + { + *outSize = size; } - if(outSize) *outSize = size; return data; } diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj index a9c7f4558..8c8a712ce 100644 --- a/source/slang/slang.vcxproj +++ b/source/slang/slang.vcxproj @@ -373,4 +373,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project>
\ No newline at end of file +</Project>
\ No newline at end of file |
