summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-08-12 15:41:41 -0400
committerGitHub <noreply@github.com>2019-08-12 15:41:41 -0400
commit6fc2c37d9a4c408331db1b33deb3b46e74d2a7d2 (patch)
treed763d0f85b61f853f5877ab9ee28d3edaeef302c
parenta0416216ffaf3bd3b0533d967a6d62c477b22d09 (diff)
Callable CPU code support (#1014)
* First pass support for compiling to a loaded shared library. * Improve documentation for cpu target. * Removed the SLANG_COMPILE_FLAG_LOAD_SHARED_LIBRARY flag. Use the SLANG_HOST_CALLABLE code target Document mechanism. * Fix typo in cpp-resource.slang In test code if the target is 'callable' we don't need to compile (indeed there is no source file). * Small refactor using CommandLineCPPCompiler as base class to implement VisualStudioCPPCompiler and GCCCPPCompiler. * Improvements around CPPCompiler. Mechanism to know products produced. Cleaning up products after execution. * Fix multiple definition of 'SourceType'
-rw-r--r--docs/cpu-target.md42
-rw-r--r--slang.h26
-rw-r--r--source/core/slang-cpp-compiler.cpp16
-rw-r--r--source/core/slang-cpp-compiler.h71
-rw-r--r--source/core/slang-gcc-compiler-util.cpp22
-rw-r--r--source/core/slang-gcc-compiler-util.h28
-rw-r--r--source/core/slang-io.h19
-rw-r--r--source/core/slang-shared-library.cpp17
-rw-r--r--source/core/slang-shared-library.h25
-rw-r--r--source/core/slang-visual-studio-compiler-util.cpp37
-rw-r--r--source/core/slang-visual-studio-compiler-util.h30
-rw-r--r--source/core/windows/slang-win-visual-studio-util.cpp6
-rw-r--r--source/slang/slang-compiler.cpp143
-rw-r--r--source/slang/slang-compiler.h11
-rw-r--r--source/slang/slang-ir-entry-point-uniforms.cpp1
-rw-r--r--source/slang/slang-parameter-binding.cpp1
-rw-r--r--source/slang/slang-type-layout.cpp2
-rw-r--r--source/slang/slang.cpp61
-rw-r--r--tests/cross-compile/cpp-resource.slang2
-rw-r--r--tools/slang-test/slang-test-main.cpp51
20 files changed, 476 insertions, 135 deletions
diff --git a/docs/cpu-target.md b/docs/cpu-target.md
index dc2319b6f..f86b7d6c5 100644
--- a/docs/cpu-target.md
+++ b/docs/cpu-target.md
@@ -9,6 +9,7 @@ Slang has preliminary support for producing CPU source and binaries.
* Can compile Slang source into C++ source code
* Supports compute style shaders
* C/C++ backend abstracts the command line options, and parses the compiler errors/out such that all supported compilers output available in same format
+* Once compilation is complete can optionally access and run CPU code directly
# Limitations
@@ -41,18 +42,19 @@ To make it possible for slang to produce CPU code, we now need a mechanism to co
In the API the `SlangCompileTarget`s are
```
-SLANG_C_SOURCE, ///< The C language
-SLANG_CPP_SOURCE, ///< The C++ language
+SLANG_C_SOURCE ///< The C language
+SLANG_CPP_SOURCE ///< The C++ language
```
If a CPU binary is required this can be specified as a `SlangCompileTarget` of
```
-SLANG_EXECUTABLE, ///< Executable (for hosting CPU/OS)
-SLANG_SHARED_LIBRARY, ///< A shared library/Dll (for hosting CPU/OS)
+SLANG_EXECUTABLE ///< Executable (for hosting CPU/OS)
+SLANG_SHARED_LIBRARY ///< A shared library/Dll (for hosting CPU/OS)
+SLANG_HOST_CALLABLE ///< A CPU target that makes the compiled code available to be run immediately
```
-These can also be specified on the slang command line as `-target exe` and `-target dll` or `-target sharedlib`.
+These can also be specified on the slang command line as `-target exe` and `-target dll` or `-target sharedlib`. `-target callable` or `-target host-callable` is also possible, but is typically not very useful from the command line, other than to test such code is avaiable for host execution.
In order to be able to use the slang code on CPU, there needs to be binding via values passed to a function that the C/C++ code will produce and export. How this works is described in the ABI section.
@@ -60,6 +62,27 @@ If a binary target is requested, the binary contents will be returned in a ISlan
Under the covers when slang is used to generate a binary via a C/C++ compiler, it must do so through the file system. Currently this means that the source (say generated by slang) and the binary (produced by the C/C++ compiler) must all be files. To make this work slang uses temporary files. That the reasoning for hiding this mechanism - and not return say filenames, is so that in the future when binaries are produced directly (for example with LLVM), nothing will need to change.
+Executing CPU Code
+==================
+
+In typically slang operation when code is compiled it produces either source or a binary that can then be loaded by another API such as a rendering API. With CPU code the binary produced could be saved to a file and then executed as an exe or a shared library/dll. In practice though it is not uncommon to want to be able to execute compiled code immediately. Having to save off to a file and then load again can be awkward. It is also not necessarily the case that code needs to be saved to a file to be executed.
+
+To handle being able call code directly, code can be compiled using the SLANG_HOST_CALLABLE code target type. To access the code that has been produced use the function
+
+```
+ SLANG_API SlangResult spGetEntryPointHostCallable(
+ SlangCompileRequest* request,
+ int entryPointIndex,
+ int targetIndex,
+ ISlangSharedLibrary** outSharedLibrary);
+```
+
+This outputs a `ISlangSharedLibrary` which whilst in scope, any contained functions remain available (even if the request or session go out of scope). The contained functions can then be accessed via the `findFuncByName` method on the `ISlangSharedLibrary` interface.
+
+The returned function pointer should be cast to the appropriate function signature before calling. For entry points - the function will appear under the same name as the entry point name. See the ABI section for what is the appropriate signature for entry points.
+
+For pass through compilation of C/C++ this mechanism allows any functions marked for export to be directly queried.
+
ABI
===
@@ -188,24 +211,19 @@ TODO
# Main
* Complete support (in terms of interfaces) for 'complex' resource types - such as Texture
-* Interface implementation for complex resource types
* Parameter block support (the difficulty is around layout)
* Split out entry point uniforms into a separate pointer passed to the entry point
-* Test system executes and tests for CPU targets
-* Slang API allows for compilation into loaded binary such that functions can be directly executed
-* Output C/C++ compiler errors as 'externalCompiler' errors through diagnostic system
+* Test system executes and tests for CPU targets - for example compute tests run on CPU
* Improve documentation
* Output of header files
-* Mechanism to specify where C/C++ binaries are located
# Internal Slang compiler features
These issues are more internal Slang features/improvements
-* Currently we only support 64 bit targets (it is assumed in layout that pointers are 64 bit)
* Slang compute tests work (where appropriate)
* Currently only generates C++ code, it would be fairly straight forward to support C (especially if we have 'intrinsic definitions')
* Have 'intrinsic definitions' in standard library - such that they can be generated where appropriate
+ This will simplify the C/C++ code generation as means slang language will generate must of the appropriate code
* Currently 'construct' IR inst is supported as is, we may want to split out to separate instructions for specific scenarios
-
+* Refactoring around swizzle. Currently in emit it has to check for a variety of scenarios - could be simplified with an IR pass and perhaps more specific instructions.
diff --git a/slang.h b/slang.h
index 281aeba6a..474ea9916 100644
--- a/slang.h
+++ b/slang.h
@@ -516,6 +516,7 @@ extern "C"
SLANG_CPP_SOURCE, ///< The C++ language
SLANG_EXECUTABLE, ///< Executable (for hosting CPU/OS)
SLANG_SHARED_LIBRARY, ///< A shared library/Dll (for hosting CPU/OS)
+ SLANG_HOST_CALLABLE, ///< A CPU target that makes the compiled code available to be run immediately
};
/* A "container format" describes the way that the outputs
@@ -1210,6 +1211,8 @@ extern "C"
int targetIndex,
SlangTargetFlags flags);
+
+
/*!
@brief Set the floating point mode (e.g., precise or fast) to use a target.
*/
@@ -1547,6 +1550,7 @@ extern "C"
/** Get the output code associated with a specific entry point.
+ @param request The request
@param entryPointIndex The index of the entry point to get code for.
@param targetIndex The index of the target to get code for (default: zero).
@param outBlob A pointer that will receive the blob of code
@@ -1560,14 +1564,36 @@ extern "C"
int targetIndex,
ISlangBlob** outBlob);
+ /** Get entry point 'callable' functions accessible through the ISlangSharedLibrary interface.
+
+ That the functions remain in scope as long as the ISlangSharedLibrary interface is in scope.
+
+ NOTE! Requires a compilation target of SLANG_HOST_CALLABLE.
+
+ @param request The request
+ @param entryPointIndex The index of the entry point to get code for.
+ @param targetIndex The index of the target to get code for (default: zero).
+ @param outSharedLibrary A pointer to a ISharedLibrary interface which functions can be queried on.
+ @returns A `SlangResult` to indicate success or failure.
+ */
+ SLANG_API SlangResult spGetEntryPointHostCallable(
+ SlangCompileRequest* request,
+ int entryPointIndex,
+ int targetIndex,
+ ISlangSharedLibrary** outSharedLibrary);
+
/** Get the output bytecode associated with an entire compile request.
The lifetime of the output pointer is the same as `request`.
+
+ DEPRECIATED: No longer outputs anything.
*/
SLANG_API void const* spGetCompileRequestCode(
SlangCompileRequest* request,
size_t* outSize);
+
+
/*
Forward declarations of types used in the reflection interface;
*/
diff --git a/source/core/slang-cpp-compiler.cpp b/source/core/slang-cpp-compiler.cpp
index 54138ab27..7ac4e96b4 100644
--- a/source/core/slang-cpp-compiler.cpp
+++ b/source/core/slang-cpp-compiler.cpp
@@ -160,9 +160,9 @@ void CPPCompiler::Output::removeByType(OutputMessage::Type type)
}
}
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! GenericCPPCompiler !!!!!!!!!!!!!!!!!!!!!!*/
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CommandLineCPPCompiler !!!!!!!!!!!!!!!!!!!!!!*/
-SlangResult GenericCPPCompiler::compile(const CompileOptions& options, Output& outOutput)
+SlangResult CommandLineCPPCompiler::compile(const CompileOptions& options, Output& outOutput)
{
outOutput.reset();
@@ -170,7 +170,7 @@ SlangResult GenericCPPCompiler::compile(const CompileOptions& options, Output& o
CommandLine cmdLine(m_cmdLine);
// Append command line args to the end of cmdLine using the target specific function for the specified options
- m_calcArgsFunc(options, cmdLine);
+ SLANG_RETURN_ON_FAIL(calcArgs(options, cmdLine));
ExecuteResult exeRes;
@@ -190,12 +190,7 @@ SlangResult GenericCPPCompiler::compile(const CompileOptions& options, Output& o
}
#endif
- return m_parseOutputFunc(exeRes, outOutput);
-}
-
-SlangResult GenericCPPCompiler::calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath)
-{
- return m_calcModuleFilePathFunc(options, outPath);
+ return parseOutput(exeRes, outOutput);
}
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CPPCompilerUtil !!!!!!!!!!!!!!!!!!!!!!*/
@@ -339,7 +334,8 @@ 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, GCCCompilerUtil::calcModuleFilePath));
+ RefPtr<CommandLineCPPCompiler> compiler(new GCCCPPCompiler(desc));
+ compiler->m_cmdLine.setExecutableFilename(exeName);
compilerSet->addCompiler(compiler);
}
}
diff --git a/source/core/slang-cpp-compiler.h b/source/core/slang-cpp-compiler.h
index 851975d72..185e960f3 100644
--- a/source/core/slang-cpp-compiler.h
+++ b/source/core/slang-cpp-compiler.h
@@ -147,6 +147,27 @@ public:
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
+ All = 0xf, ///< All the flags
+ };
+ };
+
+ enum class Product
+ {
+ DebugRun,
+ Run,
+ CompileTemporary,
+ All,
+ };
+
struct Output
{
/// Reset to an initial empty state
@@ -178,6 +199,10 @@ public:
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);
@@ -191,38 +216,31 @@ protected:
Desc m_desc;
};
-class GenericCPPCompiler : public CPPCompiler
+class CommandLineCPPCompiler : public CPPCompiler
{
public:
typedef CPPCompiler Super;
- 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);
-
+ // CPPCompiler
virtual SlangResult compile(const CompileOptions& options, Output& outOutput) SLANG_OVERRIDE;
- virtual SlangResult calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath) 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;
- GenericCPPCompiler(const Desc& desc, const String& exeName, CalcArgsFunc calcArgsFunc, ParseOutputFunc parseOutputFunc, CalcModuleFilePathFunc calcModuleFilePathFunc) :
- Super(desc),
- m_calcArgsFunc(calcArgsFunc),
- m_parseOutputFunc(parseOutputFunc),
- m_calcModuleFilePathFunc(calcModuleFilePathFunc)
+ CommandLineCPPCompiler(const Desc& desc, const String& exeName) :
+ Super(desc)
{
m_cmdLine.setExecutableFilename(exeName);
}
- GenericCPPCompiler(const Desc& desc, const CommandLine& cmdLine, CalcArgsFunc calcArgsFunc, ParseOutputFunc parseOutputFunc, CalcModuleFilePathFunc calcModuleFilePathFunc) :
+ CommandLineCPPCompiler(const Desc& desc, const CommandLine& cmdLine) :
Super(desc),
- m_cmdLine(cmdLine),
- m_calcArgsFunc(calcArgsFunc),
- m_parseOutputFunc(parseOutputFunc),
- m_calcModuleFilePathFunc(calcModuleFilePathFunc)
+ m_cmdLine(cmdLine)
{}
- CalcArgsFunc m_calcArgsFunc;
- ParseOutputFunc m_parseOutputFunc;
- CalcModuleFilePathFunc m_calcModuleFilePathFunc;
+ CommandLineCPPCompiler(const Desc& desc):Super(desc) {}
+
CommandLine m_cmdLine;
};
@@ -261,7 +279,8 @@ protected:
List<RefPtr<CPPCompiler>> m_compilers;
};
-struct CPPCompilerUtil
+/* 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;
@@ -269,6 +288,14 @@ struct CPPCompilerUtil
typedef CPPCompiler::DebugInfoType DebugInfoType;
typedef CPPCompiler::SourceType SourceType;
+ typedef CPPCompiler::OutputMessage OutputMessage;
+ typedef CPPCompiler::FloatingPointMode FloatingPointMode;
+ typedef CPPCompiler::ProductFlag ProductFlag;
+ typedef CPPCompiler::ProductFlags ProductFlags;
+};
+
+struct CPPCompilerUtil: public CPPCompilerBaseUtil
+{
enum class MatchType
{
MinGreaterEqual,
@@ -289,12 +316,8 @@ struct CPPCompilerUtil
/// Given a set, registers compilers found through standard means and determines a reasonable default compiler if possible
static SlangResult initializeSet(CPPCompilerSet* set);
-
-
-
};
-
}
#endif
diff --git a/source/core/slang-gcc-compiler-util.cpp b/source/core/slang-gcc-compiler-util.cpp
index 0a53bcac8..d42076039 100644
--- a/source/core/slang-gcc-compiler-util.cpp
+++ b/source/core/slang-gcc-compiler-util.cpp
@@ -354,8 +354,12 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse
}
case TargetType::Object:
{
+#if __CYGWIN__
+ outPath << options.modulePath << ".obj";
+#else
// Will be .o for typical gcc targets
outPath << options.modulePath << ".o";
+#endif
return SLANG_OK;
}
}
@@ -363,7 +367,21 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse
return SLANG_FAIL;
}
-/* static */void GCCCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine)
+/* static */SlangResult GCCCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, List<String>& outPaths)
+{
+ outPaths.clear();
+
+ if (flags & ProductFlag::Execution)
+ {
+ StringBuilder builder;
+ SLANG_RETURN_ON_FAIL(calcModuleFilePath(options, builder));
+ outPaths.add(builder);
+ }
+
+ return SLANG_OK;
+}
+
+/* static */SlangResult GCCCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine)
{
cmdLine.addArg("-fvisibility=hidden");
@@ -513,6 +531,8 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse
// Make maths lib available
cmdLine.addArg("-lm");
}
+
+ return SLANG_OK;
}
}
diff --git a/source/core/slang-gcc-compiler-util.h b/source/core/slang-gcc-compiler-util.h
index a72080acc..df3cb8a4b 100644
--- a/source/core/slang-gcc-compiler-util.h
+++ b/source/core/slang-gcc-compiler-util.h
@@ -7,15 +7,8 @@ namespace Slang
{
/* Utility for processing input and output of gcc-like compilers, including clang */
-struct GCCCompilerUtil
+struct GCCCompilerUtil : public CPPCompilerBaseUtil
{
- typedef CPPCompiler::CompileOptions CompileOptions;
- typedef CPPCompiler::OptimizationLevel OptimizationLevel;
- 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);
@@ -23,7 +16,7 @@ struct GCCCompilerUtil
static SlangResult calcVersion(const String& exeName, CPPCompiler::Desc& outDesc);
/// Calculate gcc family compilers (including clang) cmdLine arguments from options
- static void calcArgs(const CompileOptions& options, CommandLine& cmdLine);
+ static SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine);
/// Parse ExecuteResult into Output
static SlangResult parseOutput(const ExecuteResult& exeRes, CPPCompiler::Output& outOutput);
@@ -31,6 +24,23 @@ struct GCCCompilerUtil
/// Calculate the output module filename
static SlangResult calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath);
+ /// Given options, calculate paths to products produced for a compilation
+ static SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, List<String>& outPaths);
+};
+
+class GCCCPPCompiler : public CommandLineCPPCompiler
+{
+public:
+ typedef CommandLineCPPCompiler Super;
+ typedef GCCCompilerUtil 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 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) {}
};
}
diff --git a/source/core/slang-io.h b/source/core/slang-io.h
index e2935afe4..758a05edb 100644
--- a/source/core/slang-io.h
+++ b/source/core/slang-io.h
@@ -93,6 +93,14 @@ namespace Slang
// Helper class to clean up temporary files on dtor
struct TemporaryFileSet
{
+ void remove(const String& path)
+ {
+ if (const Index index = m_paths.indexOf(path) >= 0)
+ {
+ m_paths.removeAt(index);
+ }
+ }
+
void add(const String& path)
{
if (m_paths.indexOf(path) < 0)
@@ -100,6 +108,17 @@ namespace Slang
m_paths.add(path);
}
}
+ void add(const List<String>& paths)
+ {
+ for (const auto& path : paths)
+ {
+ add(path);
+ }
+ }
+ void clear()
+ {
+ m_paths.clear();
+ }
~TemporaryFileSet()
{
for (const auto& path : m_paths)
diff --git a/source/core/slang-shared-library.cpp b/source/core/slang-shared-library.cpp
index 9932db0b5..fd61ba0a0 100644
--- a/source/core/slang-shared-library.cpp
+++ b/source/core/slang-shared-library.cpp
@@ -56,6 +56,18 @@ SlangResult DefaultSharedLibraryLoader::loadSharedLibrary(const char* path, ISla
/* !!!!!!!!!!!!!!!!!!!!!!!!!! DefaultSharedLibrary !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+TemporarySharedLibrary::~TemporarySharedLibrary()
+{
+ if (m_sharedLibraryHandle)
+ {
+ // We have to unload if we want to be able to remove
+ SharedLibrary::unload(m_sharedLibraryHandle);
+ m_sharedLibraryHandle = nullptr;
+ }
+}
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!! DefaultSharedLibrary !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+
ISlangUnknown* DefaultSharedLibrary::getInterface(const Guid& guid)
{
return (guid == IID_ISlangUnknown || guid == IID_ISlangSharedLibrary) ? static_cast<ISlangSharedLibrary*>(this) : nullptr;
@@ -63,7 +75,10 @@ ISlangUnknown* DefaultSharedLibrary::getInterface(const Guid& guid)
DefaultSharedLibrary::~DefaultSharedLibrary()
{
- SharedLibrary::unload(m_sharedLibraryHandle);
+ if (m_sharedLibraryHandle)
+ {
+ SharedLibrary::unload(m_sharedLibraryHandle);
+ }
}
SlangFuncPtr DefaultSharedLibrary::findFuncByName(char const* name)
diff --git a/source/core/slang-shared-library.h b/source/core/slang-shared-library.h
index 5a4eb7229..e48162ebd 100644
--- a/source/core/slang-shared-library.h
+++ b/source/core/slang-shared-library.h
@@ -5,6 +5,7 @@
#include "../../slang-com-helper.h"
#include "../../slang-com-ptr.h"
+#include "../core/slang-io.h"
#include "../core/slang-platform.h"
#include "../core/slang-common.h"
#include "../core/slang-dictionary.h"
@@ -84,6 +85,30 @@ class DefaultSharedLibrary : public ISlangSharedLibrary, public RefObject
SharedLibrary::Handle m_sharedLibraryHandle = nullptr;
};
+class TemporarySharedLibrary : public DefaultSharedLibrary
+{
+public:
+ typedef DefaultSharedLibrary Super;
+
+ /// Get the path to the shared library
+ const String& getPath() const { return m_path; }
+
+ /// Ctor
+ TemporarySharedLibrary(const SharedLibrary::Handle sharedLibraryHandle, const String& path):
+ Super(sharedLibraryHandle),
+ m_path(path)
+ {
+ }
+
+ virtual ~TemporarySharedLibrary();
+
+ /// Any files specified in this set will be deleted on exit
+ TemporaryFileSet m_temporaryFileSet;
+
+protected:
+ String m_path;
+};
+
class ConfigurableSharedLibraryLoader: public ISlangSharedLibraryLoader, public RefObject
{
public:
diff --git a/source/core/slang-visual-studio-compiler-util.cpp b/source/core/slang-visual-studio-compiler-util.cpp
index 765edc349..1c79f9004 100644
--- a/source/core/slang-visual-studio-compiler-util.cpp
+++ b/source/core/slang-visual-studio-compiler-util.cpp
@@ -37,7 +37,40 @@ namespace Slang
return SLANG_FAIL;
}
-/* static */void VisualStudioCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine)
+/* static */SlangResult VisualStudioCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, List<String>& outPaths)
+{
+ outPaths.clear();
+
+ if (flags & ProductFlag::Execution)
+ {
+ StringBuilder builder;
+ SLANG_RETURN_ON_FAIL(calcModuleFilePath(options, builder));
+ outPaths.add(builder);
+ }
+ if (flags & ProductFlag::Miscellaneous)
+ {
+ outPaths.add(options.modulePath + ".ilk");
+
+ if (options.targetType == TargetType::SharedLibrary)
+ {
+ outPaths.add(options.modulePath + ".exp");
+ outPaths.add(options.modulePath + ".lib");
+ }
+ }
+ if (flags & ProductFlag::Compile)
+ {
+ outPaths.add(options.modulePath + ".obj");
+ }
+ if (flags & ProductFlag::Debug)
+ {
+ // TODO(JS): Could try and determine based on debug information
+ outPaths.add(options.modulePath + ".pdb");
+ }
+
+ return SLANG_OK;
+}
+
+/* static */SlangResult VisualStudioCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine)
{
// https://docs.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-alphabetically?view=vs-2019
@@ -190,6 +223,8 @@ namespace Slang
// Note that any escaping of the path is handled in the ProcessUtil::
cmdLine.addPrefixPathArg("/LIBPATH:", libPath);
}
+
+ return SLANG_OK;
}
static SlangResult _parseErrorType(const UnownedStringSlice& in, CPPCompiler::OutputMessage::Type& outType)
diff --git a/source/core/slang-visual-studio-compiler-util.h b/source/core/slang-visual-studio-compiler-util.h
index cc34b49f5..1e2fbb318 100644
--- a/source/core/slang-visual-studio-compiler-util.h
+++ b/source/core/slang-visual-studio-compiler-util.h
@@ -6,25 +6,35 @@
namespace Slang
{
-struct VisualStudioCompilerUtil
-{
- typedef CPPCompiler::CompileOptions CompileOptions;
- typedef CPPCompiler::OptimizationLevel OptimizationLevel;
- typedef CPPCompiler::TargetType TargetType;
- typedef CPPCompiler::DebugInfoType DebugInfoType;
- typedef CPPCompiler::SourceType SourceType;
- typedef CPPCompiler::OutputMessage OutputMessage;
- typedef CPPCompiler::FloatingPointMode FloatingPointMode;
+struct VisualStudioCompilerUtil : public CPPCompilerBaseUtil
+{
/// Calculate Visual Studio family compilers cmdLine arguments from options
- static void calcArgs(const CompileOptions& options, CommandLine& cmdLine);
+ 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 calcModuleFilePath(const CompileOptions& options, StringBuilder& outPath);
+ static SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, List<String>& outPaths);
+};
+
+class VisualStudioCPPCompiler : public CommandLineCPPCompiler
+{
+public:
+ typedef CommandLineCPPCompiler Super;
+ typedef VisualStudioCompilerUtil 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 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) {}
};
+
}
#endif
diff --git a/source/core/windows/slang-win-visual-studio-util.cpp b/source/core/windows/slang-win-visual-studio-util.cpp
index a406e168f..260f3f56f 100644
--- a/source/core/windows/slang-win-visual-studio-util.cpp
+++ b/source/core/windows/slang-win-visual-studio-util.cpp
@@ -290,10 +290,8 @@ static SlangResult _find(int versionIndex, WinVisualStudioUtil::VersionPath& out
VersionPath versionPath;
if (!set->getCompiler(desc) && SLANG_SUCCEEDED(_find(i, versionPath)))
{
- CommandLine cmdLine;
- calcExecuteCompilerArgs(versionPath, cmdLine);
-
- RefPtr<GenericCPPCompiler> compiler = new GenericCPPCompiler(desc, cmdLine, &VisualStudioCompilerUtil::calcArgs, &VisualStudioCompilerUtil::parseOutput, &VisualStudioCompilerUtil::calcModuleFilePath);
+ RefPtr<CommandLineCPPCompiler> compiler = new VisualStudioCPPCompiler(desc);
+ calcExecuteCompilerArgs(versionPath, compiler->m_cmdLine);
set->addCompiler(compiler);
}
}
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index 1c0bed065..8ead63784 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -87,7 +87,8 @@ namespace Slang
x("c", CSource) \
x("cpp", CPPSource) \
x("exe,executable", Executable) \
- x("sharedlib,sharedlibrary,dll", SharedLibrary)
+ x("sharedlib,sharedlibrary,dll", SharedLibrary) \
+ x("callable,host-callable", HostCallable)
#define SLANG_CODE_GEN_INFO(names, e) \
{ CodeGenTarget::e, UnownedStringSlice::fromLiteral(names) },
@@ -149,28 +150,64 @@ namespace Slang
{
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)
+ {
+ outSharedLibrary = sharedLibrary;
+ return SLANG_OK;
+ }
+ return SLANG_FAIL;
}
- ComPtr<ISlangBlob> CompileResult::getBlob()
+ SlangResult CompileResult::getBlob(ComPtr<ISlangBlob>& outBlob)
{
if(!blob)
{
switch(format)
{
- case ResultFormat::None:
- default:
- break;
+ case ResultFormat::None:
+ default:
+ break;
- case ResultFormat::Text:
- blob = StringUtil::createStringBlob(outputString);
- break;
+ case ResultFormat::Text:
+ blob = StringUtil::createStringBlob(outputString);
+ break;
- case ResultFormat::Binary:
- blob = createRawBlob(outputBinary.getBuffer(), outputBinary.getCount());
- 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
+ {
+ // We can read it from the shared library...
+ contents = File::readAllBytes(tempLibrary->getPath());
+ }
+ catch (const Slang::IOException&)
+ {
+ return SLANG_E_CANNOT_OPEN;
+ }
+ blob = createRawBlob(contents.getBuffer(), contents.getCount());
+ break;
+ }
}
}
- return blob;
+
+ outBlob = blob;
+ return SLANG_OK;
}
//
@@ -478,6 +515,7 @@ namespace Slang
// Don't need an external compiler to output C and C++ code
return PassThroughMode::None;
}
+ case CodeGenTarget::HostCallable:
case CodeGenTarget::SharedLibrary:
case CodeGenTarget::Executable:
{
@@ -1103,13 +1141,15 @@ SlangResult dissassembleDXILUsingDXC(
Int entryPointIndex,
TargetRequest* targetReq,
EndToEndCompileRequest* endToEndReq,
- List<uint8_t>& binOut)
+ ComPtr<ISlangSharedLibrary>& outSharedLib,
+ List<uint8_t>& outBin)
{
auto sink = slangRequest->getSink();
const String originalSourcePath = calcSourcePathForEntryPoint(endToEndReq, entryPointIndex);
- binOut.clear();
+ outBin.clear();
+ outSharedLib.setNull();
CPPCompilerSet* compilerSet = slangRequest->getSession()->requireCPPCompilerSet();
@@ -1311,6 +1351,7 @@ SlangResult dissassembleDXILUsingDXC(
// Set what kind of target we should build
switch (targetReq->target)
{
+ case CodeGenTarget::HostCallable:
case CodeGenTarget::SharedLibrary:
{
options.targetType = CPPCompiler::TargetType::SharedLibrary;
@@ -1332,8 +1373,13 @@ SlangResult dissassembleDXILUsingDXC(
moduleFilePath = builder.ProduceString();
}
- // Add so it's deleted at the end
- temporaryFileSet.add(moduleFilePath);
+ // 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
@@ -1457,16 +1503,48 @@ SlangResult dissassembleDXILUsingDXC(
return SLANG_FAIL;
}
- // Read the binary
- try
+ // If callable we need to load the shared library
+ if (targetReq->target == CodeGenTarget::HostCallable)
{
- // Read the contents of the binary
- binOut = File::readAllBytes(moduleFilePath);
+ // 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();
}
- catch (const Slang::IOException&)
+ else
{
- sink->diagnose(SourceLoc(), Diagnostics::unableToReadFile, moduleFilePath);
- return SLANG_FAIL;
+ // 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;
+ }
}
return SLANG_OK;
@@ -1550,9 +1628,12 @@ SlangResult dissassembleDXILUsingDXC(
switch (target)
{
+ case CodeGenTarget::HostCallable:
case CodeGenTarget::SharedLibrary:
case CodeGenTarget::Executable:
{
+ ComPtr<ISlangSharedLibrary> sharedLibrary;
+
List<uint8_t> code;
if (SLANG_SUCCEEDED(emitCPUBinaryForEntryPoint(
compileRequest,
@@ -1560,10 +1641,18 @@ SlangResult dissassembleDXILUsingDXC(
entryPointIndex,
targetReq,
endToEndReq,
+ sharedLibrary,
code)))
{
- maybeDumpIntermediate(compileRequest, code.getBuffer(), code.getCount(), target);
- result = CompileResult(code);
+ if (target == CodeGenTarget::HostCallable)
+ {
+ result = CompileResult(sharedLibrary);
+ }
+ else
+ {
+ maybeDumpIntermediate(compileRequest, code.getBuffer(), code.getCount(), target);
+ result = CompileResult(code);
+ }
}
}
break;
@@ -1860,6 +1949,9 @@ SlangResult dissassembleDXILUsingDXC(
writeOutputToConsole(writer, result.outputString);
break;
+ case ResultFormat::SharedLibrary:
+ break;
+
case ResultFormat::Binary:
{
auto& data = result.outputBinary;
@@ -2232,6 +2324,7 @@ SlangResult dissassembleDXILUsingDXC(
// for now
dumpIntermediateBinary(compileRequest, data, size, ".exe");
break;
+ case CodeGenTarget::HostCallable:
case CodeGenTarget::SharedLibrary:
dumpIntermediateBinary(compileRequest, data, size, ".shared-lib");
break;
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index 8f9c20044..bbc6505b0 100644
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -61,6 +61,7 @@ namespace Slang
CPPSource = SLANG_CPP_SOURCE,
Executable = SLANG_EXECUTABLE,
SharedLibrary = SLANG_SHARED_LIBRARY,
+ HostCallable = SLANG_HOST_CALLABLE,
};
CodeGenTarget calcCodeGenTargetFromName(const UnownedStringSlice& name);
@@ -84,7 +85,8 @@ namespace Slang
{
None,
Text,
- Binary
+ Binary,
+ SharedLibrary,
};
// When storing the layout for a matrix-type
@@ -122,22 +124,25 @@ namespace Slang
class TranslationUnitRequest;
// Result of compiling an entry point.
- // Should only ever be string OR binary.
+ // Should only ever be string, binary or shared library
class CompileResult
{
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) {}
void append(CompileResult const& result);
- ComPtr<ISlangBlob> getBlob();
+ SlangResult getBlob(ComPtr<ISlangBlob>& outBlob);
+ SlangResult getSharedLibrary(ComPtr<ISlangSharedLibrary>& outSharedLibrary);
ResultFormat format = ResultFormat::None;
String outputString;
List<uint8_t> outputBinary;
+ ComPtr<ISlangSharedLibrary> sharedLibrary;
ComPtr<ISlangBlob> blob;
};
diff --git a/source/slang/slang-ir-entry-point-uniforms.cpp b/source/slang/slang-ir-entry-point-uniforms.cpp
index da036d798..822174620 100644
--- a/source/slang/slang-ir-entry-point-uniforms.cpp
+++ b/source/slang/slang-ir-entry-point-uniforms.cpp
@@ -441,6 +441,7 @@ void moveEntryPointUniformParamsToGlobalScope(
case CodeGenTarget::CSource:
case CodeGenTarget::Executable:
case CodeGenTarget::SharedLibrary:
+ case CodeGenTarget::HostCallable:
{
context.targetNeedsConstantBuffer = false;
break;
diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp
index f9657e776..6e5838da5 100644
--- a/source/slang/slang-parameter-binding.cpp
+++ b/source/slang/slang-parameter-binding.cpp
@@ -2640,6 +2640,7 @@ static bool _isCPUTarget(CodeGenTarget target)
case CodeGenTarget::CSource:
case CodeGenTarget::Executable:
case CodeGenTarget::SharedLibrary:
+ case CodeGenTarget::HostCallable:
{
return true;
}
diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp
index 3b14b74c2..9551cfe4e 100644
--- a/source/slang/slang-type-layout.cpp
+++ b/source/slang/slang-type-layout.cpp
@@ -982,7 +982,7 @@ LayoutRulesFamilyImpl* getDefaultLayoutRulesFamilyForTarget(TargetRequest* targe
case CodeGenTarget::SPIRVAssembly:
return &kGLSLLayoutRulesFamilyImpl;
-
+ case CodeGenTarget::HostCallable:
case CodeGenTarget::Executable:
case CodeGenTarget::SharedLibrary:
case CodeGenTarget::CPPSource:
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index cae9855e0..bb7e705e6 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -1716,7 +1716,9 @@ SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getEntryPointCode(
if(entryPointResult.format == ResultFormat::None )
return SLANG_FAIL;
- *outCode = entryPointResult.getBlob().detach();
+ ComPtr<ISlangBlob> blob;
+ SLANG_RETURN_ON_FAIL(entryPointResult.getBlob(blob));
+ *outCode = blob.detach();
return SLANG_OK;
}
@@ -3140,29 +3142,28 @@ SLANG_API void const* spGetEntryPointCode(
return data;
}
-SLANG_API SlangResult spGetEntryPointCodeBlob(
- SlangCompileRequest* request,
- int entryPointIndex,
- int targetIndex,
- ISlangBlob** outBlob)
+static SlangResult _getEntryPointResult(
+ SlangCompileRequest* request,
+ int entryPointIndex,
+ int targetIndex,
+ Slang::CompileResult** outCompileResult)
{
using namespace Slang;
- if(!request) return SLANG_ERROR_INVALID_PARAMETER;
- if(!outBlob) return SLANG_ERROR_INVALID_PARAMETER;
-
+ if (!request) return SLANG_ERROR_INVALID_PARAMETER;
+
auto req = Slang::asInternal(request);
auto linkage = req->getLinkage();
auto program = req->getSpecializedGlobalAndEntryPointsComponentType();
Index targetCount = linkage->targets.getCount();
- if((targetIndex < 0) || (targetIndex >= targetCount))
+ if ((targetIndex < 0) || (targetIndex >= targetCount))
{
return SLANG_ERROR_INVALID_PARAMETER;
}
auto targetReq = linkage->targets[targetIndex];
Index entryPointCount = req->entryPoints.getCount();
- if((entryPointIndex < 0) || (entryPointIndex >= entryPointCount))
+ if ((entryPointIndex < 0) || (entryPointIndex >= entryPointCount))
{
return SLANG_ERROR_INVALID_PARAMETER;
}
@@ -3170,15 +3171,47 @@ SLANG_API SlangResult spGetEntryPointCodeBlob(
auto targetProgram = program->getTargetProgram(targetReq);
- if(!targetProgram)
+ if (!targetProgram)
return SLANG_FAIL;
- Slang::CompileResult& result = targetProgram->getExistingEntryPointResult(entryPointIndex);
+ *outCompileResult = &targetProgram->getExistingEntryPointResult(entryPointIndex);
+ return SLANG_OK;
+}
+
+SLANG_API SlangResult spGetEntryPointCodeBlob(
+ SlangCompileRequest* request,
+ int entryPointIndex,
+ int targetIndex,
+ ISlangBlob** outBlob)
+{
+ using namespace Slang;
+ if(!outBlob) return SLANG_ERROR_INVALID_PARAMETER;
+ Slang::CompileResult* compileResult = nullptr;
+ SLANG_RETURN_ON_FAIL(_getEntryPointResult(request, entryPointIndex, targetIndex, &compileResult));
- auto blob = result.getBlob();
+ ComPtr<ISlangBlob> blob;
+ SLANG_RETURN_ON_FAIL(compileResult->getBlob(blob));
*outBlob = blob.detach();
return SLANG_OK;
}
+SLANG_API SlangResult spGetEntryPointHostCallable(
+ SlangCompileRequest* request,
+ int entryPointIndex,
+ int targetIndex,
+ ISlangSharedLibrary** outSharedLibrary)
+{
+ using namespace Slang;
+ if (!outSharedLibrary) return SLANG_ERROR_INVALID_PARAMETER;
+
+ Slang::CompileResult* compileResult = nullptr;
+ SLANG_RETURN_ON_FAIL(_getEntryPointResult(request, entryPointIndex, targetIndex, &compileResult));
+
+ ComPtr<ISlangSharedLibrary> sharedLibrary;
+ SLANG_RETURN_ON_FAIL(compileResult->getSharedLibrary(sharedLibrary));
+ *outSharedLibrary = sharedLibrary.detach();
+ return SLANG_OK;
+}
+
SLANG_API char const* spGetEntryPointSource(
SlangCompileRequest* request,
int entryPointIndex)
diff --git a/tests/cross-compile/cpp-resource.slang b/tests/cross-compile/cpp-resource.slang
index f443249ad..9a48085df 100644
--- a/tests/cross-compile/cpp-resource.slang
+++ b/tests/cross-compile/cpp-resource.slang
@@ -1,4 +1,4 @@
-//TEST:CPP_COMPILER_COMPILE: -profile cs_5_0 -entry computeMain -target cpp
+//TEST(shared-library):CPP_COMPILER_COMPILE: -profile cs_5_0 -entry computeMain -target callable
struct Thing
{
diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp
index 8be8f797a..8137733ee 100644
--- a/tools/slang-test/slang-test-main.cpp
+++ b/tools/slang-test/slang-test-main.cpp
@@ -556,6 +556,7 @@ static PassThroughFlags _getPassThroughFlagsForTarget(SlangCompileTarget target)
return PassThroughFlag::Dxc;
}
+ case SLANG_HOST_CALLABLE:
case SLANG_EXECUTABLE:
case SLANG_SHARED_LIBRARY:
{
@@ -590,6 +591,8 @@ static SlangCompileTarget _getCompileTarget(const UnownedStringSlice& name)
CASE("exe", EXECUTABLE)
CASE("sharedlib", SHARED_LIBRARY)
CASE("dll", SHARED_LIBRARY)
+ CASE("callable", HOST_CALLABLE)
+ CASE("host-callable", HOST_CALLABLE)
#undef CASE
return SLANG_TARGET_UNKNOWN;
@@ -1369,39 +1372,49 @@ static TestResult runCPPCompilerCompile(TestContext* context, TestInput& input)
String ext = Path::getFileExt(filePath);
String modulePath = Path::combine(directory, moduleName);
- // Find the target
UnownedStringSlice targetExt = UnownedStringSlice::fromLiteral("c");
+
+ // Find the target
Index index = cmdLine.findArgIndex(UnownedStringSlice::fromLiteral("-target"));
if (index >= 0 && index + 1 < cmdLine.getArgCount())
{
targetExt = cmdLine.m_args[index + 1].value.getUnownedSlice();
}
- CPPCompiler::CompileOptions options;
- options.sourceType = (targetExt == "c") ? CPPCompiler::SourceType::C : CPPCompiler::SourceType::CPP;
+ // If output was C/C++ we should try compiling
+ if (targetExt == "c" || targetExt == "cpp")
+ {
+ CPPCompiler::CompileOptions options;
+ options.sourceType = (targetExt == "c") ? CPPCompiler::SourceType::C : CPPCompiler::SourceType::CPP;
- options.includePaths.add("tests/cross-compile");
+ options.includePaths.add("tests/cross-compile");
- // Create a filename to write this out to
- String cppSource = modulePath + "." + targetExt;
- Slang::File::writeAllText(cppSource, actualOutput);
+ // Create a filename to write this out to
+ String cppSource = modulePath + "." + targetExt;
+ Slang::File::writeAllText(cppSource, actualOutput);
- // Okay we can now try compiling
+ // Okay we can now try compiling
- // Compile this source
- options.sourceFiles.add(cppSource);
- options.modulePath = modulePath;
- options.targetType = CPPCompiler::TargetType::SharedLibrary;
+ // Compile this source
+ options.sourceFiles.add(cppSource);
+ options.modulePath = modulePath;
+ options.targetType = CPPCompiler::TargetType::SharedLibrary;
- CPPCompiler::Output output;
- if (SLANG_FAILED(compiler->compile(options, output)))
- {
- return TestResult::Fail;
- }
+ CPPCompiler::Output output;
+ if (SLANG_FAILED(compiler->compile(options, output)))
+ {
+ return TestResult::Fail;
+ }
- if (output.getCountByType(CPPCompiler::OutputMessage::Type::Error) > 0)
+ if (output.getCountByType(CPPCompiler::OutputMessage::Type::Error) > 0)
+ {
+ return TestResult::Fail;
+ }
+ }
+ else
{
- return TestResult::Fail;
+ // Can only be callable
+ SLANG_ASSERT(targetExt == "callable" || targetExt == "host-callable");
}
return TestResult::Pass;