summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2023-03-16 15:19:20 -0400
committerGitHub <noreply@github.com>2023-03-16 15:19:20 -0400
commit4cb899f824ee5e4421f36506e4c77f682b238b09 (patch)
treec348029866666fad59531032ba76f325d67c32ab /source
parent1036d1a9edec83d8840577f388af8599b5e18f5f (diff)
Preliminary SourceMap support (#2701)
* #include an absolute path didn't work - because paths were taken to always be relative. * WIP source map. * Split out handling of RttiTypeFuncs to a map type. * Make RttiTypeFuncsMap hold default impls. * Slightly more sophisticated RttiTypeFuncsMap * Source map decoding. * Fix tabs. * Fix asserts due to negative values. * Use less obscure mechanisms in SourceMap.
Diffstat (limited to 'source')
-rw-r--r--source/compiler-core/slang-json-native.cpp10
-rw-r--r--source/compiler-core/slang-json-native.h13
-rw-r--r--source/compiler-core/slang-json-rpc-connection.cpp23
-rw-r--r--source/compiler-core/slang-json-rpc-connection.h4
-rw-r--r--source/compiler-core/slang-json-rpc.cpp8
-rw-r--r--source/compiler-core/slang-source-map.cpp242
-rw-r--r--source/compiler-core/slang-source-map.h118
-rw-r--r--source/core/slang-rtti-info.cpp33
-rw-r--r--source/core/slang-rtti-info.h68
-rw-r--r--source/core/slang-rtti-util.cpp554
-rw-r--r--source/core/slang-rtti-util.h13
-rw-r--r--source/slang/slang-language-server.cpp17
-rw-r--r--source/slang/slang-language-server.h3
13 files changed, 789 insertions, 317 deletions
diff --git a/source/compiler-core/slang-json-native.cpp b/source/compiler-core/slang-json-native.cpp
index c7a90df4c..8b0ec1194 100644
--- a/source/compiler-core/slang-json-native.cpp
+++ b/source/compiler-core/slang-json-native.cpp
@@ -8,6 +8,13 @@
namespace Slang {
+/* static */RttiTypeFuncsMap JSONNativeUtil::getTypeFuncsMap()
+{
+ RttiTypeFuncsMap typeMap;
+ typeMap.add(GetRttiInfo<JSONValue>::get(), GetRttiTypeFuncsForZeroPod<JSONValue>::getFuncs());
+ return typeMap;
+}
+
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!! JSONToNativeConverter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
/* static */Index JSONToNativeConverter::_getFieldCount(const StructRttiInfo* structRttiInfo)
@@ -193,10 +200,9 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo*
const ListRttiInfo* listRttiInfo = static_cast<const ListRttiInfo*>(rttiInfo);
auto elementType = listRttiInfo->m_elementType;
- SLANG_RETURN_ON_FAIL(RttiUtil::setListCount(elementType, out, arr.getCount()));
+ SLANG_RETURN_ON_FAIL(RttiUtil::setListCount(m_typeMap, elementType, out, arr.getCount()));
// Okay, we need to copy over one by one
-
Byte* dstEles = list.getBuffer();
for (Index i = 0; i < count; ++i, dstEles += elementType->m_size)
{
diff --git a/source/compiler-core/slang-json-native.h b/source/compiler-core/slang-json-native.h
index 4235a99a8..72e339621 100644
--- a/source/compiler-core/slang-json-native.h
+++ b/source/compiler-core/slang-json-native.h
@@ -19,8 +19,9 @@ struct JSONToNativeConverter
SlangResult convertArrayToStruct(const JSONValue& value, T* in) { return convertArrayToStruct(value, GetRttiInfo<T>::get(), (void*)in); }
SlangResult convertArrayToStruct(const JSONValue& value, const RttiInfo* rttiInfo, void* out);
- JSONToNativeConverter(JSONContainer* container, DiagnosticSink* sink):
+ JSONToNativeConverter(JSONContainer* container, RttiTypeFuncsMap* typeMap, DiagnosticSink* sink):
m_container(container),
+ m_typeMap(typeMap),
m_sink(sink)
{}
@@ -31,6 +32,7 @@ protected:
SlangResult _structToNative(const ConstArrayView<JSONKeyValue>& pairs, const StructRttiInfo* structRttiInfo, void* out, Index& outFieldCount);
DiagnosticSink* m_sink;
+ RttiTypeFuncsMap* m_typeMap;
JSONContainer* m_container;
};
@@ -45,9 +47,9 @@ struct NativeToJSONConverter
template <typename T>
SlangResult convertStructToArray(T* in, JSONValue& out) { return convertStructToArray(GetRttiInfo<T>::get(), (const void*)in, out); }
-
- NativeToJSONConverter(JSONContainer* container, DiagnosticSink* sink) :
+ NativeToJSONConverter(JSONContainer* container, RttiTypeFuncsMap* typeMap, DiagnosticSink* sink) :
m_container(container),
+ m_typeMap(typeMap),
m_sink(sink)
{}
@@ -55,9 +57,14 @@ protected:
SlangResult _structToJSON(const StructRttiInfo* structRttiInfo, const void* src, List<JSONKeyValue>& outPairs);
DiagnosticSink* m_sink;
+ RttiTypeFuncsMap* m_typeMap;
JSONContainer* m_container;
};
+struct JSONNativeUtil
+{
+ static RttiTypeFuncsMap getTypeFuncsMap();
+};
} // namespace Slang
diff --git a/source/compiler-core/slang-json-rpc-connection.cpp b/source/compiler-core/slang-json-rpc-connection.cpp
index ec45f5b82..6d687d8ca 100644
--- a/source/compiler-core/slang-json-rpc-connection.cpp
+++ b/source/compiler-core/slang-json-rpc-connection.cpp
@@ -10,6 +10,13 @@
namespace Slang {
+/// Ctor
+JSONRPCConnection::JSONRPCConnection():
+ m_container(nullptr),
+ m_typeMap(JSONNativeUtil::getTypeFuncsMap())
+{
+}
+
SlangResult JSONRPCConnection::init(HTTPPacketConnection* connection, CallStyle defaultCallStyle, Process* process)
{
m_connection = connection;
@@ -98,8 +105,10 @@ void JSONRPCConnection::disconnect()
SlangResult JSONRPCConnection::sendRPC(const RttiInfo* rttiInfo, const void* data)
{
+ auto typeMap = JSONNativeUtil::getTypeFuncsMap();
+
// Convert to JSON
- NativeToJSONConverter converter(&m_container, &m_diagnosticSink);
+ NativeToJSONConverter converter(&m_container, &typeMap, &m_diagnosticSink);
JSONValue value;
SLANG_RETURN_ON_FAIL(converter.convert(rttiInfo, data, value));
@@ -132,7 +141,7 @@ SlangResult JSONRPCConnection::toNativeArgsOrSendError(const JSONValue& srcArgs,
if (dstArgsRttiInfo->m_kind == RttiInfo::Kind::Struct &&
srcArgs.getKind() == JSONValue::Kind::Array)
{
- JSONToNativeConverter converter(&m_container, &m_diagnosticSink);
+ JSONToNativeConverter converter(&m_container, &m_typeMap, &m_diagnosticSink);
if (SLANG_FAILED(converter.convertArrayToStruct(srcArgs, dstArgsRttiInfo, dstArgs)))
{
return sendError(JSONRPC::ErrorCode::InvalidRequest, id);
@@ -149,7 +158,7 @@ SlangResult JSONRPCConnection::toNativeOrSendError(const JSONValue& value, const
{
m_diagnosticSink.outputBuffer.Clear();
- JSONToNativeConverter converter(&m_container, &m_diagnosticSink);
+ JSONToNativeConverter converter(&m_container, &m_typeMap, &m_diagnosticSink);
if (SLANG_FAILED(converter.convert(value, info, dst)))
{
@@ -174,7 +183,7 @@ SlangResult JSONRPCConnection::sendResult(const RttiInfo* rttiInfo, const void*
JSONResultResponse response;
response.id = id;
- NativeToJSONConverter converter(&m_container, &m_diagnosticSink);
+ NativeToJSONConverter converter(&m_container, &m_typeMap, &m_diagnosticSink);
SLANG_RETURN_ON_FAIL(converter.convert(rttiInfo, result, response.result));
// Send the RPC
@@ -194,7 +203,7 @@ SlangResult JSONRPCConnection::sendCall(CallStyle callStyle, const UnownedString
call.method = method;
// Set up the converter to now convert the args.
- NativeToJSONConverter converter(&m_container, &m_diagnosticSink);
+ NativeToJSONConverter converter(&m_container, &m_typeMap, &m_diagnosticSink);
// If we have a struct *and* call style is 'array', do special handling
if (argsRttiInfo->m_kind == RttiInfo::Kind::Struct &&
@@ -263,7 +272,7 @@ SlangResult JSONRPCConnection::getMessage(const RttiInfo* rttiInfo, void* out)
}
m_diagnosticSink.outputBuffer.Clear();
- JSONToNativeConverter converter(&m_container, &m_diagnosticSink);
+ JSONToNativeConverter converter(&m_container, &m_typeMap, &m_diagnosticSink);
// Get the RPC response
JSONResultResponse resultResponse;
@@ -297,7 +306,7 @@ SlangResult JSONRPCConnection::getRPC(const RttiInfo* rttiInfo, void* out)
}
m_diagnosticSink.outputBuffer.Clear();
- JSONToNativeConverter converter(&m_container, &m_diagnosticSink);
+ JSONToNativeConverter converter(&m_container, &m_typeMap, &m_diagnosticSink);
// Convert the result in the response
SLANG_RETURN_ON_FAIL(converter.convert(m_jsonRoot, rttiInfo, out));
diff --git a/source/compiler-core/slang-json-rpc-connection.h b/source/compiler-core/slang-json-rpc-connection.h
index 18749229c..7246fb780 100644
--- a/source/compiler-core/slang-json-rpc-connection.h
+++ b/source/compiler-core/slang-json-rpc-connection.h
@@ -154,7 +154,7 @@ public:
~JSONRPCConnection() { disconnect(); }
/// Ctor
- JSONRPCConnection():m_container(nullptr) {}
+ JSONRPCConnection();
protected:
CallStyle _getCallStyle(CallStyle callStyle) const { return (callStyle == CallStyle::Default) ? m_defaultCallStyle : callStyle; }
@@ -171,6 +171,8 @@ protected:
CallStyle m_defaultCallStyle = CallStyle::Array; ///< The default calling style
+ RttiTypeFuncsMap m_typeMap;
+
Int m_terminationTimeOutInMs = 1 * 1000; ///< Time to wait for termination response. Default is 1 second
};
diff --git a/source/compiler-core/slang-json-rpc.cpp b/source/compiler-core/slang-json-rpc.cpp
index f4101be8c..3474718c7 100644
--- a/source/compiler-core/slang-json-rpc.cpp
+++ b/source/compiler-core/slang-json-rpc.cpp
@@ -126,7 +126,9 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti()
/* static */SlangResult JSONRPCUtil::convertToNative(JSONContainer* container, const JSONValue& value, DiagnosticSink* sink, const RttiInfo* rttiInfo, void* out)
{
- JSONToNativeConverter converter(container, sink);
+ auto typeMap = JSONNativeUtil::getTypeFuncsMap();
+
+ JSONToNativeConverter converter(container, &typeMap, sink);
SLANG_RETURN_ON_FAIL(converter.convert(value, rttiInfo, out));
return SLANG_OK;
}
@@ -136,7 +138,9 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti()
SourceManager* sourceManager = sink->getSourceManager();
JSONContainer container(sourceManager);
- NativeToJSONConverter converter(&container, sink);
+ auto typeMap = JSONNativeUtil::getTypeFuncsMap();
+
+ NativeToJSONConverter converter(&container, &typeMap, sink);
JSONValue value;
SLANG_RETURN_ON_FAIL(converter.convert(rttiInfo, in, value));
diff --git a/source/compiler-core/slang-source-map.cpp b/source/compiler-core/slang-source-map.cpp
new file mode 100644
index 000000000..6a3083ce0
--- /dev/null
+++ b/source/compiler-core/slang-source-map.cpp
@@ -0,0 +1,242 @@
+#include "slang-source-map.h"
+
+#include "../../slang-com-helper.h"
+
+#include "../core/slang-string-util.h"
+
+#include "slang-json-native.h"
+
+namespace Slang {
+
+static const StructRttiInfo _makeJSONSourceMap_Rtti()
+{
+ JSONSourceMap obj;
+
+ StructRttiBuilder builder(&obj, "SourceMap", nullptr);
+
+ builder.addField("version", &obj.version);
+ builder.addField("file", &obj.file);
+ builder.addField("sourceRoot", &obj.sourceRoot);
+ builder.addField("sources", &obj.sources);
+ builder.addField("sourcesContent", &obj.sourcesContent);
+ builder.addField("names", &obj.names);
+ builder.addField("mappings", &obj.mappings);
+
+ return builder.make();
+}
+/* static */const StructRttiInfo JSONSourceMap::g_rttiInfo = _makeJSONSourceMap_Rtti();
+
+// Encode a 6 bit value to VLQ encoding
+static const char g_vlqEncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+struct VlqDecodeTable
+{
+ VlqDecodeTable()
+ {
+ ::memset(map, -1, sizeof(map));
+ for (Index i = 0; i < SLANG_COUNT_OF(g_vlqEncodeTable); ++i)
+ {
+ map[g_vlqEncodeTable[i]] = int8_t(i);
+ }
+ }
+ /// Returns a *negative* value if invalid
+ int8_t operator[](char c) const { return (c & ~char(0x7f)) ? -1 : map[c]; }
+
+ int8_t map[128];
+};
+
+static const VlqDecodeTable g_vlqDecodeTable;
+
+/*
+https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?hl=en_US&pli=1&pli=1#
+The VLQ is a Base64 value, where the most significant bit (the 6th bit) is used as the continuation
+bit, and the “digits” are encoded into the string least significant first, and where the least significant
+bit of the first digit is used as the sign bit. */
+
+static SlangResult _decode(UnownedStringSlice& ioEncoded, Index& out)
+{
+ Index v = 0;
+
+ Index shift = 0;
+ const char* cur = ioEncoded.begin();
+ const char* end = ioEncoded.end();
+
+ // Must have some chars
+ if (cur >= end)
+ {
+ return SLANG_FAIL;
+ }
+
+ for (; cur < end; ++cur)
+ {
+ const Index value = g_vlqDecodeTable[*cur];
+ if (value < 0)
+ {
+ return SLANG_FAIL;
+ }
+
+ v += (value & 0x1f) << shift;
+
+ // If the continuation bit is not set we are done
+ if (( value & 0x20) == 0)
+ {
+ ++cur;
+ break;
+ }
+
+ shift += 5;
+ }
+
+ // Save out the remaining part
+ ioEncoded = UnownedStringSlice(cur, end);
+
+ // Double to make setting lower bit simpler
+ v += v;
+
+ // If it's negative we make positive and set the bottom bit
+ // otherwise we just return with the LSB not set.
+ out = (v < 0) ? (1 - v) : v;
+ return SLANG_OK;
+}
+
+SlangResult SourceMap::decode(JSONContainer* container, const JSONSourceMap& src)
+{
+ m_slicePool.clear();
+
+ m_file = src.file;
+ m_sourceRoot = src.sourceRoot;
+
+ m_lineStarts.clear();
+ m_lineEntries.clear();
+
+ const Count sourcesCount = src.sources.getCount();
+
+ // These should all be unique, but for simplicity, we build a table
+ m_sources.setCount(sourcesCount);
+ for (Index i = 0; i < sourcesCount; ++i)
+ {
+ m_sources[i] = m_slicePool.add(src.sources[i]);
+ }
+
+ Count sourcesContentCount = src.sourcesContent.getCount();
+ sourcesContentCount = std::min(sourcesContentCount, sourcesCount);
+
+ m_sourcesContent.setCount(sourcesContentCount);
+ for (auto& cur : m_sourcesContent)
+ {
+ cur = StringSlicePool::kNullHandle;
+ }
+
+ for (Index i = 0; i < sourcesContentCount; ++i)
+ {
+ auto value = src.sourcesContent[i];
+
+ if (value.type != JSONValue::Type::Null)
+ {
+ if (value.getKind() == JSONValue::Kind::String)
+ {
+ auto stringValue = container->getString(value);
+ m_sourcesContent[i] = m_slicePool.add(stringValue);
+ }
+ }
+ }
+
+
+ List<UnownedStringSlice> lines;
+ StringUtil::split(src.mappings, ';', lines);
+
+ List<UnownedStringSlice> segments;
+
+ // Index into sources
+ Index sourceFileIndex = 0;
+
+ Index sourceLine = 0;
+ Index sourceColumn = 0;
+ Index nameIndex = 0;
+
+ const Count linesCount = lines.getCount();
+
+ m_lineStarts.setCount(linesCount + 1);
+
+ for (Index generatedLine = 0; generatedLine < linesCount; ++generatedLine)
+ {
+ const auto line = lines[generatedLine];
+
+ m_lineStarts[generatedLine] = m_lineEntries.getCount();
+
+ // If it's empty move to next line
+ if (line.getLength() == 0)
+ {
+ continue;
+ }
+
+ // Split the line into segments
+ segments.clear();
+ StringUtil::split(line, ',', segments);
+
+ Index generatedColumn = 0;
+
+ for (auto segment : segments)
+ {
+ Index colDelta;
+ SLANG_RETURN_ON_FAIL(_decode(segment, colDelta));
+
+ generatedColumn += colDelta;
+ SLANG_ASSERT(generatedColumn >= 0);
+
+ // It can be 4 or 5 parts
+ if (segment.getLength())
+ {
+ /* If present, an zero-based index into the “sources” list. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented.
+ If present, the zero-based starting line in the original source represented. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. Always present if there is a source field.
+ If present, the zero-based starting column of the line in the source represented. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. Always present if there is a source field.
+ */
+
+ Index sourceFileDelta;
+ Index sourceLineDelta;
+ Index sourceColumnDelta;
+
+ SLANG_RETURN_ON_FAIL(_decode(segment, sourceFileDelta));
+ SLANG_RETURN_ON_FAIL(_decode(segment, sourceLineDelta));
+ SLANG_RETURN_ON_FAIL(_decode(segment, sourceColumnDelta));
+
+ sourceFileIndex += sourceFileDelta;
+ sourceLine += sourceLineDelta;
+ sourceColumn += sourceColumnDelta;
+
+ SLANG_ASSERT(sourceFileIndex >= 0);
+ SLANG_ASSERT(sourceLine >= 0);
+ SLANG_ASSERT(sourceColumn >= 0);
+
+ // 5 parts
+ if (segment.getLength() > 0)
+ {
+ /* If present, the zero - based index into the “names” list associated with this segment.This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented.
+ */
+
+ Index nameDelta;
+ SLANG_RETURN_ON_FAIL(_decode(segment, nameDelta));
+
+ nameIndex += nameDelta;
+ SLANG_ASSERT(nameIndex >= 0);
+ }
+ }
+
+ Entry entry;
+ entry.generatedColumn = generatedColumn;
+ entry.sourceColumn = sourceColumn;
+ entry.sourceLine = sourceLine;
+ entry.sourceFileIndex = sourceFileIndex;
+
+ m_lineEntries.add(entry);
+ }
+ }
+
+ // Mark the end
+ m_lineStarts[linesCount] = m_lineEntries.getCount();
+
+ return SLANG_OK;
+}
+
+
+} // namespace Slang
diff --git a/source/compiler-core/slang-source-map.h b/source/compiler-core/slang-source-map.h
new file mode 100644
index 000000000..0f84878fe
--- /dev/null
+++ b/source/compiler-core/slang-source-map.h
@@ -0,0 +1,118 @@
+#ifndef SLANG_COMPILER_CORE_SOURCE_MAP_H
+#define SLANG_COMPILER_CORE_SOURCE_MAP_H
+
+#include "../../slang.h"
+#include "../../slang-com-helper.h"
+#include "../../slang-com-ptr.h"
+
+#include "../core/slang-string.h"
+#include "../core/slang-list.h"
+#include "../core/slang-rtti-info.h"
+
+#include "../core/slang-string-slice-pool.h"
+
+#include "slang-json-value.h"
+
+namespace Slang {
+
+/*
+Support for source maps. Source maps provide a standardized mechanism to associate a location in one output file
+with another.
+
+* [Source Map Proposal](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?hl=en_US&pli=1&pli=1)
+* [Chrome Source Map post](https://developer.chrome.com/blog/sourcemaps/)
+* [Base64 VLQs in Source Maps](https://www.lucidchart.com/techblog/2019/08/22/decode-encoding-base64-vlqs-source-maps/)
+
+Example...
+
+{
+"version" : 3,
+"file": "out.js",
+"sourceRoot": "",
+"sources": ["foo.js", "bar.js"],
+"sourcesContent": [null, null],
+"names": ["src", "maps", "are", "fun"],
+"mappings": "A,AAAB;;ABCDE;"
+}
+*/
+
+struct JSONSourceMap
+{
+ /// File version (always the first entry in the object) and must be a positive integer.
+ int32_t version = 3;
+ /// An optional name of the generated code that this source map is associated with.
+ String file;
+ /// An optional source root, useful for relocating source files on a server or removing repeated values in
+ /// the sources entry. This value is prepended to the individual entries in the source field.
+ String sourceRoot;
+ /// A list of original sources used by the mappings entry.
+ List<UnownedStringSlice> sources;
+ /// An optional list of source content, useful when the source cant be hosted. The contents are listed in the same order as the sources in line 5.
+ /// null may be used if some original sources should be retrieved by name.
+ /// Because could be a string or nullptr, we use JSONValue to hold value.
+ List<JSONValue> sourcesContent;
+ /// A list of symbol names used by the mappings entry.
+ List<UnownedStringSlice> names;
+ /// A string with the encoded mapping data.
+ UnownedStringSlice mappings;
+
+ static const StructRttiInfo g_rttiInfo;
+};
+
+struct SourceMap
+{
+ struct Entry
+ {
+ // Note! All column/line are zero indexed
+
+ Index generatedColumn; ///< The generated column
+ Index sourceFileIndex; ///< The index into the source name/contents
+ Index sourceLine; ///< The line number in the originating source
+ Index sourceColumn; ///< The column number in the originating source
+ };
+
+ SlangResult decode(JSONContainer* container, const JSONSourceMap& src);
+
+ /// Get the total number of generated lines
+ Count getGeneratedLineCount() const { return m_lineStarts.getCount() - 1; }
+ /// Get the entries on the line
+ SLANG_FORCE_INLINE ConstArrayView<Entry> getEntriesForLine(Index generatedLine) const;
+
+ /// Ctor
+ SourceMap():
+ m_slicePool(StringSlicePool::Style::Default)
+ {
+ }
+
+ String m_file;
+ String m_sourceRoot;
+
+ List<StringSlicePool::Handle> m_sources;
+
+ /// Storage for the contents. Can be unset null to indicate not set.
+ List<StringSlicePool::Handle> m_sourcesContent;
+
+ List<Index> m_lineStarts;
+ List<Entry> m_lineEntries;
+
+ StringSlicePool m_slicePool;
+};
+
+// -------------------------------------------------------------
+SLANG_FORCE_INLINE ConstArrayView<SourceMap::Entry> SourceMap::getEntriesForLine(Index generatedLine) const
+{
+ const Index start = m_lineStarts[generatedLine];
+ const Index end = m_lineStarts[generatedLine + 1];
+
+ const auto entries = m_lineEntries.begin();
+
+ SLANG_ASSERT(start >= 0 && start < m_lineEntries.getCount());
+ SLANG_ASSERT(end >= start && end >= 0 && end < m_lineEntries.getCount());
+
+ return ConstArrayView<SourceMap::Entry>(entries + start, end - start);
+}
+
+
+} // namespace Slang
+
+#endif // SLANG_COMPILER_CORE_SOURCE_MAP_H
diff --git a/source/core/slang-rtti-info.cpp b/source/core/slang-rtti-info.cpp
index 043e6490a..c35444d03 100644
--- a/source/core/slang-rtti-info.cpp
+++ b/source/core/slang-rtti-info.cpp
@@ -2,6 +2,8 @@
#include "../../slang-com-helper.h"
+#include "slang-rtti-util.h"
+
#include <mutex>
namespace Slang {
@@ -191,4 +193,35 @@ StructRttiInfo StructRttiBuilder::make()
return m_rttiInfo;
}
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! RttiTypeFuncsMap !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+RttiTypeFuncs RttiTypeFuncsMap::getFuncsForType(const RttiInfo* rttiInfo)
+{
+ if (auto funcsPtr = m_map.TryGetValue(rttiInfo))
+ {
+ return *funcsPtr;
+ }
+
+ // Try to get the default impl
+ // NOTE! funcs could be invalid if there is no default impl.
+ const auto funcs = RttiUtil::getDefaultTypeFuncs(rttiInfo);
+
+ // Add to the map
+ m_map.Add(rttiInfo, funcs);
+ return funcs;
+}
+
+void RttiTypeFuncsMap::add(const RttiInfo* rttiInfo, const RttiTypeFuncs& funcs)
+{
+ if (auto funcsPtr = m_map.TryGetValueOrAdd(rttiInfo, funcs))
+ {
+ // If there are funcs set, they aren't valid otherwise this would be
+ // replacing, so assert on that scenario.
+ SLANG_ASSERT(!funcsPtr->isValid());
+
+ // Replace the funcs
+ *funcsPtr = funcs;
+ }
+}
+
} // namespace Slang
diff --git a/source/core/slang-rtti-info.h b/source/core/slang-rtti-info.h
index e9296c3ff..a7262e50f 100644
--- a/source/core/slang-rtti-info.h
+++ b/source/core/slang-rtti-info.h
@@ -10,12 +10,13 @@
namespace Slang {
struct RttiInfo;
+struct RttiTypeFuncsMap;
struct RttiTypeFuncs
{
- typedef void (*CtorArray)(const RttiInfo* rttiInfo, void* dst, Index count);
- typedef void (*DtorArray)(const RttiInfo* rttiInfo, void* dst, Index count);
- typedef void (*CopyArray)(const RttiInfo* rttiInfo, void* dst, const void* src, Index count);
+ typedef void (*CtorArray)(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* dst, Index count);
+ typedef void (*DtorArray)(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* dst, Index count);
+ typedef void (*CopyArray)(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* dst, const void* src, Index count);
bool isValid() const { return ctorArray && dtorArray && copyArray; }
@@ -26,11 +27,27 @@ struct RttiTypeFuncs
CopyArray copyArray;
};
+/* Provides a mechanism to map a type to it's RttiFuncs */
+struct RttiTypeFuncsMap
+{
+ /// For a given type returns the funcs.
+ /// If not found returns funcs that return 'isValid' as false.
+ RttiTypeFuncs getFuncsForType(const RttiInfo* rttiInfo);
+
+ /// Add funcs for a type
+ void add(const RttiInfo* rttiInfo, const RttiTypeFuncs& funcs);
+
+protected:
+ Dictionary<const RttiInfo*, RttiTypeFuncs> m_map;
+};
+
+/* Template to get funcs for any arbitrary type */
template <typename T>
struct GetRttiTypeFuncs
{
- static void ctorArray(const RttiInfo* rttiInfo, void* in, Index count)
+ static void ctorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* in, Index count)
{
+ SLANG_UNUSED(typeMap);
SLANG_UNUSED(rttiInfo);
T* dst = (T*)in;
for (Index i = 0; i < count; ++i)
@@ -38,8 +55,9 @@ struct GetRttiTypeFuncs
new (dst + i) T;
}
}
- static void dtorArray(const RttiInfo* rttiInfo, void* in, Index count)
+ static void dtorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* in, Index count)
{
+ SLANG_UNUSED(typeMap);
SLANG_UNUSED(rttiInfo);
T* dst = (T*)in;
for (Index i = 0; i < count; ++i)
@@ -47,9 +65,11 @@ struct GetRttiTypeFuncs
(dst + i)->~T();
}
}
- static void copyArray(const RttiInfo* rttiInfo, void* inDst, const void* inSrc, Index count)
+ static void copyArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, const void* inSrc, Index count)
{
SLANG_UNUSED(rttiInfo);
+ SLANG_UNUSED(typeMap);
+
T* dst = (T*)inDst;
const T* src = (T*)inSrc;
for (Index i = 0; i < count; ++i)
@@ -67,6 +87,42 @@ struct GetRttiTypeFuncs
}
};
+/* An implementation of funcs, for a type that is POD *and* can be zero initialized.
+Built in types generally fall into this catagory, but so do raw pointers and other types,
+such as structs that only contain "ZeroPod" types */
+template <typename T>
+struct GetRttiTypeFuncsForZeroPod
+{
+ static void ctorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* dst, Index count)
+ {
+ SLANG_UNUSED(typeMap);
+ SLANG_UNUSED(rttiInfo);
+ ::memset(dst, 0, sizeof(T) * count);
+ }
+ static void dtorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* dst, Index count)
+ {
+ SLANG_UNUSED(typeMap);
+ SLANG_UNUSED(rttiInfo);
+ SLANG_UNUSED(dst);
+ SLANG_UNUSED(count);
+ }
+ static void copyArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* dst, const void* src, Index count)
+ {
+ SLANG_UNUSED(typeMap);
+ SLANG_UNUSED(rttiInfo);
+ ::memcpy(dst, src, sizeof(T) * count);
+ }
+
+ static RttiTypeFuncs getFuncs()
+ {
+ RttiTypeFuncs funcs;
+ funcs.copyArray = &copyArray;
+ funcs.dtorArray = &dtorArray;
+ funcs.ctorArray = &ctorArray;
+ return funcs;
+ }
+};
+
struct RttiInfo
{
typedef uint8_t AlignmentType;
diff --git a/source/core/slang-rtti-util.cpp b/source/core/slang-rtti-util.cpp
index b4b2ddae2..9d02ec23b 100644
--- a/source/core/slang-rtti-util.cpp
+++ b/source/core/slang-rtti-util.cpp
@@ -2,215 +2,13 @@
namespace Slang {
-/* static */SlangResult RttiUtil::setInt(int64_t value, const RttiInfo* rttiInfo, void* dst)
-{
- SLANG_ASSERT(rttiInfo->isIntegral());
-
- // We could check ranges are appropriate, but for now we just write.
- // Passing in rttiInfo allows for other more complex types to be econverted
- switch (rttiInfo->m_kind)
- {
- case RttiInfo::Kind::I32: *(int32_t*)dst = int32_t(value); break;
- case RttiInfo::Kind::U32: *(uint32_t*)dst = uint32_t(value); break;
- case RttiInfo::Kind::I64: *(int64_t*)dst = int64_t(value); break;
- case RttiInfo::Kind::U64: *(uint64_t*)dst = uint64_t(value); break;
- default: return SLANG_FAIL;
- }
- return SLANG_OK;
-}
-
-/* static */int64_t RttiUtil::getInt64(const RttiInfo* rttiInfo, const void* src)
-{
- SLANG_ASSERT(rttiInfo->isIntegral());
-
- switch (rttiInfo->m_kind)
- {
- case RttiInfo::Kind::I32: return *(const int32_t*)src;
- case RttiInfo::Kind::U32: return *(const uint32_t*)src;
- case RttiInfo::Kind::I64: return *(const int64_t*)src;
- case RttiInfo::Kind::U64: return *(const uint64_t*)src;
- default: break;
- }
-
- SLANG_ASSERT(!"Not integral!");
- return -1;
-}
-
-/* static */double RttiUtil::asDouble(const RttiInfo* rttiInfo, const void* src)
-{
- if (rttiInfo->isIntegral())
- {
- return (double)getInt64(rttiInfo, src);
- }
- else if (rttiInfo->isFloat())
- {
- switch (rttiInfo->m_kind)
- {
- case RttiInfo::Kind::F32: return *(const float*)src;
- case RttiInfo::Kind::F64: return *(const double*)src;
- default: break;
- }
- }
-
- SLANG_ASSERT(!"Cannot convert to float");
- return 0.0;
-}
-
-/* static */SlangResult RttiUtil::setFromDouble(double v, const RttiInfo* rttiInfo, void* dst)
-{
- if (rttiInfo->isIntegral())
- {
- return setInt(int64_t(v), rttiInfo, dst);
- }
- else if (rttiInfo->isFloat())
- {
- switch (rttiInfo->m_kind)
- {
- case RttiInfo::Kind::F32: *(float*)dst = float(v); return SLANG_OK;
- case RttiInfo::Kind::F64: *(double*)dst = v; return SLANG_OK;
- default: break;
- }
- }
-
- return SLANG_FAIL;
-}
-
-/* static */bool RttiUtil::asBool(const RttiInfo* rttiInfo, const void* src)
-{
- if (rttiInfo->m_kind == RttiInfo::Kind::Bool)
- {
- return *(const bool*)src;
- }
-
- if (rttiInfo->isIntegral())
- {
- return getInt64(rttiInfo, src) != 0;
- }
- else if (rttiInfo->isFloat())
- {
- return asDouble(rttiInfo, src) != 0.0;
- }
-
- SLANG_ASSERT(!"Cannot convert to bool");
- return false;
-}
-
-static int64_t _getIntDefaultValue(RttiDefaultValue value)
-{
- switch (value)
- {
- default:
- case RttiDefaultValue::Normal: return 0;
- case RttiDefaultValue::One: return 1;
- case RttiDefaultValue::MinusOne: return -1;
- }
-}
-
-static bool _isStructDefault(const StructRttiInfo* type, const void* src)
-{
- if (type->m_super)
- {
- if (!_isStructDefault(type->m_super, src))
- {
- return false;
- }
- }
-
- const Byte* base = (const Byte*)src;
-
- const Index count = type->m_fieldCount;
- for (Index i = 0; i < count; ++i)
- {
- const auto& field = type->m_fields[i];
-
- const RttiDefaultValue defaultValue = RttiDefaultValue(field.m_flags & uint8_t(RttiDefaultValue::Mask));
-
- if (!RttiUtil::isDefault(defaultValue, field.m_type, base + field.m_offset))
- {
- return false;
- }
- }
-
- return true;
-}
-
-/* static */bool RttiUtil::isDefault(RttiDefaultValue defaultValue, const RttiInfo* rttiInfo, const void* src)
-{
- if (rttiInfo->isIntegral())
- {
- const auto value = getInt64(rttiInfo, src);
- return _getIntDefaultValue(defaultValue) == value;
- }
- else if (rttiInfo->isFloat())
- {
- const auto value = asDouble(rttiInfo, src);
- return _getIntDefaultValue(defaultValue) == value;
- }
-
- switch (rttiInfo->m_kind)
- {
- case RttiInfo::Kind::Invalid: return true;
- case RttiInfo::Kind::Bool: return *(const bool*)src == (_getIntDefaultValue(defaultValue) != 0);
- case RttiInfo::Kind::String:
- {
- return ((const String*)src)->getLength() == 0;
- }
- case RttiInfo::Kind::UnownedStringSlice:
- {
- return ((const UnownedStringSlice*)src)->getLength() == 0;
- }
- case RttiInfo::Kind::Struct:
- {
- return _isStructDefault(static_cast<const StructRttiInfo*>(rttiInfo), src);
- }
- case RttiInfo::Kind::Enum:
- {
- SLANG_ASSERT(!"Not implemented yet");
- return false;
- }
- case RttiInfo::Kind::List:
- {
- const auto& v = *(const List<Byte>*)src;
- return v.getCount() == 0;
- }
- case RttiInfo::Kind::Dictionary:
- {
- const auto& v = *(const Dictionary<Byte, Byte>*)src;
- return v.Count() == 0;
- }
- case RttiInfo::Kind::Other:
- {
- const OtherRttiInfo* otherRttiInfo = static_cast<const OtherRttiInfo*>(rttiInfo);
- return otherRttiInfo->m_isDefaultFunc && otherRttiInfo->m_isDefaultFunc(rttiInfo, src);
- }
- default:
- {
- return false;
- }
- }
-}
-
-template <typename T>
-struct GetRttiTypeFuncsForBuiltIn
-{
- static void ctorArray(const RttiInfo* rttiInfo, void* dst, Index count) { SLANG_UNUSED(rttiInfo); ::memset(dst, 0, sizeof(T) * count); }
- static void dtorArray(const RttiInfo* rttiInfo, void* dst, Index count) { SLANG_UNUSED(rttiInfo); SLANG_UNUSED(dst); SLANG_UNUSED(count); }
- static void copyArray(const RttiInfo* rttiInfo, void* dst, const void* src, Index count) { SLANG_UNUSED(rttiInfo); ::memcpy(dst, src, sizeof(T) * count); }
-
- static RttiTypeFuncs getFuncs()
- {
- RttiTypeFuncs funcs;
- funcs.copyArray = &copyArray;
- funcs.dtorArray = &dtorArray;
- funcs.ctorArray = &ctorArray;
- return funcs;
- }
-};
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! RttiTypeFuncs Impls !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
struct ListFuncs
{
- static void ctorArray(const RttiInfo* rttiInfo, void* inDst, Index count)
+ static void ctorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, Index count)
{
+ SLANG_UNUSED(typeMap);
SLANG_UNUSED(rttiInfo);
SLANG_ASSERT(rttiInfo->m_kind == RttiInfo::Kind::List);
@@ -225,14 +23,14 @@ struct ListFuncs
new (dst + i) Type;
}
}
- static void copyArray(const RttiInfo* rttiInfo, void* inDst, const void* inSrc, Index count)
+ static void copyArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, const void* inSrc, Index count)
{
SLANG_ASSERT(rttiInfo->m_kind == RttiInfo::Kind::List);
const ListRttiInfo* listRttiInfo = static_cast<const ListRttiInfo*>(rttiInfo);
const auto elementType = listRttiInfo->m_elementType;
// We need to get the type funcs
- auto typeFuncs = RttiUtil::getTypeFuncs(elementType);
+ auto typeFuncs = typeMap->getFuncsForType(elementType);
SLANG_ASSERT(typeFuncs.isValid());
// We need a type that we can get information from the list from - List<Byte> gives us the functions we need.
@@ -256,8 +54,8 @@ struct ListFuncs
void* newBuffer = ::malloc(count * elementType->m_size);
// Initialize it all first
- typeFuncs.ctorArray(elementType, newBuffer, count);
- typeFuncs.copyArray(elementType, newBuffer, oldBuffer, count);
+ typeFuncs.ctorArray(typeMap, elementType, newBuffer, count);
+ typeFuncs.copyArray(typeMap, elementType, newBuffer, oldBuffer, count);
// Attach the new buffer
dstList.attachBuffer((Byte*)newBuffer, count, count);
@@ -265,20 +63,20 @@ struct ListFuncs
// Free the old buffer
if (oldBuffer)
{
- typeFuncs.dtorArray(elementType, oldBuffer, dstCapacity);
+ typeFuncs.dtorArray(typeMap, elementType, oldBuffer, dstCapacity);
::free(oldBuffer);
}
}
else
{
- typeFuncs.copyArray(elementType, dstList.getBuffer(), srcList.getBuffer(), srcCount);
+ typeFuncs.copyArray(typeMap, elementType, dstList.getBuffer(), srcList.getBuffer(), srcCount);
dstList.unsafeShrinkToCount(srcCount);
}
}
}
- static void dtorArray(const RttiInfo* rttiInfo, void* inDst, Index count)
+ static void dtorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, Index count)
{
SLANG_ASSERT(rttiInfo->m_kind == RttiInfo::Kind::List);
const ListRttiInfo* listRttiInfo = static_cast<const ListRttiInfo*>(rttiInfo);
@@ -286,7 +84,7 @@ struct ListFuncs
const auto elementType = listRttiInfo->m_elementType;
// We need to get the type funcs
- auto typeFuncs = RttiUtil::getTypeFuncs(elementType);
+ auto typeFuncs = typeMap->getFuncsForType(elementType);
SLANG_ASSERT(typeFuncs.isValid());
typedef List<Byte> Type;
@@ -301,7 +99,7 @@ struct ListFuncs
if (buffer)
{
- typeFuncs.dtorArray(elementType, buffer, capacity);
+ typeFuncs.dtorArray(typeMap, elementType, buffer, capacity);
::free(buffer);
}
}
@@ -319,10 +117,9 @@ struct ListFuncs
struct StructFuncs
{
-
-
- static void ctorArray(const RttiInfo* rttiInfo, void* inDst, Index count)
+ static void ctorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, Index count)
{
+ SLANG_UNUSED(typeMap);
SLANG_UNUSED(rttiInfo);
SLANG_ASSERT(rttiInfo->m_kind == RttiInfo::Kind::List);
@@ -337,14 +134,14 @@ struct StructFuncs
new (dst + i) Type;
}
}
- static void copyArray(const RttiInfo* rttiInfo, void* inDst, const void* inSrc, Index count)
+ static void copyArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, const void* inSrc, Index count)
{
SLANG_ASSERT(rttiInfo->m_kind == RttiInfo::Kind::List);
const ListRttiInfo* listRttiInfo = static_cast<const ListRttiInfo*>(rttiInfo);
const auto elementType = listRttiInfo->m_elementType;
// We need to get the type funcs
- auto typeFuncs = RttiUtil::getTypeFuncs(elementType);
+ auto typeFuncs = typeMap->getFuncsForType(elementType);
SLANG_ASSERT(typeFuncs.isValid());
// We need a type that we can get information from the list from - List<Byte> gives us the functions we need.
@@ -368,8 +165,8 @@ struct StructFuncs
void* newBuffer = ::malloc(count * elementType->m_size);
// Initialize it all first
- typeFuncs.ctorArray(elementType, newBuffer, count);
- typeFuncs.copyArray(elementType, newBuffer, oldBuffer, count);
+ typeFuncs.ctorArray(typeMap, elementType, newBuffer, count);
+ typeFuncs.copyArray(typeMap, elementType, newBuffer, oldBuffer, count);
// Attach the new buffer
dstList.attachBuffer((Byte*)newBuffer, count, count);
@@ -377,20 +174,20 @@ struct StructFuncs
// Free the old buffer
if (oldBuffer)
{
- typeFuncs.dtorArray(elementType, oldBuffer, dstCapacity);
+ typeFuncs.dtorArray(typeMap, elementType, oldBuffer, dstCapacity);
::free(oldBuffer);
}
}
else
{
- typeFuncs.copyArray(elementType, dstList.getBuffer(), srcList.getBuffer(), srcCount);
+ typeFuncs.copyArray(typeMap, elementType, dstList.getBuffer(), srcList.getBuffer(), srcCount);
dstList.unsafeShrinkToCount(srcCount);
}
}
}
- static void dtorArray(const RttiInfo* rttiInfo, void* inDst, Index count)
+ static void dtorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, Index count)
{
SLANG_ASSERT(rttiInfo->m_kind == RttiInfo::Kind::List);
const ListRttiInfo* listRttiInfo = static_cast<const ListRttiInfo*>(rttiInfo);
@@ -398,7 +195,7 @@ struct StructFuncs
const auto elementType = listRttiInfo->m_elementType;
// We need to get the type funcs
- auto typeFuncs = RttiUtil::getTypeFuncs(elementType);
+ auto typeFuncs = typeMap->getFuncsForType(elementType);
SLANG_ASSERT(typeFuncs.isValid());
typedef List<Byte> Type;
@@ -413,7 +210,7 @@ struct StructFuncs
if (buffer)
{
- typeFuncs.dtorArray(elementType, buffer, capacity);
+ typeFuncs.dtorArray(typeMap, elementType, buffer, capacity);
::free(buffer);
}
}
@@ -429,40 +226,45 @@ struct StructFuncs
}
};
-static void _ctorStructArray(const RttiInfo* rttiInfo, void* inDst, Index count)
+struct StructArrayFuncs
{
- RttiUtil::ctorArray(rttiInfo, inDst, rttiInfo->m_size, count);
-}
+ static void ctorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, Index count)
+ {
+ return RttiUtil::ctorArray(typeMap, rttiInfo, inDst, rttiInfo->m_size, count);
+ }
-static void _copyStructArray(const RttiInfo* rttiInfo, void* inDst, const void* inSrc, Index count)
-{
- RttiUtil::copyArray(rttiInfo, inDst, inSrc, rttiInfo->m_size, count);
-}
+ static void copyArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, const void* inSrc, Index count)
+ {
+ return RttiUtil::copyArray(typeMap, rttiInfo, inDst, inSrc, rttiInfo->m_size, count);
+ }
-static void _dtorStructArray(const RttiInfo* rttiInfo, void* inDst, Index count)
-{
- RttiUtil::dtorArray(rttiInfo, inDst, rttiInfo->m_size, count);
-}
+ static void dtorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, Index count)
+ {
+ return RttiUtil::dtorArray(typeMap, rttiInfo, inDst, rttiInfo->m_size, count);
+ }
-static RttiTypeFuncs _getStructTypeFuncs()
-{
- RttiTypeFuncs funcs;
- funcs.copyArray = _copyStructArray;
- funcs.dtorArray = _dtorStructArray;
- funcs.ctorArray = _ctorStructArray;
- return funcs;
-}
+ static RttiTypeFuncs getFuncs()
+ {
+ RttiTypeFuncs funcs;
+ funcs.copyArray = copyArray;
+ funcs.dtorArray = dtorArray;
+ funcs.ctorArray = ctorArray;
+ return funcs;
+ }
+};
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! RttiUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
+RttiTypeFuncs RttiUtil::getDefaultTypeFuncs(const RttiInfo* rttiInfo)
{
if (rttiInfo->isBuiltIn())
{
switch (rttiInfo->m_size)
{
- case 1: return GetRttiTypeFuncsForBuiltIn<uint8_t>::getFuncs();
- case 2: return GetRttiTypeFuncsForBuiltIn<uint16_t>::getFuncs();
- case 4: return GetRttiTypeFuncsForBuiltIn<uint32_t>::getFuncs();
- case 8: return GetRttiTypeFuncsForBuiltIn<uint64_t>::getFuncs();
+ case 1: return GetRttiTypeFuncsForZeroPod<uint8_t>::getFuncs();
+ case 2: return GetRttiTypeFuncsForZeroPod<uint16_t>::getFuncs();
+ case 4: return GetRttiTypeFuncsForZeroPod<uint32_t>::getFuncs();
+ case 8: return GetRttiTypeFuncsForZeroPod<uint64_t>::getFuncs();
}
return RttiTypeFuncs::makeEmpty();
}
@@ -472,14 +274,202 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
case RttiInfo::Kind::String: return GetRttiTypeFuncs<String>::getFuncs();
case RttiInfo::Kind::UnownedStringSlice: return GetRttiTypeFuncs<UnownedStringSlice>::getFuncs();
case RttiInfo::Kind::List: return ListFuncs::getFuncs();
- case RttiInfo::Kind::Struct: return _getStructTypeFuncs();
+ case RttiInfo::Kind::Struct: return StructArrayFuncs::getFuncs();
default: break;
}
return RttiTypeFuncs::makeEmpty();
}
-/* static */SlangResult RttiUtil::setListCount(const RttiInfo* elementType, void* dst, Index count)
+/* static */SlangResult RttiUtil::setInt(int64_t value, const RttiInfo* rttiInfo, void* dst)
+{
+ SLANG_ASSERT(rttiInfo->isIntegral());
+
+ // We could check ranges are appropriate, but for now we just write.
+ // Passing in rttiInfo allows for other more complex types to be econverted
+ switch (rttiInfo->m_kind)
+ {
+ case RttiInfo::Kind::I32: *(int32_t*)dst = int32_t(value); break;
+ case RttiInfo::Kind::U32: *(uint32_t*)dst = uint32_t(value); break;
+ case RttiInfo::Kind::I64: *(int64_t*)dst = int64_t(value); break;
+ case RttiInfo::Kind::U64: *(uint64_t*)dst = uint64_t(value); break;
+ default: return SLANG_FAIL;
+ }
+ return SLANG_OK;
+}
+
+/* static */int64_t RttiUtil::getInt64(const RttiInfo* rttiInfo, const void* src)
+{
+ SLANG_ASSERT(rttiInfo->isIntegral());
+
+ switch (rttiInfo->m_kind)
+ {
+ case RttiInfo::Kind::I32: return *(const int32_t*)src;
+ case RttiInfo::Kind::U32: return *(const uint32_t*)src;
+ case RttiInfo::Kind::I64: return *(const int64_t*)src;
+ case RttiInfo::Kind::U64: return *(const uint64_t*)src;
+ default: break;
+ }
+
+ SLANG_ASSERT(!"Not integral!");
+ return -1;
+}
+
+/* static */double RttiUtil::asDouble(const RttiInfo* rttiInfo, const void* src)
+{
+ if (rttiInfo->isIntegral())
+ {
+ return (double)getInt64(rttiInfo, src);
+ }
+ else if (rttiInfo->isFloat())
+ {
+ switch (rttiInfo->m_kind)
+ {
+ case RttiInfo::Kind::F32: return *(const float*)src;
+ case RttiInfo::Kind::F64: return *(const double*)src;
+ default: break;
+ }
+ }
+
+ SLANG_ASSERT(!"Cannot convert to float");
+ return 0.0;
+}
+
+/* static */SlangResult RttiUtil::setFromDouble(double v, const RttiInfo* rttiInfo, void* dst)
+{
+ if (rttiInfo->isIntegral())
+ {
+ return setInt(int64_t(v), rttiInfo, dst);
+ }
+ else if (rttiInfo->isFloat())
+ {
+ switch (rttiInfo->m_kind)
+ {
+ case RttiInfo::Kind::F32: *(float*)dst = float(v); return SLANG_OK;
+ case RttiInfo::Kind::F64: *(double*)dst = v; return SLANG_OK;
+ default: break;
+ }
+ }
+
+ return SLANG_FAIL;
+}
+
+/* static */bool RttiUtil::asBool(const RttiInfo* rttiInfo, const void* src)
+{
+ if (rttiInfo->m_kind == RttiInfo::Kind::Bool)
+ {
+ return *(const bool*)src;
+ }
+
+ if (rttiInfo->isIntegral())
+ {
+ return getInt64(rttiInfo, src) != 0;
+ }
+ else if (rttiInfo->isFloat())
+ {
+ return asDouble(rttiInfo, src) != 0.0;
+ }
+
+ SLANG_ASSERT(!"Cannot convert to bool");
+ return false;
+}
+
+static int64_t _getIntDefaultValue(RttiDefaultValue value)
+{
+ switch (value)
+ {
+ default:
+ case RttiDefaultValue::Normal: return 0;
+ case RttiDefaultValue::One: return 1;
+ case RttiDefaultValue::MinusOne: return -1;
+ }
+}
+
+static bool _isStructDefault(const StructRttiInfo* type, const void* src)
+{
+ if (type->m_super)
+ {
+ if (!_isStructDefault(type->m_super, src))
+ {
+ return false;
+ }
+ }
+
+ const Byte* base = (const Byte*)src;
+
+ const Index count = type->m_fieldCount;
+ for (Index i = 0; i < count; ++i)
+ {
+ const auto& field = type->m_fields[i];
+
+ const RttiDefaultValue defaultValue = RttiDefaultValue(field.m_flags & uint8_t(RttiDefaultValue::Mask));
+
+ if (!RttiUtil::isDefault(defaultValue, field.m_type, base + field.m_offset))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* static */bool RttiUtil::isDefault(RttiDefaultValue defaultValue, const RttiInfo* rttiInfo, const void* src)
+{
+ if (rttiInfo->isIntegral())
+ {
+ const auto value = getInt64(rttiInfo, src);
+ return _getIntDefaultValue(defaultValue) == value;
+ }
+ else if (rttiInfo->isFloat())
+ {
+ const auto value = asDouble(rttiInfo, src);
+ return _getIntDefaultValue(defaultValue) == value;
+ }
+
+ switch (rttiInfo->m_kind)
+ {
+ case RttiInfo::Kind::Invalid: return true;
+ case RttiInfo::Kind::Bool: return *(const bool*)src == (_getIntDefaultValue(defaultValue) != 0);
+ case RttiInfo::Kind::String:
+ {
+ return ((const String*)src)->getLength() == 0;
+ }
+ case RttiInfo::Kind::UnownedStringSlice:
+ {
+ return ((const UnownedStringSlice*)src)->getLength() == 0;
+ }
+ case RttiInfo::Kind::Struct:
+ {
+ return _isStructDefault(static_cast<const StructRttiInfo*>(rttiInfo), src);
+ }
+ case RttiInfo::Kind::Enum:
+ {
+ SLANG_ASSERT(!"Not implemented yet");
+ return false;
+ }
+ case RttiInfo::Kind::List:
+ {
+ const auto& v = *(const List<Byte>*)src;
+ return v.getCount() == 0;
+ }
+ case RttiInfo::Kind::Dictionary:
+ {
+ const auto& v = *(const Dictionary<Byte, Byte>*)src;
+ return v.Count() == 0;
+ }
+ case RttiInfo::Kind::Other:
+ {
+ const OtherRttiInfo* otherRttiInfo = static_cast<const OtherRttiInfo*>(rttiInfo);
+ return otherRttiInfo->m_isDefaultFunc && otherRttiInfo->m_isDefaultFunc(rttiInfo, src);
+ }
+ default:
+ {
+ return false;
+ }
+ }
+}
+
+/* static */SlangResult RttiUtil::setListCount(RttiTypeFuncsMap* typeMap, const RttiInfo* elementType, void* dst, Index count)
{
// NOTE! The following only works because List<T> has capacity initialized members, and
// setting the count if it is <= capacity just sets the count (ie things aren't released(!)).
@@ -496,22 +486,17 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
return SLANG_OK;
}
- // Get funcs needed
- const auto typeFuncs = RttiUtil::getTypeFuncs(elementType);
-
- if (!typeFuncs.isValid())
- {
- return SLANG_FAIL;
- }
+ const auto typeFuncs = typeMap->getFuncsForType(elementType);
+ SLANG_ASSERT(typeFuncs.isValid());
const Index dstCapacity = dstList.getCapacity();
void* oldBuffer = dstList.detachBuffer();
void* newBuffer = ::malloc(count * elementType->m_size);
// Initialize it all first
- typeFuncs.ctorArray(elementType, newBuffer, count);
+ typeFuncs.ctorArray(typeMap, elementType, newBuffer, count);
- typeFuncs.copyArray(elementType, newBuffer, oldBuffer, oldCount);
+ typeFuncs.copyArray(typeMap, elementType, newBuffer, oldBuffer, oldCount);
// Attach the new buffer
dstList.attachBuffer((Byte*)newBuffer, count, count);
@@ -519,7 +504,7 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
// Free the old buffer
if (oldBuffer)
{
- typeFuncs.dtorArray(elementType, oldBuffer, dstCapacity);
+ typeFuncs.dtorArray(typeMap, elementType, oldBuffer, dstCapacity);
::free(oldBuffer);
}
@@ -707,7 +692,7 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
}
}
-/* static */void RttiUtil::ctorArray(const RttiInfo* rttiInfo, void* inDst, ptrdiff_t stride, Index count)
+/* static */void RttiUtil::ctorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, ptrdiff_t stride, Index count)
{
if (count <= 0)
{
@@ -741,14 +726,14 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
if (fixedArrayRttiInfo->m_size == stride)
{
// It's contiguous do in one go
- ctorArray(fixedArrayRttiInfo->m_elementType, dst, fixedArrayRttiInfo->m_elementType->m_size, fixedArrayRttiInfo->m_elementCount * count);
+ ctorArray(typeMap, fixedArrayRttiInfo->m_elementType, dst, fixedArrayRttiInfo->m_elementType->m_size, fixedArrayRttiInfo->m_elementCount * count);
}
else
{
// Do it in array runs
for (Index i = 0; i < count; ++i, dst += stride)
{
- ctorArray(fixedArrayRttiInfo->m_elementType, dst, fixedArrayRttiInfo->m_elementType->m_size, fixedArrayRttiInfo->m_elementCount);
+ ctorArray(typeMap, fixedArrayRttiInfo->m_elementType, dst, fixedArrayRttiInfo->m_elementType->m_size, fixedArrayRttiInfo->m_elementCount);
}
}
return;
@@ -757,19 +742,20 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
case RttiInfo::Kind::Dictionary:
case RttiInfo::Kind::Other:
{
- auto funcs = getTypeFuncs(rttiInfo);
+ auto funcs = typeMap->getFuncsForType(rttiInfo);
+ SLANG_ASSERT(funcs.isValid());
const OtherRttiInfo* otherRttiInfo = static_cast<const OtherRttiInfo*>(rttiInfo);
if (otherRttiInfo->m_size == stride)
{
- funcs.ctorArray(rttiInfo, dst, count);
+ funcs.ctorArray(typeMap, rttiInfo, dst, count);
}
else
{
// Do it in array runs
for (Index i = 0; i < count; ++i, dst += stride)
{
- funcs.ctorArray(rttiInfo, dst, 1);
+ funcs.ctorArray(typeMap, rttiInfo, dst, 1);
}
}
return;
@@ -787,7 +773,7 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
for (Index i = 0; i < fieldCount; ++i)
{
const auto& field = fields[i];
- ctorArray(field.m_type, dst + field.m_offset, stride, count);
+ ctorArray(typeMap, field.m_type, dst + field.m_offset, stride, count);
}
structRttiInfo = structRttiInfo->m_super;
}
@@ -800,7 +786,7 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
SLANG_ASSERT(!"Unexpected");
}
-/* static */void RttiUtil::copyArray(const RttiInfo* rttiInfo, void* inDst, const void* inSrc, ptrdiff_t stride, Index count)
+/* static */void RttiUtil::copyArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, const void* inSrc, ptrdiff_t stride, Index count)
{
if (count <= 0)
{
@@ -840,14 +826,14 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
if (ptrdiff_t(size) == stride)
{
// It's contiguous do in one go
- copyArray(elementType, dst, src, elementSize, elementCount * count);
+ copyArray(typeMap, elementType, dst, src, elementSize, elementCount * count);
}
else
{
// Do it in array runs
for (Index i = 0; i < count; ++i, dst += stride, src += stride)
{
- copyArray(elementType, dst, src, elementSize, elementCount);
+ copyArray(typeMap, elementType, dst, src, elementSize, elementCount);
}
}
return;
@@ -856,18 +842,19 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
case RttiInfo::Kind::Dictionary:
case RttiInfo::Kind::Other:
{
- auto funcs = getTypeFuncs(rttiInfo);
+ auto funcs = typeMap->getFuncsForType(rttiInfo);
+ SLANG_ASSERT(funcs.isValid());
const OtherRttiInfo* otherRttiInfo = static_cast<const OtherRttiInfo*>(rttiInfo);
if (otherRttiInfo->m_size == stride)
{
- funcs.copyArray(rttiInfo, dst, src, count);
+ funcs.copyArray(typeMap, rttiInfo, dst, src, count);
}
else
{
for (Index i = 0; i < count; ++i, dst += stride, src += stride)
{
- funcs.copyArray(rttiInfo, dst, src, 1);
+ funcs.copyArray(typeMap, rttiInfo, dst, src, 1);
}
}
return;
@@ -885,7 +872,7 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
for (Index i = 0; i < fieldCount; ++i)
{
const auto& field = fields[i];
- copyArray(field.m_type, dst + field.m_offset, src + field.m_offset, stride, count);
+ copyArray(typeMap, field.m_type, dst + field.m_offset, src + field.m_offset, stride, count);
}
structRttiInfo = structRttiInfo->m_super;
}
@@ -898,7 +885,7 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
SLANG_ASSERT(!"Unexpected");
}
-/* static */void RttiUtil::dtorArray(const RttiInfo* rttiInfo, void* inDst, ptrdiff_t stride, Index count)
+/* static */void RttiUtil::dtorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, ptrdiff_t stride, Index count)
{
if (count <= 0 || !hasDtor(rttiInfo))
{
@@ -920,14 +907,14 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
if (ptrdiff_t(size) == stride)
{
// It's contiguous do in one go
- dtorArray(elementType, dst, elementSize, elementCount * count);
+ dtorArray(typeMap, elementType, dst, elementSize, elementCount * count);
}
else
{
// Do it in array runs
for (Index i = 0; i < count; ++i, dst += stride)
{
- dtorArray(elementType, dst, elementSize, elementCount);
+ dtorArray(typeMap, elementType, dst, elementSize, elementCount);
}
}
return;
@@ -936,18 +923,19 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
case RttiInfo::Kind::Dictionary:
case RttiInfo::Kind::Other:
{
- auto funcs = getTypeFuncs(rttiInfo);
+ auto funcs = typeMap->getFuncsForType(rttiInfo);
+ SLANG_ASSERT(funcs.isValid());
const OtherRttiInfo* otherRttiInfo = static_cast<const OtherRttiInfo*>(rttiInfo);
if (otherRttiInfo->m_size == stride)
{
- funcs.dtorArray(rttiInfo, dst, count);
+ funcs.dtorArray(typeMap, rttiInfo, dst, count);
}
else
{
for (Index i = 0; i < count; ++i, dst += stride)
{
- funcs.dtorArray(rttiInfo, dst, 1);
+ funcs.dtorArray(typeMap, rttiInfo, dst, 1);
}
}
return;
@@ -965,7 +953,7 @@ RttiTypeFuncs RttiUtil::getTypeFuncs(const RttiInfo* rttiInfo)
for (Index i = 0; i < fieldCount; ++i)
{
const auto& field = fields[i];
- dtorArray(field.m_type, dst + field.m_offset, stride, count);
+ dtorArray(typeMap, field.m_type, dst + field.m_offset, stride, count);
}
structRttiInfo = structRttiInfo->m_super;
}
diff --git a/source/core/slang-rtti-util.h b/source/core/slang-rtti-util.h
index 741e1f847..cf513ecad 100644
--- a/source/core/slang-rtti-util.h
+++ b/source/core/slang-rtti-util.h
@@ -4,6 +4,8 @@
#include "slang-rtti-info.h"
namespace Slang {
+
+
struct RttiUtil
{
static SlangResult setInt(int64_t value, const RttiInfo* rttiInfo, void* dst);
@@ -17,10 +19,11 @@ struct RttiUtil
static bool isDefault(RttiDefaultValue defaultValue, const RttiInfo* rttiInfo, const void* src);
- static RttiTypeFuncs getTypeFuncs(const RttiInfo* rttiInfo);
+ /// Gets funcs for default scenarios
+ static RttiTypeFuncs getDefaultTypeFuncs(const RttiInfo* rttiInfo);
/// Set a list count
- static SlangResult setListCount(const RttiInfo* elementType, void* dst, Index count);
+ static SlangResult setListCount(RttiTypeFuncsMap* typeMap, const RttiInfo* elementType, void* dst, Index count);
/// Returns if the type can be zero initialized
static bool canZeroInit(const RttiInfo* type);
@@ -29,9 +32,9 @@ struct RttiUtil
/// Returns true if we can memcpy to copy
static bool canMemCpy(const RttiInfo* type);
- static void ctorArray(const RttiInfo* rttiInfo, void* inDst, ptrdiff_t stride, Index count);
- static void copyArray(const RttiInfo* rttiInfo, void* inDst, const void* inSrc, ptrdiff_t stride, Index count);
- static void dtorArray(const RttiInfo* rttiInfo, void* inDst, ptrdiff_t stride, Index count);
+ static void ctorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, ptrdiff_t stride, Index count);
+ static void copyArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, const void* inSrc, ptrdiff_t stride, Index count);
+ static void dtorArray(RttiTypeFuncsMap* typeMap, const RttiInfo* rttiInfo, void* inDst, ptrdiff_t stride, Index count);
};
} // namespace Slang
diff --git a/source/slang/slang-language-server.cpp b/source/slang/slang-language-server.cpp
index 80d6e466b..25c6c1a01 100644
--- a/source/slang/slang-language-server.cpp
+++ b/source/slang/slang-language-server.cpp
@@ -45,6 +45,9 @@ ArrayView<const char*> getCommitChars()
SlangResult LanguageServer::init(const InitializeParams& args)
{
SLANG_RETURN_ON_FAIL(m_connection->initWithStdStreams(JSONRPCConnection::CallStyle::Object));
+
+ m_typeMap = JSONNativeUtil::getTypeFuncsMap();
+
m_workspaceFolders = args.workspaceFolders;
m_workspace = new Workspace();
List<URI> rootUris;
@@ -1436,7 +1439,7 @@ void LanguageServer::updatePredefinedMacros(const JSONValue& macros)
if (macros.isValid())
{
auto container = m_connection->getContainer();
- JSONToNativeConverter converter(container, m_connection->getSink());
+ JSONToNativeConverter converter(container, &m_typeMap, m_connection->getSink());
List<String> predefinedMacros;
if (SLANG_SUCCEEDED(converter.convert(macros, &predefinedMacros)))
{
@@ -1453,7 +1456,7 @@ void LanguageServer::updateSearchPaths(const JSONValue& value)
if (value.isValid())
{
auto container = m_connection->getContainer();
- JSONToNativeConverter converter(container, m_connection->getSink());
+ JSONToNativeConverter converter(container, &m_typeMap, m_connection->getSink());
List<String> searchPaths;
if (SLANG_SUCCEEDED(converter.convert(value, &searchPaths)))
{
@@ -1470,7 +1473,7 @@ void LanguageServer::updateSearchInWorkspace(const JSONValue& value)
if (value.isValid())
{
auto container = m_connection->getContainer();
- JSONToNativeConverter converter(container, m_connection->getSink());
+ JSONToNativeConverter converter(container, &m_typeMap, m_connection->getSink());
bool searchPaths;
if (SLANG_SUCCEEDED(converter.convert(value, &searchPaths)))
{
@@ -1487,7 +1490,7 @@ void LanguageServer::updateCommitCharacters(const JSONValue& jsonValue)
if (jsonValue.isValid())
{
auto container = m_connection->getContainer();
- JSONToNativeConverter converter(container, m_connection->getSink());
+ JSONToNativeConverter converter(container, &m_typeMap, m_connection->getSink());
String value;
if (SLANG_SUCCEEDED(converter.convert(jsonValue, &value)))
{
@@ -1510,7 +1513,7 @@ void LanguageServer::updateCommitCharacters(const JSONValue& jsonValue)
void LanguageServer::updateFormattingOptions(const JSONValue& clangFormatLoc, const JSONValue& clangFormatStyle, const JSONValue& clangFormatFallbackStyle, const JSONValue& allowLineBreakOnType, const JSONValue& allowLineBreakInRange)
{
auto container = m_connection->getContainer();
- JSONToNativeConverter converter(container, m_connection->getSink());
+ JSONToNativeConverter converter(container, &m_typeMap, m_connection->getSink());
converter.convert(clangFormatLoc, &m_formatOptions.clangFormatLocation);
converter.convert(clangFormatStyle, &m_formatOptions.style);
converter.convert(clangFormatFallbackStyle, &m_formatOptions.fallbackStyle);
@@ -1523,7 +1526,7 @@ void LanguageServer::updateFormattingOptions(const JSONValue& clangFormatLoc, co
void LanguageServer::updateInlayHintOptions(const JSONValue& deducedTypes, const JSONValue& parameterNames)
{
auto container = m_connection->getContainer();
- JSONToNativeConverter converter(container, m_connection->getSink());
+ JSONToNativeConverter converter(container, &m_typeMap, m_connection->getSink());
bool showDeducedType = false;
bool showParameterNames = false;
converter.convert(deducedTypes, &showDeducedType);
@@ -1542,7 +1545,7 @@ void LanguageServer::updateTraceOptions(const JSONValue& value)
if (value.isValid())
{
auto container = m_connection->getContainer();
- JSONToNativeConverter converter(container, m_connection->getSink());
+ JSONToNativeConverter converter(container, &m_typeMap, m_connection->getSink());
String str;
if (SLANG_SUCCEEDED(converter.convert(value, &str)))
{
diff --git a/source/slang/slang-language-server.h b/source/slang/slang-language-server.h
index 07c7fcfaa..175ccf0f1 100644
--- a/source/slang/slang-language-server.h
+++ b/source/slang/slang-language-server.h
@@ -100,7 +100,8 @@ public:
Slang::InlayHintOptions m_inlayHintOptions;
bool m_quit = false;
List<LanguageServerProtocol::WorkspaceFolder> m_workspaceFolders;
-
+ RttiTypeFuncsMap m_typeMap;
+
SlangResult init(const LanguageServerProtocol::InitializeParams& args);
SlangResult execute();
void update();