summaryrefslogtreecommitdiffstats
path: root/source/core
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2023-08-29 06:05:26 +0800
committerGitHub <noreply@github.com>2023-08-28 15:05:26 -0700
commit508dc3a95de50de4a4d07d0a72a18e40d55b0e2e (patch)
tree7487232f5c0db0dd607e2a91b539f6a592789b06 /source/core
parent06f7ef354cdde4cf8e8797d8853ed2d9c3208b5b (diff)
Allow bitwise or expressions and numeric literals in spirv_asm blocks (#3157)
* Add -spirv-core-grammar option to load alternate spirv defs Also embed a version to use by default * Use perfect hash for spv op lookup * Neaten perfect hash embedding * Refactor spirv grammar lookup in preperation for more kinds of lookups * Load spirv capability list from spec * Add all SPIR-V enums to lookup table * regenerate vs projects * appease msvc * Use string slices for spir-v core grammar lookups * wiggle * comment * Add OpInfo for spv ops * regenerate vs projects * Embed op names * Add min/max operand counts and enum categories to spirv info * neaten * Operand kinds for spirv ops * Store and embed all information relating to spirv enums and qualifiers * Use SPIR-V spec to position instructions in spirv_asm blocks * Neaten spir-v info embedding * Neaten perfect hash embedding * Add assignment syntax to spirv_asm snippets * Better errors for spirv_asm parser * Add warning for too many operands in spirv asm * squash warnings * neaten * test wiggle * Lookup enums for spirv * Put OpCapability and OpExtension in the correct place for spirv_asm blocks * Tests for OpCapability and OpExtension * ci wiggle * Add expected failure * Allow raising immediate values to constant ids where necessary in spirv_asm blocks * Allow bitwise or expressions and numeric literals in spirv_asm blocks * test numeric literals * Fix memory issues. * fix. --------- Co-authored-by: Yong He <yonghe@outlook.com>
Diffstat (limited to 'source/core')
-rw-r--r--source/core/slang-char-util.h4
-rw-r--r--source/core/slang-common.h47
-rw-r--r--source/core/slang-dictionary.h11
-rw-r--r--source/core/slang-hash.h14
-rw-r--r--source/core/slang-rtti-util.h47
-rw-r--r--source/core/slang-string-slice-pool.cpp3
-rw-r--r--source/core/slang-string-util.cpp21
7 files changed, 139 insertions, 8 deletions
diff --git a/source/core/slang-char-util.h b/source/core/slang-char-util.h
index 1ed8f7f73..c65f676c4 100644
--- a/source/core/slang-char-util.h
+++ b/source/core/slang-char-util.h
@@ -50,6 +50,10 @@ struct CharUtil
/// Given a value between 0-15 inclusive returns the hex digit. Uses lower case hex.
SLANG_FORCE_INLINE static char getHexChar(Index i) { SLANG_ASSERT((i & ~Index(0xf)) == 0); return char(i >= 10 ? (i - 10 + 'a') : (i + '0')); }
+ /// Returns the value if c interpretted as a decimal digit
+ /// If c is not a valid digit returns -1
+ inline static int getDecimalDigitValue(char c) { return isDigit(c) ? (c - '0') : -1; }
+
/// Returns the value if c interpretted as a hex digit
/// If c is not a valid hex returns -1
inline static int getHexDigitValue(char c);
diff --git a/source/core/slang-common.h b/source/core/slang-common.h
index 62c73df08..9e73b50a9 100644
--- a/source/core/slang-common.h
+++ b/source/core/slang-common.h
@@ -84,6 +84,53 @@ namespace Slang
}
}
+//
+// Some macros for avoiding boilerplate
+// TODO: could probably deduce the size with templates, and move the whole
+// thing into a template
+//
+#if __cplusplus >= 202002L
+#define SLANG_COMPONENTWISE_EQUALITY_1(type) bool operator==(const type& other) const = default;
+#define SLANG_COMPONENTWISE_EQUALITY_2(type) bool operator==(const type& other) const = default;
+#define SLANG_COMPONENTWISE_EQUALITY_3(type) bool operator==(const type& other) const = default;
+#else
+#define SLANG_COMPONENTWISE_EQUALITY_1(type) \
+ bool operator==(const type& other) const \
+ { \
+ const auto& [m1] = *this; \
+ const auto& [o1] = other; \
+ return m1 == o1; \
+ } \
+ bool operator!=(const type& other) const \
+ { \
+ return !(*this == other); \
+ }
+
+#define SLANG_COMPONENTWISE_EQUALITY_2(type) \
+ bool operator==(const type& other) const \
+ { \
+ const auto& [m1, m2] = *this; \
+ const auto& [o1, o2] = other; \
+ return m1 == o1 && m2 == o2; \
+ } \
+ bool operator!=(const type& other) const \
+ { \
+ return !(*this == other); \
+ }
+
+#define SLANG_COMPONENTWISE_EQUALITY_3(type) \
+ bool operator==(const type& other) const \
+ { \
+ const auto& [m1, m2, m3] = *this; \
+ const auto& [o1, o2, o3] = other; \
+ return m1 == o1 && m2 == o2 && m3 == o3; \
+ } \
+ bool operator!=(const type& other) const \
+ { \
+ return !(*this == other); \
+ }
+#endif
+
// TODO: Shouldn't these be SLANG_ prefixed?
#ifdef _MSC_VER
#define UNREACHABLE_RETURN(x)
diff --git a/source/core/slang-dictionary.h b/source/core/slang-dictionary.h
index c7c0c8e05..ff7e201bf 100644
--- a/source/core/slang-dictionary.h
+++ b/source/core/slang-dictionary.h
@@ -9,6 +9,7 @@
#include "slang-math.h"
#include "slang-hash.h"
#include "../../external/unordered_dense/include/ankerl/unordered_dense.h"
+#include <initializer_list>
namespace Slang
{
@@ -87,6 +88,16 @@ namespace Slang
using ThisType = Dictionary<TKey, TValue, Hash, KeyEqual>;
InnerMap map;
public:
+ Dictionary() = default;
+ Dictionary(const Dictionary&) = default;
+ Dictionary(Dictionary&&) = default;
+ ThisType& operator=(const ThisType&) = default;
+ ThisType& operator=(ThisType&&) = default;
+ Dictionary(std::initializer_list<typename InnerMap::value_type> inits)
+ : map(std::move(inits))
+ {
+ }
+
//
// Types
//
diff --git a/source/core/slang-hash.h b/source/core/slang-hash.h
index 49685ee65..9a173c4f8 100644
--- a/source/core/slang-hash.h
+++ b/source/core/slang-hash.h
@@ -147,6 +147,20 @@ namespace Slang
return ::Slang::hashObjectBytes(*this); \
}
+# define SLANG_COMPONENTWISE_HASHABLE_1 \
+ auto getHashCode() const \
+ { \
+ const auto& [m1] = *this; \
+ return Slang::getHashCode(m1); \
+ }
+
+# define SLANG_COMPONENTWISE_HASHABLE_2 \
+ auto getHashCode() const \
+ { \
+ const auto& [m1, m2] = *this; \
+ return combineHash(::Slang::getHashCode(m1), ::Slang::getHashCode(m2)); \
+ }
+
inline HashCode64 combineHash(HashCode64 h)
{
return h;
diff --git a/source/core/slang-rtti-util.h b/source/core/slang-rtti-util.h
index cf513ecad..4807c5ea2 100644
--- a/source/core/slang-rtti-util.h
+++ b/source/core/slang-rtti-util.h
@@ -3,8 +3,53 @@
#include "slang-rtti-info.h"
-namespace Slang {
+// Some macros to help generate StructRttiInfo for structs without too much
+// boilerplate, use as so:
+//
+// struct MyStruct
+// {
+// int an_optional_field;
+// List<UnownedStringSlice> a_list_of_strings_field;
+// }
+// SLANG_MAKE_STRUCT_RTTI_INFO(
+// MyStruct,
+// SLANG_OPTIONAL_RTTI_FIELD(an_optional_field),
+// SLANG_RTTI_FIELD(a_list_of_strings_field)
+// );
+//
+// This allows parsing JSON objects like
+// {
+// "an_optional_field": 10,
+// "a_list_of_strings_field": ["hello", "world"]
+// }
+//
+// Convert from such JSON objects using JSONToNativeConverter::convert
+
+#define SLANG_MAKE_STRUCT_RTTI_INFO(S, ...) \
+ template<> \
+ struct GetRttiInfo<S> \
+ { \
+ static const RttiInfo* get() \
+ { \
+ using S_ = S; \
+ const static StructRttiInfo::Field fs[] = {__VA_ARGS__}; \
+ const auto ignoreUnknownFields = true; \
+ const static auto ret = StructRttiInfo{ \
+ {{RttiInfo::Kind::Struct, alignof(S), sizeof(S)}, #S}, \
+ nullptr, \
+ SLANG_COUNT_OF(fs), \
+ fs, \
+ ignoreUnknownFields \
+ }; \
+ return &ret; \
+ } \
+ };
+#define SLANG_RTTI_FIELD_IMPL(m, name, flags) \
+ {name, GetRttiInfo<decltype(S_::m)>::get(), offsetof(S_, m), flags}
+#define SLANG_RTTI_FIELD(m) SLANG_RTTI_FIELD_IMPL(m, #m, 0)
+#define SLANG_OPTIONAL_RTTI_FIELD(m) SLANG_RTTI_FIELD_IMPL(m, #m, StructRttiInfo::Flag::Optional)
+namespace Slang {
struct RttiUtil
{
diff --git a/source/core/slang-string-slice-pool.cpp b/source/core/slang-string-slice-pool.cpp
index 692bc2b9a..142952855 100644
--- a/source/core/slang-string-slice-pool.cpp
+++ b/source/core/slang-string-slice-pool.cpp
@@ -40,6 +40,9 @@ void StringSlicePool::_set(const ThisType& rhs)
const Index startIndex = rhs.getFirstAddedIndex();
const Count count = rhs.m_slices.getCount();
+ if (count == 0)
+ return;
+
// We need the same amount of slices
m_slices.setCount(count);
diff --git a/source/core/slang-string-util.cpp b/source/core/slang-string-util.cpp
index ac8a176ad..fb062de76 100644
--- a/source/core/slang-string-util.cpp
+++ b/source/core/slang-string-util.cpp
@@ -593,22 +593,29 @@ ComPtr<ISlangBlob> StringUtil::createStringBlob(const String& string)
cur++;
}
+ int radix = 10;
+ auto getDigit = CharUtil::getDecimalDigitValue;
+ if (cur+1 < end && *cur == '0' && (*(cur+1) == 'x' || *(cur+1) == 'X'))
+ {
+ radix = 16;
+ getDigit = CharUtil::getHexDigitValue;
+ cur += 2;
+ }
+
// We need at least one digit
if (cur >= end || !CharUtil::isDigit(*cur))
{
return SLANG_FAIL;
}
- Int value = *cur++ - '0';
- // Do the remaining digits
+ Int value = 0;
+ // Do the digits
for (; cur < end; ++cur)
{
- const char c = *cur;
- if (!CharUtil::isDigit(c))
- {
+ const auto d = getDigit(*cur);
+ if (d == -1)
return SLANG_FAIL;
- }
- value = value * 10 + (c - '0');
+ value = value * radix + d;
}
value = negate ? -value : value;