summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--slang.h431
-rw-r--r--source/core/slang-com-ptr.h57
-rw-r--r--source/core/slang-defines.h171
-rw-r--r--source/core/slang-string.h12
-rw-r--r--source/slang/compiler.cpp27
-rw-r--r--source/slang/compiler.h38
-rw-r--r--source/slang/preprocessor.cpp6
-rw-r--r--source/slang/preprocessor.h2
-rw-r--r--source/slang/slang.cpp320
-rw-r--r--source/slang/source-loc.cpp21
-rw-r--r--source/slang/source-loc.h14
11 files changed, 847 insertions, 252 deletions
diff --git a/slang.h b/slang.h
index 7b344834c..85a995e0e 100644
--- a/slang.h
+++ b/slang.h
@@ -1,6 +1,193 @@
#ifndef SLANG_H
#define SLANG_H
+/** \file slang.h
+
+The Slang API provides services to compile, reflect, and specialize code
+written in the Slang shading language.
+*/
+
+/*
+The following section attempts to detect the compiler and version in use.
+
+If an application defines `SLANG_COMPILER` before including this header,
+they take responsibility for setting any compiler-dependent macros
+used later in the file.
+
+Most applications should not need to touch this section.
+*/
+#ifndef SLANG_COMPILER
+# define SLANG_COMPILER
+
+/*
+Compiler defines, see http://sourceforge.net/p/predef/wiki/Compilers/
+NOTE that SLANG_VC holds the compiler version - not just 1 or 0
+*/
+# if defined(_MSC_VER)
+# if _MSC_VER >= 1900
+# define SLANG_VC 14
+# elif _MSC_VER >= 1800
+# define SLANG_VC 12
+# elif _MSC_VER >= 1700
+# define SLANG_VC 11
+# elif _MSC_VER >= 1600
+# define SLANG_VC 10
+# elif _MSC_VER >= 1500
+# define SLANG_VC 9
+# else
+# error "unknown version of Visual C++ compiler"
+# endif
+# elif defined(__clang__)
+# define SLANG_CLANG 1
+# elif defined(__SNC__)
+# define SLANG_SNC 1
+# elif defined(__ghs__)
+# define SLANG_GHS 1
+# elif defined(__GNUC__) /* note: __clang__, __SNC__, or __ghs__ imply __GNUC__ */
+# define SLANG_GCC 1
+# else
+# error "unknown compiler"
+# endif
+/*
+Any compilers not detected by the above logic are now now explicitly zeroed out.
+*/
+# ifndef SLANG_VC
+# define SLANG_VC 0
+# endif
+# ifndef SLANG_CLANG
+# define SLANG_CLANG 0
+# endif
+# ifndef SLANG_SNC
+# define SLANG_SNC 0
+# endif
+# ifndef SLANG_GHS
+# define SLANG_GHS 0
+# endif
+# ifndef SLANG_GCC
+# define SLANG_GCC 0
+# endif
+#endif /* SLANG_COMPILER */
+
+/*
+The following section attempts to detect the target platform being compiled for.
+
+If an application defines `SLANG_PLATFORM` before including this header,
+they take responsibility for setting any compiler-dependent macros
+used later in the file.
+
+Most applications should not need to touch this section.
+*/
+#ifndef SLANG_PLATFORM
+# define SLANG_PLATFORM
+/**
+Operating system defines, see http://sourceforge.net/p/predef/wiki/OperatingSystems/
+*/
+# if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_PARTITION_APP
+# define SLANG_WINRT 1 /* Windows Runtime, either on Windows RT or Windows 8 */
+# elif defined(XBOXONE)
+# define SLANG_XBOXONE 1
+# elif defined(_WIN64) /* note: XBOXONE implies _WIN64 */
+# define SLANG_WIN64 1
+# elif defined(_M_PPC)
+# define SLANG_X360 1
+# elif defined(_WIN32) /* note: _M_PPC implies _WIN32 */
+# define SLANG_WIN32 1
+# elif defined(__ANDROID__)
+# define SLANG_ANDROID 1
+# elif defined(__linux__) || defined(__CYGWIN__) /* note: __ANDROID__ implies __linux__ */
+# define SLANG_LINUX 1
+# elif defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
+# define SLANG_IOS 1
+# elif defined(__APPLE__)
+# define SLANG_OSX 1
+# elif defined(__CELLOS_LV2__)
+# define SLANG_PS3 1
+# elif defined(__ORBIS__)
+# define SLANG_PS4 1
+# elif defined(__SNC__) && defined(__arm__)
+# define SLANG_PSP2 1
+# elif defined(__ghs__)
+# define SLANG_WIIU 1
+# else
+# error "unknown target platform"
+# endif
+/*
+Any platforms not detected by the above logic are now now explicitly zeroed out.
+*/
+# ifndef SLANG_WINRT
+# define SLANG_WINRT 0
+# endif
+# ifndef SLANG_XBOXONE
+# define SLANG_XBOXONE 0
+# endif
+# ifndef SLANG_WIN64
+# define SLANG_WIN64 0
+# endif
+# ifndef SLANG_X360
+# define SLANG_X360 0
+# endif
+# ifndef SLANG_WIN32
+# define SLANG_WIN32 0
+# endif
+# ifndef SLANG_ANDROID
+# define SLANG_ANDROID 0
+# endif
+# ifndef SLANG_LINUX
+# define SLANG_LINUX 0
+# endif
+# ifndef SLANG_IOS
+# define SLANG_IOS 0
+# endif
+# ifndef SLANG_OSX
+# define SLANG_OSX 0
+# endif
+# ifndef SLANG_PS3
+# define SLANG_PS3 0
+# endif
+# ifndef SLANG_PS4
+# define SLANG_PS4 0
+# endif
+# ifndef SLANG_PSP2
+# define SLANG_PSP2 0
+# endif
+# ifndef SLANG_WIIU
+# define SLANG_WIIU 0
+# endif
+#endif /* SLANG_PLATFORM */
+
+/* Shorthands for "families" of compilers/platforms */
+#define SLANG_GCC_FAMILY (SLANG_CLANG || SLANG_SNC || SLANG_GHS || SLANG_GCC)
+#define SLANG_WINDOWS_FAMILY (SLANG_WINRT || SLANG_WIN32 || SLANG_WIN64)
+#define SLANG_MICROSOFT_FAMILY (SLANG_XBOXONE || SLANG_X360 || SLANG_WINDOWS_FAMILY)
+#define SLANG_LINUX_FAMILY (SLANG_LINUX || SLANG_ANDROID)
+#define SLANG_APPLE_FAMILY (SLANG_IOS || SLANG_OSX) /* equivalent to #if __APPLE__ */
+#define SLANG_UNIX_FAMILY (SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY) /* shortcut for unix/posix platforms */
+
+/* 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
+
+
#if !defined(SLANG_STATIC) && !defined(SLANG_STATIC)
#define SLANG_DYNAMIC
#endif
@@ -178,12 +365,95 @@ extern "C"
SLANG_MATRIX_LAYOUT_COLUMN_MAJOR,
};
-//#define SLANG_LAYOUT_UNIFORM 0
-//#define SLANG_LAYOUT_PACKED 1
-//#define SLANG_LAYOUT_STORAGE 2
+ /** A result code for a Slang API operation.
-#define SLANG_ERROR_INSUFFICIENT_BUFFER -1
-#define SLANG_ERROR_INVALID_PARAMETER -2
+ This type is generally compatible with the Windows API
+ `HRESULT` type. In particular, negative values indicate
+ failure results, while zero or positive results indicate
+ success.
+
+ In general, Slang APIs always return a zero result on
+ success, unless documented otherwise.
+ */
+ typedef int32_t SlangResult;
+
+ /** A "Universally Unique Identifier" (UUID)
+
+ The Slang API uses UUIDs to identify interfaces when
+ using `queryInterface`.
+
+ This type is compatible with the `GUID` type defined
+ by the Component Object Model (COM), but Slang is
+ not dependent on COM.
+ */
+ struct SlangUUID
+ {
+ uint32_t data1;
+ uint16_t data2;
+ uint16_t data3;
+ uint8_t data4[8];
+ };
+
+ /** Base interface for components exchanged through the API.
+
+ This interface definition is compatible with the COM `IUnknown`,
+ and uses the same UUID, but Slang does not require applications
+ to use or initialize COM.
+ */
+ struct ISlangUnknown
+ {
+ public:
+ 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;
+
+ /*
+ Inline methods are provided to allow the above operations to be called
+ using their traditional COM names/signatures:
+ */
+ SlangResult QueryInterface(struct _GUID const& uuid, void** outObject) { return queryInterface(*(SlangUUID const*)&uuid, outObject); }
+ uint32_t AddRef() { return addRef(); }
+ uint32_t Release() { return release(); }
+ };
+ #define SLANG_UUID_ISlangUnknown { 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }
+
+ /** A "blob" of binary data.
+
+ This interface definition is compatible with the `ID3DBlob` and `ID3D10Blob` interfaces.
+ */
+ struct ISlangBlob : public ISlangUnknown
+ {
+ public:
+ virtual SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() = 0;
+ virtual SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() = 0;
+ };
+ #define SLANG_UUID_ISlangBlob { 0x8BA5FB08, 0x5195, 0x40e2, 0xAC, 0x58, 0x0D, 0x98, 0x9C, 0x3A, 0x01, 0x02 }
+
+ /** A (real or virtual) file system.
+
+ Slang can make use of this interface whenever it would otherwise try to load files
+ from disk, allowing applications to hook and/or overide filesystem access from
+ the compiler.
+ */
+ struct ISlangFileSystem : public ISlangUnknown
+ {
+ public:
+ /** Load a file from `path` and return a blob of its contents
+
+ @param path The path to load from, as a nul-terminated UTF-8 string.
+ @param outBlob A destination pointer to receive the blob of the file contents.
+ @returns A `SlangResult` to indicate success or failure in loading the file.
+
+ If load is successful, the implementation should create a blob to hold
+ the file's content, store it to `outBlob`, and return 0.
+ If the load fails, the implementation should return a failure status
+ (any negative value will do).
+ */
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile(
+ char const* path,
+ ISlangBlob** outBlob) = 0;
+ };
+ #define SLANG_UUID_ISlangFileSystem { 0x003A09FC, 0x3A4D, 0x4BA0, 0xAD, 0x60, 0x1F, 0xD8, 0x63, 0xA9, 0x15, 0xAB }
/*!
@brief An instance of the Slang library.
@@ -197,9 +467,8 @@ extern "C"
/*!
@brief Initialize an instance of the Slang library.
- @param cacheDir The directory used to store cached compilation results. Pass NULL to disable caching.
*/
- SLANG_API SlangSession* spCreateSession(const char * cacheDir);
+ SLANG_API SlangSession* spCreateSession(const char* deprecated = 0);
/*!
@brief Clean up after an instance of the Slang library.
@@ -228,6 +497,21 @@ extern "C"
SLANG_API void spDestroyCompileRequest(
SlangCompileRequest* request);
+ /** Set the filesystem hook to use for a compile request
+
+ The provided `fileSystem` will be used to load any files that
+ need to be loaded during processing of the compile `request`.
+ This includes:
+
+ - Source files loaded via `spAddTranslationUnitSourceFile`
+ - Files referenced via `#include`
+ - Files loaded to resolve `#import` operations
+
+ */
+ SLANG_API void spSetFileSystem(
+ SlangCompileRequest* request,
+ ISlangFileSystem* fileSystem);
+
/*!
@brief Set flags to be used for compilation.
@@ -355,16 +639,35 @@ extern "C"
const char* value);
- /** Add a source file to the given translation unit
+ /** Add a source file to the given translation unit.
+
+ If a user-defined file system has been specified via
+ `spSetFileSystem`, then it will be used to load the
+ file at `path`. Otherwise, Slang will use the OS
+ file system.
+
+ This function does *not* search for a file using
+ the registered search paths (`spAddSearchPath`),
+ and instead using the given `path` as-is.
*/
SLANG_API void spAddTranslationUnitSourceFile(
SlangCompileRequest* request,
int translationUnitIndex,
char const* path);
- /** Add a source string to the given translation unit
+ /** Add a source string to the given translation unit.
+
+ @param request The comile request that owns the translation unit.
+ @param translationUnitIndex The index of the translation unit to add source to.
+ @param path The file-system path that should be assumed for the source code.
+ @param source A nul-terminated UTF-8 encoded string of source code.
+
+ The implementation will make a copy of the source code data.
+ An application may free the buffer immediately after this call returns.
- The `path` will be used in any diagnostic output.
+ The `path` will be used in any diagnostic output, as well
+ as to determine the base path when resolving relative
+ `#include`s.
*/
SLANG_API void spAddTranslationUnitSourceString(
SlangCompileRequest* request,
@@ -372,6 +675,49 @@ extern "C"
char const* path,
char const* source);
+
+ /** Add a source string to the given translation unit.
+
+ @param request The comile request that owns the translation unit.
+ @param translationUnitIndex The index of the translation unit to add source to.
+ @param path The file-system path that should be assumed for the source code.
+ @param sourceBegin A pointer to a buffer of UTF-8 encoded source code.
+ @param sourceEnd A pointer to to the end of the buffer specified in `sourceBegin`
+
+ The implementation will make a copy of the source code data.
+ An application may free the buffer immediately after this call returns.
+
+ The `path` will be used in any diagnostic output, as well
+ as to determine the base path when resolving relative
+ `#include`s.
+ */
+ SLANG_API void spAddTranslationUnitSourceStringSpan(
+ SlangCompileRequest* request,
+ int translationUnitIndex,
+ char const* path,
+ char const* sourceBegin,
+ char const* sourceEnd);
+
+ /** Add a blob of source code to the given translation unit.
+
+ @param request The comile request that owns the translation unit.
+ @param translationUnitIndex The index of the translation unit to add source to.
+ @param path The file-system path that should be assumed for the source code.
+ @param sourceBlob A blob containing UTF-8 encoded source code.
+ @param sourceEnd A pointer to to the end of the buffer specified in `sourceBegin`
+
+ The compile request will retain a reference to the blob.
+
+ The `path` will be used in any diagnostic output, as well
+ as to determine the base path when resolving relative
+ `#include`s.
+ */
+ SLANG_API void spAddTranslationUnitSourceBlob(
+ SlangCompileRequest* request,
+ int translationUnitIndex,
+ char const* path,
+ ISlangBlob* sourceBlob);
+
/** Look up a compilation profile by name.
For example, one could look up the string `"ps_5_0"` to find the corresponding target ID.
@@ -409,10 +755,28 @@ extern "C"
/** Get any diagnostic messages reported by the compiler.
+
+ @returns A nul-terminated UTF-8 encoded string of diagnostic messages.
+
+ The returned pointer is only guaranteed to be valid
+ until `reqeust` is destroyed. Applications that wish to
+ hold on to the diagnostic output for longer should use
+ `spGetDiagnosticOutputBlob`.
*/
SLANG_API char const* spGetDiagnosticOutput(
SlangCompileRequest* request);
+ /** Get diagnostic messages reported by the compiler.
+
+ @param request The compile request to get output from.
+ @param outBlob A pointer to receive a blob holding a nul-terminated UTF-8 encoded string of diagnostic messages.
+ @returns A `SlangResult` indicating success or failure.
+ */
+ SLANG_API SlangResult spGetDiagnosticOutputBlob(
+ SlangCompileRequest* request,
+ ISlangBlob** outBlob);
+
+
/** Get the number of files that this compilation depended on.
This includes both the explicit source files, as well as any
@@ -436,14 +800,6 @@ extern "C"
spGetTranslationUnitCount(
SlangCompileRequest* request);
- /** Get the output code associated with a specific translation unit.
-
- The lifetime of the output pointer is the same as `request`.
- */
- SLANG_API char const* spGetTranslationUnitSource(
- SlangCompileRequest* request,
- int translationUnitIndex);
-
/** Get the output source code associated with a specific entry point.
The lifetime of the output pointer is the same as `request`.
@@ -461,6 +817,21 @@ extern "C"
int entryPointIndex,
size_t* outSize);
+ /** Get the output code associated with a specific entry point.
+
+ @param entryPointIndex The index of the entry point to get code for.
+ @param targetIndex The index of the target to get code for (default: zero).
+ @param outBlob A pointer that will receive the blob of code
+ @returns A `SlangResult` to indicate success or failure.
+
+ The lifetime of the output pointer is the same as `request`.
+ */
+ SLANG_API SlangResult spGetEntryPointCodeBlob(
+ SlangCompileRequest* request,
+ int entryPointIndex,
+ int targetIndex,
+ ISlangBlob** outBlob);
+
/** Get the output bytecode associated with an entire compile request.
The lifetime of the output pointer is the same as `request`.
@@ -1278,4 +1649,28 @@ namespace slang
#endif
+/* DEPRECATED DEFINITIONS
+
+Everything below this point represents deprecated APIs/definition that are only
+being kept around for source/binary compatibility with old client code. New
+code should not use any of these declarations, and the Slang API will drop these
+declarations over time.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define SLANG_ERROR_INSUFFICIENT_BUFFER -1
+#define SLANG_ERROR_INVALID_PARAMETER -2
+
+SLANG_API char const* spGetTranslationUnitSource(
+ SlangCompileRequest* request,
+ int translationUnitIndex);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/source/core/slang-com-ptr.h b/source/core/slang-com-ptr.h
index 9f6651306..765edbee5 100644
--- a/source/core/slang-com-ptr.h
+++ b/source/core/slang-com-ptr.h
@@ -8,17 +8,17 @@
namespace Slang {
-/*! \brief ComPtr is a simple smart pointer that manages types which implement COM based interfaces.
+/*! \brief ComPtr is a simple smart pointer that manages types which implement COM based interfaces.
\details A class that implements a COM, must derive from the IUnknown interface or a type that matches
it's layout exactly (such as IForwardUnknown). Trying to use this template with a class that doesn't follow
-these rules, will lead to undefined behavior.
-This is a 'strong' pointer type, and will AddRef when a non null pointer is set and Release when the pointer
-leaves scope.
+these rules, will lead to undefined behavior.
+This is a 'strong' pointer type, and will AddRef when a non null pointer is set and Release when the pointer
+leaves scope.
Using 'detach' allows a pointer to be removed from the management of the ComPtr.
To set the smart pointer to null, there is the method setNull, or alternatively just assign SLANG_NULL/nullptr.
One edge case using the template is that sometimes you want access as a pointer to a pointer. Sometimes this
-is to write into the smart pointer, other times to pass as an array. To handle these different behaviors
+is to write into the smart pointer, other times to pass as an array. To handle these different behaviors
there are the methods readRef and writeRef, which are used instead of the & (ref) operator. For example
\code
@@ -31,7 +31,7 @@ ComPtr<ID3D12Resource> resources[3];
doSomething(resources[0].readRef(), SLANG_COUNT_OF(resource));
\endcode
-A more common scenario writing to the pointer
+A more common scenario writing to the pointer
\code
IUnknown* unk = ...;
@@ -40,35 +40,29 @@ ComPtr<ID3D12Resource> resource;
Result res = unk->QueryInterface(resource.writeRef());
\endcode
*/
-
-struct Guid
-{
- uint32_t data1; ///< Low field of the timestamp
- uint16_t data2; ///< Middle field of the timestamp
- uint16_t data3; ///< High field of the timestamp with multiplexed version number
- uint8_t data4[8]; ///< 0, 1 = clock_seq_hi_and_reserved, clock_seq_low, followed by 'spatially unique node' (48 bits)
-};
+
+typedef SlangUUID Guid;
SLANG_FORCE_INLINE bool operator==(const Guid& aIn, const Guid& bIn)
{
- // Use the largest type the honors the alignment of Guid
- typedef uint32_t CmpType;
- struct GuidCompare
+ // Use the largest type the honors the alignment of Guid
+ typedef uint32_t CmpType;
+ union GuidCompare
{
Guid guid;
- CmpType data[sizeof(Guid) / sizeof(CmpType)];
+ CmpType data[sizeof(Guid) / sizeof(CmpType)];
};
- // Type pun - so compiler can 'see' the pun and not break aliasing rules
+ // Type pun - so compiler can 'see' the pun and not break aliasing rules
const CmpType* a = reinterpret_cast<const GuidCompare&>(aIn).data;
const CmpType* b = reinterpret_cast<const GuidCompare&>(bIn).data;
- // Make the guid comparison a single branch, by not using short circuit
- return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3])) == 0;
-}
+ // Make the guid comparison a single branch, by not using short circuit
+ return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3])) == 0;
+}
SLANG_FORCE_INLINE bool operator!=(const Guid& a, const Guid& b)
{
return !(a == b);
-}
+}
// Allows for defining of a GUID that works in C++ and C which defines in a format similar to microsofts INTERFACE style
// MIDL_INTERFACE("00000000-0000-0000-C000-00 00 00 00 00 46")
@@ -84,16 +78,9 @@ SLANG_FORCE_INLINE bool operator!=(const Guid& a, const Guid& b)
// Compatible with Microsoft IUnknown
static const Guid IID_IComUnknown = SLANG_MAKE_GUID(00000000, 0000, 0000, C000, 000000000046);
-/// ! Must be kept in sync with IUnknown
-class IComUnknown
-{
-public:
- virtual SLANG_NO_THROW Result SLANG_MCALL queryInterface(const Guid& iid, void* objOut) = 0;
- virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() = 0;
- virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() = 0;
-};
+typedef ISlangUnknown IComUnknown;
-// Enum to force initializing as an attach (without adding a reference)
+// Enum to force initializing as an attach (without adding a reference)
enum InitAttach
{
INIT_ATTACH
@@ -139,7 +126,7 @@ public:
/// For making method invocations through the smart pointer work through the dumb pointer
SLANG_FORCE_INLINE T* operator->() const { return m_ptr; }
- /// Assign
+ /// Assign
SLANG_FORCE_INLINE const ThisType &operator=(const ThisType& rhs);
/// Assign from dumb ptr
SLANG_FORCE_INLINE T* operator=(T* in);
@@ -202,7 +189,7 @@ T* ComPtr<T>::operator=(T* ptr)
{
if (ptr) ((Ptr)ptr)->addRef();
if (m_ptr) ((Ptr)m_ptr)->release();
- m_ptr = ptr;
+ m_ptr = ptr;
return m_ptr;
}
//----------------------------------------------------------------------------
@@ -214,6 +201,6 @@ void ComPtr<T>::swap(ThisType& rhs)
rhs.m_ptr = tmp;
}
-} // namespace Slang
+} // namespace Slang
#endif // SLANG_COM_PTR_H
diff --git a/source/core/slang-defines.h b/source/core/slang-defines.h
index 98993d662..580dd801c 100644
--- a/source/core/slang-defines.h
+++ b/source/core/slang-defines.h
@@ -2,140 +2,15 @@
#define SLANG_DEFINES_H
/*
-The following preprocessor identifiers specify compiler, OS, and architecture.
-All definitions have a value of 1 or 0, use '#if' instead of '#ifdef'.
+Some of our `#define`s are needed in the public API header as well, so
+we will go ahead and include that here so that we can share the definitions.
*/
-
-#ifndef SLANG_COMPILER
-# define SLANG_COMPILER
+#include "../../slang.h"
/*
-Compiler defines, see http://sourceforge.net/p/predef/wiki/Compilers/
-NOTE that SLANG_VC holds the compiler version - not just 1 or 0
-*/
-# if defined(_MSC_VER)
-# if _MSC_VER >= 1900
-# define SLANG_VC 14
-# elif _MSC_VER >= 1800
-# define SLANG_VC 12
-# elif _MSC_VER >= 1700
-# define SLANG_VC 11
-# elif _MSC_VER >= 1600
-# define SLANG_VC 10
-# elif _MSC_VER >= 1500
-# define SLANG_VC 9
-# else
-# error "Unknown VC version"
-# endif
-# elif defined(__clang__)
-# define SLANG_CLANG 1
-# elif defined(__SNC__)
-# define SLANG_SNC 1
-# elif defined(__ghs__)
-# define SLANG_GHS 1
-# elif defined(__GNUC__) // note: __clang__, __SNC__, or __ghs__ imply __GNUC__
-# define SLANG_GCC 1
-# else
-# error "Unknown compiler"
-# endif
-
-// Zero unset
-# ifndef SLANG_VC
-# define SLANG_VC 0
-# endif
-# ifndef SLANG_CLANG
-# define SLANG_CLANG 0
-# endif
-# ifndef SLANG_SNC
-# define SLANG_SNC 0
-# endif
-# ifndef SLANG_GHS
-# define SLANG_GHS 0
-# endif
-# ifndef SLANG_GCC
-# define SLANG_GCC 0
-# endif
-
-#endif // SLANG_COMPILER
-
-#ifndef SLANG_PLATFORM
-# define SLANG_PLATFORM
-
-/**
-Operating system defines, see http://sourceforge.net/p/predef/wiki/OperatingSystems/
+The following preprocessor identifiers specify compiler, OS, and architecture.
+All definitions have a value of 1 or 0, use '#if' instead of '#ifdef'.
*/
-# if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_PARTITION_APP
-# define SLANG_WINRT 1 // Windows Runtime, either on Windows RT or Windows 8
-# elif defined(XBOXONE)
-# define SLANG_XBOXONE 1
-# elif defined(_WIN64) // note: XBOXONE implies _WIN64
-# define SLANG_WIN64 1
-# elif defined(_M_PPC)
-# define SLANG_X360 1
-# elif defined(_WIN32) // note: _M_PPC implies _WIN32
-# define SLANG_WIN32 1
-# elif defined(__ANDROID__)
-# define SLANG_ANDROID 1
-# elif defined(__linux__) || defined(__CYGWIN__) // note: __ANDROID__ implies __linux__
-# define SLANG_LINUX 1
-# elif defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
-# define SLANG_IOS 1
-# elif defined(__APPLE__)
-# define SLANG_OSX 1
-# elif defined(__CELLOS_LV2__)
-# define SLANG_PS3 1
-# elif defined(__ORBIS__)
-# define SLANG_PS4 1
-# elif defined(__SNC__) && defined(__arm__)
-# define SLANG_PSP2 1
-# elif defined(__ghs__)
-# define SLANG_WIIU 1
-# else
-# error "Unknown operating system"
-# endif
-
-// zero unset
-# ifndef SLANG_WINRT
-# define SLANG_WINRT 0
-# endif
-# ifndef SLANG_XBOXONE
-# define SLANG_XBOXONE 0
-# endif
-# ifndef SLANG_WIN64
-# define SLANG_WIN64 0
-# endif
-# ifndef SLANG_X360
-# define SLANG_X360 0
-# endif
-# ifndef SLANG_WIN32
-# define SLANG_WIN32 0
-# endif
-# ifndef SLANG_ANDROID
-# define SLANG_ANDROID 0
-# endif
-# ifndef SLANG_LINUX
-# define SLANG_LINUX 0
-# endif
-# ifndef SLANG_IOS
-# define SLANG_IOS 0
-# endif
-# ifndef SLANG_OSX
-# define SLANG_OSX 0
-# endif
-# ifndef SLANG_PS3
-# define SLANG_PS3 0
-# endif
-# ifndef SLANG_PS4
-# define SLANG_PS4 0
-# endif
-# ifndef SLANG_PSP2
-# define SLANG_PSP2 0
-# endif
-# ifndef SLANG_WIIU
-# define SLANG_WIIU 0
-# endif
-
-#endif // SLANG_PLATFORM
#ifndef SLANG_PROCESSOR
# define SLANG_PROCESSOR
@@ -217,15 +92,6 @@ define anything not defined through the command line to 0
/**
family shortcuts
*/
-// compiler
-#define SLANG_GCC_FAMILY (SLANG_CLANG || SLANG_SNC || SLANG_GHS || SLANG_GCC)
-
-// os
-#define SLANG_WINDOWS_FAMILY (SLANG_WINRT || SLANG_WIN32 || SLANG_WIN64)
-#define SLANG_MICROSOFT_FAMILY (SLANG_XBOXONE || SLANG_X360 || SLANG_WINDOWS_FAMILY)
-#define SLANG_LINUX_FAMILY (SLANG_LINUX || SLANG_ANDROID)
-#define SLANG_APPLE_FAMILY (SLANG_IOS || SLANG_OSX) // equivalent to #if __APPLE__
-#define SLANG_UNIX_FAMILY (SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY) // shortcut for unix/posix platforms
// architecture
#define SLANG_INTEL_FAMILY (SLANG_X64 || SLANG_X86) // Intel x86 family
#define SLANG_ARM_FAMILY (SLANG_ARM || SLANG_A64)
@@ -233,9 +99,9 @@ family shortcuts
#define SLANG_P64_FAMILY (SLANG_X64 || SLANG_A64) // shortcut for 64-bit architectures
-// Use for getting the amount of members of a standard C array.
+// Use for getting the amount of members of a standard C array.
#define SLANG_COUNT_OF(x) (sizeof(x)/sizeof(x[0]))
-/// SLANG_INLINE exists to have a way to inline consistent with SLANG_ALWAYS_INLINE
+/// SLANG_INLINE exists to have a way to inline consistent with SLANG_ALWAYS_INLINE
#define SLANG_INLINE inline
// Other defines
@@ -253,7 +119,7 @@ family shortcuts
General defines
*/
-// GCC Specific
+// GCC Specific
#if SLANG_GCC_FAMILY
# define SLANG_NO_INLINE __attribute__((noinline))
@@ -264,7 +130,7 @@ General defines
# if !SLANG_SNC && !SLANG_GHS
# define SLANG_OFFSET_OF(X, Y) __builtin_offsetof(X, Y)
-# endif
+# endif
//# if !SLANG_LINUX // Workaround; Fedora Core 3 do not agree with force inline
# define SLANG_FORCE_INLINE inline __attribute__((always_inline))
@@ -314,7 +180,6 @@ General defines
# define SLANG_INT64(x) (x##i64)
# define SLANG_UINT64(x) (x##ui64)
-# define SLANG_STDCALL __stdcall
# define SLANG_CALL_CONV __cdecl
#endif // SLANG_MICROSOFT_FAMILY
@@ -340,7 +205,7 @@ General defines
#ifndef SLANG_FORCE_INLINE
# define SLANG_FORCE_INLINE inline
#endif
-#ifndef SLANG_NO_INLINE
+#ifndef SLANG_NO_INLINE
# define SLANG_NO_INLINE
#endif
#ifndef SLANG_NO_ALIAS
@@ -364,15 +229,12 @@ General defines
# define SLANG_FUNCTION_SIG SLANG_FUNCTION_NAME
#endif
-#ifndef SLANG_STDCALL
-# define SLANG_STDCALL
-#endif
#ifndef SLANG_CALL_CONV
# define SLANG_CALL_CONV
#endif
//! casting the null ptr takes a special-case code path, which we don't want
-#define SLANG_OFFSETOF_BASE 0x100
+#define SLANG_OFFSETOF_BASE 0x100
#define SLANG_OFFSET_OF_RT(Class, Member) \
(reinterpret_cast<size_t>(&reinterpret_cast<Class*>(SLANG_OFFSETOF_BASE)->Member) - size_t(SLANG_OFFSETOF_BASE))
@@ -404,18 +266,13 @@ General defines
# define SLANG_HAS_ENUM_CLASS 1
# endif
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407
-# define SLANG_OVERRIDE override
+# define SLANG_OVERRIDE override
# endif
# endif
# endif // SLANG_GCC_FAMILY
// Visual Studio
-// Macro for declaring if a method is no throw. Should be set before the return parameter.
-#if SLANG_WINDOWS_FAMILY && !defined(SLANG_DISABLE_EXCEPTIONS)
-# define SLANG_NO_THROW __declspec(nothrow)
-#endif
-
# if SLANG_VC
// C4481: nonstandard extension used: override specifier 'override'
# if _MSC_VER < 1700
@@ -434,7 +291,7 @@ General defines
# if SLANG_CLANG
# endif // SLANG_CLANG
-// Set non set
+// Set non set
#ifndef SLANG_NO_THROW
# define SLANG_NO_THROW
@@ -449,8 +306,6 @@ General defines
# define SLANG_HAS_MOVE_SEMANTICS 0
#endif
-#define SLANG_MCALL SLANG_STDCALL
-
#include <new> // For placement new
#endif // __cplusplus
diff --git a/source/core/slang-string.h b/source/core/slang-string.h
index 894776ca6..a67597360 100644
--- a/source/core/slang-string.h
+++ b/source/core/slang-string.h
@@ -172,7 +172,7 @@ namespace Slang
{
return i;
}
- }
+ }
return -1;
}
@@ -412,6 +412,11 @@ namespace Slang
append(slice);
}
+ String(UnownedStringSlice const& slice)
+ {
+ append(slice);
+ }
+
~String()
{
buffer = 0;
@@ -741,6 +746,11 @@ namespace Slang
Append(str);
return *this;
}
+ StringBuilder & operator << (UnownedStringSlice const& str)
+ {
+ append(str);
+ return *this;
+ }
StringBuilder & operator << (const _EndLine)
{
Append('\n');
diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp
index 66df01db0..9c1823f91 100644
--- a/source/slang/compiler.cpp
+++ b/source/slang/compiler.cpp
@@ -52,7 +52,7 @@
// Includes to allow us to control console
// output when writing assembly dumps.
-#include <fcntl.h>
+#include <fcntl.h>
#ifdef _WIN32
#include <io.h>
#else
@@ -97,6 +97,28 @@ namespace Slang
}
}
+ ComPtr<ISlangBlob> CompileResult::getBlob()
+ {
+ if(!blob)
+ {
+ switch(format)
+ {
+ case ResultFormat::None:
+ default:
+ break;
+
+ case ResultFormat::Text:
+ blob = createStringBlob(outputString);
+ break;
+
+ case ResultFormat::Binary:
+ blob = createRawBlob(outputBinary.Buffer(), outputBinary.Count());
+ break;
+ }
+ }
+ return blob;
+ }
+
// EntryPointRequest
TranslationUnitRequest* EntryPointRequest::getTranslationUnit()
@@ -149,6 +171,7 @@ namespace Slang
}
}
codeBuilder << "\"\n";
+
codeBuilder << sourceFile->content << "\n";
}
@@ -886,7 +909,7 @@ String dissassembleDXILUsingDXC(
void emitEntryPoints(
TargetRequest* /*targetReq*/)
{
-
+
}
void generateOutputForTarget(
diff --git a/source/slang/compiler.h b/source/slang/compiler.h
index 3a5f888fe..acbad9a7e 100644
--- a/source/slang/compiler.h
+++ b/source/slang/compiler.h
@@ -2,6 +2,7 @@
#define RASTER_SHADER_COMPILER_H
#include "../core/basic.h"
+#include "../core/slang-com-ptr.h"
#include "diagnostics.h"
#include "name.h"
@@ -99,9 +100,13 @@ namespace Slang
void append(CompileResult const& result);
+ ComPtr<ISlangBlob> getBlob();
+
ResultFormat format = ResultFormat::None;
String outputString;
List<uint8_t> outputBinary;
+
+ ComPtr<ISlangBlob> blob;
};
// Describes an entry point that we've been requested to compile
@@ -281,6 +286,14 @@ namespace Slang
class Session;
+ /// Create a blob that will retain a string for its lifetime.
+ ///
+ ComPtr<ISlangBlob> createStringBlob(String const& string);
+
+ /// Create a blob that will retain (a copy of) raw data.
+ ///
+ ComPtr<ISlangBlob> createRawBlob(void const* data, size_t size);
+
class CompileRequest : public RefObject
{
public:
@@ -348,6 +361,9 @@ namespace Slang
DiagnosticSink mSink;
String mDiagnosticOutput;
+ /// A blob holding the diagnostic output
+ ComPtr<ISlangBlob> diagnosticOutputBlob;
+
// Files that compilation depended on
List<String> mDependencyFilePaths;
@@ -368,6 +384,21 @@ namespace Slang
// The resulting specialized IR module for each entry point request
List<RefPtr<IRModule>> compiledModules;
+ /// File system implementation to use when loading files from disk.
+ ///
+ /// If this member is `null`, a default implementation that tries
+ /// to use the native OS filesystem will be used instead.
+ ///
+ ComPtr<ISlangFileSystem> fileSystem;
+
+ /// Load a file into memory using the configured file system.
+ ///
+ /// @param path The path to attempt to load from
+ /// @param outBlob A destination pointer to receive the loaded blob
+ /// @returns A `SlangResult` to indicate success or failure.
+ ///
+ SlangResult loadFile(String const& path, ISlangBlob** outBlob);
+
CompileRequest(Session* session);
~CompileRequest();
@@ -394,6 +425,11 @@ namespace Slang
int translationUnitIndex,
SourceFile* sourceFile);
+ void addTranslationUnitSourceBlob(
+ int translationUnitIndex,
+ String const& path,
+ ISlangBlob* sourceBlob);
+
void addTranslationUnitSourceString(
int translationUnitIndex,
String const& path,
@@ -415,7 +451,7 @@ namespace Slang
RefPtr<ModuleDecl> loadModule(
Name* name,
String const& path,
- String const& source,
+ ISlangBlob* sourceBlob,
SourceLoc const& loc);
void loadParsedModule(
diff --git a/source/slang/preprocessor.cpp b/source/slang/preprocessor.cpp
index 301264632..3ec44fc28 100644
--- a/source/slang/preprocessor.cpp
+++ b/source/slang/preprocessor.cpp
@@ -1581,7 +1581,7 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context)
auto expandedDirectiveLoc = context->preprocessor->translationUnit->compileRequest->getSourceManager()->expandSourceLoc(directiveLoc);
String pathIncludedFrom = expandedDirectiveLoc.getSpellingPath();
String foundPath;
- String foundSource;
+ ComPtr<ISlangBlob> foundSourceBlob;
IncludeHandler* includeHandler = context->preprocessor->includeHandler;
if (!includeHandler)
@@ -1590,7 +1590,7 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context)
GetSink(context)->diagnose(pathToken.loc, Diagnostics::noIncludeHandlerSpecified);
return;
}
- auto includeResult = includeHandler->TryToFindIncludeFile(path, pathIncludedFrom, &foundPath, &foundSource);
+ auto includeResult = includeHandler->TryToFindIncludeFile(path, pathIncludedFrom, &foundPath, foundSourceBlob.writeRef());
switch (includeResult)
{
@@ -1611,7 +1611,7 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context)
// Push the new file onto our stack of input streams
// TODO(tfoley): check if we have made our include stack too deep
- SourceFile* sourceFile = context->preprocessor->getCompileRequest()->getSourceManager()->allocateSourceFile(foundPath, foundSource);
+ SourceFile* sourceFile = context->preprocessor->getCompileRequest()->getSourceManager()->allocateSourceFile(foundPath, foundSourceBlob);
PreprocessorInputStream* inputStream = CreateInputStreamForSource(context->preprocessor, sourceFile);
inputStream->parent = context->preprocessor->inputStream;
diff --git a/source/slang/preprocessor.h b/source/slang/preprocessor.h
index 64591ef03..0e30038bf 100644
--- a/source/slang/preprocessor.h
+++ b/source/slang/preprocessor.h
@@ -26,7 +26,7 @@ struct IncludeHandler
String const& pathToInclude,
String const& pathIncludedFrom,
String* outFoundPath,
- String* outFoundSource) = 0;
+ ISlangBlob** outFoundSourceBlob) = 0;
};
// Take a string of source code and preprocess it into a list of tokens.
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 2d3e9ee77..24dff88a8 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -81,32 +81,29 @@ struct IncludeHandlerImpl : IncludeHandler
String const& pathToInclude,
String const& pathIncludedFrom,
String* outFoundPath,
- String* outFoundSource) override
+ ISlangBlob** outFoundSourceBlob) override
{
String path = Path::Combine(Path::GetDirectoryName(pathIncludedFrom), pathToInclude);
- if (File::Exists(path))
+
+ if(SLANG_SUCCEEDED(request->loadFile(path, outFoundSourceBlob)))
{
*outFoundPath = path;
- *outFoundSource = File::ReadAllText(path);
-
request->mDependencyFilePaths.Add(path);
-
return IncludeResult::Found;
}
for (auto & dir : request->searchDirectories)
{
path = Path::Combine(dir.path, pathToInclude);
- if (File::Exists(path))
+
+ if(SLANG_SUCCEEDED(request->loadFile(path, outFoundSourceBlob)))
{
*outFoundPath = path;
- *outFoundSource = File::ReadAllText(path);
-
request->mDependencyFilePaths.Add(path);
-
return IncludeResult::Found;
}
}
+
return IncludeResult::NotFound;
}
};
@@ -205,11 +202,168 @@ CompileRequest::~CompileRequest()
types = decltype(types)();
}
+// Allocate static const storage for the various interface IDs that the Slang API needs to expose
+static const Guid IID_ISlangUnknown = SLANG_UUID_ISlangUnknown;
+static const Guid IID_ISlangBlob = SLANG_UUID_ISlangBlob;
+
+/** Base class for simple blobs.
+*/
+class BlobBase : public ISlangBlob
+{
+public:
+ BlobBase() {}
+ virtual ~BlobBase() {}
+
+ uint32_t referenceCount = 0;
+
+ // ISlangUnknown
+
+ SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE
+ {
+ if(uuid == IID_IComUnknown)
+ {
+ *(ISlangUnknown**)outObject = this;
+ addRef();
+ return SLANG_OK;
+ }
+ else if(uuid == IID_ISlangBlob)
+ {
+ *(ISlangBlob**)outObject = this;
+ addRef();
+ return SLANG_OK;
+ }
+
+ return SLANG_FAIL;
+ }
+
+ SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE
+ {
+ referenceCount++;
+ return 0;
+ }
+
+ SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE
+ {
+ if(--referenceCount == 0)
+ {
+ delete this;
+ }
+ return 0;
+ }
+
+};
+
+/** A blob that uses a `String` for its storage.
+*/
+class StringBlob : public BlobBase
+{
+public:
+ String string;
+
+ explicit StringBlob(String const& string)
+ : string(string)
+ {}
+
+ // ISlangBlob
+
+ SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE
+ {
+ return string.Buffer();
+ }
+
+ SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE
+ {
+ return string.Length();
+ }
+};
+
+ComPtr<ISlangBlob> createStringBlob(String const& string)
+{
+ return ComPtr<ISlangBlob>(new StringBlob(string));
+}
+
+/** A blob that manages some raw data that it owns.
+*/
+class RawBlob : public BlobBase
+{
+public:
+ void* data;
+ size_t size;
+
+ ~RawBlob()
+ {
+ free(data);
+ }
+
+ // ISlangBlob
+
+ SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE
+ {
+ return data;
+ }
+
+ SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE
+ {
+ return size;
+ }
+};
+
+
+ComPtr<ISlangBlob> createRawBlob(void const* inData, size_t size)
+{
+ void* dataCopy = malloc(size);
+ memcpy(dataCopy, inData, size);
+
+ RawBlob* rawBlob = new RawBlob();
+ rawBlob->data = dataCopy;
+ rawBlob->size = size;
+
+ return ComPtr<ISlangBlob>(rawBlob);
+}
+
+
+SlangResult CompileRequest::loadFile(String const& path, ISlangBlob** outBlob)
+{
+ // If there is a used-defined filesystem, then use that to load files.
+ //
+ if(fileSystem)
+ {
+ return fileSystem->loadFile(path.Buffer(), outBlob);
+ }
+
+ // Otherwise, fall back to a default implementation that uses the `core`
+ // libraries facilities for talking to the OS filesystem.
+ //
+ // TODO: we might want to conditionally compile these in, so that
+ // a user could create a build of Slang that doesn't include any OS
+ // filesystem calls.
+ //
+
+ if (!File::Exists(path))
+ {
+ return SLANG_FAIL;
+ }
+
+ try
+ {
+ String sourceString = File::ReadAllText(path);
+ ComPtr<ISlangBlob> sourceBlob = createStringBlob(sourceString);
+ *outBlob = sourceBlob.detach();
+
+ return SLANG_OK;
+ }
+ catch(...)
+ {
+ }
+ return SLANG_FAIL;
+
+}
+
RefPtr<Expr> CompileRequest::parseTypeString(TranslationUnitRequest * translationUnit, String typeStr, RefPtr<Scope> scope)
{
Slang::SourceFile srcFile;
- srcFile.content = typeStr;
+ srcFile.content = UnownedStringSlice(typeStr.begin(), typeStr.end());
DiagnosticSink sink;
sink.sourceManager = sourceManager;
auto tokens = preprocessSource(
@@ -484,6 +638,16 @@ void CompileRequest::addTranslationUnitSourceFile(
translationUnits[translationUnitIndex]->sourceFiles.Add(sourceFile);
}
+void CompileRequest::addTranslationUnitSourceBlob(
+ int translationUnitIndex,
+ String const& path,
+ ISlangBlob* sourceBlob)
+{
+ RefPtr<SourceFile> sourceFile = getSourceManager()->allocateSourceFile(path, sourceBlob);
+
+ addTranslationUnitSourceFile(translationUnitIndex, sourceFile);
+}
+
void CompileRequest::addTranslationUnitSourceString(
int translationUnitIndex,
String const& path,
@@ -498,12 +662,17 @@ void CompileRequest::addTranslationUnitSourceFile(
int translationUnitIndex,
String const& path)
{
- String source;
- try
- {
- source = File::ReadAllText(path);
- }
- catch (...)
+ // TODO: We need to consider whether a relative `path` should cause
+ // us to look things up using the registered search paths.
+ //
+ // This behavior wouldn't make sense for command-line invocations
+ // of `slangc`, but at least one API user wondered by the search
+ // paths were not taken into account by this function.
+ //
+
+ ComPtr<ISlangBlob> sourceBlob;
+ SlangResult result = loadFile(path, sourceBlob.writeRef());
+ if(SLANG_FAILED(result))
{
// Emit a diagnostic!
mSink.diagnose(
@@ -513,10 +682,10 @@ void CompileRequest::addTranslationUnitSourceFile(
return;
}
- addTranslationUnitSourceString(
+ addTranslationUnitSourceBlob(
translationUnitIndex,
path,
- source);
+ sourceBlob);
mDependencyFilePaths.Add(path);
}
@@ -590,7 +759,7 @@ void CompileRequest::loadParsedModule(
RefPtr<ModuleDecl> CompileRequest::loadModule(
Name* name,
String const& path,
- String const& source,
+ ISlangBlob* sourceBlob,
SourceLoc const& srcLoc)
{
RefPtr<TranslationUnitRequest> translationUnit = new TranslationUnitRequest();
@@ -603,7 +772,7 @@ RefPtr<ModuleDecl> CompileRequest::loadModule(
// TODO: decide which options, if any, should be inherited.
translationUnit->compileFlags = 0;
- RefPtr<SourceFile> sourceFile = getSourceManager()->allocateSourceFile(path, source);
+ RefPtr<SourceFile> sourceFile = getSourceManager()->allocateSourceFile(path, sourceBlob);
translationUnit->sourceFiles.Add(sourceFile);
@@ -687,8 +856,8 @@ RefPtr<ModuleDecl> CompileRequest::findOrImportModule(
String pathIncludedFrom = expandedLoc.getSpellingPath();
String foundPath;
- String foundSource;
- IncludeResult includeResult = includeHandler.TryToFindIncludeFile(fileName, pathIncludedFrom, &foundPath, &foundSource);
+ ComPtr<ISlangBlob> foundSourceBlob;
+ IncludeResult includeResult = includeHandler.TryToFindIncludeFile(fileName, pathIncludedFrom, &foundPath, foundSourceBlob.writeRef());
switch( includeResult )
{
case IncludeResult::NotFound:
@@ -715,7 +884,7 @@ RefPtr<ModuleDecl> CompileRequest::findOrImportModule(
return loadModule(
name,
foundPath,
- foundSource,
+ foundSourceBlob,
loc);
}
@@ -832,7 +1001,7 @@ Session::~Session()
constExprRate = nullptr;
destroyTypeCheckingCache();
-
+
builtinTypes = decltype(builtinTypes)();
// destroy modules next
loadedModuleCode = decltype(loadedModuleCode)();
@@ -895,6 +1064,16 @@ SLANG_API void spDestroyCompileRequest(
delete req;
}
+SLANG_API void spSetFileSystem(
+ SlangCompileRequest* request,
+ ISlangFileSystem* fileSystem)
+{
+ if(!request) return;
+ auto req = REQ(request);
+ req->fileSystem = fileSystem;
+}
+
+
SLANG_API void spSetCompileFlags(
SlangCompileRequest* request,
SlangCompileFlags flags)
@@ -1021,6 +1200,25 @@ SLANG_API char const* spGetDiagnosticOutput(
return req->mDiagnosticOutput.begin();
}
+SLANG_API SlangResult spGetDiagnosticOutputBlob(
+ SlangCompileRequest* request,
+ ISlangBlob** outBlob)
+{
+ if(!request) return SLANG_ERROR_INVALID_PARAMETER;
+ if(!outBlob) return SLANG_ERROR_INVALID_PARAMETER;
+
+ auto req = REQ(request);
+
+ if(!req->diagnosticOutputBlob)
+ {
+ req->diagnosticOutputBlob = Slang::createStringBlob(req->mDiagnosticOutput);
+ }
+
+ Slang::ComPtr<ISlangBlob> resultBlob = req->diagnosticOutputBlob;
+ *outBlob = resultBlob.detach();
+ return SLANG_OK;
+}
+
// New-fangled compilation API
SLANG_API int spAddTranslationUnit(
@@ -1063,16 +1261,31 @@ SLANG_API void spAddTranslationUnitSourceFile(
path);
}
-// Add a source string to the given translation unit
SLANG_API void spAddTranslationUnitSourceString(
SlangCompileRequest* request,
int translationUnitIndex,
char const* path,
char const* source)
{
+ if(!source) return;
+ spAddTranslationUnitSourceStringSpan(
+ request,
+ translationUnitIndex,
+ path,
+ source,
+ source + strlen(source));
+}
+
+SLANG_API void spAddTranslationUnitSourceStringSpan(
+ SlangCompileRequest* request,
+ int translationUnitIndex,
+ char const* path,
+ char const* sourceBegin,
+ char const* sourceEnd)
+{
if(!request) return;
auto req = REQ(request);
- if(!source) return;
+ if(!sourceBegin) return;
if(translationUnitIndex < 0) return;
if(Slang::UInt(translationUnitIndex) >= req->translationUnits.Count()) return;
@@ -1081,10 +1294,34 @@ SLANG_API void spAddTranslationUnitSourceString(
req->addTranslationUnitSourceString(
translationUnitIndex,
path,
- source);
+ Slang::UnownedStringSlice(sourceBegin, sourceEnd));
+}
+SLANG_API void spAddTranslationUnitSourceBlob(
+ SlangCompileRequest* request,
+ int translationUnitIndex,
+ char const* path,
+ ISlangBlob* sourceBlob)
+{
+ if(!request) return;
+ auto req = REQ(request);
+ if(!sourceBlob) return;
+ if(translationUnitIndex < 0) return;
+ if(Slang::UInt(translationUnitIndex) >= req->translationUnits.Count()) return;
+
+ if(!path) path = "";
+
+ req->addTranslationUnitSourceBlob(
+ translationUnitIndex,
+ path,
+ sourceBlob);
}
+
+
+
+
+
SLANG_API SlangProfileID spFindProfile(
SlangSession*,
char const* name)
@@ -1267,6 +1504,35 @@ SLANG_API void const* spGetEntryPointCode(
return data;
}
+SLANG_API SlangResult spGetEntryPointCodeBlob(
+ SlangCompileRequest* request,
+ int entryPointIndex,
+ int targetIndex,
+ ISlangBlob** outBlob)
+{
+ if(!request) return SLANG_ERROR_INVALID_PARAMETER;
+ if(!outBlob) return SLANG_ERROR_INVALID_PARAMETER;
+
+ auto req = REQ(request);
+
+ int targetCount = (int) req->targets.Count();
+ if((targetIndex < 0) || (targetIndex >= targetCount))
+ {
+ return SLANG_ERROR_INVALID_PARAMETER;
+ }
+ auto targetReq = req->targets[targetIndex];
+
+ int entryPointCount = (int) req->entryPoints.Count();
+ if((entryPointIndex < 0) || (entryPointIndex >= entryPointCount))
+ {
+ return SLANG_ERROR_INVALID_PARAMETER;
+ }
+ Slang::CompileResult& result = targetReq->entryPointResults[entryPointIndex];
+
+ *outBlob = result.getBlob().detach();
+ return SLANG_OK;
+}
+
SLANG_API char const* spGetEntryPointSource(
SlangCompileRequest* request,
int entryPointIndex)
diff --git a/source/slang/source-loc.cpp b/source/slang/source-loc.cpp
index 80556ac37..3042c3bd4 100644
--- a/source/slang/source-loc.cpp
+++ b/source/slang/source-loc.cpp
@@ -1,6 +1,8 @@
// source-loc.cpp
#include "source-loc.h"
+#include "compiler.h"
+
namespace Slang {
String ExpandedSourceLoc::getPath() const
@@ -70,15 +72,18 @@ SourceRange SourceManager::allocateSourceRange(UInt size)
SourceFile* SourceManager::allocateSourceFile(
String const& path,
- String const& content)
+ ISlangBlob* contentBlob)
{
- UInt size = content.Length();
+ char const* contentBegin = (char const*) contentBlob->getBufferPointer();
+ UInt contentSize = contentBlob->getBufferSize();
+ char const* contentEnd = contentBegin + contentSize;
- SourceRange sourceRange = allocateSourceRange(size);
+ SourceRange sourceRange = allocateSourceRange(contentSize);
SourceFile* sourceFile = new SourceFile();
sourceFile->path = path;
- sourceFile->content = content;
+ sourceFile->contentBlob = contentBlob;
+ sourceFile->content = UnownedStringSlice(contentBegin, contentEnd);
sourceFile->sourceRange = sourceRange;
Entry entry;
@@ -91,6 +96,14 @@ SourceFile* SourceManager::allocateSourceFile(
return sourceFile;
}
+SourceFile* SourceManager::allocateSourceFile(
+ String const& path,
+ String const& content)
+{
+ ComPtr<ISlangBlob> contentBlob = createStringBlob(content);
+ return allocateSourceFile(path, contentBlob);
+}
+
SourceLoc SourceManager::allocateSourceFileForLineDirective(
SourceLoc const& directiveLoc,
String const& path,
diff --git a/source/slang/source-loc.h b/source/slang/source-loc.h
index 83ad87633..88ec6b62a 100644
--- a/source/slang/source-loc.h
+++ b/source/slang/source-loc.h
@@ -3,6 +3,9 @@
#define SLANG_SOURCE_LOC_H_INCLUDED
#include "../core/basic.h"
+#include "../core/slang-com-ptr.h"
+
+#include "../../slang.h"
namespace Slang {
@@ -73,8 +76,11 @@ public:
// The logical file path to report for locations inside this span.
String path;
- // The actual contents of the file.
- String content;
+ /// A blob that owns the storage for the file contents
+ ComPtr<ISlangBlob> contentBlob;
+
+ /// The actual contents of the file.
+ UnownedStringSlice content;
// The range of source locations that the span covers
SourceRange sourceRange;
@@ -134,6 +140,10 @@ struct SourceManager
SourceFile* allocateSourceFile(
String const& path,
+ ISlangBlob* content);
+
+ SourceFile* allocateSourceFile(
+ String const& path,
String const& content);
SourceLoc allocateSourceFileForLineDirective(