summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--build/visual-studio/slang-rt/slang-rt.vcxproj2
-rw-r--r--build/visual-studio/slang-rt/slang-rt.vcxproj.filters6
-rw-r--r--build/visual-studio/slang/slang.vcxproj3
-rw-r--r--build/visual-studio/slang/slang.vcxproj.filters9
-rw-r--r--examples/heterogeneous-hello-world/main.slang4
-rw-r--r--prelude/slang-cpp-host-prelude.h9
-rw-r--r--source/slang-rt/slang-rt.cpp49
-rw-r--r--source/slang-rt/slang-rt.h22
-rw-r--r--source/slang/core.meta.slang14
-rw-r--r--source/slang/slang-ast-builder.cpp10
-rw-r--r--source/slang/slang-ast-builder.h4
-rw-r--r--source/slang/slang-ast-expr.h5
-rw-r--r--source/slang/slang-ast-modifier.cpp8
-rw-r--r--source/slang/slang-ast-modifier.h7
-rw-r--r--source/slang/slang-ast-type.h5
-rw-r--r--source/slang/slang-check-conversion.cpp12
-rw-r--r--source/slang/slang-check-expr.cpp6
-rw-r--r--source/slang/slang-check-impl.h1
-rw-r--r--source/slang/slang-check-modifier.cpp11
-rw-r--r--source/slang/slang-diagnostic-defs.h2
-rw-r--r--source/slang/slang-emit-c-like.cpp40
-rw-r--r--source/slang/slang-emit-c-like.h26
-rw-r--r--source/slang/slang-emit-cpp.cpp191
-rw-r--r--source/slang/slang-emit-cpp.h2
-rw-r--r--source/slang/slang-emit.cpp10
-rw-r--r--source/slang/slang-ir-dll-import.cpp249
-rw-r--r--source/slang/slang-ir-dll-import.h11
-rw-r--r--source/slang/slang-ir-inst-defs.h6
-rw-r--r--source/slang/slang-ir-insts.h35
-rw-r--r--source/slang/slang-ir.cpp19
-rw-r--r--source/slang/slang-lower-to-ir.cpp10
-rw-r--r--source/slang/slang-parser.cpp9
-rw-r--r--source/slang/slang-type-system-shared.h1
-rw-r--r--source/slang/slang.cpp1
-rw-r--r--tools/gfx/d3d12/render-d3d12.cpp11
-rw-r--r--tools/gfx/d3d12/render-d3d12.h2
37 files changed, 678 insertions, 135 deletions
diff --git a/.gitignore b/.gitignore
index f2c9be351..84a69554e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -67,3 +67,4 @@ build/**/*.tlog
build/**/*.lastbuildstate
build/**/*.recipe
build/**/*.log
+*.dll
diff --git a/build/visual-studio/slang-rt/slang-rt.vcxproj b/build/visual-studio/slang-rt/slang-rt.vcxproj
index c0fab7f97..dbe57507b 100644
--- a/build/visual-studio/slang-rt/slang-rt.vcxproj
+++ b/build/visual-studio/slang-rt/slang-rt.vcxproj
@@ -335,6 +335,7 @@
<ClInclude Include="..\..\..\source\core\slang-virtual-object-pool.h" />
<ClInclude Include="..\..\..\source\core\slang-writer.h" />
<ClInclude Include="..\..\..\source\core\slang-zip-file-system.h" />
+ <ClInclude Include="..\..\..\source\slang-rt\slang-rt.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\source\core\slang-archive-file-system.cpp" />
@@ -378,6 +379,7 @@
<ClCompile Include="..\..\..\source\core\slang-writer.cpp" />
<ClCompile Include="..\..\..\source\core\slang-zip-file-system.cpp" />
<ClCompile Include="..\..\..\source\core\windows\slang-win-process.cpp" />
+ <ClCompile Include="..\..\..\source\slang-rt\slang-rt.cpp" />
</ItemGroup>
<ItemGroup>
<Natvis Include="..\..\..\source\core\core.natvis" />
diff --git a/build/visual-studio/slang-rt/slang-rt.vcxproj.filters b/build/visual-studio/slang-rt/slang-rt.vcxproj.filters
index 51b0313f6..e77c562cd 100644
--- a/build/visual-studio/slang-rt/slang-rt.vcxproj.filters
+++ b/build/visual-studio/slang-rt/slang-rt.vcxproj.filters
@@ -192,6 +192,9 @@
<ClInclude Include="..\..\..\source\core\slang-zip-file-system.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\slang-rt\slang-rt.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\source\core\slang-archive-file-system.cpp">
@@ -317,6 +320,9 @@
<ClCompile Include="..\..\..\source\core\windows\slang-win-process.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\slang-rt\slang-rt.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<Natvis Include="..\..\..\source\core\core.natvis">
diff --git a/build/visual-studio/slang/slang.vcxproj b/build/visual-studio/slang/slang.vcxproj
index 68c93810c..d81a92fd4 100644
--- a/build/visual-studio/slang/slang.vcxproj
+++ b/build/visual-studio/slang/slang.vcxproj
@@ -347,6 +347,7 @@ IF EXIST ..\..\..\external\slang-binaries\bin\windows-aarch64\slang-glslang.dll\
<ClInclude Include="..\..\..\source\slang\slang-ir-collect-global-uniforms.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-constexpr.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-dce.h" />
+ <ClInclude Include="..\..\..\source\slang\slang-ir-dll-import.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-dominators.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-entry-point-pass.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-entry-point-raw-ptr-params.h" />
@@ -439,6 +440,7 @@ IF EXIST ..\..\..\external\slang-binaries\bin\windows-aarch64\slang-glslang.dll\
<ClCompile Include="..\..\..\source\slang\slang-ast-builder.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ast-decl.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ast-dump.cpp" />
+ <ClCompile Include="..\..\..\source\slang\slang-ast-modifier.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ast-print.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ast-reflect.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ast-substitutions.cpp" />
@@ -482,6 +484,7 @@ IF EXIST ..\..\..\external\slang-binaries\bin\windows-aarch64\slang-glslang.dll\
<ClCompile Include="..\..\..\source\slang\slang-ir-constexpr.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-dce.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-deduplicate.cpp" />
+ <ClCompile Include="..\..\..\source\slang\slang-ir-dll-import.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-dominators.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-entry-point-pass.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-entry-point-raw-ptr-params.cpp" />
diff --git a/build/visual-studio/slang/slang.vcxproj.filters b/build/visual-studio/slang/slang.vcxproj.filters
index 85401a894..8d6873f4a 100644
--- a/build/visual-studio/slang/slang.vcxproj.filters
+++ b/build/visual-studio/slang/slang.vcxproj.filters
@@ -138,6 +138,9 @@
<ClInclude Include="..\..\..\source\slang\slang-ir-dce.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\slang\slang-ir-dll-import.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\slang\slang-ir-dominators.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -410,6 +413,9 @@
<ClCompile Include="..\..\..\source\slang\slang-ast-dump.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\slang\slang-ast-modifier.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\slang\slang-ast-print.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -539,6 +545,9 @@
<ClCompile Include="..\..\..\source\slang\slang-ir-deduplicate.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\slang\slang-ir-dll-import.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\slang\slang-ir-dominators.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/examples/heterogeneous-hello-world/main.slang b/examples/heterogeneous-hello-world/main.slang
index 08b4b7f39..90f39fff7 100644
--- a/examples/heterogeneous-hello-world/main.slang
+++ b/examples/heterogeneous-hello-world/main.slang
@@ -3,8 +3,12 @@
__target_intrinsic(cpp, "printf(\"%s\", ($0).getBuffer())")
public void writeln(String text);
+[DllImport("User32")]
+int MessageBoxA(Ptr<void> hwnd, String text, String caption, uint flags);
+
public __extern_cpp int main()
{
writeln("hello world");
+ MessageBoxA(nullptr, "hello world!", "example", 0);
return 0;
} \ No newline at end of file
diff --git a/prelude/slang-cpp-host-prelude.h b/prelude/slang-cpp-host-prelude.h
index 90087d158..37f28f8d6 100644
--- a/prelude/slang-cpp-host-prelude.h
+++ b/prelude/slang-cpp-host-prelude.h
@@ -5,12 +5,13 @@
#include <cmath>
#include <cstring>
-#include "../source/core/slang-string.h"
-#include "../source/core/slang-smart-pointer.h"
+#include "../source/slang-rt/slang-rt.h"
#include "../slang-com-ptr.h"
-#include "../slang-gfx.h"
+#include "slang-cpp-types.h"
using namespace Slang;
-using namespace gfx;
+
+template<typename TResult, typename... Args>
+using Slang_FuncType = TResult(SLANG_MCALL *)(Args...);
#endif
diff --git a/source/slang-rt/slang-rt.cpp b/source/slang-rt/slang-rt.cpp
new file mode 100644
index 000000000..163a1b99c
--- /dev/null
+++ b/source/slang-rt/slang-rt.cpp
@@ -0,0 +1,49 @@
+#include "slang-rt.h"
+#include "../core/slang-basic.h"
+#include "../core/slang-shared-library.h"
+
+#if SLANG_WINDOWS_FAMILY
+# include <Windows.h>
+#endif
+
+using namespace Slang;
+Dictionary<String, ComPtr<ISlangSharedLibrary>> slangRT_loadedLibraries;
+
+extern "C"
+{
+ SLANG_RT_API void SLANG_MCALL _slang_rt_abort(Slang::String errorMessage)
+ {
+ fprintf(stderr, "%s", errorMessage.getBuffer());
+#if SLANG_WINDOWS_FAMILY
+ MessageBoxA(0, errorMessage.getBuffer(), "Slang Runtime Error", MB_ICONERROR);
+#endif
+ abort();
+ }
+
+ SLANG_RT_API void* SLANG_MCALL _slang_rt_load_dll(Slang::String modulePath)
+ {
+ ComPtr<ISlangSharedLibrary> lib;
+ if (!slangRT_loadedLibraries.TryGetValue(modulePath, lib))
+ {
+ if (DefaultSharedLibraryLoader::getSingleton()->loadSharedLibrary(
+ modulePath.getBuffer(), lib.writeRef()) != SLANG_OK)
+ {
+ _slang_rt_abort("Failed to load DLL \"" + modulePath + "\"");
+ }
+ slangRT_loadedLibraries[modulePath] = lib;
+ }
+ return lib.get();
+ }
+
+ SLANG_RT_API void* SLANG_MCALL
+ _slang_rt_load_dll_func(void* moduleHandle, Slang::String funcName)
+ {
+ auto lib = static_cast<ISlangSharedLibrary*>(moduleHandle);
+ auto funcPtr = lib->findFuncByName(funcName.getBuffer());
+ if (!funcPtr)
+ {
+ _slang_rt_abort("Cannot find function \"" + funcName + "\" in loaded library.");
+ }
+ return (void*)funcPtr;
+ }
+}
diff --git a/source/slang-rt/slang-rt.h b/source/slang-rt/slang-rt.h
new file mode 100644
index 000000000..b6f397c72
--- /dev/null
+++ b/source/slang-rt/slang-rt.h
@@ -0,0 +1,22 @@
+// slang-rt.h
+#ifndef SLANG_RT_H
+#define SLANG_RT_H
+
+#include "../core/slang-string.h"
+#include "../core/slang-smart-pointer.h"
+
+#ifdef SLANG_RT_DYNAMIC_EXPORT
+# define SLANG_RT_API SLANG_DLL_EXPORT
+#else
+# define SLANG_RT_API
+#endif
+
+extern "C"
+{
+ SLANG_RT_API void SLANG_MCALL _slang_rt_abort(Slang::String errorMessage);
+ SLANG_RT_API void* SLANG_MCALL _slang_rt_load_dll(Slang::String modulePath);
+ SLANG_RT_API void* SLANG_MCALL
+ _slang_rt_load_dll_func(void* moduleHandle, Slang::String modulePath);
+}
+
+#endif
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index c8e05d769..c3e41b8fc 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -342,11 +342,18 @@ ${{{{
// Declare built-in pointer type
// (eventually we can have the traditional syntax sugar for this)
}}}}
+
+__magic_type(NullPtrType)
+struct NullPtr
+{
+};
+
__generic<T>
__magic_type(PtrType)
__intrinsic_type($(kIROp_PtrType))
struct Ptr
-{};
+{
+};
__generic<T>
__magic_type(OutType)
@@ -2164,6 +2171,10 @@ attribute_syntax [__extern] : ExternAttribute;
__attributeTarget(FunctionDeclBase)
attribute_syntax [__unsafeForceInlineEarly] : UnsafeForceInlineEarlyAttribute;
+__attributeTarget(FuncDecl)
+attribute_syntax [DllImport(modulePath: String)] : DllImportAttribute;
+
+
// Inheritance Control
__attributeTarget(AggTypeDecl)
attribute_syntax [sealed] : SealedAttribute;
@@ -2185,3 +2196,4 @@ attribute_syntax [noinline] : NoInlineAttribute;
__attributeTarget(StructDecl)
attribute_syntax [payload] : PayloadAttribute;
+
diff --git a/source/slang/slang-ast-builder.cpp b/source/slang/slang-ast-builder.cpp
index 8e1813df3..caf4c020d 100644
--- a/source/slang/slang-ast-builder.cpp
+++ b/source/slang/slang-ast-builder.cpp
@@ -110,6 +110,16 @@ Type* SharedASTBuilder::getDynamicType()
return m_dynamicType;
}
+Type* SharedASTBuilder::getNullPtrType()
+{
+ if (!m_nullPtrType)
+ {
+ auto nullPtrTypeDecl = findMagicDecl("NullPtrType");
+ m_nullPtrType = DeclRefType::create(m_astBuilder, makeDeclRef<Decl>(nullPtrTypeDecl));
+ }
+ return m_nullPtrType;
+}
+
SharedASTBuilder::~SharedASTBuilder()
{
// Release built in types..
diff --git a/source/slang/slang-ast-builder.h b/source/slang/slang-ast-builder.h
index 7af5ae710..0642455c3 100644
--- a/source/slang/slang-ast-builder.h
+++ b/source/slang/slang-ast-builder.h
@@ -27,6 +27,8 @@ public:
Type* getEnumTypeType();
/// Get the __Dynamic type
Type* getDynamicType();
+ /// Get the NullPtr type
+ Type* getNullPtrType();
const ReflectClassInfo* findClassInfo(Name* name);
SyntaxClass<NodeBase> findSyntaxClass(Name* name);
@@ -65,6 +67,7 @@ protected:
Type* m_stringType = nullptr;
Type* m_enumTypeType = nullptr;
Type* m_dynamicType = nullptr;
+ Type* m_nullPtrType = nullptr;
Type* m_builtinTypes[Index(BaseType::CountOf)];
@@ -126,6 +129,7 @@ public:
Type* getOverloadedType() { return m_sharedASTBuilder->m_overloadedType; }
Type* getErrorType() { return m_sharedASTBuilder->m_errorType; }
Type* getStringType() { return m_sharedASTBuilder->getStringType(); }
+ Type* getNullPtrType() { return m_sharedASTBuilder->getNullPtrType(); }
Type* getEnumTypeType() { return m_sharedASTBuilder->getEnumTypeType(); }
// Construct the type `Ptr<valueType>`, where `Ptr`
diff --git a/source/slang/slang-ast-expr.h b/source/slang/slang-ast-expr.h
index b73e07042..a6c1d432c 100644
--- a/source/slang/slang-ast-expr.h
+++ b/source/slang/slang-ast-expr.h
@@ -88,6 +88,11 @@ class BoolLiteralExpr : public LiteralExpr
bool value;
};
+class NullPtrLiteralExpr : public LiteralExpr
+{
+ SLANG_AST_CLASS(NullPtrLiteralExpr)
+};
+
class StringLiteralExpr : public LiteralExpr
{
SLANG_AST_CLASS(StringLiteralExpr)
diff --git a/source/slang/slang-ast-modifier.cpp b/source/slang/slang-ast-modifier.cpp
new file mode 100644
index 000000000..3daa9b056
--- /dev/null
+++ b/source/slang/slang-ast-modifier.cpp
@@ -0,0 +1,8 @@
+// slang-ast-modifier.cpp
+#include "slang-ast-modifier.h"
+#include "slang-ast-expr.h"
+
+namespace Slang
+{
+
+} // namespace Slang
diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h
index 35a8ea317..9a450cc31 100644
--- a/source/slang/slang-ast-modifier.h
+++ b/source/slang/slang-ast-modifier.h
@@ -920,6 +920,13 @@ class AnyValueSizeAttribute : public Attribute
int32_t size;
};
+class DllImportAttribute : public Attribute
+{
+ SLANG_AST_CLASS(DllImportAttribute)
+
+ String modulePath;
+};
+
/// A `[__requiresNVAPI]` attribute indicates that the declaration being modifed
/// requires NVAPI operations for its implementation on D3D.
class RequiresNVAPIAttribute : public Attribute
diff --git a/source/slang/slang-ast-type.h b/source/slang/slang-ast-type.h
index f919e7bc2..fee7f7cac 100644
--- a/source/slang/slang-ast-type.h
+++ b/source/slang/slang-ast-type.h
@@ -489,6 +489,11 @@ class PtrTypeBase : public BuiltinType
Type* getValueType();
};
+class NullPtrType : public BuiltinType
+{
+ SLANG_AST_CLASS(NullPtrType)
+};
+
// A true (user-visible) pointer type, e.g., `T*`
class PtrType : public PtrTypeBase
{
diff --git a/source/slang/slang-check-conversion.cpp b/source/slang/slang-check-conversion.cpp
index 855590472..a1935d65c 100644
--- a/source/slang/slang-check-conversion.cpp
+++ b/source/slang/slang-check-conversion.cpp
@@ -753,6 +753,18 @@ namespace Slang
return true;
}
+ // nullptr_t can be cast into any pointer type.
+ if (as<NullPtrType>(fromType) && as<PtrType>(toType))
+ {
+ if (outCost)
+ {
+ *outCost = kConversionCost_None;
+ }
+ if (outToExpr)
+ *outToExpr = fromExpr;
+ return true;
+ }
+
// If we are casting to an interface type, then that will succeed
// if the "from" type conforms to the interface.
//
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index 88c4edec5..2290936d8 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -645,6 +645,12 @@ namespace Slang
return expr;
}
+ Expr* SemanticsExprVisitor::visitNullPtrLiteralExpr(NullPtrLiteralExpr* expr)
+ {
+ expr->type = m_astBuilder->getNullPtrType();
+ return expr;
+ }
+
Expr* SemanticsExprVisitor::visitIntegerLiteralExpr(IntegerLiteralExpr* expr)
{
// The expression might already have a type, determined by its suffix.
diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h
index 8ea693104..82a0e7453 100644
--- a/source/slang/slang-check-impl.h
+++ b/source/slang/slang-check-impl.h
@@ -1534,6 +1534,7 @@ namespace Slang
{}
Expr* visitBoolLiteralExpr(BoolLiteralExpr* expr);
+ Expr* visitNullPtrLiteralExpr(NullPtrLiteralExpr* expr);
Expr* visitIntegerLiteralExpr(IntegerLiteralExpr* expr);
Expr* visitFloatingPointLiteralExpr(FloatingPointLiteralExpr* expr);
Expr* visitStringLiteralExpr(StringLiteralExpr* expr);
diff --git a/source/slang/slang-check-modifier.cpp b/source/slang/slang-check-modifier.cpp
index 4594af28d..e597407e2 100644
--- a/source/slang/slang-check-modifier.cpp
+++ b/source/slang/slang-check-modifier.cpp
@@ -528,6 +528,17 @@ namespace Slang
allowAttr->diagnostic = diagnosticInfo;
}
+ else if (auto dllImportAttr = as<DllImportAttribute>(attr))
+ {
+ SLANG_ASSERT(attr->args.getCount() == 1);
+
+ String libraryName;
+ if (!checkLiteralStringVal(dllImportAttr->args[0], &libraryName))
+ {
+ return false;
+ }
+ dllImportAttr->modulePath = libraryName;
+ }
else
{
if(attr->args.getCount() == 0)
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index b2575b255..2f18038ac 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -565,6 +565,8 @@ DIAGNOSTIC(52005, Error, unableToReadFile, "unable to read file '$0'")
DIAGNOSTIC(52006, Error, compilerNotDefinedForTransition, "compiler not defined for transition '$0' to '$1'.")
+DIAGNOSTIC(53001,Error, invalidTypeMarshallingForImportedDLLSymbol, "invalid type marshalling in imported func $0.")
+
//
// 8xxxx - Issues specific to a particular library/technology/platform/etc.
//
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index edadcef48..562a532cd 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -159,6 +159,14 @@ void CLikeSourceEmitter::emitDeclarator(DeclaratorInfo* declarator)
}
break;
+ case DeclaratorInfo::Flavor::Ref:
+ {
+ auto refDeclarator = (RefDeclaratorInfo*)declarator;
+ m_writer->emit("&");
+ emitDeclarator(refDeclarator->next);
+ }
+ break;
+
case DeclaratorInfo::Flavor::LiteralSizedArray:
{
auto arrayDeclarator = (LiteralSizedArrayDeclaratorInfo*)declarator;
@@ -180,8 +188,6 @@ void CLikeSourceEmitter::emitDeclarator(DeclaratorInfo* declarator)
emitDeclarator(attributedDeclarator->next);
}
break;
-
-
default:
SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unknown declarator flavor");
break;
@@ -214,6 +220,8 @@ void CLikeSourceEmitter::emitSimpleType(IRType* type)
case kIROp_FloatType: return UnownedStringSlice("float");
case kIROp_DoubleType: return UnownedStringSlice("double");
+
+ case kIROp_CharType: return UnownedStringSlice("uint8_t");
default: return UnownedStringSlice();
}
}
@@ -324,7 +332,6 @@ void CLikeSourceEmitter::_emitType(IRType* type, DeclaratorInfo* declarator)
}
break;
}
-
}
void CLikeSourceEmitter::emitWitnessTable(IRWitnessTable* witnessTable)
@@ -3305,8 +3312,14 @@ void CLikeSourceEmitter::ensureInstOperandsRec(ComputeEmitActionsContext* ctx, I
UInt operandCount = inst->operandCount;
auto requiredLevel = EmitAction::Definition;
- if (inst->getOp() == kIROp_InterfaceType)
+ switch (inst->getOp())
+ {
+ case kIROp_InterfaceType:
requiredLevel = EmitAction::ForwardDeclaration;
+ break;
+ default:
+ break;
+ }
for(UInt ii = 0; ii < operandCount; ++ii)
{
@@ -3404,6 +3417,23 @@ void CLikeSourceEmitter::computeEmitActions(IRModule* module, List<EmitAction>&
}
}
+void CLikeSourceEmitter::emitForwardDeclaration(IRInst* inst)
+{
+ switch (inst->getOp())
+ {
+ case kIROp_Func:
+ emitFuncDecl(cast<IRFunc>(inst));
+ break;
+ case kIROp_StructType:
+ m_writer->emit("struct ");
+ m_writer->emit(getName(inst));
+ m_writer->emit(";\n");
+ break;
+ default:
+ SLANG_UNREACHABLE("emit forward declaration");
+ }
+}
+
void CLikeSourceEmitter::executeEmitActions(List<EmitAction> const& actions)
{
for(auto action : actions)
@@ -3411,7 +3441,7 @@ void CLikeSourceEmitter::executeEmitActions(List<EmitAction> const& actions)
switch(action.level)
{
case EmitAction::Level::ForwardDeclaration:
- emitFuncDecl(cast<IRFunc>(action.inst));
+ emitForwardDeclaration(action.inst);
break;
case EmitAction::Level::Definition:
diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h
index 6a3a31f78..ba2f5b86c 100644
--- a/source/slang/slang-emit-c-like.h
+++ b/source/slang/slang-emit-c-like.h
@@ -68,6 +68,7 @@ public:
{
Name,
Ptr,
+ Ref,
SizedArray,
UnsizedArray,
LiteralSizedArray,
@@ -110,6 +111,13 @@ public:
{}
};
+ struct RefDeclaratorInfo : ChainedDeclaratorInfo
+ {
+ RefDeclaratorInfo(DeclaratorInfo* next)
+ : ChainedDeclaratorInfo(Flavor::Ref, next)
+ {}
+ };
+
struct SizedArrayDeclaratorInfo : ChainedDeclaratorInfo
{
IRInst* elementCount;
@@ -147,6 +155,16 @@ public:
IRInst* instWithAttributes;
};
+ struct FuncTypeDeclaratorInfo : ChainedDeclaratorInfo
+ {
+ FuncTypeDeclaratorInfo(DeclaratorInfo* next, IRFuncType* funcTypeInst)
+ : ChainedDeclaratorInfo(Flavor::Attributed, next)
+ , funcType(funcTypeInst)
+ {}
+
+ IRFuncType* funcType;
+ };
+
struct ComputeEmitActionsContext;
// An action to be performed during code emit.
@@ -344,6 +362,7 @@ public:
void emitStruct(IRStructType* structType);
+
/// Emit type attributes that should appear after, e.g., a `struct` keyword
void emitPostKeywordTypeAttributes(IRInst* inst) { emitPostKeywordTypeAttributesImpl(inst); }
@@ -378,9 +397,12 @@ public:
void ensureGlobalInst(ComputeEmitActionsContext* ctx, IRInst* inst, EmitAction::Level requiredLevel);
+ void emitForwardDeclaration(IRInst* inst);
+
void computeEmitActions(IRModule* module, List<EmitAction>& ioActions);
void executeEmitActions(List<EmitAction> const& actions);
+
void emitModule(IRModule* module, DiagnosticSink* sink)
{ m_irModule = module; emitModuleImpl(module, sink); }
@@ -458,7 +480,9 @@ public:
virtual void emitPostKeywordTypeAttributesImpl(IRInst* inst) { SLANG_UNUSED(inst); }
- void _emitType(IRType* type, DeclaratorInfo* declarator);
+ void _emitFuncTypeDeclaration(IRFuncType* type, IRAttributedType* attributes);
+
+ virtual void _emitType(IRType* type, DeclaratorInfo* declarator);
void _emitInst(IRInst* inst);
virtual void _emitPrefixTypeAttr(IRAttr* attr);
diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp
index c56190f65..93bc5c979 100644
--- a/source/slang/slang-emit-cpp.cpp
+++ b/source/slang/slang-emit-cpp.cpp
@@ -217,6 +217,8 @@ static bool _isCppOrCudaTarget(CodeGenTarget target)
case kIROp_FloatType: return UnownedStringSlice("float");
case kIROp_DoubleType: return UnownedStringSlice("double");
+ case kIROp_CharType: return UnownedStringSlice("char");
+
default: return UnownedStringSlice();
}
}
@@ -429,22 +431,6 @@ SlangResult CPPSourceEmitter::calcTypeName(IRType* type, CodeGenTarget target, S
{
switch (type->getOp())
{
- case kIROp_OutType:
- case kIROp_InOutType:
- case kIROp_PtrType:
- {
- auto ptrType = static_cast<IRPtrType*>(type);
- SLANG_RETURN_ON_FAIL(calcTypeName(ptrType->getValueType(), target, out));
- out << "*";
- return SLANG_OK;
- }
- case kIROp_RefType:
- {
- auto refType = static_cast<IRRefType*>(type);
- SLANG_RETURN_ON_FAIL(calcTypeName(refType->getValueType(), target, out));
- out << "&";
- return SLANG_OK;
- }
case kIROp_HalfType:
{
// Special case half
@@ -501,27 +487,6 @@ SlangResult CPPSourceEmitter::calcTypeName(IRType* type, CodeGenTarget target, S
}
return SLANG_OK;
}
- case kIROp_ArrayType:
- {
- auto arrayType = static_cast<IRArrayType*>(type);
- auto elementType = arrayType->getElementType();
- int elementCount = int(getIntVal(arrayType->getElementCount()));
-
- out << "FixedArray<";
- SLANG_RETURN_ON_FAIL(calcTypeName(elementType, target, out));
- out << ", " << elementCount << ">";
- return SLANG_OK;
- }
- case kIROp_UnsizedArrayType:
- {
- auto arrayType = static_cast<IRUnsizedArrayType*>(type);
- auto elementType = arrayType->getElementType();
-
- out << "Array<";
- SLANG_RETURN_ON_FAIL(calcTypeName(elementType, target, out));
- out << ">";
- return SLANG_OK;
- }
case kIROp_WitnessTableType:
case kIROp_WitnessTableIDType:
{
@@ -1573,8 +1538,15 @@ SlangResult CPPSourceEmitter::calcFuncName(const HLSLIntrinsic* specOp, StringBu
{
IRType* paramType = specOp->signatureType->getParamType(0);
IRBasicType* basicType = as<IRBasicType>(paramType);
- SLANG_ASSERT(basicType);
- return calcScalarFuncName(specOp->op, basicType, outBuilder);
+ if (basicType)
+ {
+ return calcScalarFuncName(specOp->op, basicType, outBuilder);
+ }
+ else
+ {
+ outBuilder << getName(paramType) << HLSLIntrinsic::getInfo(specOp->op).name;
+ return SLANG_OK;
+ }
}
else
{
@@ -1651,40 +1623,8 @@ CPPSourceEmitter::CPPSourceEmitter(const Desc& desc):
//m_semanticUsedFlags = SemanticUsedFlag::GroupID | SemanticUsedFlag::GroupThreadID | SemanticUsedFlag::DispatchThreadID;
}
-void CPPSourceEmitter::_emitInOutParamType(IRType* type, String const& name, IRType* valueType)
-{
- StringSliceLoc nameAndLoc(name.getUnownedSlice());
-
- if (auto refType = as<IRRefType>(type))
- {
- m_writer->emit("const ");
- }
-
- UnownedStringSlice slice = _getTypeName(valueType);
- m_writer->emit(slice);
- m_writer->emit("* ");
- m_writer->emitName(nameAndLoc);
-}
-
void CPPSourceEmitter::emitParamTypeImpl(IRType* type, String const& name)
{
- // An `out` or `inout` parameter will have been
- // encoded as a parameter of pointer type, so
- // we need to decode that here.
- //
- if (auto outType = as<IROutType>(type))
- {
- return _emitInOutParamType(type, name, outType->getValueType());
- }
- else if (auto inOutType = as<IRInOutType>(type))
- {
- return _emitInOutParamType(type, name, inOutType->getValueType());
- }
- else if (auto refType = as<IRRefType>(type))
- {
- return _emitInOutParamType(type, name, refType->getValueType());
- }
-
emitType(type, name);
}
@@ -2059,15 +1999,69 @@ void CPPSourceEmitter::emitSimpleTypeImpl(IRType* inType)
m_writer->emit(slice);
}
-void CPPSourceEmitter::emitTypeImpl(IRType* type, const StringSliceLoc* nameLoc)
+void CPPSourceEmitter::_emitType(IRType* type, DeclaratorInfo* declarator)
{
- UnownedStringSlice slice = _getTypeName(type);
- m_writer->emit(slice);
-
- if (nameLoc)
+ switch (type->getOp())
{
- m_writer->emit(" ");
- m_writer->emitName(*nameLoc);
+ default:
+ CLikeSourceEmitter::_emitType(type, declarator);
+ break;
+
+ case kIROp_PtrType:
+ case kIROp_InOutType:
+ case kIROp_OutType:
+ {
+ auto ptrType = cast<IRPtrTypeBase>(type);
+ PtrDeclaratorInfo ptrDeclarator(declarator);
+ _emitType(ptrType->getValueType(), &ptrDeclarator);
+ }
+ break;
+ case kIROp_RefType:
+ {
+ auto ptrType = cast<IRPtrTypeBase>(type);
+ RefDeclaratorInfo refDeclarator(declarator);
+ _emitType(ptrType->getValueType(), &refDeclarator);
+ }
+ break;
+ case kIROp_ArrayType:
+ {
+ auto arrayType = static_cast<IRArrayType*>(type);
+ auto elementType = arrayType->getElementType();
+ int elementCount = int(getIntVal(arrayType->getElementCount()));
+
+ m_writer->emit("FixedArray<");
+ _emitType(elementType, nullptr);
+ m_writer->emit(", ");
+ m_writer->emit(elementCount);
+ m_writer->emit("> ");
+ emitDeclarator(declarator);
+ }
+ break;
+ case kIROp_UnsizedArrayType:
+ {
+ auto arrayType = static_cast<IRUnsizedArrayType*>(type);
+ auto elementType = arrayType->getElementType();
+
+ m_writer->emit("Array<");
+ _emitType(elementType, nullptr);
+ m_writer->emit("> ");
+ emitDeclarator(declarator);
+ }
+ break;
+ case kIROp_FuncType:
+ {
+ auto funcType = cast<IRFuncType>(type);
+ m_writer->emit("Slang_FuncType<");
+ _emitType(funcType->getResultType(), nullptr);
+ for (UInt i = 0; i < funcType->getParamCount(); i++)
+ {
+ m_writer->emit(", ");
+ _emitType(funcType->getParamType(i), nullptr);
+ }
+ m_writer->emit("> ");
+ emitDeclarator(declarator);
+ }
+ break;
}
}
@@ -2336,17 +2330,6 @@ bool CPPSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOut
m_writer->emit("->typeSize)");
return true;
}
- case kIROp_Copy:
- {
- m_writer->emit("memcpy(");
- emitOperand(inst->getOperand(0), EmitOpInfo::get(EmitOp::General));
- m_writer->emit(", ");
- emitOperand(inst->getOperand(1), EmitOpInfo::get(EmitOp::General));
- m_writer->emit(", ");
- emitOperand(inst->getOperand(2), EmitOpInfo::get(EmitOp::Postfix));
- m_writer->emit("->typeSize)");
- return true;
- }
case kIROp_BitCast:
{
m_writer->emit("(slang_bit_cast<");
@@ -2363,7 +2346,23 @@ bool CPPSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOut
m_writer->emit(")");
return true;
}
-
+ case kIROp_PtrLit:
+ {
+ auto ptrVal = as<IRPtrLit>(inst)->value.ptrVal;
+ if (ptrVal == nullptr)
+ {
+ m_writer->emit("nullptr");
+ }
+ else
+ {
+ m_writer->emit("reinterpret_cast<");
+ emitType(inst->getFullType());
+ m_writer->emit(">(");
+ m_writer->emitUInt64((uint64_t)ptrVal);
+ m_writer->emit(")");
+ }
+ return true;
+ }
}
}
@@ -2647,7 +2646,17 @@ void CPPSourceEmitter::_emitForwardDeclarations(const List<EmitAction>& actions)
switch (action.level)
{
case EmitAction::Level::ForwardDeclaration:
- emitFuncDecl(cast<IRFunc>(action.inst));
+ {
+ switch (action.inst->getOp())
+ {
+ case kIROp_Func:
+ case kIROp_StructType:
+ emitForwardDeclaration(action.inst);
+ break;
+ default:
+ break;
+ }
+ }
break;
case EmitAction::Level::Definition:
diff --git a/source/slang/slang-emit-cpp.h b/source/slang/slang-emit-cpp.h
index 5ba509e7d..a75fe2caf 100644
--- a/source/slang/slang-emit-cpp.h
+++ b/source/slang/slang-emit-cpp.h
@@ -56,7 +56,7 @@ protected:
virtual void emitParameterGroupImpl(IRGlobalParam* varDecl, IRUniformParameterGroupType* type) SLANG_OVERRIDE;
virtual void emitEntryPointAttributesImpl(IRFunc* irFunc, IREntryPointDecoration* entryPointDecor) SLANG_OVERRIDE;
virtual void emitSimpleTypeImpl(IRType* type) SLANG_OVERRIDE;
- virtual void emitTypeImpl(IRType* type, const StringSliceLoc* nameLoc) SLANG_OVERRIDE;
+ virtual void _emitType(IRType* type, DeclaratorInfo* declarator) SLANG_OVERRIDE;
virtual void emitVectorTypeNameImpl(IRType* elementType, IRIntegerValue elementCount) SLANG_OVERRIDE;
virtual bool tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOuterPrec) SLANG_OVERRIDE;
virtual void emitPreprocessorDirectivesImpl() SLANG_OVERRIDE;
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 067d0a99a..d09217b58 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -9,6 +9,7 @@
#include "slang-ir-byte-address-legalize.h"
#include "slang-ir-collect-global-uniforms.h"
#include "slang-ir-dce.h"
+#include "slang-ir-dll-import.h"
#include "slang-ir-entry-point-uniforms.h"
#include "slang-ir-entry-point-raw-ptr-params.h"
#include "slang-ir-explicit-global-context.h"
@@ -682,6 +683,15 @@ Result linkAndOptimizeIR(
break;
}
+ switch (target)
+ {
+ default:
+ break;
+ case CodeGenTarget::HostCPPSource:
+ generateDllImportFuncs(irModule, sink);
+ break;
+ }
+
// TODO: our current dynamic dispatch pass will remove all uses of witness tables.
// If we are going to support function-pointer based, "real" modular dynamic dispatch,
// we will need to disable this pass.
diff --git a/source/slang/slang-ir-dll-import.cpp b/source/slang/slang-ir-dll-import.cpp
new file mode 100644
index 000000000..ed0a3e007
--- /dev/null
+++ b/source/slang/slang-ir-dll-import.cpp
@@ -0,0 +1,249 @@
+// slang-ir-dll-import.cpp
+#include "slang-ir-dll-import.h"
+
+#include "slang-ir.h"
+#include "slang-ir-insts.h"
+
+namespace Slang
+{
+
+struct DllImportContext
+{
+ IRModule* module;
+ DiagnosticSink* diagnosticSink;
+
+ SharedIRBuilder sharedBuilder;
+
+ IRFunc* loadDllFunc = nullptr;
+ IRFunc* loadFuncPtrFunc = nullptr;
+ IRFunc* stringGetBufferFunc = nullptr;
+
+ IRFunc* createBuiltinIntrinsicFunc(UInt paramCount, IRType** paramTypes, IRType* resultType, UnownedStringSlice targetIntrinsic)
+ {
+ IRBuilder builder(sharedBuilder);
+ builder.setInsertInto(module->getModuleInst());
+ IRFunc* result = builder.createFunc();
+ builder.setInsertInto(result);
+ auto funcType = builder.getFuncType(paramCount, paramTypes, resultType);
+ builder.setDataType(result, funcType);
+ builder.addTargetIntrinsicDecoration(
+ result, CapabilitySet(CapabilityAtom::CPP), targetIntrinsic);
+ return result;
+ }
+
+ IRFunc* getLoadDllFunc()
+ {
+ if (!loadDllFunc)
+ {
+ IRBuilder builder(sharedBuilder);
+ builder.setInsertInto(module->getModuleInst());
+ IRType* stringType = builder.getStringType();
+ loadDllFunc = createBuiltinIntrinsicFunc(
+ 1,
+ &stringType,
+ builder.getPtrType(builder.getVoidType()),
+ UnownedStringSlice("_slang_rt_load_dll($0)"));
+ }
+ return loadDllFunc;
+ }
+
+ IRFunc* getLoadFuncPtrFunc()
+ {
+ if (!loadFuncPtrFunc)
+ {
+ IRBuilder builder(sharedBuilder);
+ builder.setInsertInto(module->getModuleInst());
+
+ IRType* stringType = builder.getStringType();
+ IRType* paramTypes[] = {builder.getPtrType(builder.getVoidType()), stringType};
+ loadFuncPtrFunc = createBuiltinIntrinsicFunc(
+ 2,
+ paramTypes,
+ builder.getPtrType(builder.getVoidType()),
+ UnownedStringSlice("_slang_rt_load_dll_func($0, $1)"));
+ }
+ return loadFuncPtrFunc;
+ }
+
+ IRFunc* getStringGetBufferFunc()
+ {
+ if (!stringGetBufferFunc)
+ {
+ IRBuilder builder(sharedBuilder);
+ builder.setInsertInto(module->getModuleInst());
+
+ IRType* stringType = builder.getStringType();
+ IRType* paramTypes[] = {stringType};
+ stringGetBufferFunc = createBuiltinIntrinsicFunc(
+ 1,
+ paramTypes,
+ builder.getPtrType(builder.getCharType()),
+ UnownedStringSlice("const_cast<char*>($0.getBuffer())"));
+ }
+ return stringGetBufferFunc;
+ }
+
+ IRType* getNativeType(IRBuilder& builder, IRType* type)
+ {
+ switch (type->getOp())
+ {
+ case kIROp_StringType:
+ return builder.getPtrType(builder.getCharType());
+ default:
+ return type;
+ }
+ }
+
+ IRType* getNativeFuncType(IRBuilder& builder, IRFunc* func)
+ {
+ List<IRInst*> nativeParamTypes;
+ auto declaredFuncType = func->getDataType();
+ assert(declaredFuncType->getOp() == kIROp_FuncType);
+ for (UInt i = 0; i < declaredFuncType->getParamCount(); ++i)
+ {
+ auto paramType = declaredFuncType->getParamType(i);
+ nativeParamTypes.add(getNativeType(builder, as<IRType>(paramType)));
+ }
+ IRType* returnType = getNativeType(builder, func->getResultType());
+ auto funcType = builder.getFuncType(
+ nativeParamTypes.getCount(), (IRType**)nativeParamTypes.getBuffer(), returnType);
+
+ return funcType;
+ }
+
+ void marshalImportRefParameter(IRBuilder& builder, IRParam* param, List<IRInst*>& args)
+ {
+ SLANG_UNUSED(builder);
+
+ auto innerType = as<IRPtrTypeBase>(param->getDataType())->getValueType();
+ switch (innerType->getOp())
+ {
+ case kIROp_StringType:
+ {
+ diagnosticSink->diagnose(
+ param->sourceLoc,
+ Diagnostics::invalidTypeMarshallingForImportedDLLSymbol,
+ param->getParent()->getParent());
+ }
+ break;
+ default:
+ args.add(param);
+ break;
+ }
+ }
+
+ void marshalImportParameter(IRBuilder& builder, IRParam* param, List<IRInst*>& args)
+ {
+ switch (param->getDataType()->getOp())
+ {
+ case kIROp_InOutType:
+ case kIROp_RefType:
+ return marshalImportRefParameter(builder, param, args);
+ case kIROp_StringType:
+ {
+ auto getStringBufferFunc = getStringGetBufferFunc();
+ args.add(builder.emitCallInst(
+ builder.getPtrType(builder.getCharType()), getStringBufferFunc, 1, (IRInst**)&param));
+ }
+ break;
+ default:
+ args.add(param);
+ break;
+ }
+ }
+
+ void processFunc(IRFunc* func, IRDllImportDecoration* dllImportDecoration)
+ {
+ assert(func->getFirstBlock() == nullptr);
+
+ IRBuilder builder(sharedBuilder);
+
+ auto nativeType = getNativeFuncType(builder, func);
+ builder.setInsertInto(module->getModuleInst());
+ auto funcPtr = builder.createGlobalVar(nativeType);
+ builder.setInsertInto(funcPtr);
+ builder.emitBlock();
+ builder.emitReturn(builder.getPtrValue(nullptr));
+
+ builder.setInsertInto(func);
+ auto block = builder.emitBlock();
+ builder.setInsertInto(block);
+
+ // Emit parameters.
+ auto declaredFuncType = func->getDataType();
+ List<IRParam*> params;
+ for (UInt i = 0; i < declaredFuncType->getParamCount(); ++i)
+ {
+ auto paramType = declaredFuncType->getParamType(i);
+ params.add(builder.emitParam((IRType*)paramType));
+ }
+
+ // Marshal parameters to arguments into native func.
+ List<IRInst*> args;
+ for (auto param : params)
+ {
+ marshalImportParameter(builder, param, args);
+ }
+ IRInst* cmpArgs[] = {builder.emitLoad(nativeType, funcPtr), builder.getPtrValue(nullptr)};
+ auto isUninitialized =
+ builder.emitIntrinsicInst(builder.getBoolType(), kIROp_Eql, 2, cmpArgs);
+
+ auto trueBlock = builder.emitBlock();
+ auto afterBlock = builder.emitBlock();
+
+ builder.setInsertInto(block);
+ builder.emitIf(isUninitialized, trueBlock, afterBlock);
+
+ builder.setInsertInto(trueBlock);
+ auto modulePtr = builder.emitCallInst(
+ builder.getPtrType(builder.getVoidType()),
+ getLoadDllFunc(),
+ builder.getStringValue(dllImportDecoration->getLibraryName()));
+
+ IRInst* loadDllFuncArgs[] = {
+ modulePtr, builder.getStringValue(dllImportDecoration->getFunctionName())};
+ auto loadedNativeFuncPtr = builder.emitCallInst(
+ builder.getPtrType(builder.getVoidType()), getLoadFuncPtrFunc(), 2, loadDllFuncArgs);
+ builder.emitStore(
+ funcPtr, builder.emitBitCast(nativeType, loadedNativeFuncPtr));
+ builder.emitBranch(afterBlock);
+ builder.setInsertInto(afterBlock);
+
+ IRType* nativeReturnType = getNativeType(builder, func->getResultType());
+ auto nativeFunc = builder.emitLoad(funcPtr);
+ auto call = builder.emitCallInst(nativeReturnType, nativeFunc, args);
+ if (declaredFuncType->getResultType()->getOp() != kIROp_VoidType)
+ {
+ builder.emitReturn(call);
+ }
+ }
+
+ void processModule()
+ {
+ for (auto childFunc : module->getGlobalInsts())
+ {
+ switch(childFunc->getOp())
+ {
+ case kIROp_Func:
+ if (auto dllImportDecoration = childFunc->findDecoration<IRDllImportDecoration>())
+ {
+ processFunc(as<IRFunc>(childFunc), dllImportDecoration);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+};
+
+void generateDllImportFuncs(IRModule* module, DiagnosticSink* sink)
+{
+ DllImportContext context;
+ context.module = module;
+ context.diagnosticSink = sink;
+ context.sharedBuilder.init(module);
+ return context.processModule();
+}
+
+}
diff --git a/source/slang/slang-ir-dll-import.h b/source/slang/slang-ir-dll-import.h
new file mode 100644
index 000000000..c330f803f
--- /dev/null
+++ b/source/slang/slang-ir-dll-import.h
@@ -0,0 +1,11 @@
+// slang-ir-dll-import.h
+#pragma once
+
+namespace Slang
+{
+ struct IRModule;
+ class DiagnosticSink;
+ /// Generate implementations for functions marked as [DllImport].
+ void generateDllImportFuncs(IRModule* module, DiagnosticSink* sink);
+
+}
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index bcc42ad9e..bce188cfa 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -92,7 +92,6 @@ INST(Nop, nop, 0, 0)
/* PtrTypeBase */
INST(PtrType, Ptr, 1, 0)
INST(RefType, Ref, 1, 0)
-
// A `PsuedoPtr<T>` logically represents a pointer to a value of type
// `T` on a platform that cannot support pointers. The expectation
// is that the "pointer" will be legalized away by storing a value
@@ -284,7 +283,6 @@ INST(Var, var, 0, 0)
INST(Load, load, 1, 0)
INST(Store, store, 2, 0)
-INST(Copy, copy, 3, 0)
INST(FieldExtract, get_field, 2, 0)
INST(FieldAddress, get_field_addr, 2, 0)
@@ -604,6 +602,10 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
/// An extern_cpp decoration marks the inst to emit its name without mangling for C++ interop.
INST(ExternCppDecoration, externCpp, 1, 0)
+ /// An dllImport decoration marks a function as imported from a DLL. Slang will generate dynamic function loading logic to use this function at runtime.
+ INST(DllImportDecoration, dllImport, 2, 0)
+
+
/* Decorations for RTTI objects */
INST(RTTITypeSizeDecoration, RTTI_typeSize, 1, 0)
INST(AnyValueSizeDecoration, AnyValueSize, 1, 0)
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index 102c48495..8b4eaf5cb 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -430,6 +430,21 @@ struct IRExternCppDecoration : IRDecoration
UnownedStringSlice getName() { return getNameOperand()->getStringSlice(); }
};
+struct IRDllImportDecoration : IRDecoration
+{
+ enum
+ {
+ kOp = kIROp_DllImportDecoration
+ };
+ IR_LEAF_ISA(DllImportDecoration)
+
+ IRStringLit* getLibraryNameOperand() { return cast<IRStringLit>(getOperand(0)); }
+ UnownedStringSlice getLibraryName() { return getLibraryNameOperand()->getStringSlice(); }
+
+ IRStringLit* getFunctionNameOperand() { return cast<IRStringLit>(getOperand(1)); }
+ UnownedStringSlice getFunctionName() { return getFunctionNameOperand()->getStringSlice(); }
+};
+
struct IRFormatDecoration : IRDecoration
{
enum { kOp = kIROp_FormatDecoration };
@@ -542,17 +557,6 @@ struct IRAlloca : IRInst
IRInst* getAllocSize() { return getOperand(0); }
};
-/// Copies `size` bytes from `src` to `dst`.
-///
-struct IRCopy : IRInst
-{
- IR_LEAF_ISA(Copy)
-
- IRInst* getDst() { return getOperand(0); }
- IRInst* getSrc() { return getOperand(1); }
- IRInst* getSize() { return getOperand(2); }
-};
-
/// Packs a value into an `AnyValue`.
/// Return type is `IRAnyValueType`.
struct IRPackAnyValue : IRInst
@@ -2025,7 +2029,9 @@ public:
IRBasicType* getIntType();
IRBasicType* getUIntType();
IRBasicType* getUInt64Type();
+ IRBasicType* getCharType();
IRStringType* getStringType();
+
IRType* getCapabilitySetType();
IRAssociatedType* getAssociatedType(ArrayView<IRInterfaceType*> constraintTypes);
@@ -2194,8 +2200,6 @@ public:
IRInst* emitAlloca(IRInst* type, IRInst* rttiObjPtr);
- IRInst* emitCopy(IRInst* dst, IRInst* src, IRInst* rttiObjPtr);
-
IRInst* emitPackAnyValue(IRType* type, IRInst* value);
IRInst* emitUnpackAnyValue(IRType* type, IRInst* value);
@@ -2811,6 +2815,11 @@ public:
addDecoration(value, kIROp_ExternCppDecoration, getStringValue(mangledName));
}
+ void addDllImportDecoration(IRInst* value, UnownedStringSlice const& libraryName, UnownedStringSlice const& functionName)
+ {
+ addDecoration(value, kIROp_DllImportDecoration, getStringValue(libraryName), getStringValue(functionName));
+ }
+
void addEntryPointDecoration(IRInst* value, Profile profile, UnownedStringSlice const& name, UnownedStringSlice const& moduleName)
{
IRInst* operands[] = { getIntValue(getIntType(), profile.raw), getStringValue(name), getStringValue(moduleName) };
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index bb1b0a9d2..09a28e394 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -2466,6 +2466,11 @@ namespace Slang
return (IRBasicType*)getType(kIROp_UInt64Type);
}
+ IRBasicType* IRBuilder::getCharType()
+ {
+ return (IRBasicType*)getType(kIROp_CharType);
+ }
+
IRStringType* IRBuilder::getStringType()
{
return (IRStringType*)getType(kIROp_StringType);
@@ -2962,20 +2967,6 @@ namespace Slang
return inst;
}
- IRInst* IRBuilder::emitCopy(IRInst* dst, IRInst* src, IRInst* rttiObjPtr)
- {
- IRInst* args[] = { dst, src, rttiObjPtr };
- auto inst = createInst<IRCopy>(
- this,
- kIROp_Copy,
- getVoidType(),
- 3,
- args);
-
- addInst(inst);
- return inst;
- }
-
IRInst* IRBuilder::emitPackAnyValue(IRType* type, IRInst* value)
{
auto inst = createInst<IRPackAnyValue>(
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index bca8bd5b6..6cdf20af4 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -1051,6 +1051,11 @@ static void addLinkageDecoration(
{
builder->addExternCppDecoration(inst, mangledName);
}
+ if (auto dllImportModifier = decl->findModifier<DllImportAttribute>())
+ {
+ auto libraryName = dllImportModifier->modulePath;
+ builder->addDllImportDecoration(inst, libraryName.getUnownedSlice(), decl->getName()->text.getUnownedSlice());
+ }
}
static void addLinkageDecoration(
@@ -3173,6 +3178,11 @@ struct ExprLoweringVisitorBase : ExprVisitor<Derived, LoweredValInfo>
return LoweredValInfo::simple(context->irBuilder->getBoolValue(expr->value));
}
+ LoweredValInfo visitNullPtrLiteralExpr(NullPtrLiteralExpr*)
+ {
+ return LoweredValInfo::simple(context->irBuilder->getPtrValue(nullptr));
+ }
+
LoweredValInfo visitIntegerLiteralExpr(IntegerLiteralExpr* expr)
{
auto type = lowerType(context, expr->type);
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp
index c08f5cf34..40bb91d77 100644
--- a/source/slang/slang-parser.cpp
+++ b/source/slang/slang-parser.cpp
@@ -3551,8 +3551,9 @@ namespace Slang
{
// User is specifying the class that should be construted
auto classNameAndLoc = expectIdentifier(parser);
-
syntaxClass = parser->astBuilder->findSyntaxClass(classNameAndLoc.name);
+
+ assert(syntaxClass.classInfo);
}
else
{
@@ -4822,6 +4823,11 @@ namespace Slang
return parseBoolLitExpr(parser, false);
}
+ static NodeBase* parseNullPtrExpr(Parser* parser, void* /*userData*/)
+ {
+ return parser->astBuilder->create<NullPtrLiteralExpr>();
+ }
+
static bool _isFinite(double value)
{
// Lets type pun double to uint64_t, so we can detect special double values
@@ -6296,6 +6302,7 @@ namespace Slang
_makeParseExpr("This", parseThisTypeExpr),
_makeParseExpr("true", parseTrueExpr),
_makeParseExpr("false", parseFalseExpr),
+ _makeParseExpr("nullptr", parseNullPtrExpr),
_makeParseExpr("__TaggedUnion", parseTaggedUnionType),
};
diff --git a/source/slang/slang-type-system-shared.h b/source/slang/slang-type-system-shared.h
index 3b3dc6a91..d0972881a 100644
--- a/source/slang/slang-type-system-shared.h
+++ b/source/slang/slang-type-system-shared.h
@@ -19,6 +19,7 @@ namespace Slang
X(Half) \
X(Float) \
X(Double) \
+ X(Char) \
/* end */
enum class BaseType
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 2d992ef36..ab4d0749d 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -70,6 +70,7 @@ namespace Slang {
{ uint8_t(sizeof(uint16_t)), BaseTypeInfo::Flag::FloatingPoint , uint8_t(BaseType::Half) },
{ uint8_t(sizeof(float)), BaseTypeInfo::Flag::FloatingPoint , uint8_t(BaseType::Float) },
{ uint8_t(sizeof(double)), BaseTypeInfo::Flag::FloatingPoint , uint8_t(BaseType::Double) },
+ { uint8_t(sizeof(char)), BaseTypeInfo::Flag::Signed | BaseTypeInfo::Flag::Integer , uint8_t(BaseType::Char) },
};
/* static */bool BaseTypeInfo::check()
diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp
index 657769284..b98229d7b 100644
--- a/tools/gfx/d3d12/render-d3d12.cpp
+++ b/tools/gfx/d3d12/render-d3d12.cpp
@@ -2784,11 +2784,18 @@ Result AccelerationStructureImpl::getNativeHandle(InteropHandle* outHandle)
#endif // SLANG_GFX_HAS_DXR_SUPPORT
-Result TransientResourceHeapImpl::synchronizeAndReset()
+Result TransientResourceHeapImpl::synchronize()
{
WaitForMultipleObjects(
(DWORD)m_waitHandles.getCount(), m_waitHandles.getArrayView().getBuffer(), TRUE, INFINITE);
m_waitHandles.clear();
+ return SLANG_OK;
+}
+
+Result TransientResourceHeapImpl::synchronizeAndReset()
+{
+ synchronize();
+
m_currentViewHeapIndex = -1;
m_currentSamplerHeapIndex = -1;
allocateNewViewDescriptorHeap(m_device);
@@ -2875,7 +2882,7 @@ Result TransientResourceHeapImpl::allocateTransientDescriptorTable(
TransientResourceHeapImpl::~TransientResourceHeapImpl()
{
- synchronizeAndReset();
+ synchronize();
for (auto& waitInfo : m_waitInfos)
CloseHandle(waitInfo.fenceEvent);
}
diff --git a/tools/gfx/d3d12/render-d3d12.h b/tools/gfx/d3d12/render-d3d12.h
index 89498d033..c8929984b 100644
--- a/tools/gfx/d3d12/render-d3d12.h
+++ b/tools/gfx/d3d12/render-d3d12.h
@@ -546,6 +546,8 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL
createCommandBuffer(ICommandBuffer** outCommandBuffer) override;
+ Result synchronize();
+
virtual SLANG_NO_THROW Result SLANG_MCALL synchronizeAndReset() override;
virtual SLANG_NO_THROW Result SLANG_MCALL finish() override;