diff options
Diffstat (limited to 'source/core')
| -rw-r--r-- | source/core/core.vcxproj | 2 | ||||
| -rw-r--r-- | source/core/core.vcxproj.filters | 6 | ||||
| -rw-r--r-- | source/core/slang-cpp-compiler.cpp | 46 | ||||
| -rw-r--r-- | source/core/slang-cpp-compiler.h | 53 | ||||
| -rw-r--r-- | source/core/slang-gcc-compiler-util.cpp | 77 | ||||
| -rw-r--r-- | source/core/slang-gcc-compiler-util.h | 5 | ||||
| -rw-r--r-- | source/core/slang-hex-dump-util.cpp | 183 | ||||
| -rw-r--r-- | source/core/slang-hex-dump-util.h | 28 | ||||
| -rw-r--r-- | source/core/slang-io.cpp | 96 | ||||
| -rw-r--r-- | source/core/slang-io.h | 24 | ||||
| -rw-r--r-- | source/core/slang-string.cpp | 6 | ||||
| -rw-r--r-- | source/core/slang-string.h | 3 | ||||
| -rw-r--r-- | source/core/slang-visual-studio-compiler-util.cpp | 91 | ||||
| -rw-r--r-- | source/core/slang-visual-studio-compiler-util.h | 4 | ||||
| -rw-r--r-- | source/core/slang-writer.cpp | 17 | ||||
| -rw-r--r-- | source/core/slang-writer.h | 8 | ||||
| -rw-r--r-- | source/core/windows/slang-win-visual-studio-util.cpp | 2 |
17 files changed, 611 insertions, 40 deletions
diff --git a/source/core/core.vcxproj b/source/core/core.vcxproj index 9238cf058..a5a6c1b24 100644 --- a/source/core/core.vcxproj +++ b/source/core/core.vcxproj @@ -182,6 +182,7 @@ <ClInclude Include="slang-free-list.h" /> <ClInclude Include="slang-gcc-compiler-util.h" /> <ClInclude Include="slang-hash.h" /> + <ClInclude Include="slang-hex-dump-util.h" /> <ClInclude Include="slang-io.h" /> <ClInclude Include="slang-list.h" /> <ClInclude Include="slang-math.h" /> @@ -213,6 +214,7 @@ <ClCompile Include="slang-cpp-compiler.cpp" /> <ClCompile Include="slang-free-list.cpp" /> <ClCompile Include="slang-gcc-compiler-util.cpp" /> + <ClCompile Include="slang-hex-dump-util.cpp" /> <ClCompile Include="slang-io.cpp" /> <ClCompile Include="slang-memory-arena.cpp" /> <ClCompile Include="slang-object-scope-manager.cpp" /> diff --git a/source/core/core.vcxproj.filters b/source/core/core.vcxproj.filters index 3b3e429ba..fa4101506 100644 --- a/source/core/core.vcxproj.filters +++ b/source/core/core.vcxproj.filters @@ -45,6 +45,9 @@ <ClInclude Include="slang-hash.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="slang-hex-dump-util.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="slang-io.h"> <Filter>Header Files</Filter> </ClInclude> @@ -134,6 +137,9 @@ <ClCompile Include="slang-gcc-compiler-util.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="slang-hex-dump-util.cpp"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="slang-io.cpp"> <Filter>Source Files</Filter> </ClCompile> diff --git a/source/core/slang-cpp-compiler.cpp b/source/core/slang-cpp-compiler.cpp index 0ed0a1ba8..54138ab27 100644 --- a/source/core/slang-cpp-compiler.cpp +++ b/source/core/slang-cpp-compiler.cpp @@ -19,6 +19,17 @@ 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::OutputMessage::getTypeText(OutputMessage::Type type) @@ -33,6 +44,21 @@ namespace Slang } } +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 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 !!!!!!!!!!!!!!!!!!!!!!*/ @@ -167,6 +193,11 @@ SlangResult GenericCPPCompiler::compile(const CompileOptions& options, Output& o return m_parseOutputFunc(exeRes, outOutput); } +SlangResult GenericCPPCompiler::calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath) +{ + return m_calcModuleFilePathFunc(options, outPath); +} + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CPPCompilerUtil !!!!!!!!!!!!!!!!!!!!!!*/ static CPPCompiler::Desc _calcCompiledWithDesc() @@ -308,7 +339,7 @@ static void _addGCCFamilyCompiler(const String& exeName, CPPCompilerSet* compile CPPCompiler::Desc desc; if (SLANG_SUCCEEDED(GCCCompilerUtil::calcVersion(exeName, desc))) { - RefPtr<CPPCompiler> compiler(new GenericCPPCompiler(desc, exeName, &GCCCompilerUtil::calcArgs, &GCCCompilerUtil::parseOutput)); + RefPtr<CPPCompiler> compiler(new GenericCPPCompiler(desc, exeName, &GCCCompilerUtil::calcArgs, &GCCCompilerUtil::parseOutput, GCCCompilerUtil::calcModuleFilePath)); compilerSet->addCompiler(compiler); } } @@ -377,6 +408,19 @@ void CPPCompilerSet::getCompilers(List<CPPCompiler*>& outCompilers) const 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()); diff --git a/source/core/slang-cpp-compiler.h b/source/core/slang-cpp-compiler.h index 60b534556..851975d72 100644 --- a/source/core/slang-cpp-compiler.h +++ b/source/core/slang-cpp-compiler.h @@ -40,6 +40,8 @@ public: /// 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) {} @@ -50,16 +52,26 @@ public: enum class OptimizationLevel { - Normal, ///< Normal optimization - Debug, ///< General has no optimizations + 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 DebugInfoType + 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 { - None, ///< Binary has no debug information - Maximum, ///< Has maximum debug information - Normal, ///< Has normal debug information + Default, + Fast, + Precise, }; + enum TargetType { Executable, ///< Produce an executable @@ -84,10 +96,11 @@ public: }; }; - OptimizationLevel optimizationLevel = OptimizationLevel::Debug; - DebugInfoType debugInfoType = DebugInfoType::Normal; + OptimizationLevel optimizationLevel = OptimizationLevel::Default; + DebugInfoType debugInfoType = DebugInfoType::Standard; TargetType targetType = TargetType::Executable; SourceType sourceType = SourceType::CPP; + FloatingPointMode floatingPointMode = FloatingPointMode::Default; Flags flags = Flag::EnableExceptionHandling; @@ -163,6 +176,11 @@ public: 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; + + /// Return the compiler type as name + static UnownedStringSlice getCompilerTypeAsText(CompilerType type); protected: @@ -180,26 +198,31 @@ public: typedef void(*CalcArgsFunc)(const CPPCompiler::CompileOptions& options, CommandLine& cmdLine); typedef SlangResult(*ParseOutputFunc)(const ExecuteResult& exeResult, Output& output); + typedef SlangResult(*CalcModuleFilePathFunc)(const CPPCompiler::CompileOptions& options, StringBuilder& outPath); virtual SlangResult compile(const CompileOptions& options, Output& outOutput) SLANG_OVERRIDE; + virtual SlangResult calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath) SLANG_OVERRIDE; - GenericCPPCompiler(const Desc& desc, const String& exeName, CalcArgsFunc calcArgsFunc, ParseOutputFunc parseOutputFunc) : + GenericCPPCompiler(const Desc& desc, const String& exeName, CalcArgsFunc calcArgsFunc, ParseOutputFunc parseOutputFunc, CalcModuleFilePathFunc calcModuleFilePathFunc) : Super(desc), m_calcArgsFunc(calcArgsFunc), - m_parseOutputFunc(parseOutputFunc) + m_parseOutputFunc(parseOutputFunc), + m_calcModuleFilePathFunc(calcModuleFilePathFunc) { m_cmdLine.setExecutableFilename(exeName); } - GenericCPPCompiler(const Desc& desc, const CommandLine& cmdLine, CalcArgsFunc calcArgsFunc, ParseOutputFunc parseOutputFunc) : + GenericCPPCompiler(const Desc& desc, const CommandLine& cmdLine, CalcArgsFunc calcArgsFunc, ParseOutputFunc parseOutputFunc, CalcModuleFilePathFunc calcModuleFilePathFunc) : Super(desc), m_cmdLine(cmdLine), m_calcArgsFunc(calcArgsFunc), - m_parseOutputFunc(parseOutputFunc) + m_parseOutputFunc(parseOutputFunc), + m_calcModuleFilePathFunc(calcModuleFilePathFunc) {} CalcArgsFunc m_calcArgsFunc; ParseOutputFunc m_parseOutputFunc; + CalcModuleFilePathFunc m_calcModuleFilePathFunc; CommandLine m_cmdLine; }; @@ -225,6 +248,9 @@ public: /// 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; @@ -263,6 +289,9 @@ struct CPPCompilerUtil /// Given a set, registers compilers found through standard means and determines a reasonable default compiler if possible static SlangResult initializeSet(CPPCompilerSet* set); + + + }; diff --git a/source/core/slang-gcc-compiler-util.cpp b/source/core/slang-gcc-compiler-util.cpp index d210fa829..69d68e608 100644 --- a/source/core/slang-gcc-compiler-util.cpp +++ b/source/core/slang-gcc-compiler-util.cpp @@ -335,6 +335,34 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse return SLANG_OK; } +/* static */ SlangResult GCCCompilerUtil::calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath) +{ + outPath.Clear(); + + switch (options.targetType) + { + case TargetType::SharedLibrary: + { + outPath << SharedLibrary::calcPlatformPath(options.modulePath.getUnownedSlice()); + return SLANG_OK; + } + case TargetType::Executable: + { + outPath << options.modulePath; + outPath << ProcessUtil::getExecutableSuffix(); + return SLANG_OK; + } + case TargetType::Object: + { + // Will be .o for typical gcc targets + outPath << options.modulePath << ".o"; + return SLANG_OK; + } + } + + return SLANG_FAIL; +} + /* static */void GCCCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine) { cmdLine.addArg("-fvisibility=hidden"); @@ -349,17 +377,27 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse switch (options.optimizationLevel) { - case OptimizationLevel::Debug: + case OptimizationLevel::None: { // No optimization cmdLine.addArg("-O0"); break; } - case OptimizationLevel::Normal: + case OptimizationLevel::Default: { cmdLine.addArg("-Os"); break; } + case OptimizationLevel::High: + { + cmdLine.addArg("-O2"); + break; + } + case OptimizationLevel::Maximal: + { + cmdLine.addArg("-O4"); + break; + } default: break; } @@ -368,6 +406,29 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse cmdLine.addArg("-g"); } + switch (options.floatingPointMode) + { + case FloatingPointMode::Default: break; + case FloatingPointMode::Precise: + { + //cmdLine.addArg("-fno-unsafe-math-optimizations"); + break; + } + case FloatingPointMode::Fast: + { + // We could enable SSE with -mfpmath=sse + // But that would only make sense on a x64/x86 type processor and only if that feature is present (it is on all x64) + cmdLine.addArg("-ffast-math"); + break; + } + } + + StringBuilder moduleFilePath; + calcModuleFilePath(options, moduleFilePath); + + cmdLine.addArg("-o"); + cmdLine.addArg(moduleFilePath); + switch (options.targetType) { case TargetType::SharedLibrary: @@ -376,22 +437,10 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse cmdLine.addArg("-shared"); // Position independent cmdLine.addArg("-fPIC"); - - String sharedLibraryPath = SharedLibrary::calcPlatformPath(options.modulePath.getUnownedSlice()); - - cmdLine.addArg("-o"); - cmdLine.addArg(sharedLibraryPath); break; } case TargetType::Executable: { - cmdLine.addArg("-o"); - - StringBuilder builder; - builder << options.modulePath; - builder << ProcessUtil::getExecutableSuffix(); - - cmdLine.addArg(options.modulePath); break; } case TargetType::Object: diff --git a/source/core/slang-gcc-compiler-util.h b/source/core/slang-gcc-compiler-util.h index 29070fc61..a72080acc 100644 --- a/source/core/slang-gcc-compiler-util.h +++ b/source/core/slang-gcc-compiler-util.h @@ -14,6 +14,7 @@ struct GCCCompilerUtil typedef CPPCompiler::TargetType TargetType; typedef CPPCompiler::DebugInfoType DebugInfoType; typedef CPPCompiler::SourceType SourceType; + typedef CPPCompiler::FloatingPointMode FloatingPointMode; /// 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); @@ -26,6 +27,10 @@ struct GCCCompilerUtil /// Parse ExecuteResult into Output static SlangResult parseOutput(const ExecuteResult& exeRes, CPPCompiler::Output& outOutput); + + /// Calculate the output module filename + static SlangResult calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath); + }; } diff --git a/source/core/slang-hex-dump-util.cpp b/source/core/slang-hex-dump-util.cpp new file mode 100644 index 000000000..908f6c1b6 --- /dev/null +++ b/source/core/slang-hex-dump-util.cpp @@ -0,0 +1,183 @@ +// slang-hex-dump-util.cpp +#include "slang-hex-dump-util.h" + +#include "slang-common.h" +#include "slang-string-util.h" +#include "slang-writer.h" + +#include "../../slang-com-helper.h" + +namespace Slang +{ + +static const UnownedStringSlice s_start = UnownedStringSlice::fromLiteral("--START--"); +static const UnownedStringSlice s_end = UnownedStringSlice::fromLiteral("--END--"); + +/* static */SlangResult HexDumpUtil::dumpWithMarkers(const List<uint8_t>& data, 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(dump(data, maxBytesPerLine, writer)); + + SLANG_RETURN_ON_FAIL(helper.write(s_end.begin(), s_end.size())); + SLANG_RETURN_ON_FAIL(helper.put("\n")); + return SLANG_OK; +} + +/* static */SlangResult HexDumpUtil::dump(const List<uint8_t>& data, int maxBytesPerLine, ISlangWriter* writer) +{ + int maxCharsPerLine = 2 * maxBytesPerLine + 1 + maxBytesPerLine + 1; + + const uint8_t* cur = data.begin(); + const uint8_t* end = data.end(); + + static char s_hex[] = "0123456789abcdef"; + + while (cur < end) + { + size_t count = size_t(end - cur); + count = (count > size_t(maxBytesPerLine)) ? size_t(maxBytesPerLine) : count; + + char* startDst = writer->beginAppendBuffer(maxCharsPerLine); + char* dst = startDst; + + for (size_t i = 0; i < count; ++i) + { + uint8_t byte = cur[i]; + *dst++ = s_hex[byte >> 4]; + *dst++ = s_hex[byte & 0xf]; + } + + *dst++ = ' '; + + for (size_t i = 0; i < count; ++i) + { + char c = char(cur[i]); + + if ((c >= '0' && c <= '9') || + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= 32 && (c & 0x80) == 0)) + { + } + else + { + c = '.'; + } + *dst++ = c; + } + + *dst++ = '\n'; + SLANG_ASSERT(dst <= startDst + maxCharsPerLine); + + SLANG_RETURN_ON_FAIL(writer->endAppendBuffer(startDst, size_t(dst - startDst))); + + cur += count; + } + + return SLANG_OK; +} + +static int _parseHexDigit(char c) +{ + if (c >= '0' && c <= '9') + { + return c -'0'; + } + else if (c >= 'a' && c <= 'f') + { + return c - 'a' + 10; + } + else if (c >= 'A' && c <= 'F') + { + return c - 'A' + 10; + } + return -1; +} + +/* static */SlangResult HexDumpUtil::parse(const UnownedStringSlice& lines, List<uint8_t>& outBytes) +{ + 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') + { + // Skip to next line + break; + } + + const int hi = _parseHexDigit(c); + const int lo = _parseHexDigit(cur[1]); + cur += 2; + + if (hi < 0 || lo < 0) + { + return SLANG_FAIL; + } + outBytes.add(uint8_t((hi << 4) | lo)); + } + } + + return SLANG_OK; +} + +/* static */SlangResult HexDumpUtil::parseWithMarkers(const UnownedStringSlice& lines, List<uint8_t>& outBytes) +{ + UnownedStringSlice remaining(lines), line; + + while(StringUtil::extractLine(remaining, line)) + { + if (line.startsWith(s_start)) + { + // 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; +} + +} diff --git a/source/core/slang-hex-dump-util.h b/source/core/slang-hex-dump-util.h new file mode 100644 index 000000000..580f5a120 --- /dev/null +++ b/source/core/slang-hex-dump-util.h @@ -0,0 +1,28 @@ +#ifndef SLANG_HEX_DUMP_UTIL_H +#define SLANG_HEX_DUMP_UTIL_H + +#include "slang-common.h" +#include "slang-string.h" + +#include "slang-list.h" +#include "../../slang.h" + +namespace Slang +{ + +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 dumpWithMarkers(const List<uint8_t>& data, 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); +}; + +} + +#endif diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp index 6cdd75c74..caa45c8f4 100644 --- a/source/core/slang-io.cpp +++ b/source/core/slang-io.cpp @@ -17,7 +17,7 @@ # include <Windows.h> #endif -#if defined(__linux__) || defined(__CYGWIN__) +#if defined(__linux__) || defined(__CYGWIN__) || SLANG_APPLE_FAMILY # include <unistd.h> #endif @@ -51,6 +51,99 @@ namespace Slang #endif } + +#ifdef _WIN32 + /* static */SlangResult File::generateTemporary(const UnownedStringSlice& inPrefix, Slang::String& outFileName) + { + // https://docs.microsoft.com/en-us/windows/win32/fileio/creating-and-using-a-temporary-file + + String tempPath; + { + int count = MAX_PATH + 1; + while (true) + { + char* chars = tempPath.prepareForAppend(count); + // Gets the temp path env string (no guarantee it's a valid path). + // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha + DWORD ret = ::GetTempPathA(count - 1, chars); + if (ret == 0) + { + return SLANG_FAIL; + } + if (ret > DWORD(count - 1)) + { + count = ret + 1; + continue; + } + tempPath.appendInPlace(chars, count); + break; + } + } + + if (!File::exists(tempPath)) + { + return SLANG_FAIL; + } + + const String prefix(inPrefix); + String tempFileName; + + { + int count = MAX_PATH + 1; + char* chars = tempFileName.prepareForAppend(count); + + // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettempfilenamea + // Generates a temporary file name. + DWORD ret = ::GetTempFileNameA(tempPath.getBuffer(), prefix.getBuffer(), 0, chars); + + if (ret == 0) + { + return SLANG_FAIL; + } + tempFileName.appendInPlace(chars, ::strlen(chars)); + } + + outFileName = tempFileName; + return SLANG_OK; + } +#else + /* static */SlangResult File::generateTemporary(const UnownedStringSlice& inPrefix, Slang::String& outFileName) + { + StringBuilder builder; + builder << "/tmp/" << inPrefix << "-XXXXXX"; + + List<char> buffer; + buffer.setCount(builder.getLength() + 1); + ::memcpy(buffer.getBuffer(), builder.getBuffer(), builder.getLength()); + buffer[builder.getLength()] = 0; + + int handle = mkstemp(buffer.getBuffer()); + if (handle == -1) + { + return SLANG_FAIL; + } + + // Close the handle.. + close(handle); + + outFileName = buffer.getBuffer(); + return SLANG_OK; + } +#endif + + /* static */SlangResult File::makeExecutable(const String& fileName) + { +#ifdef _WIN32 + SLANG_UNUSED(fileName); + // As long as file extension is executable, it can be executed + return SLANG_OK; +#else + const int ret = ::chmod(fileName.getBuffer(), S_IXUSR); + return (ret == 0) ? SLANG_OK : SLANG_FAIL; +#endif + } + + bool File::exists(const String& fileName) { #ifdef _WIN32 @@ -585,5 +678,6 @@ namespace Slang writer.Write(text); } + } diff --git a/source/core/slang-io.h b/source/core/slang-io.h index da63e9c20..e2935afe4 100644 --- a/source/core/slang-io.h +++ b/source/core/slang-io.h @@ -16,6 +16,10 @@ namespace Slang static Slang::List<unsigned char> readAllBytes(const Slang::String& fileName); static void writeAllText(const Slang::String& fileName, const Slang::String& text); static SlangResult remove(const String& fileName); + + static SlangResult makeExecutable(const String& fileName); + + static SlangResult generateTemporary(const UnownedStringSlice& prefix, Slang::String& outFileName); }; class Path @@ -85,6 +89,26 @@ namespace Slang /// @return The first element of the path, or empty static UnownedStringSlice getFirstElement(const UnownedStringSlice& path); }; + + // Helper class to clean up temporary files on dtor + struct TemporaryFileSet + { + void add(const String& path) + { + if (m_paths.indexOf(path) < 0) + { + m_paths.add(path); + } + } + ~TemporaryFileSet() + { + for (const auto& path : m_paths) + { + File::remove(path); + } + } + List<String> m_paths; + }; } #endif diff --git a/source/core/slang-string.cpp b/source/core/slang-string.cpp index 8b2a35b3f..22049f82d 100644 --- a/source/core/slang-string.cpp +++ b/source/core/slang-string.cpp @@ -361,6 +361,12 @@ namespace Slang append(&chr, &chr + 1); } + + void String::appendChar(char chr) + { + append(&chr, &chr + 1); + } + void String::append(String const& str) { if (!m_buffer) diff --git a/source/core/slang-string.h b/source/core/slang-string.h index cb2731cee..357eb726e 100644 --- a/source/core/slang-string.h +++ b/source/core/slang-string.h @@ -443,6 +443,9 @@ namespace Slang void append(StringSlice const& slice); void append(UnownedStringSlice const& slice); + /// Append a character (to remove ambiguity with other integral types) + void appendChar(char chr); + String(int32_t val, int radix = 10) { append(val, radix); diff --git a/source/core/slang-visual-studio-compiler-util.cpp b/source/core/slang-visual-studio-compiler-util.cpp index 20d655e78..765edc349 100644 --- a/source/core/slang-visual-studio-compiler-util.cpp +++ b/source/core/slang-visual-studio-compiler-util.cpp @@ -10,6 +10,33 @@ namespace Slang { +/* static */ SlangResult VisualStudioCompilerUtil::calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath) +{ + outPath.Clear(); + + switch (options.targetType) + { + case TargetType::SharedLibrary: + { + outPath << options.modulePath << ".dll"; + return SLANG_OK; + } + case TargetType::Executable: + { + outPath << options.modulePath << ".exe"; + return SLANG_OK; + } + case TargetType::Object: + { + outPath << options.modulePath << ".obj"; + return SLANG_OK; + } + default: break; + } + + return SLANG_FAIL; +} + /* static */void VisualStudioCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine) { // https://docs.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-alphabetically?view=vs-2019 @@ -30,30 +57,72 @@ namespace Slang } } + switch (options.debugInfoType) + { + default: + { + // Multithreaded statically linked runtime library + cmdLine.addArg("/MD"); + break; + } + case DebugInfoType::Maximal: + { + // Multithreaded statically linked *debug* runtime library + cmdLine.addArg("/MDd"); + break; + } + } + + // /Fd - followed by name of the pdb file + if (options.debugInfoType != DebugInfoType::None) + { + cmdLine.addPrefixPathArg("/Fd", options.modulePath, ".pdb"); + } + switch (options.optimizationLevel) { - case OptimizationLevel::Debug: + case OptimizationLevel::None: { // No optimization - cmdLine.addArg("/Od"); - - cmdLine.addArg("/MDd"); + cmdLine.addArg("/Od"); + break; + } + case OptimizationLevel::Default: + { break; } - case OptimizationLevel::Normal: + case OptimizationLevel::High: { cmdLine.addArg("/O2"); - // Multithreaded DLL - cmdLine.addArg("/MD"); + break; + } + case OptimizationLevel::Maximal: + { + cmdLine.addArg("/Ox"); break; } default: break; } - // /Fd - followed by name of the pdb file - if (options.debugInfoType != DebugInfoType::None) + switch (options.floatingPointMode) { - cmdLine.addPrefixPathArg("/Fd", options.modulePath, ".pdb"); + case FloatingPointMode::Default: break; + case FloatingPointMode::Precise: + { + // precise is default behavior, VS also has 'strict' + // + // ```/fp:strict has behavior similar to /fp:precise, that is, the compiler preserves the source ordering and rounding properties of floating-point code when + // it generates and optimizes object code for the target machine, and observes the standard when handling special values. In addition, the program may safely + // access or modify the floating-point environment at runtime.``` + + cmdLine.addArg("/fp:precise"); + break; + } + case FloatingPointMode::Fast: + { + cmdLine.addArg("/fp:fast"); + break; + } } switch (options.targetType) @@ -61,7 +130,7 @@ namespace Slang case TargetType::SharedLibrary: { // Create dynamic link library - if (options.optimizationLevel == OptimizationLevel::Debug) + if (options.debugInfoType == DebugInfoType::None) { cmdLine.addArg("/LDd"); } diff --git a/source/core/slang-visual-studio-compiler-util.h b/source/core/slang-visual-studio-compiler-util.h index 86845b5af..cc34b49f5 100644 --- a/source/core/slang-visual-studio-compiler-util.h +++ b/source/core/slang-visual-studio-compiler-util.h @@ -14,11 +14,15 @@ struct VisualStudioCompilerUtil typedef CPPCompiler::DebugInfoType DebugInfoType; typedef CPPCompiler::SourceType SourceType; typedef CPPCompiler::OutputMessage OutputMessage; + typedef CPPCompiler::FloatingPointMode FloatingPointMode; /// Calculate Visual Studio family compilers cmdLine arguments from options static void calcArgs(const CompileOptions& options, CommandLine& cmdLine); /// Parse Visual Studio exeRes into CPPCompiler::Output static SlangResult parseOutput(const ExecuteResult& exeRes, CPPCompiler::Output& outOutput); + + static SlangResult calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath); + }; } diff --git a/source/core/slang-writer.cpp b/source/core/slang-writer.cpp index 5b643fff8..2f694aeec 100644 --- a/source/core/slang-writer.cpp +++ b/source/core/slang-writer.cpp @@ -1,3 +1,5 @@ +#define _CRT_SECURE_NO_WARNINGS + #include "slang-writer.h" #include "slang-platform.h" @@ -166,6 +168,21 @@ SlangResult FileWriter::setMode(SlangWriterMode mode) return SLANG_FAIL; } +/* static */SlangResult FileWriter::create(const char* filePath, const char* writeOptions, WriterFlags flags, ComPtr<ISlangWriter>& outWriter) +{ + flags &= ~WriterFlag::IsUnowned; + + FILE* file = fopen(filePath, writeOptions); + if (!file) + { + return SLANG_E_CANNOT_OPEN; + } + + outWriter = new FileWriter(file, flags); + return SLANG_OK; +} + + /* !!!!!!!!!!!!!!!!!!!!!!!!! StringWriter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ SLANG_NO_THROW char* SLANG_MCALL StringWriter::beginAppendBuffer(size_t maxNumChars) diff --git a/source/core/slang-writer.h b/source/core/slang-writer.h index cd5737b3d..759644fde 100644 --- a/source/core/slang-writer.h +++ b/source/core/slang-writer.h @@ -4,6 +4,8 @@ #include "slang-string.h" #include "../../slang-com-helper.h" +#include "../../slang-com-ptr.h" + #include "slang-list.h" namespace Slang @@ -118,6 +120,12 @@ public: m_file(file) {} + /// + static SlangResult create(const char* filePath, const char* writeOptions, WriterFlags flags, ComPtr<ISlangWriter>& outWriter); + + static SlangResult createBinary(const char* filePath, WriterFlags flags, ComPtr<ISlangWriter>& outWriter) { return create(filePath, "wb", flags, outWriter); } + static SlangResult createText(const char* filePath, WriterFlags flags, ComPtr<ISlangWriter>& outWriter) { return create(filePath, "w", flags, outWriter); } + /// Dtor ~FileWriter(); diff --git a/source/core/windows/slang-win-visual-studio-util.cpp b/source/core/windows/slang-win-visual-studio-util.cpp index 7e683ee55..a406e168f 100644 --- a/source/core/windows/slang-win-visual-studio-util.cpp +++ b/source/core/windows/slang-win-visual-studio-util.cpp @@ -293,7 +293,7 @@ static SlangResult _find(int versionIndex, WinVisualStudioUtil::VersionPath& out CommandLine cmdLine; calcExecuteCompilerArgs(versionPath, cmdLine); - RefPtr<GenericCPPCompiler> compiler = new GenericCPPCompiler(desc, cmdLine, &VisualStudioCompilerUtil::calcArgs, &VisualStudioCompilerUtil::parseOutput); + RefPtr<GenericCPPCompiler> compiler = new GenericCPPCompiler(desc, cmdLine, &VisualStudioCompilerUtil::calcArgs, &VisualStudioCompilerUtil::parseOutput, &VisualStudioCompilerUtil::calcModuleFilePath); set->addCompiler(compiler); } } |
