summaryrefslogtreecommitdiffstats
path: root/source/core
diff options
context:
space:
mode:
Diffstat (limited to 'source/core')
-rw-r--r--source/core/core.vcxproj2
-rw-r--r--source/core/core.vcxproj.filters6
-rw-r--r--source/core/slang-cpp-compiler.cpp46
-rw-r--r--source/core/slang-cpp-compiler.h53
-rw-r--r--source/core/slang-gcc-compiler-util.cpp77
-rw-r--r--source/core/slang-gcc-compiler-util.h5
-rw-r--r--source/core/slang-hex-dump-util.cpp183
-rw-r--r--source/core/slang-hex-dump-util.h28
-rw-r--r--source/core/slang-io.cpp96
-rw-r--r--source/core/slang-io.h24
-rw-r--r--source/core/slang-string.cpp6
-rw-r--r--source/core/slang-string.h3
-rw-r--r--source/core/slang-visual-studio-compiler-util.cpp91
-rw-r--r--source/core/slang-visual-studio-compiler-util.h4
-rw-r--r--source/core/slang-writer.cpp17
-rw-r--r--source/core/slang-writer.h8
-rw-r--r--source/core/windows/slang-win-visual-studio-util.cpp2
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);
}
}