summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt8
-rw-r--r--cmake/SlangTarget.cmake15
-rw-r--r--source/slang-stdlib/CMakeLists.txt125
-rw-r--r--source/slang-stdlib/slang-embedded-stdlib-source.cpp338
-rw-r--r--source/slang-stdlib/slang-embedded-stdlib.cpp (renamed from source/slang/slang-stdlib-api.cpp)19
-rw-r--r--source/slang/CMakeLists.txt188
-rw-r--r--source/slang/slang-stdlib.cpp330
7 files changed, 568 insertions, 455 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index da22ec19a..4e27a724e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -334,7 +334,12 @@ generator(
source/slangc
TARGET_NAME slang-bootstrap
USE_FEWER_WARNINGS
- LINK_WITH_PRIVATE prelude slang-no-embedded-stdlib slang-capability-lookup slang-lookup-tables Threads::Threads
+ LINK_WITH_PRIVATE
+ prelude
+ slang-without-embedded-stdlib
+ slang-capability-lookup
+ slang-lookup-tables
+ Threads::Threads
)
#
@@ -344,6 +349,7 @@ generator(
# keep these non-trivial targets in their own directories so as not to clutter
# this file
add_subdirectory(prelude)
+add_subdirectory(source/slang-stdlib)
add_subdirectory(source/slang)
if(SLANG_ENABLE_SLANGD)
diff --git a/cmake/SlangTarget.cmake b/cmake/SlangTarget.cmake
index 5387cd2ce..9e3fe11cd 100644
--- a/cmake/SlangTarget.cmake
+++ b/cmake/SlangTarget.cmake
@@ -18,6 +18,9 @@ function(slang_add_target dir type)
WIN32_EXECUTABLE
# Install this target for a non-component install
INSTALL
+ # Don't include any source in this target, this is a complement to
+ # EXPLICIT_SOURCE, and doesn't interact with EXTRA_SOURCE_DIRS
+ NO_SOURCE
)
set(single_value_args
# Set the target name, useful for multiple targets from the same
@@ -35,6 +38,10 @@ function(slang_add_target dir type)
# ${EXPORT_MACRO_PREFIX}_DYNAMIC_EXPORT macros are set for using and
# building respectively
EXPORT_MACRO_PREFIX
+ # Ignore target type and use a particular style of export macro
+ # _DYNAMIC or _STATIC, this is useful when the target type is OBJECT
+ # pass in STATIC or SHARED
+ EXPORT_TYPE_AS
# The folder in which to place this target for IDE-based generators (VS
# and XCode)
FOLDER
@@ -115,7 +122,8 @@ function(slang_add_target dir type)
#
# Find the source for this target
#
- if(ARG_EXPLICIT_SOURCE)
+ if(ARG_NO_SOURCE)
+ elseif(ARG_EXPLICIT_SOURCE)
list(APPEND source ${ARG_EXPLICIT_SOURCE})
else()
slang_glob_sources(source ${dir})
@@ -269,6 +277,8 @@ function(slang_add_target dir type)
if(
target_type STREQUAL SHARED_LIBRARY
OR target_type STREQUAL MODULE_LIBRARY
+ OR ARG_EXPORT_TYPE_AS STREQUAL SHARED
+ OR ARG_EXPORT_TYPE_AS STREQUAL MODULE
)
target_compile_definitions(
${target}
@@ -277,11 +287,14 @@ function(slang_add_target dir type)
)
elseif(
target_type STREQUAL STATIC_LIBRARY
+ OR ARG_EXPORT_TYPE_AS STREQUAL STATIC
)
target_compile_definitions(
${target}
PUBLIC "${ARG_EXPORT_MACRO_PREFIX}_STATIC"
)
+ else()
+ message(WARNING "unhandled case in slang_add_target while setting export macro")
endif()
endif()
diff --git a/source/slang-stdlib/CMakeLists.txt b/source/slang-stdlib/CMakeLists.txt
new file mode 100644
index 000000000..eca23859a
--- /dev/null
+++ b/source/slang-stdlib/CMakeLists.txt
@@ -0,0 +1,125 @@
+#
+# In this file, for stdlib source embed and stdlib embed itself, we define two
+# targets, one which includes the embed and one which does not, these are
+# linked in as needed to libslang and libslang-without-embedded-stdlib (for
+# slang-bootstrap)
+#
+# If MSVC supported weak linking we could just have a single library for each
+# and just not link it if we didn't want the embed...
+#
+
+#
+# Generate an embeddable stdlib
+#
+
+set(stdlib_generated_header_dir ${CMAKE_CURRENT_BINARY_DIR})
+set(stdlib_generated_header
+ ${stdlib_generated_header_dir}/slang-stdlib-generated.h
+)
+add_custom_command(
+ OUTPUT ${stdlib_generated_header}
+ COMMAND
+ slang-bootstrap -archive-type riff-lz4 -save-stdlib-bin-source
+ ${stdlib_generated_header}
+ DEPENDS slang-bootstrap
+ VERBATIM
+)
+
+set(stdlib_common_args
+ .
+ OBJECT
+ EXCLUDE_FROM_ALL
+ EXPORT_MACRO_PREFIX SLANG
+ EXPORT_TYPE_AS ${SLANG_LIB_TYPE}
+ FOLDER generated
+ LINK_WITH_PRIVATE core
+ USE_EXTRA_WARNINGS
+ EXPLICIT_SOURCE ./slang-embedded-stdlib.cpp
+)
+
+slang_add_target(
+ ${stdlib_common_args}
+ TARGET_NAME slang-embedded-stdlib
+ EXPLICIT_SOURCE ${stdlib_generated_header}
+ EXTRA_COMPILE_DEFINITIONS_PRIVATE SLANG_EMBED_STDLIB
+ INCLUDE_DIRECTORIES_PRIVATE ${stdlib_generated_header_dir}
+)
+
+slang_add_target(
+ ${stdlib_common_args}
+ TARGET_NAME slang-no-embedded-stdlib
+)
+
+#
+# Compiling the meta.slang files
+#
+
+# List of *.meta.slang headers
+set(stdlib_meta_source_dir "${slang_SOURCE_DIR}/source/slang")
+glob_append(stdlib_meta_source "${stdlib_meta_source_dir}/*.meta.slang")
+
+set(stdlib_meta_output_dir "${CMAKE_CURRENT_BINARY_DIR}/stdlib-meta")
+
+# Generate the output file list
+set(stdlib_meta_generated_headers)
+foreach(meta_source ${stdlib_meta_source})
+ file(
+ RELATIVE_PATH
+ meta_source_relative
+ "${stdlib_meta_source_dir}"
+ ${meta_source}
+ )
+ list(
+ APPEND
+ stdlib_meta_generated_headers
+ "${stdlib_meta_output_dir}/${meta_source_relative}.h"
+ )
+endforeach()
+
+add_custom_command(
+ OUTPUT ${stdlib_meta_generated_headers}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${stdlib_meta_output_dir}
+ COMMAND
+ slang-generate ${stdlib_meta_source} --target-directory
+ ${stdlib_meta_output_dir}
+ DEPENDS ${stdlib_meta_source} slang-generate
+ WORKING_DIRECTORY "${stdlib_meta_source_dir}"
+ VERBATIM
+)
+
+#
+# Generate embedded stdlib source
+#
+
+set(stdlib_source_common_args
+ .
+ OBJECT
+ EXCLUDE_FROM_ALL
+ USE_EXTRA_WARNINGS
+ LINK_WITH_PRIVATE
+ core
+ slang-capability-defs
+ slang-reflect-headers
+ SPIRV-Headers
+ INCLUDE_DIRECTORIES_PRIVATE ../slang
+ FOLDER generated
+ EXPLICIT_SOURCE
+ ./slang-embedded-stdlib-source.cpp
+ ${stdlib_meta_generated_headers}
+ EXTRA_COMPILE_DEFINITIONS_PRIVATE SLANG_EMBED_STDLIB_SOURCE
+ INCLUDE_DIRECTORIES_PRIVATE
+ ${stdlib_meta_output_dir}
+ EXPORT_MACRO_PREFIX SLANG
+ EXPORT_TYPE_AS ${SLANG_LIB_TYPE}
+)
+
+slang_add_target(
+ ${stdlib_source_common_args}
+ TARGET_NAME slang-embedded-stdlib-source
+ EXTRA_COMPILE_DEFINITIONS_PRIVATE SLANG_EMBED_STDLIB_SOURCE
+)
+
+slang_add_target(
+ ${stdlib_source_common_args}
+ TARGET_NAME slang-no-embedded-stdlib-source
+)
diff --git a/source/slang-stdlib/slang-embedded-stdlib-source.cpp b/source/slang-stdlib/slang-embedded-stdlib-source.cpp
new file mode 100644
index 000000000..d77126c94
--- /dev/null
+++ b/source/slang-stdlib/slang-embedded-stdlib-source.cpp
@@ -0,0 +1,338 @@
+#include "slang-compiler.h"
+#include "slang-ir.h"
+#include "slang-ir-util.h"
+#include "slang-stdlib-textures.h"
+
+#define STRINGIZE(x) STRINGIZE2(x)
+#define STRINGIZE2(x) #x
+#define LINE_STRING STRINGIZE(__LINE__)
+
+namespace Slang
+{
+ // We are going to generate the stdlib source code from a more compact
+ // description. For example, we need to generate all the `operator`
+ // declarations for the basic unary and binary math operations on
+ // builtin types. To do this, we will make a big array of all these
+ // types, and associate them with data on their categories/capabilities
+ // so that we generate only the correct operations.
+ //
+ enum
+ {
+ SINT_MASK = 1 << 0,
+ FLOAT_MASK = 1 << 1,
+ BOOL_RESULT = 1 << 2,
+ BOOL_MASK = 1 << 3,
+ UINT_MASK = 1 << 4,
+
+ INT_MASK = SINT_MASK | UINT_MASK,
+ ARITHMETIC_MASK = INT_MASK | FLOAT_MASK,
+ LOGICAL_MASK = INT_MASK | BOOL_MASK,
+ ANY_MASK = INT_MASK | FLOAT_MASK | BOOL_MASK,
+ };
+
+ // We are going to declare initializers that allow for conversion between
+ // all of our base types, and we need a way to priotize those conversion
+ // by giving them different costs. Rather than maintain a hard-coded table
+ // of N^2 costs for N basic types, we are going to try to do things a bit
+ // more systematically.
+ //
+ // Every base type will be given a "kind" and a "rank" for conversion.
+ // The kind will classify it as signed/unsigned/float, and the rank will
+ // classify it by its logical bit size (with a distinct rank for pointer-sized
+ // types that logically sits between 32- and 64-bit types).
+ //
+ enum BaseTypeConversionKind : uint8_t
+ {
+ kBaseTypeConversionKind_Signed,
+ kBaseTypeConversionKind_Unsigned,
+ kBaseTypeConversionKind_Float,
+ kBaseTypeConversionKind_Error,
+ };
+ enum BaseTypeConversionRank : uint8_t
+ {
+ kBaseTypeConversionRank_Bool,
+ kBaseTypeConversionRank_Int8,
+ kBaseTypeConversionRank_Int16,
+ kBaseTypeConversionRank_Int32,
+ kBaseTypeConversionRank_IntPtr,
+ kBaseTypeConversionRank_Int64,
+ kBaseTypeConversionRank_Error,
+ };
+
+ // Here we declare the table of all our builtin types, so that we can generate all the relevant declarations.
+ //
+ struct BaseTypeConversionInfo
+ {
+ char const* name;
+ BaseType tag;
+ unsigned flags;
+ BaseTypeConversionKind conversionKind;
+ BaseTypeConversionRank conversionRank;
+ };
+ static const BaseTypeConversionInfo kBaseTypes[] = {
+ // TODO: `void` really shouldn't be in the `BaseType` enumeration, since it behaves so differently across the board
+ { "void", BaseType::Void, 0, kBaseTypeConversionKind_Error, kBaseTypeConversionRank_Error},
+
+ { "bool", BaseType::Bool, BOOL_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Bool },
+
+ { "int8_t", BaseType::Int8, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_Int8},
+ { "int16_t", BaseType::Int16, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_Int16},
+ { "int", BaseType::Int, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_Int32},
+ { "int64_t", BaseType::Int64, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_Int64},
+ { "intptr_t", BaseType::IntPtr, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_IntPtr},
+
+
+ { "half", BaseType::Half, FLOAT_MASK, kBaseTypeConversionKind_Float, kBaseTypeConversionRank_Int16},
+ { "float", BaseType::Float, FLOAT_MASK, kBaseTypeConversionKind_Float, kBaseTypeConversionRank_Int32},
+ { "double", BaseType::Double, FLOAT_MASK, kBaseTypeConversionKind_Float, kBaseTypeConversionRank_Int64},
+
+ { "uint8_t", BaseType::UInt8, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int8},
+ { "uint16_t", BaseType::UInt16, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int16},
+ { "uint", BaseType::UInt, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int32},
+ { "uint64_t", BaseType::UInt64, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int64},
+ { "uintptr_t", BaseType::UIntPtr, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_IntPtr},
+
+ };
+
+ void Session::finalizeSharedASTBuilder()
+ {
+ // Force creation of all builtin types so we can make sure
+ // they are created by the builtin AST builder instead of
+ // some user linkage's ast builder. This avoid the problem
+ // of storing a reference to these global types that are
+ // owned by a user linkage that gets deleted with the linkage.
+ //
+ globalAstBuilder->getNoneType();
+ globalAstBuilder->getNullPtrType();
+ globalAstBuilder->getBottomType();
+ globalAstBuilder->getErrorType();
+ globalAstBuilder->getInitializerListType();
+ globalAstBuilder->getOverloadedType();
+ globalAstBuilder->getStringType();
+ globalAstBuilder->getEnumTypeType();
+ globalAstBuilder->getDiffInterfaceType();
+ globalAstBuilder->getSharedASTBuilder()->getDynamicType();
+ globalAstBuilder->getSharedASTBuilder()->getDiffInterfaceType();
+ globalAstBuilder->getSharedASTBuilder()->getNativeStringType();
+ for (auto& baseType : kBaseTypes)
+ globalAstBuilder->getBuiltinType(baseType.tag);
+ }
+
+
+ // Given two base types, we need to be able to compute the cost of converting between them.
+ ConversionCost getBaseTypeConversionCost(
+ BaseTypeConversionInfo const& toInfo,
+ BaseTypeConversionInfo const& fromInfo)
+ {
+ if(toInfo.conversionKind == fromInfo.conversionKind
+ && toInfo.conversionRank == fromInfo.conversionRank)
+ {
+ // Thse should represent the exact same type.
+ return kConversionCost_None;
+ }
+
+ // Conversions within the same kind are easist to handle
+ if (toInfo.conversionKind == fromInfo.conversionKind)
+ {
+ // If we are converting to a "larger" type, then
+ // we are doing a lossless promotion, and otherwise
+ // we are doing a demotion.
+ if (toInfo.conversionRank > fromInfo.conversionRank)
+ return kConversionCost_RankPromotion;
+ else
+ return kConversionCost_GeneralConversion;
+ }
+ else if (fromInfo.tag == BaseType::Bool && toInfo.tag == BaseType::Int)
+ {
+ return kConversionCost_BoolToInt;
+ }
+
+ // If we are converting from an unsigned integer type to
+ // a signed integer type that is guaranteed to be larger,
+ // then that is also a lossless promotion.
+ //
+ // There is one additional wrinkle here, which is that
+ // a conversion from a 32-bit unsigned integer to a
+ // "pointer-sized" signed integer should be treated
+ // as unsafe, because the pointer size might also be
+ // 32 bits.
+ //
+ // The same basic exemption applied when converting
+ // *from* a pointer-sized unsigned integer.
+ else if(toInfo.conversionKind == kBaseTypeConversionKind_Signed
+ && fromInfo.conversionKind == kBaseTypeConversionKind_Unsigned
+ && toInfo.conversionRank > fromInfo.conversionRank
+ && toInfo.conversionRank != kBaseTypeConversionRank_IntPtr
+ && fromInfo.conversionRank != kBaseTypeConversionRank_IntPtr)
+ {
+ return kConversionCost_UnsignedToSignedPromotion;
+ }
+ // Same-size unsigned to signed integer conversion.
+ else if (toInfo.conversionKind == kBaseTypeConversionKind_Signed
+ && fromInfo.conversionKind == kBaseTypeConversionKind_Unsigned
+ && toInfo.conversionRank == fromInfo.conversionRank
+ && toInfo.conversionRank != kBaseTypeConversionRank_IntPtr
+ && fromInfo.conversionRank != kBaseTypeConversionRank_IntPtr)
+ {
+ return kConversionCost_SameSizeUnsignedToSignedConversion;
+ }
+
+ // Conversion from signed to unsigned is always lossy,
+ // but it is preferred over conversions from unsigned
+ // to signed, for same-size types.
+ else if(toInfo.conversionKind == kBaseTypeConversionKind_Unsigned
+ && fromInfo.conversionKind == kBaseTypeConversionKind_Signed
+ && toInfo.conversionRank >= fromInfo.conversionRank)
+ {
+ return kConversionCost_SignedToUnsignedConversion;
+ }
+
+ // Conversion from an integer to a floating-point type
+ // is never considered a promotion (even when the value
+ // would fit in the available mantissa bits).
+ // If the destination type is at least 32 bits we consider
+ // this a reasonably good conversion, though.
+ //
+ // Note that this means we do *not* consider implicit
+ // conversion to `half` as a good conversion, even for small
+ // types. This makes sense because we relaly want to prefer
+ // conversion to `float` as the default.
+ else if (toInfo.conversionKind == kBaseTypeConversionKind_Float
+ && toInfo.conversionRank >= kBaseTypeConversionRank_Int32
+ && fromInfo.conversionRank >= kBaseTypeConversionRank_Int8)
+ {
+ return kConversionCost_IntegerToFloatConversion;
+ }
+ else if (toInfo.conversionKind == kBaseTypeConversionKind_Float
+ && toInfo.conversionRank >= kBaseTypeConversionRank_Int16
+ && fromInfo.conversionRank >= kBaseTypeConversionRank_Int8)
+ {
+ return kConversionCost_IntegerToHalfConversion;
+ }
+ // All other cases are considered as "general" conversions,
+ // where we don't consider any one conversion better than
+ // any others.
+ else
+ {
+ return kConversionCost_GeneralConversion;
+ }
+ }
+
+ IROp getBaseTypeConversionOp(
+ BaseTypeConversionInfo const& toInfo,
+ BaseTypeConversionInfo const& fromInfo)
+ {
+ if (toInfo.tag == fromInfo.tag)
+ return kIROp_Nop;
+
+ IROp intrinsicOpCode = kIROp_Nop;
+ auto toStyle = getTypeStyle(toInfo.tag);
+ auto fromStyle = getTypeStyle(fromInfo.tag);
+ if (toStyle == kIROp_BoolType) toStyle = kIROp_IntType;
+ if (fromStyle == kIROp_BoolType) fromStyle = kIROp_IntType;
+ if (toStyle == kIROp_IntType && fromStyle == kIROp_IntType)
+ intrinsicOpCode = kIROp_IntCast;
+ if (toStyle == kIROp_IntType && fromStyle == kIROp_FloatType)
+ intrinsicOpCode = kIROp_CastFloatToInt;
+ if (toStyle == kIROp_FloatType && fromStyle == kIROp_IntType)
+ intrinsicOpCode = kIROp_CastIntToFloat;
+ if (toStyle == kIROp_FloatType && fromStyle == kIROp_FloatType)
+ intrinsicOpCode = kIROp_FloatCast;
+ return intrinsicOpCode;
+ }
+
+ struct IntrinsicOpInfo { IROp opCode; char const* funcName; char const* opName; char const* interface; unsigned flags; };
+
+ [[maybe_unused]]
+ static const IntrinsicOpInfo intrinsicUnaryOps[] = {
+ { kIROp_Neg, "neg", "-", "__BuiltinArithmeticType", ARITHMETIC_MASK },
+ { kIROp_Not, "logicalNot", "!", nullptr, BOOL_MASK | BOOL_RESULT },
+ { kIROp_BitNot, "not", "~", "__BuiltinLogicalType", INT_MASK },
+ };
+
+ [[maybe_unused]]
+ static const IntrinsicOpInfo intrinsicBinaryOps[] = {
+ {kIROp_Add, "add", "+", "__BuiltinArithmeticType", ARITHMETIC_MASK},
+ {kIROp_Sub, "sub", "-", "__BuiltinArithmeticType", ARITHMETIC_MASK},
+ {kIROp_Mul, "mul", "*", "__BuiltinArithmeticType", ARITHMETIC_MASK},
+ {kIROp_Div, "div", "/", "__BuiltinArithmeticType", ARITHMETIC_MASK},
+ {kIROp_IRem, "irem", "%", "__BuiltinIntegerType", INT_MASK},
+ {kIROp_FRem, "frem", "%", "__BuiltinFloatingPointType", FLOAT_MASK},
+ {kIROp_And, "logicalAnd", "&&", nullptr, BOOL_MASK | BOOL_RESULT},
+ {kIROp_Or, "logicalOr", "||", nullptr, BOOL_MASK | BOOL_RESULT},
+ {kIROp_BitAnd, "and", "&", "__BuiltinLogicalType", LOGICAL_MASK},
+ {kIROp_BitOr, "or", "|", "__BuiltinLogicalType", LOGICAL_MASK},
+ {kIROp_BitXor, "xor", "^", "__BuiltinLogicalType", LOGICAL_MASK},
+ {kIROp_Eql, "eql", "==", "__BuiltinType", ANY_MASK | BOOL_RESULT},
+ {kIROp_Neq, "neq", "!=", "__BuiltinType", ANY_MASK | BOOL_RESULT},
+ {kIROp_Greater, "greater", ">", "__BuiltinArithmeticType", ARITHMETIC_MASK | BOOL_RESULT},
+ {kIROp_Less, "less", "<", "__BuiltinArithmeticType", ARITHMETIC_MASK | BOOL_RESULT},
+ {kIROp_Geq, "geq", ">=", "__BuiltinArithmeticType", ARITHMETIC_MASK | BOOL_RESULT},
+ {kIROp_Leq, "leq", "<=", "__BuiltinArithmeticType", ARITHMETIC_MASK | BOOL_RESULT},
+ };
+
+ // Integer types that can be used in atomic operations in CUDA.
+ [[maybe_unused]]
+ static const char* kCudaAtomicIntegerTypes[] = { "int", "uint", "uint64_t", "int64_t" };
+
+ // Both the following functions use these macros.
+ // NOTE! They require a variable named path to emit the #line correctly if in source file.
+#define SLANG_RAW(TEXT) sb << TEXT;
+#define SLANG_SPLICE(EXPR) sb << (EXPR);
+
+#define EMIT_LINE_DIRECTIVE() sb << "#line " << (__LINE__+1) << " \"" << path << "\"\n"
+
+ ComPtr<ISlangBlob> Session::getCoreLibraryCode()
+ {
+#if SLANG_EMBED_STDLIB_SOURCE
+ if (!coreLibraryCode)
+ {
+ StringBuilder sb;
+ const String path = getStdlibPath();
+ #include "core.meta.slang.h"
+ coreLibraryCode = StringBlob::moveCreate(sb);
+ }
+#endif
+ return coreLibraryCode;
+ }
+
+ ComPtr<ISlangBlob> Session::getHLSLLibraryCode()
+ {
+#if SLANG_EMBED_STDLIB_SOURCE
+ if (!hlslLibraryCode)
+ {
+ const String path = getStdlibPath();
+ StringBuilder sb;
+ #include "hlsl.meta.slang.h"
+ hlslLibraryCode = StringBlob::moveCreate(sb);
+ }
+#endif
+ return hlslLibraryCode;
+ }
+
+ ComPtr<ISlangBlob> Session::getAutodiffLibraryCode()
+ {
+#if SLANG_EMBED_STDLIB_SOURCE
+ if (!autodiffLibraryCode)
+ {
+ const String path = getStdlibPath();
+ StringBuilder sb;
+ #include "diff.meta.slang.h"
+ autodiffLibraryCode = StringBlob::moveCreate(sb);
+ }
+#endif
+ return autodiffLibraryCode;
+ }
+
+ ComPtr<ISlangBlob> Session::getGLSLLibraryCode()
+ {
+ if (!glslLibraryCode)
+ {
+ const String path = getStdlibPath();
+ StringBuilder sb;
+ #include "glsl.meta.slang.h"
+ glslLibraryCode = StringBlob::moveCreate(sb);
+ }
+ return glslLibraryCode;
+ }
+}
diff --git a/source/slang/slang-stdlib-api.cpp b/source/slang-stdlib/slang-embedded-stdlib.cpp
index e5934531a..87107fa50 100644
--- a/source/slang/slang-stdlib-api.cpp
+++ b/source/slang-stdlib/slang-embedded-stdlib.cpp
@@ -1,18 +1,8 @@
-// slang-stdlib-api.cpp
-
#include "../core/slang-basic.h"
#include "../core/slang-array-view.h"
-
#include "../core/slang-blob.h"
-#ifdef SLANG_WITHOUT_EMBEDDED_STD_LIB
-
-SLANG_API ISlangBlob* slang_getEmbeddedStdLib()
-{
- return nullptr;
-}
-
-#else
+#ifdef SLANG_EMBED_STDLIB
static const uint8_t g_stdLib[] =
{
@@ -26,4 +16,11 @@ SLANG_API ISlangBlob* slang_getEmbeddedStdLib()
return &g_stdLibBlob;
}
+#else
+
+SLANG_API ISlangBlob* slang_getEmbeddedStdLib()
+{
+ return nullptr;
+}
+
#endif
diff --git a/source/slang/CMakeLists.txt b/source/slang/CMakeLists.txt
index 78d2376a7..27600e3f8 100644
--- a/source/slang/CMakeLists.txt
+++ b/source/slang/CMakeLists.txt
@@ -1,50 +1,3 @@
-#
-# Compiling the meta.slang files
-#
-
-# List of *.meta.slang headers
-glob_append(SLANG_STDLIB_META_SOURCE "*.meta.slang")
-
-set(SLANG_STDLIB_META_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/stdlib-meta")
-
-# Generate the output file list
-set(SLANG_STDLIB_META_GENERATED_HEADERS)
-foreach(meta_source ${SLANG_STDLIB_META_SOURCE})
- file(
- RELATIVE_PATH
- meta_source_relative
- ${CMAKE_CURRENT_LIST_DIR}
- ${meta_source}
- )
- list(
- APPEND
- SLANG_STDLIB_META_GENERATED_HEADERS
- "${SLANG_STDLIB_META_OUTPUT_DIR}/${meta_source_relative}.h"
- )
-endforeach()
-
-add_custom_command(
- OUTPUT ${SLANG_STDLIB_META_GENERATED_HEADERS}
- COMMAND ${CMAKE_COMMAND} -E make_directory ${SLANG_STDLIB_META_OUTPUT_DIR}
- COMMAND
- slang-generate ${SLANG_STDLIB_META_SOURCE} --target-directory
- ${SLANG_STDLIB_META_OUTPUT_DIR}
- DEPENDS ${SLANG_STDLIB_META_SOURCE} slang-generate
- WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
- VERBATIM
-)
-
-add_library(
- slang-meta-headers
- INTERFACE
- EXCLUDE_FROM_ALL
- ${SLANG_STDLIB_META_GENERATED_HEADERS}
-)
-set_target_properties(slang-meta-headers PROPERTIES FOLDER generated)
-target_include_directories(
- slang-meta-headers
- INTERFACE ${SLANG_STDLIB_META_OUTPUT_DIR}
-)
#
# generate capability files
@@ -211,33 +164,6 @@ slang_add_target(
)
#
-# Generate an embeddable stdlib
-#
-
-set(SLANG_STDLIB_GENERATED_HEADER
- ${CMAKE_CURRENT_BINARY_DIR}/slang-stdlib-generated.h
-)
-add_custom_command(
- OUTPUT ${SLANG_STDLIB_GENERATED_HEADER}
- COMMAND
- slang-bootstrap -archive-type riff-lz4 -save-stdlib-bin-source
- ${SLANG_STDLIB_GENERATED_HEADER}
- DEPENDS slang-bootstrap
- VERBATIM
-)
-add_library(
- slang-stdlib-embed-headers
- INTERFACE
- EXCLUDE_FROM_ALL
- ${SLANG_STDLIB_GENERATED_HEADER}
-)
-set_target_properties(slang-stdlib-embed-headers PROPERTIES FOLDER generated)
-target_include_directories(
- slang-stdlib-embed-headers
- INTERFACE ${CMAKE_CURRENT_BINARY_DIR}
-)
-
-#
# Generate the version header
#
@@ -247,60 +173,98 @@ configure_file(${slang_SOURCE_DIR}/slang-tag-version.h.in slang-version-header/s
# Slang itself
#
-set(slang_common_args
- EXTRA_SOURCE_DIRS ${SLANG_RECORD_REPLAY_SYSTEM}
+set(slang_build_args
USE_EXTRA_WARNINGS
+ EXTRA_COMPILE_OPTIONS_PRIVATE
+ # a warning is disabled for a memset boundary check.
+ # everything looked fine and it is unclear why the checking fails
+ $<$<CXX_COMPILER_ID:GNU>:-Wno-error=stringop-overflow>
+ # slang.h is in the project root, so include that directory in the interface
+ # for slang
+ INCLUDE_DIRECTORIES_PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/slang-version-header
+ EXPORT_MACRO_PREFIX SLANG
+ EXPORT_TYPE_AS ${SLANG_LIB_TYPE}
+ EXTRA_SOURCE_DIRS ${SLANG_RECORD_REPLAY_SYSTEM}
+)
+set(slang_link_args
LINK_WITH_PRIVATE
core
+ prelude
compiler-core
slang-capability-defs
slang-capability-lookup
slang-reflect-headers
slang-lookup-tables
SPIRV-Headers
- EXTRA_COMPILE_OPTIONS_PRIVATE
- # a warning is disabled for a memset boundary check.
- # everything looked fine and it is unclear why the checking fails
- $<$<CXX_COMPILER_ID:GNU>:-Wno-error=stringop-overflow>
- # slang.h is in the project root, so include that directory in the interface
- # for slang
+)
+set(slang_interface_args
INCLUDE_DIRECTORIES_PUBLIC ${slang_SOURCE_DIR}
- INCLUDE_DIRECTORIES_PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/slang-version-header
- EXPORT_MACRO_PREFIX SLANG
+)
+set(slang_public_lib_args
+ PUBLIC_HEADERS
+ ${slang_SOURCE_DIR}/slang*.h
+ ${CMAKE_CURRENT_BINARY_DIR}/slang-version-header/*.h
+ LINK_WITH_PRIVATE
+ $<IF:$<BOOL:${SLANG_EMBED_STDLIB}>,slang-embedded-stdlib,slang-no-embedded-stdlib>
+ $<IF:$<BOOL:${SLANG_EMBED_STDLIB_SOURCE}>,slang-embedded-stdlib-source,slang-no-embedded-stdlib-source>
+ INSTALL
)
#
# Minimal static slang used in generating the embedded stdlib
#
-slang_add_target(
- .
- OBJECT
- ${slang_common_args}
- TARGET_NAME slang-no-embedded-stdlib
- EXCLUDE_FROM_ALL
- LINK_WITH_PRIVATE slang-meta-headers
- EXTRA_COMPILE_DEFINITIONS_PUBLIC SLANG_STATIC
- EXTRA_COMPILE_DEFINITIONS_PRIVATE SLANG_WITHOUT_EMBEDDED_STD_LIB
- FOLDER generators
-)
-
#
-# Slang with whatever options
+# Slang itself
#
-slang_add_target(
- .
- ${SLANG_LIB_TYPE}
- ${slang_common_args}
- LINK_WITH_PRIVATE
- prelude
- $<$<BOOL:${SLANG_EMBED_STDLIB}>:slang-stdlib-embed-headers>
- $<$<BOOL:${SLANG_EMBED_STDLIB_SOURCE}>:slang-meta-headers>
- EXTRA_COMPILE_DEFINITIONS_PRIVATE
- $<$<NOT:$<BOOL:${SLANG_EMBED_STDLIB}>>:SLANG_WITHOUT_EMBEDDED_STD_LIB>
- $<$<NOT:$<BOOL:${SLANG_EMBED_STDLIB_SOURCE}>>:SLANG_DISABLE_STDLIB_SOURCE>
- EXPORT_MACRO_PREFIX SLANG
- INSTALL
- PUBLIC_HEADERS ${slang_SOURCE_DIR}/slang*.h ${CMAKE_CURRENT_BINARY_DIR}/slang-version-header/*.h
-)
+if(NOT SLANG_EMBED_STDLIB)
+ # If we're not embedding stdlib we can just do a normal build of slang,
+ # including all the options, this can also serve as our no embedded stdlib
+ # library for slang-bootstrap (not that we need that anyway)
+ slang_add_target(
+ .
+ ${SLANG_LIB_TYPE}
+ ${slang_build_args}
+ ${slang_link_args}
+ ${slang_interface_args}
+ ${slang_public_lib_args}
+ )
+ add_library(slang-without-embedded-stdlib ALIAS slang)
+else()
+ # However if we're embedding stdlib, we need to make two different
+ # libraries, one with the embedded stdlib and one without, so first define
+ # the shared objects as one target so we don't build them twice.
+ slang_add_target(
+ .
+ OBJECT
+ ${slang_build_args}
+ ${slang_link_args}
+ TARGET_NAME slang-common-objects
+ EXCLUDE_FROM_ALL
+ )
+ slang_add_target(
+ .
+ ${SLANG_LIB_TYPE}
+ ${slang_link_args}
+ ${slang_interface_args}
+ NO_SOURCE
+ TARGET_NAME
+ slang-without-embedded-stdlib
+ EXCLUDE_FROM_ALL
+ LINK_WITH_PRIVATE
+ slang-common-objects
+ slang-no-embedded-stdlib
+ slang-embedded-stdlib-source
+ )
+ slang_add_target(
+ .
+ ${SLANG_LIB_TYPE}
+ ${slang_link_args}
+ ${slang_interface_args}
+ ${slang_public_lib_args}
+ LINK_WITH_PRIVATE
+ slang-common-objects
+ NO_SOURCE
+ )
+endif()
diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp
index dbc358c18..e28d95ad5 100644
--- a/source/slang/slang-stdlib.cpp
+++ b/source/slang/slang-stdlib.cpp
@@ -2,9 +2,6 @@
#include "slang-compiler.h"
#include "slang-ir.h"
-#include "slang-syntax.h"
-#include "slang-ir-util.h"
-#include "slang-stdlib-textures.h"
#include "../core/slang-string-util.h"
#define STRINGIZE(x) STRINGIZE2(x)
@@ -27,331 +24,4 @@ namespace Slang
}
return stdlibPath;
}
-
- // We are going to generate the stdlib source code from a more compact
- // description. For example, we need to generate all the `operator`
- // declarations for the basic unary and binary math operations on
- // builtin types. To do this, we will make a big array of all these
- // types, and associate them with data on their categories/capabilities
- // so that we generate only the correct operations.
- //
- enum
- {
- SINT_MASK = 1 << 0,
- FLOAT_MASK = 1 << 1,
- BOOL_RESULT = 1 << 2,
- BOOL_MASK = 1 << 3,
- UINT_MASK = 1 << 4,
-
- INT_MASK = SINT_MASK | UINT_MASK,
- ARITHMETIC_MASK = INT_MASK | FLOAT_MASK,
- LOGICAL_MASK = INT_MASK | BOOL_MASK,
- ANY_MASK = INT_MASK | FLOAT_MASK | BOOL_MASK,
- };
-
- // We are going to declare initializers that allow for conversion between
- // all of our base types, and we need a way to priotize those conversion
- // by giving them different costs. Rather than maintain a hard-coded table
- // of N^2 costs for N basic types, we are going to try to do things a bit
- // more systematically.
- //
- // Every base type will be given a "kind" and a "rank" for conversion.
- // The kind will classify it as signed/unsigned/float, and the rank will
- // classify it by its logical bit size (with a distinct rank for pointer-sized
- // types that logically sits between 32- and 64-bit types).
- //
- enum BaseTypeConversionKind : uint8_t
- {
- kBaseTypeConversionKind_Signed,
- kBaseTypeConversionKind_Unsigned,
- kBaseTypeConversionKind_Float,
- kBaseTypeConversionKind_Error,
- };
- enum BaseTypeConversionRank : uint8_t
- {
- kBaseTypeConversionRank_Bool,
- kBaseTypeConversionRank_Int8,
- kBaseTypeConversionRank_Int16,
- kBaseTypeConversionRank_Int32,
- kBaseTypeConversionRank_IntPtr,
- kBaseTypeConversionRank_Int64,
- kBaseTypeConversionRank_Error,
- };
-
- // Here we declare the table of all our builtin types, so that we can generate all the relevant declarations.
- //
- struct BaseTypeConversionInfo
- {
- char const* name;
- BaseType tag;
- unsigned flags;
- BaseTypeConversionKind conversionKind;
- BaseTypeConversionRank conversionRank;
- };
- static const BaseTypeConversionInfo kBaseTypes[] = {
- // TODO: `void` really shouldn't be in the `BaseType` enumeration, since it behaves so differently across the board
- { "void", BaseType::Void, 0, kBaseTypeConversionKind_Error, kBaseTypeConversionRank_Error},
-
- { "bool", BaseType::Bool, BOOL_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Bool },
-
- { "int8_t", BaseType::Int8, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_Int8},
- { "int16_t", BaseType::Int16, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_Int16},
- { "int", BaseType::Int, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_Int32},
- { "int64_t", BaseType::Int64, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_Int64},
- { "intptr_t", BaseType::IntPtr, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_IntPtr},
-
-
- { "half", BaseType::Half, FLOAT_MASK, kBaseTypeConversionKind_Float, kBaseTypeConversionRank_Int16},
- { "float", BaseType::Float, FLOAT_MASK, kBaseTypeConversionKind_Float, kBaseTypeConversionRank_Int32},
- { "double", BaseType::Double, FLOAT_MASK, kBaseTypeConversionKind_Float, kBaseTypeConversionRank_Int64},
-
- { "uint8_t", BaseType::UInt8, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int8},
- { "uint16_t", BaseType::UInt16, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int16},
- { "uint", BaseType::UInt, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int32},
- { "uint64_t", BaseType::UInt64, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int64},
- { "uintptr_t", BaseType::UIntPtr, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_IntPtr},
-
- };
-
- void Session::finalizeSharedASTBuilder()
- {
- // Force creation of all builtin types so we can make sure
- // they are created by the builtin AST builder instead of
- // some user linkage's ast builder. This avoid the problem
- // of storing a reference to these global types that are
- // owned by a user linkage that gets deleted with the linkage.
- //
- globalAstBuilder->getNoneType();
- globalAstBuilder->getNullPtrType();
- globalAstBuilder->getBottomType();
- globalAstBuilder->getErrorType();
- globalAstBuilder->getInitializerListType();
- globalAstBuilder->getOverloadedType();
- globalAstBuilder->getStringType();
- globalAstBuilder->getEnumTypeType();
- globalAstBuilder->getDiffInterfaceType();
- globalAstBuilder->getSharedASTBuilder()->getDynamicType();
- globalAstBuilder->getSharedASTBuilder()->getDiffInterfaceType();
- globalAstBuilder->getSharedASTBuilder()->getNativeStringType();
- for (auto& baseType : kBaseTypes)
- globalAstBuilder->getBuiltinType(baseType.tag);
- }
-
-
- // Given two base types, we need to be able to compute the cost of converting between them.
- ConversionCost getBaseTypeConversionCost(
- BaseTypeConversionInfo const& toInfo,
- BaseTypeConversionInfo const& fromInfo)
- {
- if(toInfo.conversionKind == fromInfo.conversionKind
- && toInfo.conversionRank == fromInfo.conversionRank)
- {
- // Thse should represent the exact same type.
- return kConversionCost_None;
- }
-
- // Conversions within the same kind are easist to handle
- if (toInfo.conversionKind == fromInfo.conversionKind)
- {
- // If we are converting to a "larger" type, then
- // we are doing a lossless promotion, and otherwise
- // we are doing a demotion.
- if (toInfo.conversionRank > fromInfo.conversionRank)
- return kConversionCost_RankPromotion;
- else
- return kConversionCost_GeneralConversion;
- }
- else if (fromInfo.tag == BaseType::Bool && toInfo.tag == BaseType::Int)
- {
- return kConversionCost_BoolToInt;
- }
-
- // If we are converting from an unsigned integer type to
- // a signed integer type that is guaranteed to be larger,
- // then that is also a lossless promotion.
- //
- // There is one additional wrinkle here, which is that
- // a conversion from a 32-bit unsigned integer to a
- // "pointer-sized" signed integer should be treated
- // as unsafe, because the pointer size might also be
- // 32 bits.
- //
- // The same basic exemption applied when converting
- // *from* a pointer-sized unsigned integer.
- else if(toInfo.conversionKind == kBaseTypeConversionKind_Signed
- && fromInfo.conversionKind == kBaseTypeConversionKind_Unsigned
- && toInfo.conversionRank > fromInfo.conversionRank
- && toInfo.conversionRank != kBaseTypeConversionRank_IntPtr
- && fromInfo.conversionRank != kBaseTypeConversionRank_IntPtr)
- {
- return kConversionCost_UnsignedToSignedPromotion;
- }
- // Same-size unsigned to signed integer conversion.
- else if (toInfo.conversionKind == kBaseTypeConversionKind_Signed
- && fromInfo.conversionKind == kBaseTypeConversionKind_Unsigned
- && toInfo.conversionRank == fromInfo.conversionRank
- && toInfo.conversionRank != kBaseTypeConversionRank_IntPtr
- && fromInfo.conversionRank != kBaseTypeConversionRank_IntPtr)
- {
- return kConversionCost_SameSizeUnsignedToSignedConversion;
- }
-
- // Conversion from signed to unsigned is always lossy,
- // but it is preferred over conversions from unsigned
- // to signed, for same-size types.
- else if(toInfo.conversionKind == kBaseTypeConversionKind_Unsigned
- && fromInfo.conversionKind == kBaseTypeConversionKind_Signed
- && toInfo.conversionRank >= fromInfo.conversionRank)
- {
- return kConversionCost_SignedToUnsignedConversion;
- }
-
- // Conversion from an integer to a floating-point type
- // is never considered a promotion (even when the value
- // would fit in the available mantissa bits).
- // If the destination type is at least 32 bits we consider
- // this a reasonably good conversion, though.
- //
- // Note that this means we do *not* consider implicit
- // conversion to `half` as a good conversion, even for small
- // types. This makes sense because we relaly want to prefer
- // conversion to `float` as the default.
- else if (toInfo.conversionKind == kBaseTypeConversionKind_Float
- && toInfo.conversionRank >= kBaseTypeConversionRank_Int32
- && fromInfo.conversionRank >= kBaseTypeConversionRank_Int8)
- {
- return kConversionCost_IntegerToFloatConversion;
- }
- else if (toInfo.conversionKind == kBaseTypeConversionKind_Float
- && toInfo.conversionRank >= kBaseTypeConversionRank_Int16
- && fromInfo.conversionRank >= kBaseTypeConversionRank_Int8)
- {
- return kConversionCost_IntegerToHalfConversion;
- }
- // All other cases are considered as "general" conversions,
- // where we don't consider any one conversion better than
- // any others.
- else
- {
- return kConversionCost_GeneralConversion;
- }
- }
-
- IROp getBaseTypeConversionOp(
- BaseTypeConversionInfo const& toInfo,
- BaseTypeConversionInfo const& fromInfo)
- {
- if (toInfo.tag == fromInfo.tag)
- return kIROp_Nop;
-
- IROp intrinsicOpCode = kIROp_Nop;
- auto toStyle = getTypeStyle(toInfo.tag);
- auto fromStyle = getTypeStyle(fromInfo.tag);
- if (toStyle == kIROp_BoolType) toStyle = kIROp_IntType;
- if (fromStyle == kIROp_BoolType) fromStyle = kIROp_IntType;
- if (toStyle == kIROp_IntType && fromStyle == kIROp_IntType)
- intrinsicOpCode = kIROp_IntCast;
- if (toStyle == kIROp_IntType && fromStyle == kIROp_FloatType)
- intrinsicOpCode = kIROp_CastFloatToInt;
- if (toStyle == kIROp_FloatType && fromStyle == kIROp_IntType)
- intrinsicOpCode = kIROp_CastIntToFloat;
- if (toStyle == kIROp_FloatType && fromStyle == kIROp_FloatType)
- intrinsicOpCode = kIROp_FloatCast;
- return intrinsicOpCode;
- }
-
- struct IntrinsicOpInfo { IROp opCode; char const* funcName; char const* opName; char const* interface; unsigned flags; };
-
- [[maybe_unused]]
- static const IntrinsicOpInfo intrinsicUnaryOps[] = {
- { kIROp_Neg, "neg", "-", "__BuiltinArithmeticType", ARITHMETIC_MASK },
- { kIROp_Not, "logicalNot", "!", nullptr, BOOL_MASK | BOOL_RESULT },
- { kIROp_BitNot, "not", "~", "__BuiltinLogicalType", INT_MASK },
- };
-
- [[maybe_unused]]
- static const IntrinsicOpInfo intrinsicBinaryOps[] = {
- {kIROp_Add, "add", "+", "__BuiltinArithmeticType", ARITHMETIC_MASK},
- {kIROp_Sub, "sub", "-", "__BuiltinArithmeticType", ARITHMETIC_MASK},
- {kIROp_Mul, "mul", "*", "__BuiltinArithmeticType", ARITHMETIC_MASK},
- {kIROp_Div, "div", "/", "__BuiltinArithmeticType", ARITHMETIC_MASK},
- {kIROp_IRem, "irem", "%", "__BuiltinIntegerType", INT_MASK},
- {kIROp_FRem, "frem", "%", "__BuiltinFloatingPointType", FLOAT_MASK},
- {kIROp_And, "logicalAnd", "&&", nullptr, BOOL_MASK | BOOL_RESULT},
- {kIROp_Or, "logicalOr", "||", nullptr, BOOL_MASK | BOOL_RESULT},
- {kIROp_BitAnd, "and", "&", "__BuiltinLogicalType", LOGICAL_MASK},
- {kIROp_BitOr, "or", "|", "__BuiltinLogicalType", LOGICAL_MASK},
- {kIROp_BitXor, "xor", "^", "__BuiltinLogicalType", LOGICAL_MASK},
- {kIROp_Eql, "eql", "==", "__BuiltinType", ANY_MASK | BOOL_RESULT},
- {kIROp_Neq, "neq", "!=", "__BuiltinType", ANY_MASK | BOOL_RESULT},
- {kIROp_Greater, "greater", ">", "__BuiltinArithmeticType", ARITHMETIC_MASK | BOOL_RESULT},
- {kIROp_Less, "less", "<", "__BuiltinArithmeticType", ARITHMETIC_MASK | BOOL_RESULT},
- {kIROp_Geq, "geq", ">=", "__BuiltinArithmeticType", ARITHMETIC_MASK | BOOL_RESULT},
- {kIROp_Leq, "leq", "<=", "__BuiltinArithmeticType", ARITHMETIC_MASK | BOOL_RESULT},
- };
-
- // Integer types that can be used in atomic operations in CUDA.
- [[maybe_unused]]
- static const char* kCudaAtomicIntegerTypes[] = { "int", "uint", "uint64_t", "int64_t" };
-
- // Both the following functions use these macros.
- // NOTE! They require a variable named path to emit the #line correctly if in source file.
-#define SLANG_RAW(TEXT) sb << TEXT;
-#define SLANG_SPLICE(EXPR) sb << (EXPR);
-
-#define EMIT_LINE_DIRECTIVE() sb << "#line " << (__LINE__+1) << " \"" << path << "\"\n"
-
- ComPtr<ISlangBlob> Session::getCoreLibraryCode()
- {
-#if !defined(SLANG_DISABLE_STDLIB_SOURCE)
- if (!coreLibraryCode)
- {
- StringBuilder sb;
- const String path = getStdlibPath();
- #include "core.meta.slang.h"
- coreLibraryCode = StringBlob::moveCreate(sb);
- }
-#endif
- return coreLibraryCode;
- }
-
- ComPtr<ISlangBlob> Session::getHLSLLibraryCode()
- {
-#if !defined(SLANG_DISABLE_STDLIB_SOURCE)
- if (!hlslLibraryCode)
- {
- const String path = getStdlibPath();
- StringBuilder sb;
- #include "hlsl.meta.slang.h"
- hlslLibraryCode = StringBlob::moveCreate(sb);
- }
-#endif
- return hlslLibraryCode;
- }
-
- ComPtr<ISlangBlob> Session::getAutodiffLibraryCode()
- {
-#if !defined(SLANG_DISABLE_STDLIB_SOURCE)
- if (!autodiffLibraryCode)
- {
- const String path = getStdlibPath();
- StringBuilder sb;
- #include "diff.meta.slang.h"
- autodiffLibraryCode = StringBlob::moveCreate(sb);
- }
-#endif
- return autodiffLibraryCode;
- }
-
- ComPtr<ISlangBlob> Session::getGLSLLibraryCode()
- {
- if (!glslLibraryCode)
- {
- const String path = getStdlibPath();
- StringBuilder sb;
- #include "glsl.meta.slang.h"
- glslLibraryCode = StringBlob::moveCreate(sb);
- }
- return glslLibraryCode;
- }
}