summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2022-06-02 14:13:35 -0400
committerGitHub <noreply@github.com>2022-06-02 14:13:35 -0400
commitb39c99661b3ad482bbd419c24991ed325b5738a9 (patch)
tree0f90fecdae10e704b2c1135c48ca5eeafa60b780
parentbc6bc56db51d06b92dc63ef9c9e0def6c9760c9e (diff)
COM interfaces with host callable (#2258)
* #include an absolute path didn't work - because paths were taken to always be relative. * Use TerminatedUnownedStringSlice for literals in output C++. * Remove Escape/Unescape functions used in slang-token-reader.cpp Add target type of 'host-cpp' etc to map to the target types. * Fix some corner cases around string encoding. * Added unit test for string escaping. Fixed some assorted escaping bugs. * Updated test output. * Added decode test. * Stop using hex output, to get around 'greedy' aspect. Use octal instead. * Added HostHostCallable Small changes to use ArtifactDesc/Info instead of large switches. * Fix C++ emit to handle arbitrary function export. * Add options handling for callable without an output being specified. * Can compile with COM interface. Added example using com interface. * Use the IR Ptr type instead of hack in C++ emit for interfaces. * Fix issue with outputting the COM call when ptr is used. * Fix crash issue on compilation failure.
-rw-r--r--build/visual-studio/cpu-com-example/cpu-com-example.vcxproj293
-rw-r--r--build/visual-studio/cpu-com-example/cpu-com-example.vcxproj.filters18
-rw-r--r--examples/cpu-com-example/README.md8
-rw-r--r--examples/cpu-com-example/main.cpp135
-rw-r--r--examples/cpu-com-example/shader.slang21
-rw-r--r--prelude/slang-cpp-prelude.h46
-rw-r--r--premake5.lua3
-rw-r--r--slang.h1
-rw-r--r--slang.sln15
-rw-r--r--source/compiler-core/slang-artifact-info.cpp6
-rw-r--r--source/compiler-core/slang-artifact-info.h6
-rw-r--r--source/compiler-core/slang-artifact.cpp1
-rw-r--r--source/core/slang-type-text-util.cpp2
-rw-r--r--source/slang/slang-compiler.cpp76
-rwxr-xr-xsource/slang/slang-compiler.h3
-rw-r--r--source/slang/slang-emit-c-like.cpp12
-rw-r--r--source/slang/slang-emit-cpp.cpp91
-rw-r--r--source/slang/slang-emit-cpp.h5
-rw-r--r--source/slang/slang-emit.cpp22
-rw-r--r--source/slang/slang-ir-com-interface.cpp22
-rw-r--r--source/slang/slang-ir-com-interface.h4
-rw-r--r--source/slang/slang-ir-generics-lowering-context.cpp17
-rw-r--r--source/slang/slang-options.cpp15
-rw-r--r--source/slang/slang-parameter-binding.cpp16
-rw-r--r--source/slang/slang-type-layout.cpp16
-rw-r--r--source/slang/slang.cpp22
-rw-r--r--tools/slang-test/slang-test-main.cpp2
27 files changed, 770 insertions, 108 deletions
diff --git a/build/visual-studio/cpu-com-example/cpu-com-example.vcxproj b/build/visual-studio/cpu-com-example/cpu-com-example.vcxproj
new file mode 100644
index 000000000..d5f326bfe
--- /dev/null
+++ b/build/visual-studio/cpu-com-example/cpu-com-example.vcxproj
@@ -0,0 +1,293 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|ARM">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug aarch64|Win32">
+ <Configuration>Debug aarch64</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug aarch64|x64">
+ <Configuration>Debug aarch64</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug aarch64|ARM">
+ <Configuration>Debug aarch64</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM">
+ <Configuration>Release</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release aarch64|Win32">
+ <Configuration>Release aarch64</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release aarch64|x64">
+ <Configuration>Release aarch64</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release aarch64|ARM">
+ <Configuration>Release aarch64</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{0996B38F-F512-A7D2-1E90-A7E60A6C4366}</ProjectGuid>
+ <IgnoreWarnCompileDuplicatedFilename>true</IgnoreWarnCompileDuplicatedFilename>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>cpu-com-example</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug aarch64|ARM'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release aarch64|ARM'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug aarch64|ARM'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release aarch64|ARM'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\bin\windows-x86\debug\</OutDir>
+ <IntDir>..\..\..\intermediate\windows-x86\debug\cpu-com-example\</IntDir>
+ <TargetName>cpu-com-example</TargetName>
+ <TargetExt>.exe</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\bin\windows-x64\debug\</OutDir>
+ <IntDir>..\..\..\intermediate\windows-x64\debug\cpu-com-example\</IntDir>
+ <TargetName>cpu-com-example</TargetName>
+ <TargetExt>.exe</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug aarch64|ARM'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\bin\windows-aarch64\debug\</OutDir>
+ <IntDir>..\..\..\intermediate\windows-aarch64\debug\cpu-com-example\</IntDir>
+ <TargetName>cpu-com-example</TargetName>
+ <TargetExt>.exe</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\bin\windows-x86\release\</OutDir>
+ <IntDir>..\..\..\intermediate\windows-x86\release\cpu-com-example\</IntDir>
+ <TargetName>cpu-com-example</TargetName>
+ <TargetExt>.exe</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\bin\windows-x64\release\</OutDir>
+ <IntDir>..\..\..\intermediate\windows-x64\release\cpu-com-example\</IntDir>
+ <TargetName>cpu-com-example</TargetName>
+ <TargetExt>.exe</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release aarch64|ARM'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\bin\windows-aarch64\release\</OutDir>
+ <IntDir>..\..\..\intermediate\windows-aarch64\release\cpu-com-example\</IntDir>
+ <TargetName>cpu-com-example</TargetName>
+ <TargetExt>.exe</TargetExt>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\tools;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <Optimization>Disabled</Optimization>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\tools;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <Optimization>Disabled</Optimization>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug aarch64|ARM'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\tools;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <Optimization>Disabled</Optimization>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\tools;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Optimization>Full</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\tools;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Optimization>Full</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release aarch64|ARM'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\tools;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Optimization>Full</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\examples\cpu-com-example\main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\..\examples\cpu-com-example\shader.slang" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\example-base\example-base.vcxproj">
+ <Project>{37BED5B5-23FA-D81F-8C0C-F1167867813A}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\slang\slang.vcxproj">
+ <Project>{DB00DA62-0533-4AFD-B59F-A67D5B3A0808}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\gfx\gfx.vcxproj">
+ <Project>{222F7498-B40C-4F3F-A704-DDEB91A4484A}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\gfx-util\gfx-util.vcxproj">
+ <Project>{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\platform\platform.vcxproj">
+ <Project>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\core\core.vcxproj">
+ <Project>{F9BE7957-8399-899E-0C49-E714FDDD4B65}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/build/visual-studio/cpu-com-example/cpu-com-example.vcxproj.filters b/build/visual-studio/cpu-com-example/cpu-com-example.vcxproj.filters
new file mode 100644
index 000000000..ad9cb293f
--- /dev/null
+++ b/build/visual-studio/cpu-com-example/cpu-com-example.vcxproj.filters
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{E9C7FDCE-D52A-8D73-7EB0-C5296AF258F6}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\examples\cpu-com-example\main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\..\examples\cpu-com-example\shader.slang">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/examples/cpu-com-example/README.md b/examples/cpu-com-example/README.md
new file mode 100644
index 000000000..a5e234d15
--- /dev/null
+++ b/examples/cpu-com-example/README.md
@@ -0,0 +1,8 @@
+Slang COM Example
+=================
+
+The goal of this example is to demonstrate Slang generating CPU code that can be communicated with via Common Object Model (COM) style interfaces.
+
+The `shader.slang` file contains Slang code that uses COM interfaces.
+
+The `main.cpp` file contains the C++ application code, showing how to use the Slang API to load and compile the shader code and communicate via interfaces.
diff --git a/examples/cpu-com-example/main.cpp b/examples/cpu-com-example/main.cpp
new file mode 100644
index 000000000..2e9eeed79
--- /dev/null
+++ b/examples/cpu-com-example/main.cpp
@@ -0,0 +1,135 @@
+// main.cpp
+
+#include <stdio.h>
+
+#include <slang.h>
+
+#include <slang-com-ptr.h>
+#include <slang-com-helper.h>
+
+
+// This includes a useful small function for setting up the prelude (described more further below).
+#include "../../source/core/slang-test-tool-util.h"
+
+// Slang namespace is used for elements support code (like core) which we use here
+// for ComPtr<> and TestToolUtil
+using namespace Slang;
+
+// For the moment we have to explicitly write the Slang COM interface in C++ code. It *MUST* match
+// the interface in the slang source
+// As it stands all interfaces need to derive from ISlangUnknown (or IUnknown).
+class IDoThings : public ISlangUnknown
+{
+public:
+ virtual int SLANG_MCALL doThing(int a, int b) = 0;
+ virtual int SLANG_MCALL calcHash(const char* in) = 0;
+};
+
+static int _calcHash(const char* in)
+{
+ int hash = 0;
+ for (; *in; ++in)
+ {
+ // A very poor hash function
+ hash = hash * 13 + *in;
+ }
+ return hash;
+}
+
+class DoThings :public IDoThings
+{
+public:
+ // We don't need queryInterface for this impl, or ref counting
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE { return SLANG_E_NOT_IMPLEMENTED; }
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; }
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; }
+
+ // IDoThings
+ virtual int SLANG_MCALL doThing(int a, int b) SLANG_OVERRIDE { return a + b + 1; }
+ virtual int SLANG_MCALL calcHash(const char* in) SLANG_OVERRIDE { return (int)_calcHash(in); }
+};
+
+static SlangResult _innerMain(int argc, char** argv)
+{
+ // Create the session
+ ComPtr<slang::IGlobalSession> slangSession;
+ slangSession.attach(spCreateSession(NULL));
+
+ // Set up the prelude
+ TestToolUtil::setSessionDefaultPreludeFromExePath(argv[0], slangSession);
+
+ // Create a compile request
+ Slang::ComPtr<slang::ICompileRequest> request;
+ SLANG_RETURN_ON_FAIL(slangSession->createCompileRequest(request.writeRef()));
+
+ // We want to compile to 'HOST_CALLABLE' here such that we can execute the Slang code.
+ //
+ // Note that it is possible to use HOST_HOST_CALLABLE, but this currently only works with 'regular' C++ compilers
+ // not with `slang-llvm`.
+ const int targetIndex = request->addCodeGenTarget(SLANG_SHADER_HOST_CALLABLE);
+
+ // Set the target flag to indicate that we want to compile all into a library.
+ request->setTargetFlags(targetIndex, SLANG_TARGET_FLAG_GENERATE_WHOLE_PROGRAM);
+
+ // Add the translation unit
+ const int translationUnitIndex = request->addTranslationUnit(SLANG_SOURCE_LANGUAGE_SLANG, nullptr);
+
+ // Set the source file for the translation unit
+ request->addTranslationUnitSourceFile(translationUnitIndex, "shader.slang");
+
+ const SlangResult compileRes = request->compile();
+
+ // Even if there were no errors that forced compilation to fail, the
+ // compiler may have produced "diagnostic" output such as warnings.
+ // We will go ahead and print that output here.
+ //
+ if(auto diagnostics = request->getDiagnosticOutput())
+ {
+ printf("%s", diagnostics);
+ }
+
+ // Get the 'shared library' (note that this doesn't necessarily have to be implemented as a shared library
+ // it's just an interface to executable code).
+ ComPtr<ISlangSharedLibrary> sharedLibrary;
+ SLANG_RETURN_ON_FAIL(request->getTargetHostCallable(0, sharedLibrary.writeRef()));
+
+ {
+ typedef const char* (*Func)(const char*);
+ Func func = (Func)sharedLibrary->findFuncByName("getString");
+
+ if (!func)
+ {
+ return SLANG_FAIL;
+ }
+
+ String text = "Hello World!";
+ String returnedText = func(text.getBuffer());
+
+ SLANG_ASSERT(text == returnedText);
+ }
+ {
+ typedef int (*Func)(const char* text, IDoThings* doThings);
+
+ Func func = (Func)sharedLibrary->findFuncByName("calcHash");
+
+ if (!func)
+ {
+ return SLANG_FAIL;
+ }
+
+ DoThings doThings;
+
+ String text("Hello");
+
+ const int hash = func(text.getBuffer(), &doThings);
+
+ SLANG_ASSERT(hash == _calcHash(text.getBuffer()));
+ }
+
+ return SLANG_OK;
+}
+
+int main(int argc, char** argv)
+{
+ return SLANG_SUCCEEDED(_innerMain(argc, argv)) ? 0 : -1;
+}
diff --git a/examples/cpu-com-example/shader.slang b/examples/cpu-com-example/shader.slang
new file mode 100644
index 000000000..b0fe259be
--- /dev/null
+++ b/examples/cpu-com-example/shader.slang
@@ -0,0 +1,21 @@
+// shader.slang
+
+// Example of using 'NativeString'
+
+public __extern_cpp NativeString getString(NativeString in)
+{
+ return in;
+}
+
+[COM]
+interface IDoThings
+{
+ int doThing(int a, int b);
+ int calcHash(NativeString in);
+}
+
+public __extern_cpp int calcHash(NativeString text, IDoThings doThings)
+{
+ return doThings.calcHash(text);
+}
+
diff --git a/prelude/slang-cpp-prelude.h b/prelude/slang-cpp-prelude.h
index 612f9ec9f..db83222a6 100644
--- a/prelude/slang-cpp-prelude.h
+++ b/prelude/slang-cpp-prelude.h
@@ -120,6 +120,52 @@ Any compilers not detected by the above logic are now now explicitly zeroed out.
# define SLANG_OFFSET_OF(X, Y) offsetof(X, Y)
#endif
+// If slang.h has been included we don't need any of these definitions
+#ifndef SLANG_H
+
+/* Macro for declaring if a method is no throw. Should be set before the return parameter. */
+#ifndef SLANG_NO_THROW
+# if SLANG_WINDOWS_FAMILY && !defined(SLANG_DISABLE_EXCEPTIONS)
+# define SLANG_NO_THROW __declspec(nothrow)
+# endif
+#endif
+#ifndef SLANG_NO_THROW
+# define SLANG_NO_THROW
+#endif
+
+/* The `SLANG_STDCALL` and `SLANG_MCALL` defines are used to set the calling
+convention for interface methods.
+*/
+#ifndef SLANG_STDCALL
+# if SLANG_MICROSOFT_FAMILY
+# define SLANG_STDCALL __stdcall
+# else
+# define SLANG_STDCALL
+# endif
+#endif
+#ifndef SLANG_MCALL
+# define SLANG_MCALL SLANG_STDCALL
+#endif
+
+struct SlangUUID
+{
+ uint32_t data1;
+ uint16_t data2;
+ uint16_t data3;
+ uint8_t data4[8];
+};
+
+typedef int32_t SlangResult;
+
+struct ISlangUnknown
+{
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) = 0;
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() = 0;
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() = 0;
+};
+
+#endif // SLANG_H
+
#include "slang-cpp-types.h"
#include "slang-cpp-scalar-intrinsics.h"
diff --git a/premake5.lua b/premake5.lua
index 8b4348cfa..75d093612 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -692,6 +692,9 @@ newoption {
example "shader-object"
kind "ConsoleApp"
+ example "cpu-com-example"
+ kind "ConsoleApp"
+
example "cpu-hello-world"
kind "ConsoleApp"
if enableExperimental then
diff --git a/slang.h b/slang.h
index d08c6be34..1c6eb5fed 100644
--- a/slang.h
+++ b/slang.h
@@ -570,6 +570,7 @@ extern "C"
SLANG_PTX, ///< PTX
SLANG_OBJECT_CODE, ///< Object code that can be used for later linking
SLANG_HOST_CPP_SOURCE, ///< C++ code for host library or executable.
+ SLANG_HOST_HOST_CALLABLE, ///<
SLANG_TARGET_COUNT_OF,
};
diff --git a/slang.sln b/slang.sln
index c00df8e81..560163096 100644
--- a/slang.sln
+++ b/slang.sln
@@ -29,6 +29,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "build\visual-studio
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpu-com-example", "build\visual-studio\cpu-com-example\cpu-com-example.vcxproj", "{0996B38F-F512-A7D2-1E90-A7E60A6C4366}"
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpu-hello-world", "build\visual-studio\cpu-hello-world\cpu-hello-world.vcxproj", "{4B47A364-37C4-96A7-6041-97BB4C1D333B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example-base", "build\visual-studio\example-base\example-base.vcxproj", "{37BED5B5-23FA-D81F-8C0C-F1167867813A}"
@@ -235,6 +237,18 @@ Global
{F9BE7957-8399-899E-0C49-E714FDDD4B65}.Release|Win32.Build.0 = Release|Win32
{F9BE7957-8399-899E-0C49-E714FDDD4B65}.Release|x64.ActiveCfg = Release|x64
{F9BE7957-8399-899E-0C49-E714FDDD4B65}.Release|x64.Build.0 = Release|x64
+ {0996B38F-F512-A7D2-1E90-A7E60A6C4366}.Debug|aarch64.ActiveCfg = Debug aarch64|ARM
+ {0996B38F-F512-A7D2-1E90-A7E60A6C4366}.Debug|aarch64.Build.0 = Debug aarch64|ARM
+ {0996B38F-F512-A7D2-1E90-A7E60A6C4366}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0996B38F-F512-A7D2-1E90-A7E60A6C4366}.Debug|Win32.Build.0 = Debug|Win32
+ {0996B38F-F512-A7D2-1E90-A7E60A6C4366}.Debug|x64.ActiveCfg = Debug|x64
+ {0996B38F-F512-A7D2-1E90-A7E60A6C4366}.Debug|x64.Build.0 = Debug|x64
+ {0996B38F-F512-A7D2-1E90-A7E60A6C4366}.Release|aarch64.ActiveCfg = Release aarch64|ARM
+ {0996B38F-F512-A7D2-1E90-A7E60A6C4366}.Release|aarch64.Build.0 = Release aarch64|ARM
+ {0996B38F-F512-A7D2-1E90-A7E60A6C4366}.Release|Win32.ActiveCfg = Release|Win32
+ {0996B38F-F512-A7D2-1E90-A7E60A6C4366}.Release|Win32.Build.0 = Release|Win32
+ {0996B38F-F512-A7D2-1E90-A7E60A6C4366}.Release|x64.ActiveCfg = Release|x64
+ {0996B38F-F512-A7D2-1E90-A7E60A6C4366}.Release|x64.Build.0 = Release|x64
{4B47A364-37C4-96A7-6041-97BB4C1D333B}.Debug|aarch64.ActiveCfg = Debug aarch64|ARM
{4B47A364-37C4-96A7-6041-97BB4C1D333B}.Debug|aarch64.Build.0 = Debug aarch64|ARM
{4B47A364-37C4-96A7-6041-97BB4C1D333B}.Debug|Win32.ActiveCfg = Debug|Win32
@@ -490,6 +504,7 @@ Global
{B2D63B45-92B0-40F7-B242-CCA4DFD64341} = {FD47AE19-69FD-260F-F2F1-20E65EA61D13}
{BE412850-4BB9-429A-877C-BFBC4B34186C} = {FD47AE19-69FD-260F-F2F1-20E65EA61D13}
{23149706-C12F-4329-B6AA-8266407C32D3} = {FD47AE19-69FD-260F-F2F1-20E65EA61D13}
+ {0996B38F-F512-A7D2-1E90-A7E60A6C4366} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{4B47A364-37C4-96A7-6041-97BB4C1D333B} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{37BED5B5-23FA-D81F-8C0C-F1167867813A} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{57C81DD3-4304-213D-AC16-39349871C957} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
diff --git a/source/compiler-core/slang-artifact-info.cpp b/source/compiler-core/slang-artifact-info.cpp
index 1b9209516..b67adb666 100644
--- a/source/compiler-core/slang-artifact-info.cpp
+++ b/source/compiler-core/slang-artifact-info.cpp
@@ -152,6 +152,12 @@ static const KindExtension g_cpuKindExts[] =
return info.isSet(ArtifactPayloadInfo::Flag::IsGpuNative) && info.flavor == ArtifactPayloadInfo::Flavor::Binary;
}
+/* static */bool ArtifactInfoUtil::isPayloadCpuTarget(Payload payload)
+{
+ return isPayloadCpuBinary(payload) ||
+ (payload == Payload::C || payload == Payload::CPP);
+}
+
/* static */UnownedStringSlice ArtifactInfoUtil::getDefaultExtensionForPayload(Payload payload)
{
switch (payload)
diff --git a/source/compiler-core/slang-artifact-info.h b/source/compiler-core/slang-artifact-info.h
index 1db3712dc..e63349937 100644
--- a/source/compiler-core/slang-artifact-info.h
+++ b/source/compiler-core/slang-artifact-info.h
@@ -67,6 +67,12 @@ struct ArtifactInfoUtil
/// Returns true if the payload type is applicable to the GPU
static bool isPayloadGpuBinary(Payload payload);
+ /// True if is a CPU target
+ static bool isPayloadCpuTarget(Payload payload);
+
+ /// True if is a CPU target - either
+ static bool isCpuTarget(const ArtifactDesc& desc) { return isPayloadCpuTarget(desc.payload); }
+
/// True if is a CPU binary
static bool isCpuBinary(const ArtifactDesc& desc) { return isPayloadCpuBinary(desc.payload); }
/// True if is a GPU binary
diff --git a/source/compiler-core/slang-artifact.cpp b/source/compiler-core/slang-artifact.cpp
index dfa9e645b..5e5b93578 100644
--- a/source/compiler-core/slang-artifact.cpp
+++ b/source/compiler-core/slang-artifact.cpp
@@ -38,6 +38,7 @@ namespace Slang {
case SLANG_CUDA_SOURCE: return make(Kind::Text, Payload::CUDA, Style::Kernel, 0);
case SLANG_PTX: return make(Kind::Executable, Payload::PTX, Style::Kernel, 0);
case SLANG_OBJECT_CODE: return make(Kind::ObjectCode, Payload::HostCPU, Style::Kernel, 0);
+ case SLANG_HOST_HOST_CALLABLE: return make(Kind::Callable, Payload::HostCPU, Style::Host, 0);
default: break;
}
diff --git a/source/core/slang-type-text-util.cpp b/source/core/slang-type-text-util.cpp
index 454ca4258..9985b8b23 100644
--- a/source/core/slang-type-text-util.cpp
+++ b/source/core/slang-type-text-util.cpp
@@ -75,6 +75,8 @@ static const CompileTargetInfo s_compileTargetInfos[] =
{ SLANG_PTX, "ptx", "ptx" },
{ SLANG_SHADER_HOST_CALLABLE, "", "host-callable,callable" },
{ SLANG_OBJECT_CODE, "obj,o", "object-code" },
+ { SLANG_HOST_HOST_CALLABLE, "", "host-host-callable" },
+
};
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index 74162d2ef..bcf857fc8 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -13,6 +13,7 @@
#include "slang-compiler.h"
#include "../compiler-core/slang-lexer.h"
+#include "../compiler-core/slang-artifact.h"
#include "slang-lower-to-ir.h"
#include "slang-mangle.h"
@@ -56,14 +57,7 @@ namespace Slang
bool isHeterogeneousTarget(CodeGenTarget target)
{
- switch (target)
- {
- case CodeGenTarget::HostCPPSource:
- case CodeGenTarget::HostExecutable:
- return true;
- default:
- return false;
- }
+ return ArtifactDesc::makeFromCompileTarget(asExternal(target)).style == ArtifactStyle::Host;
}
void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
@@ -592,6 +586,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
case CodeGenTarget::ShaderHostCallable:
case CodeGenTarget::ShaderSharedLibrary:
case CodeGenTarget::HostExecutable:
+ case CodeGenTarget::HostHostCallable:
{
// We need some C/C++ compiler
return PassThroughMode::GenericCCpp;
@@ -983,9 +978,14 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
{
case CodeGenTarget::ShaderHostCallable:
case CodeGenTarget::ShaderSharedLibrary:
+ {
return CodeGenTarget::CPPSource;
+ }
+ case CodeGenTarget::HostHostCallable:
case CodeGenTarget::HostExecutable:
+ {
return CodeGenTarget::HostCPPSource;
+ }
case CodeGenTarget::PTX: return CodeGenTarget::CUDASource;
case CodeGenTarget::DXBytecode: return CodeGenTarget::HLSL;
case CodeGenTarget::DXIL: return CodeGenTarget::HLSL;
@@ -997,14 +997,8 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
static bool _isCPUHostTarget(CodeGenTarget target)
{
- switch (target)
- {
- case CodeGenTarget::HostCPPSource:
- case CodeGenTarget::HostExecutable:
- return true;
- default:
- return false;
- }
+ auto desc = ArtifactDesc::makeFromCompileTarget(asExternal(target));
+ return desc.style == ArtifactStyle::Host;
}
SlangResult CodeGenContext::emitWithDownstreamForEntryPoints(
@@ -1299,7 +1293,8 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
}
// If we aren't using LLVM 'host callable', we want downstream compile to produce a shared library
- if (compilerType != PassThroughMode::LLVM && target == CodeGenTarget::ShaderHostCallable)
+ if (compilerType != PassThroughMode::LLVM &&
+ ArtifactDesc::makeFromCompileTarget(asExternal(target)).kind == ArtifactKind::Callable)
{
target = CodeGenTarget::ShaderSharedLibrary;
}
@@ -1586,6 +1581,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
case CodeGenTarget::ShaderHostCallable:
case CodeGenTarget::ShaderSharedLibrary:
case CodeGenTarget::HostExecutable:
+ case CodeGenTarget::HostHostCallable:
SLANG_RETURN_ON_FAIL(emitWithDownstreamForEntryPoints(outDownstreamResult, outMetadata));
return SLANG_OK;
@@ -1611,6 +1607,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
case CodeGenTarget::DXIL:
case CodeGenTarget::DXBytecode:
case CodeGenTarget::PTX:
+ case CodeGenTarget::HostHostCallable:
case CodeGenTarget::ShaderHostCallable:
case CodeGenTarget::ShaderSharedLibrary:
case CodeGenTarget::HostExecutable:
@@ -1794,7 +1791,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
ComPtr<ISlangBlob> blob;
if (SLANG_FAILED(result.getBlob(blob)))
{
- if (targetReq->getTarget() == CodeGenTarget::ShaderHostCallable)
+ if (ArtifactDesc::makeFromCompileTarget(asExternal(targetReq->getTarget())).kind == ArtifactKind::Callable)
{
// Some HostCallable are not directly representable as a 'binary'.
// So here, we just ignore if that appears the case, and don't output an unexpected error.
@@ -1838,6 +1835,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
case CodeGenTarget::PTX:
// For now we just dump PTX out as hex
+ case CodeGenTarget::HostHostCallable:
case CodeGenTarget::ShaderHostCallable:
case CodeGenTarget::ShaderSharedLibrary:
case CodeGenTarget::HostExecutable:
@@ -2411,11 +2409,19 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
case CodeGenTarget::CUDASource: return ".cu";
case CodeGenTarget::CPPSource: return ".cpp";
case CodeGenTarget::HostCPPSource: return ".cpp";
- // What these should be called is target specific, but just use these exts to make clear for now
- // for now
- case CodeGenTarget::HostExecutable: return ".exe";
+
+ // What these should be called is target specific, but just use these exts to make clear for now
+ // for now
+ case CodeGenTarget::HostExecutable:
+ {
+ return ".exe";
+ }
+ case CodeGenTarget::HostHostCallable:
case CodeGenTarget::ShaderHostCallable:
- case CodeGenTarget::ShaderSharedLibrary: return ".shared-lib";
+ case CodeGenTarget::ShaderSharedLibrary:
+ {
+ return ".shared-lib";
+ }
default: break;
}
return nullptr;
@@ -2429,22 +2435,16 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
return;
auto target = getTargetFormat();
- switch (target)
- {
- case CodeGenTarget::CPPSource:
- case CodeGenTarget::HostCPPSource:
- case CodeGenTarget::CUDASource:
- case CodeGenTarget::CSource:
- case CodeGenTarget::DXILAssembly:
- case CodeGenTarget::DXBytecodeAssembly:
- case CodeGenTarget::SPIRVAssembly:
- case CodeGenTarget::GLSL:
- case CodeGenTarget::HLSL:
- {
- dumpIntermediateText(data, size, _getTargetExtension(target));
- break;
- }
+ const auto desc = ArtifactDesc::makeFromCompileTarget(asExternal(target));
+ if (desc.kind == ArtifactKind::Text)
+ {
+ dumpIntermediateText(data, size, _getTargetExtension(target));
+ return;
+ }
+
+ switch (target)
+ {
#if 0
case CodeGenTarget::SlangIRAssembly:
{
@@ -2452,7 +2452,6 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
break;
}
#endif
-
case CodeGenTarget::DXIL:
case CodeGenTarget::DXBytecode:
case CodeGenTarget::SPIRV:
@@ -2471,6 +2470,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val)
break;
}
+ case CodeGenTarget::HostHostCallable:
case CodeGenTarget::ShaderHostCallable:
case CodeGenTarget::ShaderSharedLibrary:
case CodeGenTarget::HostExecutable:
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index e0152566c..683e1f7f1 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -79,6 +79,7 @@ namespace Slang
CUDASource = SLANG_CUDA_SOURCE,
PTX = SLANG_PTX,
ObjectCode = SLANG_OBJECT_CODE,
+ HostHostCallable = SLANG_HOST_HOST_CALLABLE,
CountOf = SLANG_TARGET_COUNT_OF,
};
@@ -3136,6 +3137,8 @@ SLANG_FORCE_INLINE EndToEndCompileRequest* asInternal(SlangCompileRequest* reque
return endToEndRequest;
}
+SLANG_FORCE_INLINE SlangCompileTarget asExternal(CodeGenTarget target) { return (SlangCompileTarget)target; }
+
}
#endif
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 6b6d462b9..e0b1a44f2 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -1540,11 +1540,15 @@ void CLikeSourceEmitter::emitCallExpr(IRCall* inst, EmitOpInfo outerPrec)
handleRequiredCapabilities(funcValue);
// Detect if this is a call into a COM interface method.
- if (funcValue->getOp() == kIROp_lookup_interface_method &&
- funcValue->getOperand(0)->getDataType()->getOp() == kIROp_ComPtrType)
+ if (funcValue->getOp() == kIROp_lookup_interface_method)
{
- emitComInterfaceCallExpr(inst, outerPrec);
- return;
+ const auto operand0TypeOp = funcValue->getOperand(0)->getDataType()->getOp();
+
+ if (operand0TypeOp == kIROp_ComPtrType || operand0TypeOp == kIROp_PtrType)
+ {
+ emitComInterfaceCallExpr(inst, outerPrec);
+ return;
+ }
}
// We want to detect any call to an intrinsic operation,
diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp
index 482ada394..ddc8b24ed 100644
--- a/source/slang/slang-emit-cpp.cpp
+++ b/source/slang/slang-emit-cpp.cpp
@@ -544,9 +544,10 @@ SlangResult CPPSourceEmitter::calcTypeName(IRType* type, CodeGenTarget target, S
}
case kIROp_ComPtrType:
{
- out << "ComPtr<";
auto comPtrType = static_cast<IRComPtrType*>(type);
auto baseType = cast<IRType>(comPtrType->getOperand(0));
+
+ out << "ComPtr<";
SLANG_RETURN_ON_FAIL(calcTypeName(baseType, target, out));
out << ">";
return SLANG_OK;
@@ -1635,6 +1636,12 @@ CPPSourceEmitter::CPPSourceEmitter(const Desc& desc):
{
m_semanticUsedFlags = 0;
//m_semanticUsedFlags = SemanticUsedFlag::GroupID | SemanticUsedFlag::GroupThreadID | SemanticUsedFlag::DispatchThreadID;
+
+
+ const auto artifactDesc = ArtifactDesc::makeFromCompileTarget(asExternal(getTarget()));
+
+ // If we have runtime library we can convert to a terminated string slice
+ m_hasString = (artifactDesc.style == ArtifactStyle::Host);
}
void CPPSourceEmitter::emitParamTypeImpl(IRType* type, String const& name)
@@ -1945,6 +1952,9 @@ void CPPSourceEmitter::emitEntryPointAttributesImpl(IRFunc* irFunc, IREntryPoint
void CPPSourceEmitter::emitSimpleFuncImpl(IRFunc* func)
{
+ // Emit function decorations
+ emitFuncDecorations(func);
+
auto resultType = func->getResultType();
auto name = getName(func);
@@ -1952,7 +1962,6 @@ void CPPSourceEmitter::emitSimpleFuncImpl(IRFunc* func)
// Deal with decorations that need
// to be emitted as attributes
-
// We start by emitting the result type and function name.
//
if (IREntryPointDecoration* entryPointDecor = func->findDecoration<IREntryPointDecoration>())
@@ -2416,16 +2425,23 @@ bool CPPSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOut
}
case kIROp_StringLit:
{
- m_writer->emit("toTerminatedSlice(");
-
auto handler = StringEscapeUtil::getHandler(StringEscapeUtil::Style::Cpp);
-
+
StringBuilder buf;
const auto slice = as<IRStringLit>(inst)->getStringSlice();
StringEscapeUtil::appendQuoted(handler, slice, buf);
- m_writer->emit(buf);
+
+ if (m_hasString)
+ {
+ m_writer->emit("toTerminatedSlice(");
+ m_writer->emit(buf);
+ m_writer->emit(")");
+ }
+ else
+ {
+ m_writer->emit(buf);
+ }
- m_writer->emit(")");
return true;
}
case kIROp_PtrLit:
@@ -2475,12 +2491,17 @@ void CPPSourceEmitter::emitPreModuleImpl()
{
if (m_target == CodeGenTarget::CPPSource)
{
- // NOTE, that this opens an anonymous scope.
+ // TODO(JS): Previously this opened an anonymous scope for all generated functions
+ // Unfortunately this is a problem if we are just emitting code that is externally available
+ // and is not only accessible through entry points. So for now we disable
+
+ // that this opens an anonymous scope.
// The scope is closed in `emitModuleImpl`
+ //m_writer->emit("namespace { // anonymous \n\n");
+
// When generating kernel code in C++, put all into an anonymous namespace
// This includes any generated types, and generated intrinsics.
- m_writer->emit("namespace { // anonymous \n\n");
m_writer->emit("#ifdef SLANG_PRELUDE_NAMESPACE\n");
m_writer->emit("using namespace SLANG_PRELUDE_NAMESPACE;\n");
m_writer->emit("#endif\n\n");
@@ -2526,6 +2547,45 @@ void CPPSourceEmitter::emitPreModuleImpl()
}
}
+/* virtual */void CPPSourceEmitter::emitFuncDecorationsImpl(IRFunc* func)
+{
+ // Specially handle export, as we don't want to emit it multiple times
+ if (getTargetReq()->isWholeProgramRequest())
+ {
+ bool isExternC = false;
+ bool isExported = false;
+
+ // If public/export made it externally visible
+ for (auto decoration : func->getDecorations())
+ {
+ const auto op = decoration->getOp();
+ if (op == kIROp_ExternCppDecoration)
+ {
+ isExternC = true;
+ }
+ else if (op == kIROp_PublicDecoration ||
+ op == kIROp_HLSLExportDecoration)
+ {
+ isExported = true;
+ }
+ }
+
+ // TODO(JS): Currently export *also* implies it's extern "C" and we can't list twice
+ if (isExported)
+ {
+ m_writer->emit("SLANG_PRELUDE_EXPORT\n");
+ }
+ else if (isExternC)
+ {
+ // It's name is not manged.
+ m_writer->emit("extern \"C\"\n");
+ }
+ }
+
+ // Use the default for others
+ Super::emitFuncDecorationsImpl(func);
+}
+
void CPPSourceEmitter::emitOperandImpl(IRInst* inst, EmitOpInfo const& outerPrec)
{
if (shouldFoldInstIntoUseSites(inst))
@@ -2792,11 +2852,16 @@ void CPPSourceEmitter::emitModuleImpl(IRModule* module, DiagnosticSink* sink)
// Emit all witness table definitions.
_emitWitnessTableDefinitions();
- if (m_target == CodeGenTarget::CPPSource)
- {
+ // TODO(JS):
+ // Previously output code was placed in an anonymous namespace
+ // Now that we can have any function available externally (not just entry points)
+ // this doesn't work.
+
+ //if (m_target == CodeGenTarget::CPPSource)
+ //{
// Need to close the anonymous namespace when outputting for C++ kernel.
- m_writer->emit("} // anonymous\n\n");
- }
+ //m_writer->emit("} // anonymous\n\n");
+ //}
// Finally we need to output dll entry points
diff --git a/source/slang/slang-emit-cpp.h b/source/slang/slang-emit-cpp.h
index 0d9327b9e..f5ba35933 100644
--- a/source/slang/slang-emit-cpp.h
+++ b/source/slang/slang-emit-cpp.h
@@ -74,7 +74,8 @@ protected:
virtual bool tryEmitGlobalParamImpl(IRGlobalParam* varDecl, IRType* varType) SLANG_OVERRIDE;
virtual void emitIntrinsicCallExprImpl(IRCall* inst, IRTargetIntrinsicDecoration* targetIntrinsic, EmitOpInfo const& inOuterPrec) SLANG_OVERRIDE;
virtual void emitLoopControlDecorationImpl(IRLoopControlDecoration* decl) SLANG_OVERRIDE;
-
+ virtual void emitFuncDecorationsImpl(IRFunc* func) SLANG_OVERRIDE;
+
virtual const UnownedStringSlice* getVectorElementNames(BaseType elemType, Index elemCount);
// Replaceable for classes derived from CPPSourceEmitter
@@ -153,6 +154,8 @@ protected:
// They must be emitted last, after the entire `Context` class so those member functions defined
// in `Context` may be referenced.
List<IRWitnessTable*> pendingWitnessTableDefinitions;
+
+ bool m_hasString = false;
};
}
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 72ad80873..0bb1d73e5 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -177,6 +177,8 @@ Result linkAndOptimizeIR(
auto target = codeGenContext->getTargetFormat();
auto targetRequest = codeGenContext->getTargetReq();
+ // Get the artifact desc for the target
+ const auto artifactDesc = ArtifactDesc::makeFromCompileTarget(asExternal(target));
// We start out by performing "linking" at the level of the IR.
// This step will create a fresh IR module to be used for
@@ -203,12 +205,20 @@ Result linkAndOptimizeIR(
switch (target)
{
- default:
- break;
- case CodeGenTarget::HostCPPSource:
- lowerComInterfaces(irModule, sink);
- generateDllImportFuncs(irModule, sink);
- break;
+ case CodeGenTarget::CPPSource:
+ {
+ // TODO(JS):
+ // We want the interface transformation to take place for 'regular' CPPSource for now too.
+ lowerComInterfaces(irModule, artifactDesc.style, sink);
+ break;
+ }
+ case CodeGenTarget::HostCPPSource:
+ {
+ lowerComInterfaces(irModule, artifactDesc.style, sink);
+ generateDllImportFuncs(irModule, sink);
+ break;
+ }
+ default: break;
}
// Lower `Result<T,E>` types into ordinary struct types.
diff --git a/source/slang/slang-ir-com-interface.cpp b/source/slang/slang-ir-com-interface.cpp
index 1bcf3d2b6..009d2314d 100644
--- a/source/slang/slang-ir-com-interface.cpp
+++ b/source/slang/slang-ir-com-interface.cpp
@@ -12,9 +12,9 @@ struct ComInterfaceLoweringContext
IRModule* module;
DiagnosticSink* diagnosticSink;
- SharedIRBuilder sharedBuilder;
+ ArtifactStyle artifactStyle;
- Dictionary<IRInterfaceType*, IRComPtrType*> comPtrTypes;
+ SharedIRBuilder sharedBuilder;
void replaceTypeUses(IRInst* inst, IRInst* newValue)
{
@@ -33,6 +33,7 @@ struct ComInterfaceLoweringContext
case kIROp_RTTIPointerType:
case kIROp_RTTIHandleType:
case kIROp_ComPtrType:
+ case kIROp_PtrType:
continue;
default:
break;
@@ -41,19 +42,17 @@ struct ComInterfaceLoweringContext
}
}
- IRComPtrType* processInterfaceType(IRInterfaceType* type)
+ IRType* processInterfaceType(IRInterfaceType* type)
{
if (!type->findDecoration<IRComInterfaceDecoration>())
return nullptr;
-
- IRComPtrType* result = nullptr;
-
- if (comPtrTypes.TryGetValue(type, result))
- return result;
-
+
IRBuilder builder(sharedBuilder);
builder.setInsertInto(module->getModuleInst());
- result = builder.getComPtrType(type);
+
+ IRType* result = (artifactStyle == ArtifactStyle::Kernel) ?
+ static_cast<IRType*>(builder.getPtrType(type)) :
+ static_cast<IRType*>(builder.getComPtrType(type));
replaceTypeUses(type, result);
return result;
@@ -86,11 +85,12 @@ struct ComInterfaceLoweringContext
}
};
-void lowerComInterfaces(IRModule* module, DiagnosticSink* sink)
+void lowerComInterfaces(IRModule* module, ArtifactStyle artifactStyle, DiagnosticSink* sink)
{
ComInterfaceLoweringContext context;
context.module = module;
context.diagnosticSink = sink;
+ context.artifactStyle = artifactStyle;
context.sharedBuilder.init(module);
return context.processModule();
}
diff --git a/source/slang/slang-ir-com-interface.h b/source/slang/slang-ir-com-interface.h
index 0f6737880..2fffc90fd 100644
--- a/source/slang/slang-ir-com-interface.h
+++ b/source/slang/slang-ir-com-interface.h
@@ -1,6 +1,8 @@
// slang-ir-com-interface.cpp
#pragma once
+#include "../compiler-core/slang-artifact.h"
+
namespace Slang
{
@@ -10,6 +12,6 @@ class DiagnosticSink;
/// Lower com interface types.
/// A use of `IRInterfaceType` with `IRComInterfaceDecoration` will be translated into a `IRComPtr` type.
/// A use of `IRThisType` with a COM interface will also be translated into a `IRComPtr` type.
-void lowerComInterfaces(IRModule* module, DiagnosticSink* sink);
+void lowerComInterfaces(IRModule* module, ArtifactStyle artifactStyle, DiagnosticSink* sink);
}
diff --git a/source/slang/slang-ir-generics-lowering-context.cpp b/source/slang/slang-ir-generics-lowering-context.cpp
index bf3b8d855..e20b8b680 100644
--- a/source/slang/slang-ir-generics-lowering-context.cpp
+++ b/source/slang/slang-ir-generics-lowering-context.cpp
@@ -38,8 +38,21 @@ namespace Slang
bool isComInterfaceType(IRType* type)
{
- return type->findDecoration<IRComInterfaceDecoration>() != nullptr ||
- type->getOp() == kIROp_ComPtrType;
+ if (type->findDecoration<IRComInterfaceDecoration>() ||
+ type->getOp() == kIROp_ComPtrType)
+ {
+ return true;
+ }
+
+ // TODO(JS): Perhaps it should do IRPtrTypeBase, or some more expansive set of 'PtrType's
+ // but for now test for PtrType
+ if (auto ptrType = as<IRPtrType>(type))
+ {
+ auto valueType = ptrType->getValueType();
+ return valueType->findDecoration<IRComInterfaceDecoration>() != nullptr;
+ }
+
+ return false;
}
bool isTypeValue(IRInst* typeInst)
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index 875f18980..9825e4e23 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -2032,6 +2032,18 @@ struct OptionsParser
}
}
+ // If we don't have any raw outputs but do have a raw target,
+ // and output type is callable, add an empty' rawOutput.
+ if (rawOutputs.getCount() == 0 &&
+ rawTargets.getCount() == 1 &&
+ ArtifactDesc::makeFromCompileTarget(asExternal(rawTargets[0].format)).kind == ArtifactKind::Callable)
+ {
+ RawOutput rawOutput;
+ rawOutput.impliedFormat = rawTargets[0].format;
+ rawOutput.targetIndex = 0;
+ rawOutputs.add(rawOutput);
+ }
+
// Consider the output files specified via `-o` and try to figure
// out how to deal with them.
//
@@ -2083,6 +2095,8 @@ struct OptionsParser
case CodeGenTarget::CPPSource:
case CodeGenTarget::PTX:
case CodeGenTarget::CUDASource:
+
+ case CodeGenTarget::HostHostCallable:
case CodeGenTarget::ShaderHostCallable:
case CodeGenTarget::HostExecutable:
case CodeGenTarget::ShaderSharedLibrary:
@@ -2099,6 +2113,7 @@ struct OptionsParser
}
}
+
// Now that we've diagnosed the output paths, we can add them
// to the compile request at the appropriate locations.
//
diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp
index 7bff7118e..d0b12b19b 100644
--- a/source/slang/slang-parameter-binding.cpp
+++ b/source/slang/slang-parameter-binding.cpp
@@ -5,6 +5,8 @@
#include "slang-compiler.h"
#include "slang-type-layout.h"
+#include "../compiler-core/slang-artifact-info.h"
+
#include "slang-ir-string-hash.h"
#include "../../slang.h"
@@ -3029,18 +3031,8 @@ static int _calcTotalNumUsedRegistersForLayoutResourceKind(ParameterBindingConte
static bool _isCPUTarget(CodeGenTarget target)
{
- switch (target)
- {
- case CodeGenTarget::CPPSource:
- case CodeGenTarget::CSource:
- case CodeGenTarget::HostExecutable:
- case CodeGenTarget::ShaderSharedLibrary:
- case CodeGenTarget::ShaderHostCallable:
- {
- return true;
- }
- default: return false;
- }
+ const auto desc = ArtifactDesc::makeFromCompileTarget(asExternal(target));
+ return ArtifactInfoUtil::isCpuTarget(desc);
}
static bool _isPTXTarget(CodeGenTarget target)
diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp
index cd81c6173..09a21fb6f 100644
--- a/source/slang/slang-type-layout.cpp
+++ b/source/slang/slang-type-layout.cpp
@@ -4,6 +4,8 @@
#include "slang-syntax.h"
#include "slang-ir-insts.h"
+#include "../compiler-core/slang-artifact-info.h"
+
#include <assert.h>
namespace Slang {
@@ -1403,6 +1405,7 @@ LayoutRulesFamilyImpl* getDefaultLayoutRulesFamilyForTarget(TargetRequest* targe
case CodeGenTarget::SPIRVAssembly:
return &kGLSLLayoutRulesFamilyImpl;
+ case CodeGenTarget::HostHostCallable:
case CodeGenTarget::ShaderHostCallable:
case CodeGenTarget::HostExecutable:
case CodeGenTarget::ShaderSharedLibrary:
@@ -1603,18 +1606,7 @@ bool isKhronosTarget(TargetRequest* targetReq)
bool isCPUTarget(TargetRequest* targetReq)
{
- switch( targetReq->getTarget() )
- {
- default:
- return false;
-
- case CodeGenTarget::CPPSource:
- case CodeGenTarget::CSource:
- case CodeGenTarget::ShaderHostCallable:
- case CodeGenTarget::HostExecutable:
- case CodeGenTarget::ShaderSharedLibrary:
- return true;
- }
+ return ArtifactInfoUtil::isCpuTarget(ArtifactDesc::makeFromCompileTarget(asExternal(targetReq->getTarget())));
}
bool isCUDATarget(TargetRequest* targetReq)
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 7b22d04de..9379f3b03 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -670,17 +670,17 @@ SlangPassThrough Session::getDownstreamCompilerForTransition(SlangCompileTarget
return (SlangPassThrough)m_codeGenTransitionMap.getTransition(source, target);
}
+ const auto desc = ArtifactDesc::makeFromCompileTarget(inTarget);
+
// Special case host-callable
- if (target == CodeGenTarget::ShaderHostCallable)
+ if ((desc.kind == ArtifactKind::Callable) &&
+ (source == CodeGenTarget::CSource || source == CodeGenTarget::CPPSource))
{
- if (source == CodeGenTarget::CSource || source == CodeGenTarget::CPPSource)
+ // We prefer LLVM if it's available
+ DownstreamCompiler* llvm = getOrLoadDownstreamCompiler(PassThroughMode::LLVM, nullptr);
+ if (llvm)
{
- // We prefer LLVM if it's available
- DownstreamCompiler* llvm = getOrLoadDownstreamCompiler(PassThroughMode::LLVM, nullptr);
- if (llvm)
- {
- return SLANG_PASS_THROUGH_LLVM;
- }
+ return SLANG_PASS_THROUGH_LLVM;
}
}
@@ -1334,6 +1334,7 @@ CapabilitySet TargetRequest::getTargetCaps()
case CodeGenTarget::CPPSource:
case CodeGenTarget::HostExecutable:
case CodeGenTarget::ShaderSharedLibrary:
+ case CodeGenTarget::HostHostCallable:
case CodeGenTarget::ShaderHostCallable:
atoms.add(CapabilityAtom::CPP);
break;
@@ -4711,6 +4712,11 @@ static SlangResult _getWholeProgramResult(
auto linkage = req->getLinkage();
auto program = req->getSpecializedGlobalAndEntryPointsComponentType();
+ if (!program)
+ {
+ return SLANG_FAIL;
+ }
+
Index targetCount = linkage->targets.getCount();
if ((targetIndex < 0) || (targetIndex >= targetCount))
{
diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp
index d5f4408ed..f0d92b810 100644
--- a/tools/slang-test/slang-test-main.cpp
+++ b/tools/slang-test/slang-test-main.cpp
@@ -781,6 +781,8 @@ static PassThroughFlags _getPassThroughFlagsForTarget(SlangCompileTarget target)
}
case SLANG_SHADER_HOST_CALLABLE:
+ case SLANG_HOST_HOST_CALLABLE:
+
case SLANG_HOST_EXECUTABLE:
case SLANG_SHADER_SHARED_LIBRARY:
{