summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2023-08-16 08:57:47 +0800
committerGitHub <noreply@github.com>2023-08-16 08:57:47 +0800
commit45d9961a6a86d184248ef84f6a07125b0c224f97 (patch)
treec91d9b9aa722ceb727f7f1c8c2041d7d2bb13466 /source
parente34b005c47d265105e7bba509cadaa3e225237af (diff)
Use ankerl/unordered_dense as a hashmap implementation (#3036)
* Correct namespace for getClockFrequency * missing const * Add missing assignment operator * Remove unused variables * Return correct modified variable * Use stable hash code for file system identity * terse static_assert * Structured binding for map iteration * Make (==) and getHashCode const on many structs * Add ConstIterator for LinkedList * Replace uses of ItemProxy::getValue with Dictionary::at * Extract list of loads from gradientsMap before updating it * Const correctness in type layout * Add unordered_dense hashmap submodule * Use wyhash or getHashCode in slang-hash.h * refactor slang-hash.h * Use ankerl/unordered_dense as a hashmap implementation Notable changes: - The subscript operator returns a reference directly to the value, rather than a lazy ItemProxy (pair of dict pointer and key) slang-profile time (95% over 10 runs): - Before: 6.3913906 (±0.0746) - After: 5.9276123 (±0.0964) * 64 bit hash for strings So they have the same hash as char buffers with the same contents * Narrowing warnings for gcc to match msvc * revert back to c++17 * Correct c++ version for msvc * Use path to unordered_dense which keeps tests happy * Do not assign to and read from map in same expression * Remove redundant map operations in primal-hoist * Split out stable hash functions into slang-stable-hash.h * 64 bit hash by default * regenerate vs projects * Correct return type from HashSetBase::getCount() * correct width for call to Dictionary::reserve * Use stable hash for obfuscated module ids * Signed int for reserve * clearer variable naming * Parameterize Dictionary on hash and equality functors * Allow heterogenous lookup for Dictionary * missing const * Use set over operator[] in some places * Remove unused function * s/at/getValue
Diffstat (limited to 'source')
-rw-r--r--source/compiler-core/slang-source-loc.cpp1
-rw-r--r--source/compiler-core/slang-visual-studio-compiler-util.cpp7
-rw-r--r--source/core/slang-dictionary.h637
-rw-r--r--source/core/slang-file-system.cpp19
-rw-r--r--source/core/slang-hash.h282
-rw-r--r--source/core/slang-hex-dump-util.cpp10
-rw-r--r--source/core/slang-linked-list.h39
-rw-r--r--source/core/slang-memory-file-system.cpp10
-rw-r--r--source/core/slang-riff-file-system.cpp18
-rw-r--r--source/core/slang-smart-pointer.h2
-rw-r--r--source/core/slang-stable-hash.h99
-rw-r--r--source/core/slang-string.cpp18
-rw-r--r--source/core/slang-string.h27
-rw-r--r--source/slang/slang-ast-base.h4
-rw-r--r--source/slang/slang-ast-builder.cpp12
-rw-r--r--source/slang/slang-ast-builder.h33
-rw-r--r--source/slang/slang-ast-dump.cpp5
-rw-r--r--source/slang/slang-ast-support-types.h2
-rw-r--r--source/slang/slang-check-decl.cpp26
-rw-r--r--source/slang/slang-check-impl.h6
-rw-r--r--source/slang/slang-compiler.cpp24
-rwxr-xr-xsource/slang/slang-compiler.h4
-rw-r--r--source/slang/slang-doc-markdown-writer.cpp4
-rw-r--r--source/slang/slang-emit-c-like.cpp7
-rw-r--r--source/slang/slang-emit-source-writer.cpp31
-rw-r--r--source/slang/slang-emit-source-writer.h8
-rw-r--r--source/slang/slang-emit-spirv.cpp3
-rw-r--r--source/slang/slang-ir-any-value-marshalling.cpp2
-rw-r--r--source/slang/slang-ir-autodiff-fwd.cpp6
-rw-r--r--source/slang/slang-ir-autodiff-primal-hoist.cpp19
-rw-r--r--source/slang/slang-ir-autodiff-primal-hoist.h37
-rw-r--r--source/slang/slang-ir-autodiff-rev.cpp4
-rw-r--r--source/slang/slang-ir-autodiff-transpose.h25
-rw-r--r--source/slang/slang-ir-autodiff-unzip.cpp2
-rw-r--r--source/slang/slang-ir-autodiff-unzip.h7
-rw-r--r--source/slang/slang-ir-autodiff.cpp2
-rw-r--r--source/slang/slang-ir-eliminate-multilevel-break.cpp4
-rw-r--r--source/slang/slang-ir-eliminate-phis.cpp12
-rw-r--r--source/slang/slang-ir-generics-lowering-context.cpp2
-rw-r--r--source/slang/slang-ir-glsl-legalize.cpp4
-rw-r--r--source/slang/slang-ir-inline.cpp4
-rw-r--r--source/slang/slang-ir-link.cpp6
-rw-r--r--source/slang/slang-ir-lower-generic-function.cpp6
-rw-r--r--source/slang/slang-ir-lower-optional-type.cpp6
-rw-r--r--source/slang/slang-ir-lower-result-type.cpp6
-rw-r--r--source/slang/slang-ir-lower-tuple-types.cpp6
-rw-r--r--source/slang/slang-ir-obfuscate-loc.cpp11
-rw-r--r--source/slang/slang-ir-reachability.h10
-rw-r--r--source/slang/slang-ir-specialize-dispatch.cpp4
-rw-r--r--source/slang/slang-ir-specialize.cpp12
-rw-r--r--source/slang/slang-ir-spirv-snippet.cpp2
-rw-r--r--source/slang/slang-ir-spirv-snippet.h4
-rw-r--r--source/slang/slang-ir.h1
-rw-r--r--source/slang/slang-language-server.cpp20
-rw-r--r--source/slang/slang-mangle.cpp2
-rw-r--r--source/slang/slang-parameter-binding.cpp48
-rw-r--r--source/slang/slang-preprocessor.cpp11
-rw-r--r--source/slang/slang-reflection-api.cpp4
-rw-r--r--source/slang/slang-repro.cpp45
-rw-r--r--source/slang/slang-repro.h3
-rw-r--r--source/slang/slang-serialize-ir.h2
-rw-r--r--source/slang/slang-serialize-source-loc.cpp3
-rw-r--r--source/slang/slang-type-layout.cpp48
-rw-r--r--source/slang/slang-type-layout.h9
-rw-r--r--source/slang/slang-workspace-version.cpp4
-rw-r--r--source/slang/slang.cpp33
66 files changed, 783 insertions, 991 deletions
diff --git a/source/compiler-core/slang-source-loc.cpp b/source/compiler-core/slang-source-loc.cpp
index f9014e0d8..33f93074e 100644
--- a/source/compiler-core/slang-source-loc.cpp
+++ b/source/compiler-core/slang-source-loc.cpp
@@ -318,7 +318,6 @@ SlangResult SourceView::_findSourceMapLoc(SourceLoc loc, SourceLocType type, Han
// view, which may be a parent to the current one.
auto lookupSourceManager = m_sourceFile->getSourceManager();
- HandleSourceLoc handleLoc;
SLANG_RETURN_ON_FAIL(_findLocWithSourceMap(lookupSourceManager, this, loc, type, outLoc));
return SLANG_OK;
diff --git a/source/compiler-core/slang-visual-studio-compiler-util.cpp b/source/compiler-core/slang-visual-studio-compiler-util.cpp
index 81e00d73e..14fad0aec 100644
--- a/source/compiler-core/slang-visual-studio-compiler-util.cpp
+++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp
@@ -83,14 +83,17 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa
// Display full path of source files in diagnostics
cmdLine.addArg("/FC");
- if (options.flags & CompileOptions::Flag::EnableExceptionHandling)
+ if (options.sourceLanguage == SLANG_SOURCE_LANGUAGE_CPP)
{
- if (options.sourceLanguage == SLANG_SOURCE_LANGUAGE_CPP)
+ if (options.flags & CompileOptions::Flag::EnableExceptionHandling)
{
// https://docs.microsoft.com/en-us/cpp/build/reference/eh-exception-handling-model?view=vs-2019
// Assumes c functions cannot throw
cmdLine.addArg("/EHsc");
}
+
+ // To maintain parity with the slang compiler headers which are shared
+ cmdLine.addArg("/std:c++17");
}
if (options.flags & CompileOptions::Flag::Verbose)
diff --git a/source/core/slang-dictionary.h b/source/core/slang-dictionary.h
index 2c683abfe..c7c0c8e05 100644
--- a/source/core/slang-dictionary.h
+++ b/source/core/slang-dictionary.h
@@ -8,6 +8,7 @@
#include "slang-exception.h"
#include "slang-math.h"
#include "slang-hash.h"
+#include "../../external/unordered_dense/include/ankerl/unordered_dense.h"
namespace Slang
{
@@ -55,7 +56,7 @@ namespace Slang
value = that.value;
return *this;
}
- HashCode getHashCode()
+ HashCode getHashCode() const
{
return combineHash(
Slang::getHashCode(key),
@@ -75,495 +76,188 @@ namespace Slang
const float kMaxLoadFactor = 0.7f;
- template<typename TKey, typename TValue>
+ template<typename TKey, typename TValue, typename Hash = Slang::Hash<TKey>, typename KeyEqual = std::equal_to<TKey>>
class Dictionary
{
- friend class Iterator;
- friend class ItemProxy;
+ using InnerMap = ankerl::unordered_dense::map<
+ TKey,
+ TValue,
+ Hash,
+ KeyEqual>;
+ using ThisType = Dictionary<TKey, TValue, Hash, KeyEqual>;
+ InnerMap map;
public:
- typedef TValue ValueType;
- typedef TKey KeyType;
- typedef Dictionary ThisType;
- private:
- inline int getProbeOffset(int /*probeId*/) const
- {
- // linear probing
- return 1;
- }
- private:
- int m_bucketCountMinusOne;
- int m_count;
- UIntSet m_marks;
- KeyValuePair<TKey, TValue>* m_hashMap;
- void deallocateAll()
- {
- if (m_hashMap)
- delete[] m_hashMap;
- m_hashMap = nullptr;
- }
- inline bool isDeleted(int pos) const
- {
- return m_marks.contains((pos << 1) + 1);
- }
- inline bool isEmpty(int pos) const
- {
- return !m_marks.contains((pos << 1));
- }
- inline void setDeleted(int pos, bool val)
- {
- if (val)
- m_marks.add((pos << 1) + 1);
- else
- m_marks.remove((pos << 1) + 1);
- }
- inline void setEmpty(int pos, bool val)
- {
- if (val)
- m_marks.remove((pos << 1));
- else
- m_marks.add((pos << 1));
- }
- struct FindPositionResult
- {
- int objectPosition;
- int insertionPosition;
+ //
+ // Types
+ //
+ using Iterator = typename InnerMap::iterator;
+ using ConstIterator = typename InnerMap::const_iterator;
+ using KeyType = TKey;
+ using ValueType = TValue;
- FindPositionResult()
- {
- objectPosition = -1;
- insertionPosition = -1;
- }
- FindPositionResult(int objPos, int insertPos)
- {
- objectPosition = objPos;
- insertionPosition = insertPos;
- }
- };
- template<typename KeyType>
- inline int getHashPos(KeyType& key) const
- {
- SLANG_ASSERT(m_bucketCountMinusOne > 0);
- const unsigned int hash = (unsigned int)getHashCode(key);
- return (hash * 2654435761u) % (unsigned int)(m_bucketCountMinusOne);
- }
- template<typename KeyType>
- FindPositionResult findPosition(const KeyType& key) const
- {
- int hashPos = getHashPos(const_cast<KeyType&>(key));
- int insertPos = -1;
- int numProbes = 0;
- while (numProbes <= m_bucketCountMinusOne)
- {
- if (isEmpty(hashPos))
- {
- if (insertPos == -1)
- return FindPositionResult(-1, hashPos);
- else
- return FindPositionResult(-1, insertPos);
- }
- else if (isDeleted(hashPos))
- {
- if (insertPos == -1)
- insertPos = hashPos;
- }
- else if (m_hashMap[hashPos].key == key)
- {
- return FindPositionResult(hashPos, -1);
- }
- numProbes++;
- hashPos = (hashPos + getProbeOffset(numProbes)) & m_bucketCountMinusOne;
- }
- if (insertPos != -1)
- return FindPositionResult(-1, insertPos);
- SLANG_ASSERT_FAILURE("Hash map is full. This indicates an error in Key::Equal or Key::getHashCode.");
- }
- TValue& _insert(KeyValuePair<TKey, TValue>&& kvPair, int pos)
- {
- m_hashMap[pos] = _Move(kvPair);
- setEmpty(pos, false);
- setDeleted(pos, false);
- return m_hashMap[pos].value;
- }
- void maybeRehash()
- {
- if (m_bucketCountMinusOne == -1 || m_count >= int(kMaxLoadFactor * m_bucketCountMinusOne))
- {
- int newSize = (m_bucketCountMinusOne + 1) * 2;
- if (newSize == 0)
- {
- newSize = 64;
- }
- reserve(newSize);
- }
- }
+ //
+ // Iterators
+ //
- bool addIfNotExists(KeyValuePair<TKey, TValue>&& kvPair)
- {
- maybeRehash();
- auto pos = findPosition(kvPair.key);
- if (pos.objectPosition != -1)
- return false;
- else if (pos.insertionPosition != -1)
- {
- m_count++;
- _insert(_Move(kvPair), pos.insertionPosition);
- return true;
- }
- else
- SLANG_ASSERT_FAILURE("Inconsistent find result returned. This is a bug in Dictionary implementation.");
- }
- void add(KeyValuePair<TKey, TValue>&& kvPair)
- {
- if (!addIfNotExists(_Move(kvPair)))
- SLANG_ASSERT_FAILURE("The key already exists in Dictionary.");
- }
- TValue& set(KeyValuePair<TKey, TValue>&& kvPair)
- {
- maybeRehash();
- auto pos = findPosition(kvPair.key);
- if (pos.objectPosition != -1)
- return _insert(_Move(kvPair), pos.objectPosition);
- else if (pos.insertionPosition != -1)
- {
- m_count++;
- return _insert(_Move(kvPair), pos.insertionPosition);
- }
- else
- SLANG_ASSERT_FAILURE("Inconsistent find result returned. This is a bug in Dictionary implementation.");
- }
- public:
- class Iterator
- {
- private:
- const Dictionary<TKey, TValue>* dict;
- int pos;
- public:
- KeyValuePair<TKey, TValue>& operator*() const
- {
- return dict->m_hashMap[pos];
- }
- KeyValuePair<TKey, TValue>* operator->() const
- {
- return dict->m_hashMap + pos;
- }
- Iterator& operator++()
- {
- if (pos > dict->m_bucketCountMinusOne)
- return *this;
- pos++;
- while (pos <= dict->m_bucketCountMinusOne && (dict->isDeleted(pos) || dict->isEmpty(pos)))
- {
- pos++;
- }
- return *this;
- }
- Iterator operator++(int)
- {
- Iterator rs = *this;
- operator++();
- return rs;
- }
- bool operator!=(const Iterator& that) const
- {
- return pos != that.pos || dict != that.dict;
- }
- bool operator==(const Iterator& that) const
- {
- return pos == that.pos && dict == that.dict;
- }
- Iterator(const Dictionary<TKey, TValue>* inDict, int inPos)
- {
- this->dict = inDict;
- this->pos = inPos;
- }
- Iterator()
- {
- this->dict = nullptr;
- this->pos = 0;
- }
- };
+ auto begin() { return map.begin(); }
+ auto begin() const { return map.begin(); }
+ auto end() { return map.end(); }
+ auto end() const { return map.end(); }
- Iterator begin() const
- {
- int pos = 0;
- while (pos < m_bucketCountMinusOne + 1)
- {
- if (isEmpty(pos) || isDeleted(pos))
- pos++;
- else
- break;
- }
- return Iterator(this, pos);
- }
- Iterator end() const
- {
- return Iterator(this, m_bucketCountMinusOne + 1);
- }
- public:
- void add(const TKey& key, const TValue& value)
- {
- add(KeyValuePair<TKey, TValue>(key, value));
- }
- void add(TKey&& key, TValue&& value)
- {
- add(KeyValuePair<TKey, TValue>(_Move(key), _Move(value)));
- }
- bool addIfNotExists(const TKey& key, const TValue& value)
- {
- return addIfNotExists(KeyValuePair<TKey, TValue>(key, value));
- }
- bool addIfNotExists(TKey&& key, TValue&& value)
- {
- return addIfNotExists(KeyValuePair<TKey, TValue>(_Move(key), _Move(value)));
- }
- void remove(const TKey& key)
- {
- if (m_count == 0)
- return;
- auto pos = findPosition(key);
- if (pos.objectPosition != -1)
- {
- setDeleted(pos.objectPosition, true);
- m_count--;
- }
- }
- void clear()
- {
- m_count = 0;
- m_marks.clear();
- }
+ //
+ // Modifiers
+ //
- void reserve(int newSize)
- {
- if (newSize <= m_bucketCountMinusOne + 1)
- return;
+ // Removes all values from the map
+ void clear() { map.clear(); }
- Dictionary<TKey, TValue> newDict;
- newDict.m_bucketCountMinusOne = newSize - 1;
- newDict.m_hashMap = new KeyValuePair<TKey, TValue>[newSize];
- newDict.m_marks.resizeAndClear(newSize * 2);
- if (m_hashMap)
- {
- for (auto& kvPair : *this)
- {
- newDict.add(_Move(kvPair));
- }
- }
- *this = _Move(newDict);
- }
+ // Erases the value at the specified key if it exists
+ void remove(const TKey& key) { map.erase(key); }
- TValue* tryGetValueOrAdd(const TKey& key, const TValue& value)
- {
- maybeRehash();
- auto pos = findPosition(key);
- if (pos.objectPosition != -1)
- {
- return &m_hashMap[pos.objectPosition].value;
- }
- else if (pos.insertionPosition != -1)
- {
- // Make pair
- KeyValuePair<TKey, TValue> kvPair(_Move(key), _Move(value));
- m_count++;
- _insert(_Move(kvPair), pos.insertionPosition);
- return nullptr;
- }
- else
- SLANG_ASSERT_FAILURE("Inconsistent find result returned. This is a bug in Dictionary implementation.");
- }
+ // Reserves enough space for the specified number of values
+ void reserve(Index size) { map.reserve(std::size_t(size)); };
- /// This differs from tryGetValueOrAdd, in that it always returns the Value held in the Dictionary.
- /// If there isn't already an entry for 'key', a value is added with defaultValue.
- TValue& getOrAddValue(const TKey& key, const TValue& defaultValue)
+ // Swap with another map
+ void swapWith(ThisType& rhs) { std::swap(*this, rhs); }
+
+ //
+ // Query capacity
+ //
+
+ std::size_t getCount() const { return map.size(); }
+
+ //
+ // Lookup
+ //
+
+ // Returns true if the map contains an equivalent key
+ template<typename K>
+ bool containsKey(const K& k) const { return map.contains(k); }
+
+ // Returns a valid pointer to the requested element, or nullptr if it
+ // doesn't exist
+ template<typename K>
+ const TValue* tryGetValue(const K& key) const
{
- maybeRehash();
- auto pos = findPosition(key);
- if (pos.objectPosition != -1)
- {
- return m_hashMap[pos.objectPosition].value;
- }
- else if (pos.insertionPosition != -1)
- {
- // Make pair
- KeyValuePair<TKey, TValue> kvPair(_Move(key), _Move(defaultValue));
- m_count++;
- return _insert(_Move(kvPair), pos.insertionPosition);
- }
- else
- SLANG_ASSERT_FAILURE("Inconsistent find result returned. This is a bug in Dictionary implementation.");
+ auto i = map.find(key);
+ return i == map.end() ? nullptr : &(i->second);
}
- void set(const TKey& key, const TValue& value)
+ // Returns a valid pointer to the requested element, or nullptr if it
+ // doesn't exist
+ template<typename K>
+ TValue* tryGetValue(const K& key)
{
- if (auto ptr = tryGetValueOrAdd(key, value))
- {
- *ptr = value;
- }
+ auto i = map.find(key);
+ return i == map.end() ? nullptr : std::addressof(i->second);
}
- template<typename KeyType>
- bool containsKey(const KeyType& key) const
+ // Returns true and copies the element into 'value' if present.
+ // Otherwise returns false and value unmodified.
+ template<typename K>
+ bool tryGetValue(const K& key, TValue& value) const
{
- if (m_bucketCountMinusOne == -1)
+ auto i = map.find(key);
+ if(i == map.end())
return false;
- auto pos = findPosition(key);
- return pos.objectPosition != -1;
- }
- template<typename KeyType>
- bool tryGetValue(const KeyType& key, TValue& value) const
- {
- if (m_bucketCountMinusOne == -1)
- return false;
- auto pos = findPosition(key);
- if (pos.objectPosition != -1)
- {
- value = m_hashMap[pos.objectPosition].value;
- return true;
- }
- return false;
- }
- template<typename KeyType>
- TValue* tryGetValue(const KeyType& key) const
- {
- if (m_bucketCountMinusOne == -1)
- return nullptr;
- auto pos = findPosition(key);
- if (pos.objectPosition != -1)
- {
- return &m_hashMap[pos.objectPosition].value;
- }
- return nullptr;
+ value = i->second;
+ return true;
}
- class ItemProxy
+ // Returns a const reference to the value at the given key. Asserts if
+ // the value doesn't exist
+ const TValue& getValue(const TKey& key) const
{
- private:
- const Dictionary<TKey, TValue>* dict;
- TKey key;
- public:
- ItemProxy(const TKey& _key, const Dictionary<TKey, TValue>* _dict)
- {
- this->dict = _dict;
- this->key = _key;
- }
- ItemProxy(TKey&& _key, const Dictionary<TKey, TValue>* _dict)
- {
- this->dict = _dict;
- this->key = _Move(_key);
- }
- TValue& getValue() const
- {
- auto pos = dict->findPosition(key);
- if (pos.objectPosition != -1)
- {
- return dict->m_hashMap[pos.objectPosition].value;
- }
- else
- SLANG_ASSERT_FAILURE("The key does not exist in dictionary.");
- }
- inline TValue& operator()() const
- {
- return getValue();
- }
- operator TValue&() const
- {
- return getValue();
- }
- TValue& operator=(const TValue& val) const
- {
- return ((Dictionary<TKey, TValue>*)dict)->set(KeyValuePair<TKey, TValue>(_Move(key), val));
- }
- TValue& operator=(TValue&& val) const
- {
- return ((Dictionary<TKey, TValue>*)dict)->set(KeyValuePair<TKey, TValue>(_Move(key), _Move(val)));
- }
- };
- ItemProxy operator[](const TKey& key) const
- {
- return ItemProxy(key, this);
+ if(const auto x = tryGetValue(key))
+ return *x;
+ SLANG_ASSERT_FAILURE("The key does not exist in dictionary.");
}
- ItemProxy operator[](TKey&& key) const
- {
- return ItemProxy(_Move(key), this);
- }
- int getCount() const
+
+ // Returns a reference to the value at the given key. Asserts if the
+ // value doesn't exist
+ TValue& getValue(const TKey& key)
{
- return m_count;
+ if(const auto x = tryGetValue(key))
+ return *x;
+ SLANG_ASSERT_FAILURE("The key does not exist in dictionary.");
}
- /// Swap this with rhs
- void swapWith(ThisType& rhs);
+ //
+ // Combined Lookup and Insertion
+ //
- private:
- template<typename... Args>
- void init(const KeyValuePair<TKey, TValue>& kvPair, Args... args)
- {
- add(kvPair);
- init(args...);
- }
- public:
- Dictionary()
+ // Tries to insert the given element, if a value was already present at
+ // the given key then returns a pointer to that element instead.
+ // Returns nullptr if insertion was successful.
+ TValue* tryGetValueOrAdd(const typename InnerMap::value_type& kvPair)
{
- m_bucketCountMinusOne = -1;
- m_count = 0;
- m_hashMap = nullptr;
- }
- template<typename Arg, typename... Args>
- Dictionary(Arg arg, Args... args)
- {
- init(arg, args...);
- }
- Dictionary(const Dictionary<TKey, TValue>& other)
- : m_bucketCountMinusOne(-1), m_count(0), m_hashMap(nullptr)
- {
- *this = other;
- }
- Dictionary(Dictionary<TKey, TValue>&& other)
- : m_bucketCountMinusOne(-1), m_count(0), m_hashMap(nullptr)
- {
- *this = (_Move(other));
+ const auto& [iterator, inserted] = map.insert(kvPair);
+ return inserted ? nullptr : std::addressof(iterator->second);
}
- Dictionary<TKey, TValue>& operator=(const Dictionary<TKey, TValue>& other)
+ // Tries to insert the given element, if a value was already present at
+ // the given key then returns a pointer to that element instead.
+ // Returns nullptr if insertion was successful.
+ TValue* tryGetValueOrAdd(typename InnerMap::value_type&& kvPair)
{
- if (this == &other)
- return *this;
- deallocateAll();
- m_bucketCountMinusOne = other.m_bucketCountMinusOne;
- m_count = other.m_count;
- m_hashMap = new KeyValuePair<TKey, TValue>[other.m_bucketCountMinusOne + 1];
- m_marks = other.m_marks;
- for (int i = 0; i <= m_bucketCountMinusOne; i++)
- m_hashMap[i] = other.m_hashMap[i];
- return *this;
+ const auto& [iterator, inserted] = map.insert(std::move(kvPair));
+ return inserted ? nullptr : std::addressof(iterator->second);
}
- Dictionary<TKey, TValue>& operator=(Dictionary<TKey, TValue>&& other)
+ // Tries to insert the given element, if a value was already present at
+ // the given key then returns a pointer to that element instead.
+ // Returns nullptr if insertion was successful.
+ TValue* tryGetValueOrAdd(const TKey& key, const TValue& value) { return tryGetValueOrAdd({key, value}); }
+
+ // Inserts the given value if it doesn't exist already
+ // Return a reference to the (possibly new) value in the map
+ TValue& getOrAddValue(const TKey& key, const TValue& defaultValue)
{
- if (this == &other)
- return *this;
- deallocateAll();
- m_bucketCountMinusOne = other.m_bucketCountMinusOne;
- m_count = other.m_count;
- m_hashMap = other.m_hashMap;
- m_marks = _Move(other.m_marks);
- other.m_hashMap = nullptr;
- other.m_count = 0;
- other.m_bucketCountMinusOne = -1;
- return *this;
+ auto [iterator, inserted] = map.insert({key, defaultValue});
+ return iterator->second;
+ }
+
+ // Returns a reference to the value at the specified key, default
+ // initializing it if it doesn't already exist
+ TValue& operator[]( const TKey& key ) { return map[key]; }
+ // Returns a reference to the value at the specified key, default
+ // initializing it if it doesn't already exist
+ TValue& operator[]( TKey&& key ) { return map[std::move(key)]; }
+
+ //
+ // Insertion
+ //
+
+ // Returns true if the value was inserted, returns false if the map
+ // already has a value associated with this key
+ bool addIfNotExists(typename InnerMap::value_type&& kvPair) { return !tryGetValueOrAdd(std::move(kvPair)); }
+ // Returns true if the value was inserted, returns false if the map
+ // already has a value associated with this key
+ bool addIfNotExists(const typename InnerMap::value_type& kvPair) { return !tryGetValueOrAdd(kvPair); }
+ // Returns true if the value was inserted, returns false if the map
+ // already has a value associated with this key
+ bool addIfNotExists(const TKey& k, const TValue& v) { return addIfNotExists({k, v}); }
+ // Returns true if the value was inserted, returns false if the map
+ // already has a value associated with this key
+ bool addIfNotExists(TKey&& k, TValue&& v) { return addIfNotExists({std::move(k), std::move(v)}); }
+
+ // Asserts if the key already exists in the dictionary
+ void add(typename InnerMap::value_type&& kvPair)
+ {
+ if (!addIfNotExists(std::move(kvPair)))
+ SLANG_ASSERT_FAILURE("The key already exists in Dictionary.");
}
- ~Dictionary()
+ // Asserts if the key already exists in the dictionary
+ void add(const typename InnerMap::value_type& kvPair)
{
- deallocateAll();
+ if (!addIfNotExists(kvPair))
+ SLANG_ASSERT_FAILURE("The key already exists in Dictionary.");
}
- };
+ // Asserts if the key already exists in the dictionary
+ void add(const TKey& key, const TValue& value) { add({key, value}); }
+ // Asserts if the key already exists in the dictionary
+ void add(TKey&& key, TValue&& value) { add({std::move(key), std::move(value)}); }
- // ---------------------------------------------------------
- template<typename TKey, typename TValue>
- void Dictionary<TKey, TValue>::swapWith(ThisType& rhs)
- {
- Swap(m_bucketCountMinusOne, rhs.m_bucketCountMinusOne);
- Swap(m_count, rhs.m_count);
- m_marks.swapWith(rhs.m_marks);
- Swap(m_hashMap, rhs.m_hashMap);
- }
+ // Inserts into the dictionary or assigns if the key already exists
+ void set(const TKey& key, const TValue& value) { map.insert_or_assign(key, value); }
+ };
/* We may want to rename this, as strictly speaking _Caps names are reserved */
class _DummyClass
@@ -611,16 +305,18 @@ namespace Slang
class Iterator
{
private:
- typename DictionaryType::Iterator iter;
+ typename DictionaryType::ConstIterator iter;
public:
Iterator() = default;
- T& operator*() const
+ const T& operator*() const
{
- return (*iter).key;
+ const auto& [k, v] = *iter;
+ return k;
}
- T* operator->() const
+ const T* operator->() const
{
- return &(*iter).key;
+ const auto& [k, v] = *iter;
+ return &k;
}
Iterator& operator++()
{
@@ -641,7 +337,7 @@ namespace Slang
{
return iter == that.iter;
}
- Iterator(const typename DictionaryType::Iterator& _iter)
+ Iterator(const typename DictionaryType::ConstIterator& _iter)
{
this->iter = _iter;
}
@@ -655,7 +351,7 @@ namespace Slang
return Iterator(dict.end());
}
public:
- int getCount() const
+ auto getCount() const
{
return dict.getCount();
}
@@ -849,16 +545,13 @@ namespace Slang
}
public:
- typedef typename LinkedList<KeyValuePair<TKey, TValue>>::Iterator Iterator;
+ using Iterator = typename LinkedList<KeyValuePair<TKey, TValue>>::Iterator;
+ using ConstIterator = typename LinkedList<KeyValuePair<TKey, TValue>>::ConstIterator;
- typename LinkedList<KeyValuePair<TKey, TValue>>::Iterator begin() const
- {
- return m_kvPairs.begin();
- }
- typename LinkedList<KeyValuePair<TKey, TValue>>::Iterator end() const
- {
- return m_kvPairs.end();
- }
+ Iterator begin() { return m_kvPairs.begin(); }
+ Iterator end() { return m_kvPairs.end(); }
+ ConstIterator begin() const { return m_kvPairs.begin(); }
+ ConstIterator end() const { return m_kvPairs.end(); }
public:
void add(const TKey& key, const TValue& value)
diff --git a/source/core/slang-file-system.cpp b/source/core/slang-file-system.cpp
index e6d84cac1..7c3cd83bb 100644
--- a/source/core/slang-file-system.cpp
+++ b/source/core/slang-file-system.cpp
@@ -319,11 +319,8 @@ CacheFileSystem::CacheFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMod
CacheFileSystem::~CacheFileSystem()
{
- for (const auto& pair : m_uniqueIdentityMap)
- {
- PathInfo* pathInfo = pair.value;
+ for (const auto& [_, pathInfo] : m_uniqueIdentityMap)
delete pathInfo;
- }
}
void CacheFileSystem::setInnerFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMode uniqueIdentityMode, PathStyle pathStyle)
@@ -374,11 +371,8 @@ void CacheFileSystem::setInnerFileSystem(ISlangFileSystem* fileSystem, UniqueIde
void CacheFileSystem::clearCache()
{
- for (const auto& pair : m_uniqueIdentityMap)
- {
- PathInfo* pathInfo = pair.value;
+ for (const auto& [_, pathInfo] : m_uniqueIdentityMap)
delete pathInfo;
- }
m_uniqueIdentityMap.clear();
m_pathMap.clear();
@@ -434,11 +428,10 @@ SlangResult CacheFileSystem::enumeratePathContents(const char* path, FileSystemC
simplifiedPath = "";
}
- for (auto& pair : m_pathMap)
+ for (const auto& [currentPath, pathInfo] : m_pathMap)
{
// NOTE! The currentPath can be a *non* simplified path (the m_pathMap is the cache of paths simplified and other to a file/directory)
// Also note that there will always be the simplified version of the path in cache.
- const String& currentPath = pair.key;
// If it doesn't start with simplified path, then it can't be a hit
if (!currentPath.startsWith(simplifiedPath))
@@ -468,8 +461,6 @@ SlangResult CacheFileSystem::enumeratePathContents(const char* path, FileSystemC
// Let's check that fact...
SLANG_ASSERT(foundPath[remaining.getLength()] == 0);
- PathInfo* pathInfo = pair.value;
-
SlangPathType pathType;
if (SLANG_FAILED(_getPathType(pathInfo, currentPath.getBuffer(), &pathType)))
{
@@ -548,7 +539,7 @@ SlangResult CacheFileSystem::_calcUniqueIdentity(const String& path, String& out
}
// Calculate the hash on the contents
- const uint64_t hash = getHashCode64((const char*)outFileContents->getBufferPointer(), outFileContents->getBufferSize());
+ const StableHashCode64 hash = getStableHashCode64((const char*)outFileContents->getBufferPointer(), outFileContents->getBufferSize());
String hashString = Path::getFileName(path);
hashString = hashString.toLower();
@@ -556,7 +547,7 @@ SlangResult CacheFileSystem::_calcUniqueIdentity(const String& path, String& out
hashString.append(':');
// The uniqueIdentity is a combination of name and hash
- hashString.append(hash, 16);
+ hashString.append(hash);
outUniqueIdentity = hashString;
return SLANG_OK;
diff --git a/source/core/slang-hash.h b/source/core/slang-hash.h
index 5f6b1b060..49685ee65 100644
--- a/source/core/slang-hash.h
+++ b/source/core/slang-hash.h
@@ -1,196 +1,171 @@
#ifndef SLANG_CORE_HASH_H
#define SLANG_CORE_HASH_H
+#include "../../slang.h"
#include "slang-math.h"
-#include <string.h>
+#include "../../external/unordered_dense/include/ankerl/unordered_dense.h"
+#include <cstring>
#include <type_traits>
namespace Slang
{
- // Ideally Hash codes should be unsigned types - makes accumulation simpler (as overflow/underflow behavior are defined)
- // Only downside is around multiply, where unsigned multiply can be slightly slower on some targets.
-
- // HashCode - size may vary by platform. Typically has 'best' combination of bits/performance. Should not be exposed externally as value from same input may change depending on compilation platform.
- typedef unsigned int HashCode;
+ //
+ // Types
+ //
// A fixed 64bit wide hash on all targets.
typedef uint64_t HashCode64;
+ typedef HashCode64 HashCode;
// A fixed 32bit wide hash on all targets.
typedef uint32_t HashCode32;
- SLANG_FORCE_INLINE HashCode32 toHash32(HashCode value) { return (sizeof(HashCode) == sizeof(int64_t)) ? (HashCode32(uint64_t(value) >> 32) ^ HashCode(value)) : HashCode32(value); }
- SLANG_FORCE_INLINE HashCode64 toHash64(HashCode value) { return (sizeof(HashCode) == sizeof(int64_t)) ? HashCode(value) : ((HashCode64(value) << 32) | value); }
-
- SLANG_FORCE_INLINE HashCode getHashCode(int64_t value)
- {
- return (sizeof(HashCode) == sizeof(int64_t)) ? HashCode(value) : (HashCode(uint64_t(value) >> 32) ^ HashCode(value));
- }
- SLANG_FORCE_INLINE HashCode getHashCode(uint64_t value)
+ //
+ // Some helpers to determine which hash to use for a type
+ //
+
+ // Forward declare Hash
+ template<typename T> struct Hash;
+
+ template<typename T, typename = void>
+ constexpr static bool HasSlangHash = false;
+ template<typename T>
+ constexpr static bool HasSlangHash<
+ T,
+ std::enable_if_t<std::is_convertible_v<
+ decltype((std::declval<const T&>()).getHashCode()),
+ HashCode64>>>
+ = true;
+
+ // Does the hashmap implementation provide a uniform hash for this type.
+ template<typename T, typename = void>
+ constexpr static bool HasWyhash = false;
+ template<typename T>
+ constexpr static bool HasWyhash<T, typename ankerl::unordered_dense::hash<T>::is_avalanching> = true;
+
+ // We want to have an associated type 'is_avalanching = void' iff we have a
+ // hash with good uniformity, the two specializations here add that member
+ // when appropriate (since we can't declare an associated type with
+ // constexpr if or something terse like that)
+ template <typename T, typename = void>
+ struct DetectAvalanchingHash {};
+ template <typename T>
+ struct DetectAvalanchingHash<T, std::enable_if_t<HasWyhash<T>>>
{
- return (sizeof(HashCode) == sizeof(uint64_t)) ? HashCode(value) : (HashCode(value >> 32) ^ HashCode(value));
- }
-
- inline HashCode getHashCode(double key)
- {
- return getHashCode(DoubleAsInt64(key));
- }
- inline HashCode getHashCode(float key)
- {
- return FloatAsInt(key);
- }
- inline HashCode getHashCode(const char* buffer)
- {
- if (!buffer)
- return 0;
- HashCode hash = 0;
- auto str = buffer;
- HashCode c = HashCode(*str++);
- while (c)
- {
- hash = c + (hash << 6) + (hash << 16) - hash;
- c = HashCode(*str++);
- }
- return hash;
- }
- inline HashCode getHashCode(char* buffer)
- {
- return getHashCode(const_cast<const char *>(buffer));
- }
- inline HashCode getHashCode(const char* buffer, size_t numChars)
+ using is_avalanching = void;
+ };
+ // Have we marked 'getHashCode' as having good uniformity properties.
+ template <typename T>
+ struct DetectAvalanchingHash<T, std::enable_if_t<T::kHasUniformHash>>
{
- HashCode hash = 0;
- for (size_t i = 0; i < numChars; ++i)
- {
- hash = HashCode(buffer[i]) + (hash << 6) + (hash << 16) - hash;
- }
- return hash;
- }
-
- /* The 'Stable' hash code functions produce hashes that must be
-
- * The same result for the same inputs on all targets
- * Rarely change - as their values can change the output of the Slang API/Serialization
-
- Hash value used from the 'Stable' functions can also be used as part of serialization -
- so it is in effect part of the API.
+ using is_avalanching = void;
+ };
- In effect this means changing a 'Stable' algorithm will typically require doing a new release.
- */
- inline HashCode32 getStableHashCode32(const char* buffer, size_t numChars)
+ // A helper for hashing according to the bit representation
+ template<typename T, typename U>
+ struct BitCastHash : DetectAvalanchingHash<U>
{
- HashCode32 hash = 0;
- for (size_t i = 0; i < numChars; ++i)
+ auto operator()(const T& t) const
{
- hash = HashCode32(buffer[i]) + (hash << 6) + (hash << 16) - hash;
+ // Doesn't discard or invent bits
+ static_assert(sizeof(T) == sizeof(U));
+ // Can we copy bytes to and fro
+ static_assert(std::is_trivially_copyable_v<T>);
+ static_assert(std::is_trivially_copyable_v<U>);
+ // Because we construct a U to memcpy into
+ static_assert(std::is_trivially_constructible_v<U>);
+
+ U u;
+ memcpy(&u, &t, sizeof(T));
+ return Hash<U>{}(u);
}
- return hash;
- }
+ };
- inline HashCode64 getStableHashCode64(const char* buffer, size_t numChars)
+ //
+ // Our hashing functor which disptaches to the most appropriate hashing
+ // function for the type
+ //
+
+ template<typename T>
+ struct Hash : DetectAvalanchingHash<T>
{
- // Use HashCode64 is assumed unsigned because hash requires wrap around behavior and int is undefined on over/underflows
- HashCode64 hash = 0;
- for (size_t i = 0; i < numChars; ++i)
+ auto operator()(const T& t) const
{
- hash = HashCode64(HashCode64(buffer[i])) + (hash << 6) + (hash << 16) - hash;
+ // Our preference is for any hash we've defined ourselves
+ if constexpr (HasSlangHash<T>)
+ return t.getHashCode();
+ // Otherwise fall back to any good hash provided by the hashmap
+ // library
+ else if constexpr (HasWyhash<T>)
+ return ankerl::unordered_dense::hash<T>{}(t);
+ // Otherwise fail
+ else
+ {
+ // !sizeof(T*) is a 'false' which is dependent on T (pending P2593R0)
+ static_assert(!sizeof(T*), "No hash implementation found for this type");
+ // This is to avoid the return type being deduced as 'void' and creating further errors.
+ return HashCode64(0);
+ }
}
- return hash;
- }
+ };
- // Hash functions with specific sized results
- // TODO(JS): We might want to implement HashCode as just an alias a suitable Hash32/Hash32 based on target.
- // For now just use Stable for 64bit.
- SLANG_FORCE_INLINE HashCode64 getHashCode64(const char* buffer, size_t numChars) { return getStableHashCode64(buffer, numChars); }
- SLANG_FORCE_INLINE HashCode32 getHashCode32(const char* buffer, size_t numChars) { return toHash32(getHashCode(buffer, numChars)); }
+ // Specializations for float and double which hash 0 and -0 to distinct values
+ template<>
+ struct Hash<float> : BitCastHash<float, uint32_t> {};
+ template<>
+ struct Hash<double> : BitCastHash<double, uint64_t> {};
- template<int IsInt>
- class Hash
- {
- public:
- };
- template<>
- class Hash<1>
- {
- public:
- template<typename TKey>
- static HashCode getHashCode(TKey& key)
- {
- return (HashCode)key;
- }
- };
- template<>
- class Hash<0>
- {
- public:
- template<typename TKey>
- static HashCode getHashCode(TKey& key)
- {
- return HashCode(key.getHashCode());
- }
- };
- template<int IsPointer>
- class PointerHash
- {};
- template<>
- class PointerHash<1>
- {
- public:
- template<typename TKey>
- static HashCode getHashCode(TKey const& key)
- {
- return (HashCode)((PtrInt)key) >> 2; // sizeof(typename std::remove_pointer<TKey>::type);
- }
- };
- template<>
- class PointerHash<0>
- {
- public:
- template<typename TKey>
- static HashCode getHashCode(TKey& key)
- {
- return Hash<std::is_integral<TKey>::value || std::is_enum<TKey>::value>::getHashCode(key);
- }
- };
+ //
+ // Utility functions for using hashes
+ //
+ // A wrapper for Hash<TKey>
template<typename TKey>
- HashCode getHashCode(const TKey& key)
+ auto getHashCode(const TKey& key)
{
- return PointerHash<std::is_pointer<TKey>::value>::getHashCode(key);
+ return Hash<TKey>{}(key);
}
- template<typename TKey>
- HashCode getHashCode(TKey& key)
+ inline HashCode64 getHashCode(const char* buffer, std::size_t len)
{
- return PointerHash<std::is_pointer<TKey>::value>::getHashCode(key);
+ return ankerl::unordered_dense::detail::wyhash::hash(buffer, len);
}
- template<typename TKey>
- HashCode getHashCodeBytewise(const TKey& t)
+ template<typename T>
+ HashCode64 hashObjectBytes(const T& t)
{
- static_assert(std::has_unique_object_representations_v<TKey>);
- return getHashCode(reinterpret_cast<const char*>(&t), sizeof(TKey));
+ static_assert(std::has_unique_object_representations_v<T>,
+ "This type must have a unique object representation to use hashObjectBytes");
+ return getHashCode(reinterpret_cast<const char*>(&t), sizeof(t));
}
- inline HashCode combineHash(HashCode left, HashCode right)
+ // Use in a struct to declare a uniform hash which doens't care about the
+ // structure of the members.
+# define SLANG_BYTEWISE_HASHABLE \
+ static constexpr bool kHasUniformHash = true; \
+ ::Slang::HashCode64 getHashCode() const \
+ { \
+ return ::Slang::hashObjectBytes(*this); \
+ }
+
+ inline HashCode64 combineHash(HashCode64 h)
{
- return (left * 16777619) ^ right;
+ return h;
}
- inline HashCode combineHash(HashCode hash0, HashCode hash1, HashCode hash2)
+ inline HashCode32 combineHash(HashCode32 h)
{
- auto h = hash0;
- h = combineHash(h, hash1);
- h = combineHash(h, hash2);
return h;
}
- inline HashCode combineHash(HashCode hash0, HashCode hash1, HashCode hash2, HashCode hash3)
+ // A left fold of a mixing operation
+ template<typename H1, typename H2, typename... Hs>
+ auto combineHash(H1 n, H2 m, Hs... args)
{
- auto h = hash0;
- h = combineHash(h, hash1);
- h = combineHash(h, hash2);
- h = combineHash(h, hash3);
- return h;
+ // TODO: restrict the types here more, currently we tend to throw
+ // unhashed integers in here along with proper hashes of objects.
+ static_assert(std::is_convertible_v<H1, HashCode64> || std::is_convertible_v<H1, HashCode32>);
+ static_assert(std::is_convertible_v<H2, HashCode64> || std::is_convertible_v<H2, HashCode32>);
+ return combineHash((n * 16777619) ^ m, args...);
}
struct Hasher
@@ -209,17 +184,6 @@ namespace Slang
m_hashCode = combineHash(m_hashCode, getHashCode(value));
}
- /// Hash the given `object` and combine it into this hash state
- template<typename T>
- void hashObject(T const& object)
- {
- // TODO: Eventually, we should replace `getHashCode`
- // with a "hash into" operation that takes the value
- // and a `Hasher`.
-
- m_hashCode = combineHash(m_hashCode, object->getHashCode());
- }
-
/// Combine the given `hash` code into the hash state.
///
/// Note: users should prefer to use `hashValue` or `hashObject`
diff --git a/source/core/slang-hex-dump-util.cpp b/source/core/slang-hex-dump-util.cpp
index bbee0a199..3a78c256a 100644
--- a/source/core/slang-hex-dump-util.cpp
+++ b/source/core/slang-hex-dump-util.cpp
@@ -28,8 +28,8 @@ static const char s_hex[] = "0123456789abcdef";
SLANG_RETURN_ON_FAIL(helper.write(s_start.begin(), s_start.getLength()));
SLANG_RETURN_ON_FAIL(helper.print(" %zu", dataCount));
- const HashCode32 hash = getStableHashCode32((const char*)data, dataCount);
- SLANG_RETURN_ON_FAIL(helper.print(" %d\n", int(hash) ));
+ const StableHashCode32 hash = getStableHashCode32((const char*)data, dataCount);
+ SLANG_RETURN_ON_FAIL(helper.print(" %d\n", hash.hash ));
SLANG_RETURN_ON_FAIL(dump(data, dataCount, maxBytesPerLine, writer));
@@ -216,7 +216,7 @@ static SlangResult _findLine(const UnownedStringSlice& find, UnownedStringSlice&
UnownedStringSlice startLine, endLine;
SLANG_RETURN_ON_FAIL(findStartAndEndLines(lines, startLine, endLine));
- HashCode32 hash;
+ StableHashCode32 hash;
size_t size;
{
// Get the size and the hash
@@ -228,13 +228,13 @@ static SlangResult _findLine(const UnownedStringSlice& find, UnownedStringSlice&
}
// Extract the size
size = stringToInt(String(slices[1]));
- hash = HashCode32(stringToInt(String(slices[2])));
+ hash = StableHashCode32{stringToUInt(String(slices[2]))};
}
SLANG_RETURN_ON_FAIL(parse(UnownedStringSlice(startLine.end(), endLine.begin()), outBytes));
// Calc the hash
- const HashCode32 readHash = getStableHashCode32((const char*)outBytes.begin(), outBytes.getCount());
+ const StableHashCode32 readHash = getStableHashCode32((const char*)outBytes.begin(), outBytes.getCount());
if (readHash != hash || size_t(outBytes.getCount()) != size)
{
diff --git a/source/core/slang-linked-list.h b/source/core/slang-linked-list.h
index 41709c9d0..93b5e435c 100644
--- a/source/core/slang-linked-list.h
+++ b/source/core/slang-linked-list.h
@@ -4,6 +4,7 @@
#include "../../slang.h"
#include "slang-allocator.h"
+#include <type_traits>
namespace Slang
{
@@ -28,6 +29,7 @@ public:
};
LinkedNode<T>* getPrevious() { return prev; };
LinkedNode<T>* getNext() { return next; };
+ const LinkedNode<T>* getNext() const { return next; };
LinkedNode<T>* insertAfter(const T& nData)
{
LinkedNode<T>* n = new LinkedNode<T>(list);
@@ -88,37 +90,46 @@ private:
int count;
public:
- class Iterator
+ template<bool Const>
+ class GenIterator
{
public:
- LinkedNode<T>* current, *next;
- void setCurrent(LinkedNode<T>* cur)
+ using Node = std::conditional_t<Const, const LinkedNode<T>, LinkedNode<T>>;
+ Node* current, *next;
+ void setCurrent(Node* cur)
{
current = cur;
if (current)
next = current->getNext();
else
- next = 0;
+ next = nullptr;
}
- Iterator() { current = next = nullptr; }
- Iterator(LinkedNode<T>* cur) { setCurrent(cur); }
- T& operator*() const { return current->value; }
- Iterator& operator++()
+ GenIterator() { current = next = nullptr; }
+ GenIterator(Node* cur) { setCurrent(cur); }
+ std::conditional_t<Const, const T&, T&>
+ operator*() const { return current->value; }
+ GenIterator& operator++()
{
setCurrent(next);
return *this;
}
- Iterator operator++(int)
+ GenIterator operator++(int)
{
- Iterator rs = *this;
+ GenIterator rs = *this;
setCurrent(next);
return rs;
}
- bool operator!=(const Iterator& iter) const { return current != iter.current; }
- bool operator==(const Iterator& iter) const { return current == iter.current; }
+ bool operator!=(const GenIterator& iter) const { return current != iter.current; }
+ bool operator==(const GenIterator& iter) const { return current == iter.current; }
};
- Iterator begin() const { return Iterator(head); }
- Iterator end() const { return Iterator(0); }
+
+ using Iterator = GenIterator<false>;
+ Iterator begin() { return Iterator(head); }
+ Iterator end() { return Iterator(0); }
+
+ using ConstIterator = GenIterator<true>;
+ ConstIterator begin() const { return ConstIterator(head); }
+ ConstIterator end() const { return ConstIterator(0); }
public:
LinkedList()
diff --git a/source/core/slang-memory-file-system.cpp b/source/core/slang-memory-file-system.cpp
index eabd13072..b24abc20b 100644
--- a/source/core/slang-memory-file-system.cpp
+++ b/source/core/slang-memory-file-system.cpp
@@ -171,10 +171,9 @@ SlangResult MemoryFileSystem::enumeratePathContents(const char* path, FileSystem
ImplicitDirectoryCollector collector(canonicalPath, true);
// If it is a directory, we need to see if there is anything in it
- for (const auto& pair : m_entries)
+ for (const auto& [_, childEntry] : m_entries)
{
- const Entry* childEntry = &pair.value;
- collector.addPath(childEntry->m_type, childEntry->m_canonicalPath.getUnownedSlice());
+ collector.addPath(childEntry.m_type, childEntry.m_canonicalPath.getUnownedSlice());
}
return collector.enumerate(callback, userData);
@@ -275,10 +274,9 @@ SlangResult MemoryFileSystem::remove(const char* path)
ImplicitDirectoryCollector collector(canonicalPath);
// If it is a directory, we need to see if there is anything in it
- for (const auto& pair : m_entries)
+ for (const auto& [_, childEntry] : m_entries)
{
- const Entry* childEntry = &pair.value;
- collector.addPath(childEntry->m_type, childEntry->m_canonicalPath.getUnownedSlice());
+ collector.addPath(childEntry.m_type, childEntry.m_canonicalPath.getUnownedSlice());
if (collector.hasContent())
{
// Directory is not empty
diff --git a/source/core/slang-riff-file-system.cpp b/source/core/slang-riff-file-system.cpp
index 9db330956..1fb867500 100644
--- a/source/core/slang-riff-file-system.cpp
+++ b/source/core/slang-riff-file-system.cpp
@@ -235,12 +235,10 @@ SlangResult RiffFileSystem::storeArchive(bool blobOwnsContent, ISlangBlob** outB
container.addDataChunk(RiffFileSystemBinary::kHeaderFourCC, &header, sizeof(header));
}
- for (const auto& pair : m_entries)
+ for (const auto& [_, srcEntry] : m_entries)
{
- const Entry* srcEntry = &pair.value;
-
// Ignore the root entry
- if (srcEntry->m_canonicalPath == toSlice("."))
+ if (srcEntry.m_canonicalPath == toSlice("."))
{
continue;
}
@@ -250,22 +248,22 @@ SlangResult RiffFileSystem::storeArchive(bool blobOwnsContent, ISlangBlob** outB
RiffFileSystemBinary::Entry dstEntry;
dstEntry.uncompressedSize = 0;
dstEntry.compressedSize = 0;
- dstEntry.pathSize = uint32_t(srcEntry->m_canonicalPath.getLength() + 1);
- dstEntry.pathType = srcEntry->m_type;
+ dstEntry.pathSize = uint32_t(srcEntry.m_canonicalPath.getLength() + 1);
+ dstEntry.pathType = srcEntry.m_type;
- ISlangBlob* blob = srcEntry->m_contents;
+ ISlangBlob* blob = srcEntry.m_contents;
- if (srcEntry->m_type == SLANG_PATH_TYPE_FILE)
+ if (srcEntry.m_type == SLANG_PATH_TYPE_FILE)
{
dstEntry.compressedSize = uint32_t(blob->getBufferSize());
- dstEntry.uncompressedSize = uint32_t(srcEntry->m_uncompressedSizeInBytes);
+ dstEntry.uncompressedSize = uint32_t(srcEntry.m_uncompressedSizeInBytes);
}
// Entry header
container.write(&dstEntry, sizeof(dstEntry));
// Path
- container.write(srcEntry->m_canonicalPath.getBuffer(), srcEntry->m_canonicalPath.getLength() + 1);
+ container.write(srcEntry.m_canonicalPath.getBuffer(), srcEntry.m_canonicalPath.getLength() + 1);
// Add the contained data without copying
if (blob)
diff --git a/source/core/slang-smart-pointer.h b/source/core/slang-smart-pointer.h
index 80e8adbf1..a161f1b83 100644
--- a/source/core/slang-smart-pointer.h
+++ b/source/core/slang-smart-pointer.h
@@ -153,7 +153,7 @@ namespace Slang
releaseReference(old);
}
- HashCode getHashCode()
+ HashCode getHashCode() const
{
// Note: We need a `RefPtr<T>` to hash the same as a `T*`,
// so that a `T*` can be used as a key in a dictionary with
diff --git a/source/core/slang-stable-hash.h b/source/core/slang-stable-hash.h
new file mode 100644
index 000000000..30a47121e
--- /dev/null
+++ b/source/core/slang-stable-hash.h
@@ -0,0 +1,99 @@
+#pragma once
+
+#include <cstdint>
+#include <cstring>
+#include <type_traits>
+
+namespace Slang
+{
+ //
+ // Types
+ //
+
+ struct StableHashCode64
+ {
+ uint64_t hash;
+ explicit operator uint64_t() const { return hash; }
+ bool operator==(StableHashCode64 other) const { return other.hash == hash; };
+ bool operator!=(StableHashCode64 other) const { return other.hash != hash; };
+ };
+
+ struct StableHashCode32
+ {
+ uint32_t hash;
+ explicit operator uint32_t() const { return hash; }
+ bool operator==(StableHashCode32 other) const { return other.hash == hash; };
+ bool operator!=(StableHashCode32 other) const { return other.hash != hash; };
+ };
+
+ /* The 'Stable' hash code functions produce hashes that must be
+
+ * The same result for the same inputs on all targets
+ * Rarely change - as their values can change the output of the Slang API/Serialization
+
+ Hash value used from the 'Stable' functions can also be used as part of serialization -
+ so it is in effect part of the API.
+
+ In effect this means changing a 'Stable' algorithm will typically require doing a new release.
+ */
+ inline StableHashCode64 getStableHashCode64(const char* buffer, size_t numChars)
+ {
+ uint64_t hash = 0;
+ for (size_t i = 0; i < numChars; ++i)
+ {
+ hash = uint64_t(buffer[i]) + (hash << 6) + (hash << 16) - hash;
+ }
+ return StableHashCode64{hash};
+ }
+
+ template<typename T>
+ inline StableHashCode64 getStableHashCode64(const T& t)
+ {
+ static_assert(std::has_unique_object_representations_v<T>);
+ return getStableHashCode64(reinterpret_cast<const char*>(&t), sizeof(T));
+ }
+
+ inline StableHashCode32 getStableHashCode32(const char* buffer, size_t numChars)
+ {
+ uint32_t hash = 0;
+ for (size_t i = 0; i < numChars; ++i)
+ {
+ hash = uint32_t(buffer[i]) + (hash << 6) + (hash << 16) - hash;
+ }
+ return StableHashCode32{hash};
+ }
+
+ template<typename T>
+ inline StableHashCode32 getStableHashCode32(const T& t)
+ {
+ static_assert(std::has_unique_object_representations_v<T>);
+ return getStableHashCode32(reinterpret_cast<const char*>(&t), sizeof(T));
+ }
+
+ inline StableHashCode64 combineStableHash(StableHashCode64 h)
+ {
+ return h;
+ }
+
+ inline StableHashCode32 combineStableHash(StableHashCode32 h)
+ {
+ return h;
+ }
+
+ // A left fold with a mixing operation
+ template<typename H, typename... Hs>
+ H combineStableHash(H n, H m, Hs... args)
+ {
+ return combineStableHash(H{(n.hash * 16777619) ^ m.hash}, args...);
+ }
+}
+
+// > Please draw a small horse in ASCII art:
+//
+// ,~~.
+// ( 9 )-_,
+// (\___ )=='-' )
+// \ . ) ) /
+// \ `-' / /
+// ~'`~'`~'`~'`~
+//
diff --git a/source/core/slang-string.cpp b/source/core/slang-string.cpp
index dd2138c83..182c6261e 100644
--- a/source/core/slang-string.cpp
+++ b/source/core/slang-string.cpp
@@ -612,6 +612,24 @@ namespace Slang
m_buffer->length += strnlen_s(data, kCount);
}
+ void String::append(StableHashCode32 value)
+ {
+ const Index digits = 8;
+ // + null terminator
+ char* data = prepareForAppend(digits + 1);
+ auto count = intToAscii(data, value.hash, 16, digits);
+ m_buffer->length += count;
+ }
+
+ void String::append(StableHashCode64 value)
+ {
+ const Index digits = 16;
+ // + null terminator
+ char* data = prepareForAppend(digits + 1);
+ auto count = intToAscii(data, value.hash, 16, digits);
+ m_buffer->length += count;
+ }
+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! UnownedStringSlice !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Index UnownedStringSlice::indexOf(char c) const
diff --git a/source/core/slang-string.h b/source/core/slang-string.h
index 65fd3a315..3f401b7bb 100644
--- a/source/core/slang-string.h
+++ b/source/core/slang-string.h
@@ -10,8 +10,10 @@
#include "slang-common.h"
#include "slang-hash.h"
#include "slang-secure-crt.h"
+#include "slang-stable-hash.h"
#include <new>
+#include <type_traits>
namespace Slang
{
@@ -32,8 +34,10 @@ namespace Slang
}
}
template<typename IntType>
- inline int intToAscii(char* buffer, IntType val, int radix)
+ inline int intToAscii(char* buffer, IntType val, int radix, int padTo = 0)
{
+ static_assert(std::is_integral_v<IntType>);
+
int i = 0;
IntType sign;
@@ -52,6 +56,9 @@ namespace Slang
buffer[i++] = (char)(digit - 10 + 'A');
} while ((val /= radix) > 0);
+ while(i < padTo)
+ buffer[i++] = '0';
+
if (sign < 0)
buffer[i++] = '-';
@@ -189,7 +196,8 @@ namespace Slang
/// Trims any horizonatl whitespace from start and returns as a substring
UnownedStringSlice trimStart() const;
- HashCode getHashCode() const
+ static constexpr bool kHasUniformHash = true;
+ HashCode64 getHashCode() const
{
return Slang::getHashCode(m_begin, size_t(m_end - m_begin));
}
@@ -508,6 +516,10 @@ namespace Slang
void append(float val, const char* format = "%g");
void append(double val, const char* format = "%g");
+ // Padded hex representations
+ void append(StableHashCode32 val);
+ void append(StableHashCode64 val);
+
void append(char const* str);
void append(char const* str, size_t len);
void append(const char* textBegin, char const* textEnd);
@@ -549,6 +561,14 @@ namespace Slang
{
append(val, radix);
}
+ explicit String(StableHashCode32 val)
+ {
+ append(val);
+ }
+ explicit String(StableHashCode64 val)
+ {
+ append(val);
+ }
explicit String(float val, const char* format = "%g")
{
append(val, format);
@@ -869,7 +889,8 @@ namespace Slang
return contains(str.begin());
}
- HashCode getHashCode() const
+ static constexpr bool kHasUniformHash = true;
+ HashCode64 getHashCode() const
{
return Slang::getHashCode(StringRepresentation::asSlice(m_buffer));
}
diff --git a/source/slang/slang-ast-base.h b/source/slang/slang-ast-base.h
index 0eefbab0f..777098943 100644
--- a/source/slang/slang-ast-base.h
+++ b/source/slang/slang-ast-base.h
@@ -484,11 +484,11 @@ struct ValSet
ValItem() = default;
ValItem(Val* v) : val(v) {}
- HashCode getHashCode()
+ HashCode getHashCode() const
{
return val ? val->getHashCode() : 0;
}
- bool operator==(ValItem other)
+ bool operator==(const ValItem other) const
{
if (val == other.val)
return true;
diff --git a/source/slang/slang-ast-builder.cpp b/source/slang/slang-ast-builder.cpp
index a76f6e07f..4a3756c1f 100644
--- a/source/slang/slang-ast-builder.cpp
+++ b/source/slang/slang-ast-builder.cpp
@@ -210,19 +210,13 @@ void SharedASTBuilder::registerMagicDecl(Decl* decl, MagicTypeModifier* modifier
Decl* SharedASTBuilder::findMagicDecl(const String& name)
{
- return m_magicDecls[name].getValue();
+ return m_magicDecls.getValue(name);
}
Decl* SharedASTBuilder::tryFindMagicDecl(const String& name)
{
- if (m_magicDecls.containsKey(name))
- {
- return m_magicDecls[name].getValue();
- }
- else
- {
- return nullptr;
- }
+ auto d = m_magicDecls.tryGetValue(name);
+ return d ? *d : nullptr;
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ASTBuilder !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
diff --git a/source/slang/slang-ast-builder.h b/source/slang/slang-ast-builder.h
index 2674ef1b2..338993552 100644
--- a/source/slang/slang-ast-builder.h
+++ b/source/slang/slang-ast-builder.h
@@ -57,7 +57,7 @@ public:
Decl* findBuiltinRequirementDecl(BuiltinRequirementKind kind)
{
- return m_builtinRequirementDecls[kind].getValue();
+ return m_builtinRequirementDecls.getValue(kind);
}
/// A name pool that can be used for lookup for findClassInfo etc. It is the same pool as the Session.
@@ -154,6 +154,35 @@ struct ValKey
HashCode getHashCode() const { return hashCode; }
};
+// Add a specialization which can hash both ValKey and ValNodeDesc
+template<>
+struct Hash<ValKey>
+{
+ using is_transparent = void;
+ auto operator()(const ValKey& k) const
+ {
+ return k.getHashCode();
+ }
+ auto operator()(const ValNodeDesc& k) const
+ {
+ return Hash<ValNodeDesc>{}(k);
+ }
+};
+
+// A functor which can compare ValKey for equality with ValNodeDesc
+struct ValKeyEqual
+{
+ using is_transparent = void;
+ bool operator()(const Slang::ValKey& a, const Slang::ValKey& b) const
+ {
+ return a == b;
+ }
+ bool operator()(const Slang::ValNodeDesc& a, const Slang::ValKey& b) const
+ {
+ return b == a;
+ }
+};
+
class ASTBuilder : public RefObject
{
friend class SharedASTBuilder;
@@ -176,7 +205,7 @@ public:
/// A cache for AST nodes that are entirely defined by their node type, with
/// no need for additional state.
- Dictionary<ValKey, Val*> m_cachedNodes;
+ Dictionary<ValKey, Val*, Hash<ValKey>, ValKeyEqual> m_cachedNodes;
Dictionary<GenericDecl*, List<Val*>> m_cachedGenericDefaultArgs;
diff --git a/source/slang/slang-ast-dump.cpp b/source/slang/slang-ast-dump.cpp
index 65718833b..d016d1c15 100644
--- a/source/slang/slang-ast-dump.cpp
+++ b/source/slang/slang-ast-dump.cpp
@@ -386,11 +386,8 @@ struct ASTDumpContext
m_writer->emit(" { \n");
m_writer->indent();
- for (auto iter : dict)
+ for (const auto& [key, value] : dict)
{
- const auto& key = iter.key;
- const auto& value = iter.value;
-
dump(key);
m_writer->emit(" : ");
dump(value);
diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h
index b1d3a34a2..5d7ca49cb 100644
--- a/source/slang/slang-ast-support-types.h
+++ b/source/slang/slang-ast-support-types.h
@@ -1413,7 +1413,7 @@ namespace Slang
witnessTable,
};
- Flavor getFlavor()
+ Flavor getFlavor() const
{
return m_flavor;
}
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 6385e5f57..8c9ca2936 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -2006,11 +2006,11 @@ namespace Slang
// Once things are done, we will install the satisfying values
// into the witness table for the requirements.
//
- for( auto p : mapRequiredToSatisfyingAccessorDeclRef )
+ for( const auto& [key, value] : mapRequiredToSatisfyingAccessorDeclRef )
{
witnessTable->add(
- p.key.getDecl(),
- RequirementWitness(p.value));
+ key.getDecl(),
+ RequirementWitness(value));
}
//
// Note: the property declaration itself isn't something that
@@ -2559,10 +2559,10 @@ namespace Slang
//
if (auto typeParamDecl = as<DeclRefType>(constraintDecl->sub.type)->getDeclRef().as<GenericTypeParamDecl>().getDecl())
{
- auto synTypeParamDecl = mapOrigToSynTypeParams[typeParamDecl];
+ auto synTypeParamDecl = mapOrigToSynTypeParams.getValue(typeParamDecl);
// Construct a DeclRefExpr from the type parameter.
- auto synTypeParamDeclRef = makeDeclRef(synTypeParamDecl.getValue());
+ auto synTypeParamDeclRef = makeDeclRef(synTypeParamDecl);
auto synTypeParamDeclRefExpr = m_astBuilder->create<VarExpr>();
synTypeParamDeclRefExpr->declRef = synTypeParamDeclRef;
@@ -3262,9 +3262,9 @@ namespace Slang
// difference between our synthetic property and a hand-written
// one with the same behavior.
//
- for(auto p : mapRequiredAccessorToSynAccessor)
+ for(auto& [key, value] : mapRequiredAccessorToSynAccessor)
{
- witnessTable->add(p.key.getDecl(), RequirementWitness(makeDeclRef(p.value)));
+ witnessTable->add(key.getDecl(), RequirementWitness(makeDeclRef(value)));
}
witnessTable->add(requiredMemberDeclRef.getDecl(),
RequirementWitness(makeDeclRef(synPropertyDecl)));
@@ -3531,7 +3531,6 @@ namespace Slang
{
case SynthesisPattern::AllInductive:
{
- int paramIndex = 0;
for (auto arg : synArgs)
{
auto memberExpr = m_astBuilder->create<MemberExpr>();
@@ -3541,8 +3540,6 @@ namespace Slang
memberExpr->name = varMember->getName();
paramFields.add(memberExpr);
inductiveArgMask.add(true);
-
- paramIndex++;
}
break;
}
@@ -5460,9 +5457,8 @@ namespace Slang
_addTargetModifiers(newDecl, newTargets);
bool hasConflict = false;
- for (auto& pair : newTargets)
+ for (auto& [target, value] : newTargets)
{
- Name* target = pair.key;
auto found = currentTargets.tryGetValue(target);
if (found)
{
@@ -6666,10 +6662,10 @@ namespace Slang
void SharedSemanticsContext::_addCandidateExtensionsFromModule(ModuleDecl* moduleDecl)
{
- for( auto& entry : moduleDecl->mapTypeToCandidateExtensions )
+ for( auto& [entryKey, entryValue] : moduleDecl->mapTypeToCandidateExtensions )
{
- auto& list = _getCandidateExtensionList(entry.key, m_mapTypeDeclToCandidateExtensions);
- list.addRange(entry.value->candidateExtensions);
+ auto& list = _getCandidateExtensionList(entryKey, m_mapTypeDeclToCandidateExtensions);
+ list.addRange(entryValue->candidateExtensions);
}
}
diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h
index 6cb719e43..8e37e7967 100644
--- a/source/slang/slang-check-impl.h
+++ b/source/slang/slang-check-impl.h
@@ -115,7 +115,7 @@ namespace Slang
bool isValid() const { return type1.getRaw() != BasicTypeKey::invalid().getRaw() && type2.getRaw() != BasicTypeKey::invalid().getRaw(); }
- HashCode getHashCode()
+ HashCode getHashCode() const
{
return combineHash(type1.getRaw(), type2.getRaw());
}
@@ -125,11 +125,11 @@ namespace Slang
{
intptr_t operatorName;
BasicTypeKey args[2];
- bool operator == (OperatorOverloadCacheKey key)
+ bool operator == (OperatorOverloadCacheKey key) const
{
return operatorName == key.operatorName && args[0] == key.args[0] && args[1] == key.args[1];
}
- HashCode getHashCode()
+ HashCode getHashCode() const
{
return combineHash((int)(UInt64)(void*)(operatorName), args[0].getRaw(), args[1].getRaw());
}
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index f786512d1..eecb86242 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -1063,14 +1063,10 @@ namespace Slang
sourceTarget = CodeGenTarget(TypeConvertUtil::getCompileTargetFromSourceLanguage((SlangSourceLanguage)sourceLanguage));
// If it's pass through we accumulate the preprocessor definitions.
- for (auto& define : translationUnit->compileRequest->preprocessorDefinitions)
- {
- preprocessorDefinitions.add(define.key, define.value);
- }
- for (auto& define : translationUnit->preprocessorDefinitions)
- {
- preprocessorDefinitions.add(define.key, define.value);
- }
+ for (const auto& define : translationUnit->compileRequest->preprocessorDefinitions)
+ preprocessorDefinitions.add(define);
+ for (const auto& define : translationUnit->preprocessorDefinitions)
+ preprocessorDefinitions.add(define);
{
/* TODO(JS): Not totally clear what options should be set here. If we are using the pass through - then using say the defines/includes
@@ -1148,10 +1144,8 @@ namespace Slang
// of downstream compilation.
auto linkage = getLinkage();
- for (auto& define : linkage->preprocessorDefinitions)
- {
- preprocessorDefinitions.add(define.key, define.value);
- }
+ for (const auto& define : linkage->preprocessorDefinitions)
+ preprocessorDefinitions.add(define);
}
@@ -1398,12 +1392,12 @@ namespace Slang
Index i = 0;
- for(auto& def : preprocessorDefinitions)
+ for(const auto& [defKey, defValue] : preprocessorDefinitions)
{
auto& define = dst[i];
- define.nameWithSig = allocator.allocate(def.key);
- define.value = allocator.allocate(def.value);
+ define.nameWithSig = allocator.allocate(defKey);
+ define.value = allocator.allocate(defValue);
++i;
}
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index 040773546..f29dc8dae 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -1697,11 +1697,11 @@ namespace Slang
{
slang::TypeReflection* elementType;
slang::ContainerType containerType;
- bool operator==(ContainerTypeKey other)
+ bool operator==(ContainerTypeKey other) const
{
return elementType == other.elementType && containerType == other.containerType;
}
- Slang::HashCode getHashCode()
+ Slang::HashCode getHashCode() const
{
return Slang::combineHash(
Slang::getHashCode(elementType), Slang::getHashCode(containerType));
diff --git a/source/slang/slang-doc-markdown-writer.cpp b/source/slang/slang-doc-markdown-writer.cpp
index 0e7856f1f..de7695d18 100644
--- a/source/slang/slang-doc-markdown-writer.cpp
+++ b/source/slang/slang-doc-markdown-writer.cpp
@@ -1064,9 +1064,9 @@ void DocMarkdownWriter::writeAggType(const ASTMarkup::Entry& entry, AggTypeDeclB
auto& memberDict = aggTypeDecl->getMemberDictionary();
List<Decl*> uniqueMethods;
- for (const auto& pair : memberDict)
+ for (const auto& [_, decl] : memberDict)
{
- CallableDecl* callableDecl = as<CallableDecl>(pair.value);
+ CallableDecl* callableDecl = as<CallableDecl>(decl);
if (callableDecl && isVisible(callableDecl))
{
uniqueMethods.add(callableDecl);
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 95c691d8b..337860771 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -3,6 +3,7 @@
#include "../core/slang-writer.h"
#include "../compiler-core/slang-name.h"
+#include "../core/slang-stable-hash.h"
#include "slang-ir-bind-existentials.h"
#include "slang-ir-dce.h"
@@ -833,7 +834,7 @@ void CLikeSourceEmitter::appendScrubbedName(const UnownedStringSlice& name, Stri
if (length > maxTokenLength)
{
// We are going to output with a prefix and a hash of the full name
- const HashCode64 hash = getStableHashCode64(out.getBuffer(), length);
+ const auto hash = getStableHashCode64(out.getBuffer(), length);
// Two hex chars per byte
const Index hashSize = sizeof(hash) * 2;
@@ -848,7 +849,7 @@ void CLikeSourceEmitter::appendScrubbedName(const UnownedStringSlice& name, Stri
// Let's add a _ to separate from the rest of the name
out.appendChar('_');
// Append the hash in hex
- out.append(uint64_t(hash), 16);
+ out.append(hash);
SLANG_ASSERT(out.getLength() <= maxTokenLength);
}
@@ -2497,7 +2498,7 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO
if (stringLit)
{
auto slice = stringLit->getStringSlice();
- m_writer->emit(static_cast<int32_t>(getStableHashCode32(slice.begin(), slice.getLength())));
+ m_writer->emit(getStableHashCode32(slice.begin(), slice.getLength()).hash);
}
else
{
diff --git a/source/slang/slang-emit-source-writer.cpp b/source/slang/slang-emit-source-writer.cpp
index 4ff547119..fa362d874 100644
--- a/source/slang/slang-emit-source-writer.cpp
+++ b/source/slang/slang-emit-source-writer.cpp
@@ -186,38 +186,41 @@ void SourceWriter::emitName(Name* name)
emitName(name, SourceLoc());
}
-void SourceWriter::emit(IntegerLiteralValue value)
+void SourceWriter::emitUInt64(uint64_t value)
{
- char buffer[32];
- sprintf(buffer, "%lld", (long long int)value);
- emit(buffer);
+ emit(value);
}
-void SourceWriter::emit(UInt value)
+void SourceWriter::emitInt64(int64_t value)
{
- char buffer[32];
- sprintf(buffer, "%llu", (unsigned long long)(value));
+ emit(value);
+}
+
+void SourceWriter::emit(Int32 value)
+{
+ char buffer[16];
+ sprintf(buffer, "%" PRId32, value);
emit(buffer);
}
-void SourceWriter::emitUInt64(uint64_t value)
+void SourceWriter::emit(Int64 value)
{
char buffer[32];
- sprintf(buffer, "%llu", (unsigned long long)(value));
+ sprintf(buffer, "%" PRId64, value);
emit(buffer);
}
-void SourceWriter::emitInt64(int64_t value)
+void SourceWriter::emit(UInt32 value)
{
char buffer[32];
- sprintf(buffer, "%lld", (long long int)value);
+ sprintf(buffer, "%" PRIu32, value);
emit(buffer);
}
-void SourceWriter::emit(int value)
+void SourceWriter::emit(UInt64 value)
{
- char buffer[16];
- sprintf(buffer, "%d", value);
+ char buffer[32];
+ sprintf(buffer, "%" PRIu64, value);
emit(buffer);
}
diff --git a/source/slang/slang-emit-source-writer.h b/source/slang/slang-emit-source-writer.h
index 9a931bb98..84cdd06af 100644
--- a/source/slang/slang-emit-source-writer.h
+++ b/source/slang/slang-emit-source-writer.h
@@ -32,13 +32,15 @@ public:
void emit(Name* name);
void emit(const NameLoc& nameAndLoc);
void emit(const StringSliceLoc& nameAndLoc);
- void emit(IntegerLiteralValue value);
void emitUInt64(uint64_t value);
void emitInt64(int64_t value);
- void emit(UInt value);
- void emit(int value);
+ void emit(Int32 value);
+ void emit(UInt32 value);
+ void emit(Int64 value);
+ void emit(UInt64 value);
+
void emit(double value);
void emitChar(char c);
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index 3947e8468..d93a50756 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -2533,8 +2533,7 @@ struct SPIRVEmitContext
case SpvSnippet::ASMOperandType::ResultTypeId:
if (operand.content != 0xFFFFFFFF)
{
- emitOperand(context.qualifiedResultTypes[(SpvStorageClass)operand.content]
- .getValue());
+ emitOperand(context.qualifiedResultTypes.getValue((SpvStorageClass)operand.content));
}
else
{
diff --git a/source/slang/slang-ir-any-value-marshalling.cpp b/source/slang/slang-ir-any-value-marshalling.cpp
index 35e063848..79aea9011 100644
--- a/source/slang/slang-ir-any-value-marshalling.cpp
+++ b/source/slang/slang-ir-any-value-marshalling.cpp
@@ -27,7 +27,7 @@ namespace Slang
{
IRType* originalType;
IRIntegerValue anyValueSize;
- bool operator ==(MarshallingFunctionKey other)
+ bool operator ==(MarshallingFunctionKey other) const
{
return originalType == other.originalType && anyValueSize == other.anyValueSize;
}
diff --git a/source/slang/slang-ir-autodiff-fwd.cpp b/source/slang/slang-ir-autodiff-fwd.cpp
index 25051cb6d..c17d7d5c4 100644
--- a/source/slang/slang-ir-autodiff-fwd.cpp
+++ b/source/slang/slang-ir-autodiff-fwd.cpp
@@ -1608,10 +1608,8 @@ void insertTempVarForMutableParams(IRModule* module, IRFunc* func)
if (inst->getOp() == kIROp_Return)
{
builder.setInsertBefore(inst);
- for (auto& kv : mapParamToTempVar)
- {
- builder.emitStore(kv.key, builder.emitLoad(kv.value));
- }
+ for (const auto& [param, var] : mapParamToTempVar)
+ builder.emitStore(param, builder.emitLoad(var));
}
}
}
diff --git a/source/slang/slang-ir-autodiff-primal-hoist.cpp b/source/slang/slang-ir-autodiff-primal-hoist.cpp
index 898a86049..6ccf7caf4 100644
--- a/source/slang/slang-ir-autodiff-primal-hoist.cpp
+++ b/source/slang/slang-ir-autodiff-primal-hoist.cpp
@@ -108,7 +108,7 @@ static Dictionary<IRBlock*, IRBlock*> createPrimalRecomputeBlocks(
recomputeBlock->insertAtEnd(func);
builder.addDecoration(recomputeBlock, kIROp_RecomputeBlockDecoration);
recomputeBlockMap.add(primalBlock, recomputeBlock);
- indexedBlockInfo[recomputeBlock] = indexedBlockInfo[primalBlock].getValue();
+ indexedBlockInfo.set(recomputeBlock, indexedBlockInfo.getValue(primalBlock));
return recomputeBlock;
};
@@ -188,7 +188,7 @@ static Dictionary<IRBlock*, IRBlock*> createPrimalRecomputeBlocks(
// Queue work for the subregion.
auto loop = as<IRLoop>(primalBlock->getTerminator());
auto bodyBlock = getLoopRegionBodyBlock(loop);
- auto diffLoop = mapPrimalLoopToDiffLoop[loop].getValue();
+ auto diffLoop = mapPrimalLoopToDiffLoop.getValue(loop);
auto diffBodyBlock = getLoopRegionBodyBlock(diffLoop);
auto bodyRecomputeBlock = createRecomputeBlock(bodyBlock);
bodyRecomputeBlock->insertBefore(diffBodyBlock);
@@ -499,11 +499,10 @@ RefPtr<HoistedPrimalsInfo> AutodiffCheckpointPolicyBase::processFunc(
struct ImplicationParams
{
IRInst *condition, *induction, *block;
- HashCode getHashCode() const { return getHashCodeBytewise(*this); }
- // C++20: friend auto operator<=>(const ImplicationParams&, const ImplicationParams&) = default;
- friend bool operator==(const ImplicationParams& x, const ImplicationParams& y)
+ SLANG_BYTEWISE_HASHABLE;
+ bool operator==(const ImplicationParams& other) const
{
- return x.condition == y.condition && x.induction == y.induction && x.block == y.block;
+ return condition == other.condition && induction == other.induction && block == other.block;
}
};
@@ -993,7 +992,7 @@ void applyCheckpointSet(
predecessorSet.add(predecessor);
auto primalPhiArg = as<IRUnconditionalBranch>(predecessor->getTerminator())->getArg(ii);
- auto recomputePredecessor = mapPrimalBlockToRecomputeBlock[predecessor].getValue();
+ auto recomputePredecessor = mapPrimalBlockToRecomputeBlock.getValue(predecessor);
// For now, find the primal phi argument in this predecessor,
// and stick it into the recompute predecessor's branch inst. We
@@ -1236,7 +1235,7 @@ static int getInstRegionNestLevel(
IRBlock* defBlock,
IRInst* inst)
{
- auto result = indexedBlockInfo[defBlock].getValue().getCount();
+ auto result = indexedBlockInfo.getValue(defBlock).getCount();
// Loop counters are considered to not belong to the region started by the its loop.
if (result > 0 && inst->findDecoration<IRLoopCounterDecoration>())
result--;
@@ -1261,7 +1260,7 @@ static List<IndexTrackingInfo> maybeTrimIndices(
{
auto useInst = use->getUser();
auto useBlock = useInst->getParent();
- auto useBlockIndices = indexedBlockInfo[as<IRBlock>(useBlock)].getValue();
+ auto useBlockIndices = indexedBlockInfo.getValue(as<IRBlock>(useBlock));
if (useBlockIndices.contains(index))
{
found = true;
@@ -1410,7 +1409,7 @@ RefPtr<HoistedPrimalsInfo> ensurePrimalAvailability(
continue;
}
- auto defBlockIndices = indexedBlockInfo[defBlock].getValue();
+ auto defBlockIndices = indexedBlockInfo.getValue(defBlock);
IRBlock* varBlock = defaultVarBlock;
if (isRecomputeInst)
{
diff --git a/source/slang/slang-ir-autodiff-primal-hoist.h b/source/slang/slang-ir-autodiff-primal-hoist.h
index 96e4ea99b..d655d45a6 100644
--- a/source/slang/slang-ir-autodiff-primal-hoist.h
+++ b/source/slang/slang-ir-autodiff-primal-hoist.h
@@ -103,26 +103,21 @@ namespace Slang
RefPtr<HoistedPrimalsInfo> applyMap(IRCloneEnv* env)
{
RefPtr<HoistedPrimalsInfo> newPrimalsInfo = new HoistedPrimalsInfo();
-
- for (auto inst : this->storeSet)
- if (env->mapOldValToNew.containsKey(inst))
- newPrimalsInfo->storeSet.add(env->mapOldValToNew[inst]);
-
- for (auto inst : this->recomputeSet)
- if (env->mapOldValToNew.containsKey(inst))
- newPrimalsInfo->recomputeSet.add(env->mapOldValToNew[inst]);
-
- for (auto inst : this->invertSet)
- if (env->mapOldValToNew.containsKey(inst))
- newPrimalsInfo->invertSet.add(env->mapOldValToNew[inst]);
-
- for (auto inst : this->instsToInvert)
- if (env->mapOldValToNew.containsKey(inst))
- newPrimalsInfo->instsToInvert.add(env->mapOldValToNew[inst]);
- for (auto kvpair : this->invertInfoMap)
- if (env->mapOldValToNew.containsKey(kvpair.key))
- newPrimalsInfo->invertInfoMap[env->mapOldValToNew[kvpair.key]] = kvpair.value.applyMap(env);
+ const auto goSet = [&env](const auto& inSet, auto& outSet){
+ for (auto inst : inSet)
+ if (const auto newKey = env->mapOldValToNew.tryGetValue(inst))
+ outSet.add(*newKey);
+ };
+
+ goSet(this->storeSet, newPrimalsInfo->storeSet);
+ goSet(this->recomputeSet, newPrimalsInfo->recomputeSet);
+ goSet(this->invertSet, newPrimalsInfo->invertSet);
+ goSet(this->instsToInvert, newPrimalsInfo->instsToInvert);
+
+ for (auto [key, value] : this->invertInfoMap)
+ if (const auto newKey = env->mapOldValToNew.tryGetValue(key))
+ newPrimalsInfo->invertInfoMap.set(*newKey, value.applyMap(env));
return newPrimalsInfo;
}
@@ -141,8 +136,8 @@ namespace Slang
for (auto inst : info->instsToInvert)
instsToInvert.add(inst);
- for (auto kvpair : info->invertInfoMap)
- invertInfoMap[kvpair.key] = kvpair.value;
+ for (auto invertInfo : info->invertInfoMap)
+ invertInfoMap.add(invertInfo);
}
};
diff --git a/source/slang/slang-ir-autodiff-rev.cpp b/source/slang/slang-ir-autodiff-rev.cpp
index fc8979551..532fb88ac 100644
--- a/source/slang/slang-ir-autodiff-rev.cpp
+++ b/source/slang/slang-ir-autodiff-rev.cpp
@@ -658,8 +658,8 @@ namespace Slang
// Remove [KeepAlive] decorations for primal param replacement insts.
static void _unlockPrimalParamReplacementInsts(ParameterBlockTransposeInfo& paramInfo)
{
- for (auto& kv : paramInfo.mapPrimalSpecificParamToReplacementInPropFunc)
- kv.value->findDecoration<IRKeepAliveDecoration>()->removeAndDeallocate();
+ for (const auto& [_, value] : paramInfo.mapPrimalSpecificParamToReplacementInPropFunc)
+ value->findDecoration<IRKeepAliveDecoration>()->removeAndDeallocate();
}
// Transcribe a function definition.
diff --git a/source/slang/slang-ir-autodiff-transpose.h b/source/slang/slang-ir-autodiff-transpose.h
index 739ce6553..dad4ab192 100644
--- a/source/slang/slang-ir-autodiff-transpose.h
+++ b/source/slang/slang-ir-autodiff-transpose.h
@@ -571,7 +571,7 @@ struct DiffTransposePass
// Keep track of first diff block, since this is where
// we'll emit temporary vars to hold per-block derivatives.
//
- auto firstRevDiffBlock = revBlockMap[terminalDiffBlocks[0]].getValue();
+ auto firstRevDiffBlock = revBlockMap.getValue(terminalDiffBlocks[0]);
firstRevDiffBlockMap[revDiffFunc] = firstRevDiffBlock;
// Move all diff vars to first block, and initialize them with zero.
@@ -855,11 +855,14 @@ struct DiffTransposePass
// function scope variable, since control flow can affect what blocks contribute to
// for a specific inst.
//
- for (auto pair : gradientsMap)
+ List<IRLoad*> loads;
+ for (const auto& [key, _] : gradientsMap)
{
- if (auto loadInst = as<IRLoad>(pair.key))
- accumulateGradientsForLoad(&builder, loadInst);
+ if (auto load = as<IRLoad>(key))
+ loads.add(load);
}
+ for(const auto& load : loads)
+ accumulateGradientsForLoad(&builder, load);
// Do the same thing with the phi parameters if the block.
List<IRInst*> phiParamRevGradInsts;
@@ -903,16 +906,16 @@ struct DiffTransposePass
// Also handle any remaining gradients for insts that appear in prior blocks.
List<IRInst*> externInsts; // Holds insts in a different block, same function.
List<IRInst*> globalInsts; // Holds insts in the global scope.
- for (auto pair : gradientsMap)
+ for (const auto& [inst, _] : gradientsMap)
{
- auto instParent = pair.key->getParent();
+ auto instParent = inst->getParent();
if (instParent != fwdBlock)
{
if (instParent->getParent() == fwdBlock->getParent())
- externInsts.add(pair.key);
+ externInsts.add(inst);
if (as<IRModuleInst>(instParent))
- globalInsts.add(pair.key);
+ globalInsts.add(inst);
}
}
@@ -1357,7 +1360,7 @@ struct DiffTransposePass
SLANG_ASSERT(!(afterBlockMap.containsKey(afterBlock) && \
afterBlockMap[afterBlock] != block->getTerminator()));
- afterBlockMap[afterBlock] = block->getTerminator();
+ afterBlockMap.set(afterBlock, block->getTerminator());
}
}
}
@@ -2779,7 +2782,7 @@ struct DiffTransposePass
{
gradientsMap[fwdInst] = List<RevGradient>();
}
- gradientsMap[fwdInst].getValue().add(assignment);
+ gradientsMap.getValue(fwdInst).add(assignment);
}
List<RevGradient> getRevGradients(IRInst* fwdInst)
@@ -2789,7 +2792,7 @@ struct DiffTransposePass
List<RevGradient> popRevGradients(IRInst* fwdInst)
{
- List<RevGradient> val = gradientsMap[fwdInst].getValue();
+ List<RevGradient> val = gradientsMap.getValue(fwdInst);
gradientsMap.remove(fwdInst);
return val;
}
diff --git a/source/slang/slang-ir-autodiff-unzip.cpp b/source/slang/slang-ir-autodiff-unzip.cpp
index 1b14856e6..95ad0d921 100644
--- a/source/slang/slang-ir-autodiff-unzip.cpp
+++ b/source/slang/slang-ir-autodiff-unzip.cpp
@@ -331,7 +331,7 @@ IRFunc* DiffUnzipPass::extractPrimalFunc(
for (auto param : func->getParams())
{
if (paramInfo.primalFuncParams.contains(param))
- newPrimalParams.add(subEnv.mapOldValToNew[param].getValue());
+ newPrimalParams.add(subEnv.mapOldValToNew.getValue(param));
}
ExtractPrimalFuncContext context;
diff --git a/source/slang/slang-ir-autodiff-unzip.h b/source/slang/slang-ir-autodiff-unzip.h
index 2a5d73a01..4846fc840 100644
--- a/source/slang/slang-ir-autodiff-unzip.h
+++ b/source/slang/slang-ir-autodiff-unzip.h
@@ -159,11 +159,8 @@ struct DiffUnzipPass
//
{
List<IRBlock*> workList;
- for (auto blockRegionPair : indexRegionMap->map)
- {
- IRBlock* block = blockRegionPair.key;
+ for (auto [block, _] : indexRegionMap->map)
workList.add(block);
- }
for (auto block : workList)
{
@@ -171,7 +168,7 @@ struct DiffUnzipPass
indexRegionMap->map[as<IRBlock>(primalMap[block])] = (IndexedRegion*)indexRegionMap->map[block];
if (diffMap.containsKey(block))
- indexRegionMap->map[as<IRBlock>(diffMap[block])] = (IndexedRegion*)indexRegionMap->map[block];
+ indexRegionMap->map.set(as<IRBlock>(diffMap[block]), (IndexedRegion*)indexRegionMap->map[block]);
}
}
diff --git a/source/slang/slang-ir-autodiff.cpp b/source/slang/slang-ir-autodiff.cpp
index 2231e0ce7..cb710ac6b 100644
--- a/source/slang/slang-ir-autodiff.cpp
+++ b/source/slang/slang-ir-autodiff.cpp
@@ -1782,7 +1782,7 @@ bool finalizeAutoDiffPass(IRModule* module)
// Remove auto-diff related decorations.
stripAutoDiffDecorations(module);
- return false;
+ return modified;
}
IRBlock* getBlock(IRInst* inst)
diff --git a/source/slang/slang-ir-eliminate-multilevel-break.cpp b/source/slang/slang-ir-eliminate-multilevel-break.cpp
index 8f7307f1b..65e388608 100644
--- a/source/slang/slang-ir-eliminate-multilevel-break.cpp
+++ b/source/slang/slang-ir-eliminate-multilevel-break.cpp
@@ -338,10 +338,8 @@ struct EliminateMultiLevelBreakContext
// Once we have rewritten regions' break blocks with additional targetLevel parameter, all
// original branches into that block without a parameter will now need to provide a default
// value equal to the level of its corresponding region.
- for (auto breakBlockKV : mapNewBreakBlockToRegionLevel)
+ for (auto [breakBlock, level] : mapNewBreakBlockToRegionLevel)
{
- auto breakBlock = breakBlockKV.key;
- auto level = breakBlockKV.value;
IRInst* levelInst = nullptr;
List<IRUse*> uses;
for (auto use = breakBlock->firstUse; use; use = use->nextUse)
diff --git a/source/slang/slang-ir-eliminate-phis.cpp b/source/slang/slang-ir-eliminate-phis.cpp
index 48e95303f..c628b937e 100644
--- a/source/slang/slang-ir-eliminate-phis.cpp
+++ b/source/slang/slang-ir-eliminate-phis.cpp
@@ -140,11 +140,10 @@ struct PhiEliminationContext
{
IRBuilder builder(m_module);
- for (auto instAlloc : m_registerAllocation.mapInstToRegister)
+ for (const auto& [inst, reg] : m_registerAllocation.mapInstToRegister)
{
- auto inst = instAlloc.key;
IRInst* registerVar = nullptr;
- m_mapRegToTempVar.tryGetValue(instAlloc.value, registerVar);
+ m_mapRegToTempVar.tryGetValue(reg, registerVar);
SLANG_RELEASE_ASSERT(registerVar);
switch (inst->getOp())
@@ -159,7 +158,7 @@ struct PhiEliminationContext
m_registerAllocation.mapInstToRegister.tryGetValue(updateInst->getOldValue(), oldReg);
// If the original value is not assigned to the same register as this inst,
// we need to insert a copy.
- if (instAlloc.value != oldReg)
+ if (reg != oldReg)
{
builder.emitStore(registerVar, updateInst->getOldValue());
}
@@ -178,11 +177,10 @@ struct PhiEliminationContext
{
IRBuilder builder(m_module);
- for (auto instAlloc : m_registerAllocation.mapInstToRegister)
+ for (const auto& [inst, reg] : m_registerAllocation.mapInstToRegister)
{
- auto inst = instAlloc.key;
IRInst* registerVar = nullptr;
- m_mapRegToTempVar.tryGetValue(instAlloc.value, registerVar);
+ m_mapRegToTempVar.tryGetValue(reg, registerVar);
SLANG_RELEASE_ASSERT(registerVar);
while (auto use = inst->firstUse)
{
diff --git a/source/slang/slang-ir-generics-lowering-context.cpp b/source/slang/slang-ir-generics-lowering-context.cpp
index 609a9e298..325568040 100644
--- a/source/slang/slang-ir-generics-lowering-context.cpp
+++ b/source/slang/slang-ir-generics-lowering-context.cpp
@@ -88,7 +88,7 @@ namespace Slang
IRInst* SharedGenericsLoweringContext::findInterfaceRequirementVal(IRInterfaceType* interfaceType, IRInst* requirementKey)
{
if (auto dict = mapInterfaceRequirementKeyValue.tryGetValue(interfaceType))
- return (*dict)[requirementKey].getValue();
+ return dict->getValue(requirementKey);
_builldInterfaceRequirementMap(interfaceType);
return findInterfaceRequirementVal(interfaceType, requirementKey);
}
diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp
index a5bb299c5..5c4e1d037 100644
--- a/source/slang/slang-ir-glsl-legalize.cpp
+++ b/source/slang/slang-ir-glsl-legalize.cpp
@@ -2744,10 +2744,8 @@ void legalizeEntryPointForGLSL(
// Let's fix the size array type globals now that we know the maximum index
{
- for (const auto& a : context.systemNameToGlobalMap)
+ for (const auto& [_, value] : context.systemNameToGlobalMap)
{
- const auto& value = a.value;
-
auto type = value.globalParam->getDataType();
// Strip out if there is one
diff --git a/source/slang/slang-ir-inline.cpp b/source/slang/slang-ir-inline.cpp
index db4bb50a8..e878c56f7 100644
--- a/source/slang/slang-ir-inline.cpp
+++ b/source/slang/slang-ir-inline.cpp
@@ -573,7 +573,7 @@ struct InliningPassBase
// Insert a branch into the cloned first block at the end of `callerBlock`.
builder->setInsertInto(callerBlock);
- auto mainBlock = as<IRBlock>(env->mapOldValToNew[callee->getFirstBlock()].getValue());
+ auto mainBlock = as<IRBlock>(env->mapOldValToNew.getValue(callee->getFirstBlock()));
auto newBranch = builder->emitLoop(mainBlock, afterBlock, mainBlock);
_setSourceLoc(newBranch, call, callSite);
@@ -581,7 +581,7 @@ struct InliningPassBase
bool isFirstBlock = true;
for (auto calleeBlock : callee->getBlocks())
{
- auto clonedBlock = env->mapOldValToNew[calleeBlock].getValue();
+ auto clonedBlock = env->mapOldValToNew.getValue(calleeBlock);
builder->setInsertInto(clonedBlock);
// We will loop over the instructions of the each block,
// and clone each of them appropriately.
diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp
index 364613074..66fda8a86 100644
--- a/source/slang/slang-ir-link.cpp
+++ b/source/slang/slang-ir-link.cpp
@@ -595,10 +595,8 @@ IRGeneric* cloneGenericImpl(
// Generic parameter list does not match, bail.
if (clonedParam || originalParam)
continue;
- for (auto kv : paramMapping)
- {
- registerClonedValue(context, kv.key, kv.value);
- }
+ for (const auto& [key, value] : paramMapping)
+ registerClonedValue(context, key, value);
IRBuilder builderStorage = *builder;
IRBuilder* decorBuilder = &builderStorage;
diff --git a/source/slang/slang-ir-lower-generic-function.cpp b/source/slang/slang-ir-lower-generic-function.cpp
index 3edc373c4..baedbbd22 100644
--- a/source/slang/slang-ir-lower-generic-function.cpp
+++ b/source/slang/slang-ir-lower-generic-function.cpp
@@ -370,10 +370,8 @@ namespace Slang
void replaceLoweredInterfaceTypes()
{
- for (auto lowered : sharedContext->loweredInterfaceTypes)
- {
- lowered.key->replaceUsesWith(lowered.value);
- }
+ for (const auto& [loweredKey, loweredValue] : sharedContext->loweredInterfaceTypes)
+ loweredKey->replaceUsesWith(loweredValue);
sharedContext->mapInterfaceRequirementKeyValue.clear();
}
diff --git a/source/slang/slang-ir-lower-optional-type.cpp b/source/slang/slang-ir-lower-optional-type.cpp
index 91b108ffe..ba2584976 100644
--- a/source/slang/slang-ir-lower-optional-type.cpp
+++ b/source/slang/slang-ir-lower-optional-type.cpp
@@ -270,10 +270,8 @@ namespace Slang
}
// Replace all optional types with lowered struct types.
- for (auto kv : loweredOptionalTypes)
- {
- kv.key->replaceUsesWith(kv.value->loweredType);
- }
+ for (const auto& [key, value] : loweredOptionalTypes)
+ key->replaceUsesWith(value->loweredType);
}
};
diff --git a/source/slang/slang-ir-lower-result-type.cpp b/source/slang/slang-ir-lower-result-type.cpp
index a10a9d343..ee69a4fed 100644
--- a/source/slang/slang-ir-lower-result-type.cpp
+++ b/source/slang/slang-ir-lower-result-type.cpp
@@ -291,10 +291,8 @@ namespace Slang
}
// Replace all result types with lowered struct types.
- for (auto kv : loweredResultTypes)
- {
- kv.key->replaceUsesWith(kv.value->loweredType);
- }
+ for (const auto& [key, value] : loweredResultTypes)
+ key->replaceUsesWith(value->loweredType);
}
};
diff --git a/source/slang/slang-ir-lower-tuple-types.cpp b/source/slang/slang-ir-lower-tuple-types.cpp
index 1392ab453..caa031d85 100644
--- a/source/slang/slang-ir-lower-tuple-types.cpp
+++ b/source/slang/slang-ir-lower-tuple-types.cpp
@@ -170,10 +170,8 @@ namespace Slang
}
// Replace all tuple types with lowered struct types.
- for (auto kv : loweredTuples)
- {
- kv.key->replaceUsesWith(kv.value->structType);
- }
+ for (const auto& [key, value] : loweredTuples)
+ key->replaceUsesWith(value->structType);
}
};
diff --git a/source/slang/slang-ir-obfuscate-loc.cpp b/source/slang/slang-ir-obfuscate-loc.cpp
index 860633106..9aef6f6a6 100644
--- a/source/slang/slang-ir-obfuscate-loc.cpp
+++ b/source/slang/slang-ir-obfuscate-loc.cpp
@@ -4,7 +4,7 @@
#include "../../slang.h"
#include "../core/slang-random-generator.h"
-#include "../core/slang-hash.h"
+#include "../core/slang-stable-hash.h"
#include "../core/slang-char-util.h"
#include "../core/slang-castable.h"
@@ -81,7 +81,7 @@ SlangResult obfuscateModuleLocs(IRModule* module, SourceManager* sourceManager)
// Doing so would mean that we could use the obfuscated location ouput to output
// the origin.
- HashCode hash = 0;
+ StableHashCode32 hash{0};
List<LocPair> locPairs;
@@ -124,10 +124,10 @@ SlangResult obfuscateModuleLocs(IRModule* module, SourceManager* sourceManager)
const auto pathInfo = sourceView->getViewPathInfo();
const auto name = pathInfo.getName();
- const auto nameHash = getHashCode(pathInfo.getName().getUnownedSlice());
+ const auto nameHash = getStableHashCode32(name.getBuffer(), name.getLength());
// Combine the name
- hash = combineHash(hash, nameHash);
+ hash = combineStableHash(hash, nameHash);
}
// We *can't* just use the offset to produce the hash, because the source might have
@@ -140,8 +140,7 @@ SlangResult obfuscateModuleLocs(IRModule* module, SourceManager* sourceManager)
const auto lineIndex = sourceFile->calcLineIndexFromOffset(offset);
const auto lineOffset = sourceFile->calcColumnOffset(lineIndex, offset);
- hash = combineHash(hash, getHashCode(lineIndex));
- hash = combineHash(hash, getHashCode(lineOffset));
+ hash = combineStableHash(hash, getStableHashCode32(lineIndex), getStableHashCode32(lineOffset));
}
}
}
diff --git a/source/slang/slang-ir-reachability.h b/source/slang/slang-ir-reachability.h
index f605abd41..74463b7fe 100644
--- a/source/slang/slang-ir-reachability.h
+++ b/source/slang/slang-ir-reachability.h
@@ -13,17 +13,17 @@ struct ReachabilityContext
{
IRBlock* first;
IRBlock* second;
- HashCode getHashCode()
+ bool operator == (const BlockPair& other) const
+ {
+ return first == other.first && second == other.second;
+ }
+ HashCode getHashCode() const
{
Hasher h;
h.hashValue(first);
h.hashValue(second);
return h.getResult();
}
- bool operator == (const BlockPair& other)
- {
- return first == other.first && second == other.second;
- }
};
Dictionary<BlockPair, bool> reachabilityResults;
diff --git a/source/slang/slang-ir-specialize-dispatch.cpp b/source/slang/slang-ir-specialize-dispatch.cpp
index 4b26ced32..d57e1ed96 100644
--- a/source/slang/slang-ir-specialize-dispatch.cpp
+++ b/source/slang/slang-ir-specialize-dispatch.cpp
@@ -333,10 +333,8 @@ void specializeDispatchFunctions(SharedGenericsLoweringContext* sharedContext)
ensureWitnessTableSequentialIDs(sharedContext);
// Generate specialized dispatch functions and fixup call sites.
- for (auto kv : sharedContext->mapInterfaceRequirementKeyToDispatchMethods)
+ for (const auto& [_, dispatchFunc] : sharedContext->mapInterfaceRequirementKeyToDispatchMethods)
{
- auto dispatchFunc = kv.value;
-
// Generate a specialized `switch` statement based dispatch func,
// from the witness tables present in the module.
auto newDispatchFunc = specializeDispatchFunction(sharedContext, dispatchFunc);
diff --git a/source/slang/slang-ir-specialize.cpp b/source/slang/slang-ir-specialize.cpp
index 83e2cad70..b2cd5edc4 100644
--- a/source/slang/slang-ir-specialize.cpp
+++ b/source/slang/slang-ir-specialize.cpp
@@ -632,7 +632,7 @@ struct SpecializationContext
int childrenCount = 0;
for (auto child = dictInst->getFirstChild(); child; child = child->next)
childrenCount++;
- dict.reserve(1 << Math::Log2Ceil(childrenCount * 2));
+ dict.reserve(Index{1} << Math::Log2Ceil(childrenCount * 2));
for (auto child : dictInst->getChildren())
{
auto item = as<IRSpecializationDictionaryItem>(child);
@@ -698,18 +698,18 @@ struct SpecializationContext
builder.setInsertInto(moduleInst);
auto dictInst = builder.emitIntrinsicInst(nullptr, dictOp, 0, nullptr);
builder.setInsertInto(dictInst);
- for (auto kv : dict)
+ for (const auto& [key, value] : dict)
{
- if (!kv.value->parent)
+ if (!value->parent)
continue;
- for (auto keyVal : kv.key.vals)
+ for (auto keyVal : key.vals)
{
if (!keyVal->parent) goto next;
}
{
List<IRInst*> args;
- args.add(kv.value);
- args.addRange(kv.key.vals);
+ args.add(value);
+ args.addRange(key.vals);
builder.emitIntrinsicInst(nullptr, kIROp_SpecializationDictionaryItem, args.getCount(), args.getBuffer());
}
next:;
diff --git a/source/slang/slang-ir-spirv-snippet.cpp b/source/slang/slang-ir-spirv-snippet.cpp
index 40a506d64..ecb8d1b5e 100644
--- a/source/slang/slang-ir-spirv-snippet.cpp
+++ b/source/slang/slang-ir-spirv-snippet.cpp
@@ -102,7 +102,7 @@ RefPtr<SpvSnippet> SpvSnippet::parse(UnownedStringSlice definition)
if (tokenReader.AdvanceIf("%"))
{
String instName = tokenReader.ReadToken().Content;
- mapInstNameToIndex[instName] = (int)snippet->instructions.getCount();
+ mapInstNameToIndex.set(instName, (int)snippet->instructions.getCount());
tokenReader.Read(Slang::Misc::TokenType::OpAssign);
}
SpvOp opCode;
diff --git a/source/slang/slang-ir-spirv-snippet.h b/source/slang/slang-ir-spirv-snippet.h
index 75edf0b38..c1497496d 100644
--- a/source/slang/slang-ir-spirv-snippet.h
+++ b/source/slang/slang-ir-spirv-snippet.h
@@ -76,7 +76,7 @@ struct SpvSnippet : public RefObject
ASMType type;
SpvWord intValues[4];
float floatValues[4];
- HashCode getHashCode()
+ HashCode getHashCode() const
{
HashCode result = (HashCode)type;
for (int i = 0; i < 4; i++)
@@ -96,7 +96,7 @@ struct SpvSnippet : public RefObject
}
return result;
}
- bool operator==(const ASMConstant& other)
+ bool operator==(const ASMConstant& other) const
{
if (type != other.type)
return false;
diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h
index 68ca403bd..b765f6aee 100644
--- a/source/slang/slang-ir.h
+++ b/source/slang/slang-ir.h
@@ -2034,6 +2034,7 @@ public:
{
hashCode = _getHashCode();
}
+ IRInstKey& operator=(const IRInstKey&) = default;
HashCode getHashCode() const { return hashCode; }
IRInst* getInst() const { return inst; }
diff --git a/source/slang/slang-language-server.cpp b/source/slang/slang-language-server.cpp
index bc12ad34f..5574b995d 100644
--- a/source/slang/slang-language-server.cpp
+++ b/source/slang/slang-language-server.cpp
@@ -1537,14 +1537,14 @@ void LanguageServer::publishDiagnostics()
// Send updates to clear diagnostics for files that no longer have any messages.
List<String> filesToRemove;
- for (auto& file : m_lastPublishedDiagnostics)
+ for (const auto& [filepath, _] : m_lastPublishedDiagnostics)
{
- if (!version->diagnostics.containsKey(file.key))
+ if (!version->diagnostics.containsKey(filepath))
{
PublishDiagnosticsParams args;
- args.uri = URI::fromLocalFilePath(file.key.getUnownedSlice()).uri;
+ args.uri = URI::fromLocalFilePath(filepath.getUnownedSlice()).uri;
m_connection->sendCall(UnownedStringSlice("textDocument/publishDiagnostics"), &args);
- filesToRemove.add(file.key);
+ filesToRemove.add(filepath);
}
}
for (auto& toRemove : filesToRemove)
@@ -1552,17 +1552,17 @@ void LanguageServer::publishDiagnostics()
m_lastPublishedDiagnostics.remove(toRemove);
}
// Send updates for any files whose diagnostic messages has changed since last update.
- for (auto& list : version->diagnostics)
+ for (const auto& [listKey, listValue] : version->diagnostics)
{
- auto lastPublished = m_lastPublishedDiagnostics.tryGetValue(list.key);
- if (!lastPublished || *lastPublished != list.value.originalOutput)
+ auto lastPublished = m_lastPublishedDiagnostics.tryGetValue(listKey);
+ if (!lastPublished || *lastPublished != listValue.originalOutput)
{
PublishDiagnosticsParams args;
- args.uri = URI::fromLocalFilePath(list.key.getUnownedSlice()).uri;
- for (auto& d : list.value.messages)
+ args.uri = URI::fromLocalFilePath(listKey.getUnownedSlice()).uri;
+ for (auto& d : listValue.messages)
args.diagnostics.add(d);
m_connection->sendCall(UnownedStringSlice("textDocument/publishDiagnostics"), &args);
- m_lastPublishedDiagnostics[list.key] = list.value.originalOutput;
+ m_lastPublishedDiagnostics[listKey] = listValue.originalOutput;
}
}
}
diff --git a/source/slang/slang-mangle.cpp b/source/slang/slang-mangle.cpp
index 6a3a17caa..59110ea05 100644
--- a/source/slang/slang-mangle.cpp
+++ b/source/slang/slang-mangle.cpp
@@ -681,7 +681,7 @@ namespace Slang
String getHashedName(const UnownedStringSlice& mangledName)
{
- HashCode64 hash = getStableHashCode64(mangledName.begin(), mangledName.getLength());
+ StableHashCode64 hash = getStableHashCode64(mangledName.begin(), mangledName.getLength());
StringBuilder builder;
builder << "_Sh";
diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp
index c0389d1cd..f9e2433cf 100644
--- a/source/slang/slang-parameter-binding.cpp
+++ b/source/slang/slang-parameter-binding.cpp
@@ -676,8 +676,9 @@ RefPtr<TypeLayout> getTypeLayoutForGlobalShaderParameter(
if(varDecl->hasModifier<ShaderRecordAttribute>() && as<ConstantBufferType>(type))
{
- return createTypeLayout(
- layoutContext.with(rules->getShaderRecordConstantBufferRules()),
+ return createTypeLayoutWith(
+ layoutContext,
+ rules->getShaderRecordConstantBufferRules(),
type);
}
@@ -686,8 +687,9 @@ RefPtr<TypeLayout> getTypeLayoutForGlobalShaderParameter(
// qualifier before we move on to anything else.
if( varDecl->hasModifier<PushConstantAttribute>() && as<ConstantBufferType>(type) )
{
- return createTypeLayout(
- layoutContext.with(rules->getPushConstantBufferRules()),
+ return createTypeLayoutWith(
+ layoutContext,
+ rules->getPushConstantBufferRules(),
type);
}
@@ -710,8 +712,9 @@ RefPtr<TypeLayout> getTypeLayoutForGlobalShaderParameter(
// An "ordinary" global variable is implicitly a uniform
// shader parameter.
- return createTypeLayout(
- layoutContext.with(rules->getConstantBufferRules(context->getTargetRequest())),
+ return createTypeLayoutWith(
+ layoutContext,
+ rules->getConstantBufferRules(context->getTargetRequest()),
type);
}
@@ -1910,15 +1913,19 @@ static RefPtr<TypeLayout> processEntryPointVaryingParameter(
case Stage::ClosestHit:
case Stage::Miss:
// `in out` or `out` parameter is payload
- return createTypeLayout(context->layoutContext.with(
- context->getRulesFamily()->getRayPayloadParameterRules()),
- type);
+ return createTypeLayoutWith(
+ context->layoutContext,
+ context->getRulesFamily()->getRayPayloadParameterRules(),
+ type
+ );
case Stage::Callable:
// `in out` or `out` parameter is payload
- return createTypeLayout(context->layoutContext.with(
- context->getRulesFamily()->getCallablePayloadParameterRules()),
- type);
+ return createTypeLayoutWith(
+ context->layoutContext,
+ context->getRulesFamily()->getCallablePayloadParameterRules(),
+ type
+ );
}
}
@@ -1946,9 +1953,11 @@ static RefPtr<TypeLayout> processEntryPointVaryingParameter(
case Stage::AnyHit:
case Stage::ClosestHit:
// `in` parameter is hit attributes
- return createTypeLayout(context->layoutContext.with(
- context->getRulesFamily()->getHitAttributesParameterRules()),
- type);
+ return createTypeLayoutWith(
+ context->layoutContext,
+ context->getRulesFamily()->getHitAttributesParameterRules(),
+ type
+ );
}
}
@@ -2226,9 +2235,9 @@ static RefPtr<TypeLayout> computeEntryPointParameterTypeLayout(
// a uniform shader parameter passed via the implicitly-defined
// constant buffer (e.g., the `$Params` constant buffer seen in fxc/dxc output).
//
- return createTypeLayout(
- context->layoutContext.with(
- context->getRulesFamily()->getConstantBufferRules(context->getTargetRequest())),
+ return createTypeLayoutWith(
+ context->layoutContext,
+ context->getRulesFamily()->getConstantBufferRules(context->getTargetRequest()),
paramType);
}
else
@@ -3171,9 +3180,8 @@ void diagnoseGlobalUniform(
static int _calcTotalNumUsedRegistersForLayoutResourceKind(ParameterBindingContext* bindingContext, LayoutResourceKind kind)
{
int numUsed = 0;
- for (auto& pair : bindingContext->shared->globalSpaceUsedRangeSets)
+ for (auto& [_, rangeSet] : bindingContext->shared->globalSpaceUsedRangeSets)
{
- UsedRangeSet* rangeSet = pair.value;
const auto& usedRanges = rangeSet->usedResourceRanges[kind];
for (const auto& usedRange : usedRanges.ranges)
{
diff --git a/source/slang/slang-preprocessor.cpp b/source/slang/slang-preprocessor.cpp
index 4cc9bd113..aefbf7619 100644
--- a/source/slang/slang-preprocessor.cpp
+++ b/source/slang/slang-preprocessor.cpp
@@ -3864,11 +3864,8 @@ static Token ReadToken(Preprocessor* preprocessor)
// clean up after an environment
Environment::~Environment()
{
- for (auto pair : this->macros)
- {
- auto macro = pair.value;
+ for (const auto& [_, macro] : this->macros)
delete macro;
- }
}
// Add a simple macro definition from a string (e.g., for a
@@ -4066,10 +4063,8 @@ TokenList preprocessSource(
if(desc.defines)
{
- for (auto p : *desc.defines)
- {
- DefineMacro(&preprocessor, p.key, p.value);
- }
+ for (const auto& [key, value] : *desc.defines)
+ DefineMacro(&preprocessor, key, value);
}
{
diff --git a/source/slang/slang-reflection-api.cpp b/source/slang/slang-reflection-api.cpp
index 9f83d325d..a52b7b886 100644
--- a/source/slang/slang-reflection-api.cpp
+++ b/source/slang/slang-reflection-api.cpp
@@ -2962,9 +2962,9 @@ SLANG_API const char* spReflection_getHashedString(
return slice.begin();
}
-SLANG_API int spComputeStringHash(const char* chars, size_t count)
+SLANG_API SlangUInt32 spComputeStringHash(const char* chars, size_t count)
{
- return (int)getStableHashCode32(chars, count);
+ return SlangUInt32(getStableHashCode32(chars, count));
}
SLANG_API SlangReflectionTypeLayout* spReflection_getGlobalParamsTypeLayout(
diff --git a/source/slang/slang-repro.cpp b/source/slang/slang-repro.cpp
index 7ddf2f304..de698cf46 100644
--- a/source/slang/slang-repro.cpp
+++ b/source/slang/slang-repro.cpp
@@ -57,7 +57,7 @@ namespace Slang {
#define SLANG_STATE_TYPE_SIZE(x) uint32_t(sizeof(x)),
// A function to calculate the hash related in list in part to how the types used are sized. Can catch crude breaking binary differences.
-static HashCode32 _calcTypeHash()
+static StableHashCode32 _calcTypeHash()
{
typedef ReproUtil Util;
const uint32_t sizes[] =
@@ -67,9 +67,9 @@ static HashCode32 _calcTypeHash()
return getStableHashCode32((const char*)&sizes, sizeof(sizes));
}
-static HashCode32 _getTypeHash()
+static StableHashCode32 _getTypeHash()
{
- static HashCode32 s_hash = _calcTypeHash();
+ static StableHashCode32 s_hash = _calcTypeHash();
return s_hash;
}
@@ -278,15 +278,11 @@ struct StoreContext
OffsetBase& base = m_container->asBase();
Index index = 0;
- for (const auto& srcDefine : srcDefines)
+ for (const auto& [srcDefineName, srcDefineVal] : srcDefines)
{
- // Do allocation before setting
- const auto key = fromString(srcDefine.key);
- const auto value = fromString(srcDefine.value);
-
auto& dstDefine = base[dstDefines[index]];
- dstDefine.first = key;
- dstDefine.second = value;
+ dstDefine.first = fromString(srcDefineName);
+ dstDefine.second = fromString(srcDefineVal);
index++;
}
@@ -447,7 +443,7 @@ static String _scrubName(const String& in)
{
const auto& srcTargetInfos = request->m_targetInfos;
- if (RefPtr<EndToEndCompileRequest::TargetInfo>* infosPtr = srcTargetInfos.tryGetValue(srcTargetRequest))
+ if (const RefPtr<EndToEndCompileRequest::TargetInfo>* infosPtr = srcTargetInfos.tryGetValue(srcTargetRequest))
{
EndToEndCompileRequest::TargetInfo* infos = *infosPtr;
@@ -456,13 +452,13 @@ static String _scrubName(const String& in)
Offset32Array<OutputState> dstOutputStates = inOutContainer.newArray<OutputState>(entryPointOutputPaths.getCount());
Index index = 0;
- for (const auto& pair : entryPointOutputPaths)
+ for (const auto& [key, value] : entryPointOutputPaths)
{
- Offset32Ptr<OffsetString> outputPath = inOutContainer.newString(pair.value.getUnownedSlice());
+ Offset32Ptr<OffsetString> outputPath = inOutContainer.newString(value.getUnownedSlice());
auto& dstOutputState = base[dstOutputStates[index]];
- dstOutputState.entryPointIndex = int32_t(pair.key);
+ dstOutputState.entryPointIndex = int32_t(key);
dstOutputState.outputPath = outputPath;
index++;
@@ -545,10 +541,10 @@ static String _scrubName(const String& in)
Offset32Array<PathAndPathInfo> pathMap = inOutContainer.newArray<PathAndPathInfo>(srcFiles.getCount());
Index index = 0;
- for (const auto& pair : srcFiles)
+ for (const auto& [key, value] : srcFiles)
{
- const auto path = context.fromString(pair.key);
- const auto pathInfo = context.addPathInfo(pair.value);
+ const auto path = context.fromString(key);
+ const auto pathInfo = context.addPathInfo(value);
PathAndPathInfo& dstInfo = base[pathMap[index]];
dstInfo.path = path;
@@ -637,9 +633,9 @@ static String _scrubName(const String& in)
auto dstSourceFiles = inOutContainer.newArray<Offset32Ptr<SourceFileState>>(srcSourceFiles.getCount());
Index index = 0;
- for (const auto& pair : srcSourceFiles)
+ for (const auto& [_, value] : srcSourceFiles)
{
- base[dstSourceFiles[index]] = pair.value;
+ base[dstSourceFiles[index]] = value;
index++;
}
base[requestState]->sourceFiles = dstSourceFiles;
@@ -873,9 +869,8 @@ struct LoadContext
// Put all the path infos in the cache system
{
- for (const auto& pair : context.m_fileToPathInfoMap)
+ for (const auto& [_, pathInfo] : context.m_fileToPathInfoMap)
{
- CacheFileSystem::PathInfo* pathInfo = pair.value;
SLANG_ASSERT(pathInfo->m_uniqueIdentity.getLength());
dstUniqueMap.add(pathInfo->m_uniqueIdentity, pathInfo);
@@ -1069,10 +1064,8 @@ struct LoadContext
}
// Put all the path infos in the cache system
{
- for (const auto& pair : context.m_fileToPathInfoMap)
+ for (const auto& [_, pathInfo] : context.m_fileToPathInfoMap)
{
- CacheFileSystem::PathInfo* pathInfo = pair.value;
-
// TODO(JS): It's not 100% clear why we are ending up
// with entries that don't have a unique identity.
// For now we ignore adding to the unique map, because
@@ -1105,7 +1098,7 @@ struct LoadContext
Header header;
header.m_chunk.type = kSlangStateFourCC;
header.m_semanticVersion = g_semanticVersion;
- header.m_typeHash = uint32_t(_getTypeHash());
+ header.m_typeHash = _getTypeHash();
return RiffUtil::writeData(&header.m_chunk, sizeof(header),container.getData(), container.getDataCount(), stream);
}
@@ -1152,7 +1145,7 @@ struct LoadContext
return SLANG_FAIL;
}
- if (header.m_typeHash != uint32_t(_getTypeHash()))
+ if (header.m_typeHash != _getTypeHash())
{
sink->diagnose(SourceLoc(), Diagnostics::riffHashMismatch);
return SLANG_FAIL;
diff --git a/source/slang/slang-repro.h b/source/slang/slang-repro.h
index bb0da53c5..03276d6d3 100644
--- a/source/slang/slang-repro.h
+++ b/source/slang/slang-repro.h
@@ -4,6 +4,7 @@
#include "../core/slang-riff.h"
#include "../core/slang-string.h"
+#include "../core/slang-stable-hash.h"
// For TranslationUnitRequest
#include "slang-compiler.h"
@@ -35,7 +36,7 @@ struct ReproUtil
{
RiffHeader m_chunk; ///< The chunk
RiffSemanticVersion m_semanticVersion; ///< The semantic version
- uint32_t m_typeHash; ///< A hash based on the binary representation. If doesn't match then not binary compatible (extra check over semantic versioning)
+ StableHashCode32 m_typeHash; ///< A hash based on the binary representation. If doesn't match then not binary compatible (extra check over semantic versioning)
};
struct FileState
diff --git a/source/slang/slang-serialize-ir.h b/source/slang/slang-serialize-ir.h
index 038335a60..a509db5c8 100644
--- a/source/slang/slang-serialize-ir.h
+++ b/source/slang/slang-serialize-ir.h
@@ -26,7 +26,7 @@ struct IRSerialWriter
static Result writeContainer(const IRSerialData& data, SerialCompressionType compressionType, RiffContainer* container);
/// Get an instruction index from an instruction
- Ser::InstIndex getInstIndex(IRInst* inst) const { return inst ? Ser::InstIndex(m_instMap[inst]) : Ser::InstIndex(0); }
+ Ser::InstIndex getInstIndex(IRInst* inst) const { return inst ? Ser::InstIndex(m_instMap.getValue(inst)) : Ser::InstIndex(0); }
/// Get a slice from an index
UnownedStringSlice getStringSlice(Ser::StringIndex index) const { return m_stringSlicePool.getSlice(StringSlicePool::Handle(index)); }
diff --git a/source/slang/slang-serialize-source-loc.cpp b/source/slang/slang-serialize-source-loc.cpp
index 2ec732f93..afa6c1205 100644
--- a/source/slang/slang-serialize-source-loc.cpp
+++ b/source/slang/slang-serialize-source-loc.cpp
@@ -124,9 +124,8 @@ void SerialSourceLocWriter::write(SerialSourceLocData* outSourceLocData)
// Okay we can now calculate the final source information
- for (auto& pair : m_sourceFileMap)
+ for (const auto& [_, debugSourceFile] : m_sourceFileMap)
{
- Source* debugSourceFile = pair.value;
SourceFile* sourceFile = debugSourceFile->m_sourceFile;
SerialSourceLocData::SourceInfo sourceInfo;
diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp
index bf3df4adc..cdf1f3694 100644
--- a/source/slang/slang-type-layout.cpp
+++ b/source/slang/slang-type-layout.cpp
@@ -1986,12 +1986,12 @@ RefPtr<TypeLayout> applyOffsetToTypeLayout(
mapOldFieldToNew.add(oldField.Ptr(), newField.Ptr());
}
- for (auto entry : oldStructTypeLayout->mapVarToLayout)
+ for (const auto& [entryKey, entryValue] : oldStructTypeLayout->mapVarToLayout)
{
VarLayout* newFieldLayout = nullptr;
- if (mapOldFieldToNew.tryGetValue(entry.value.Ptr(), newFieldLayout))
+ if (mapOldFieldToNew.tryGetValue(entryValue.Ptr(), newFieldLayout))
{
- newStructTypeLayout->mapVarToLayout.add(entry.key, newFieldLayout);
+ newStructTypeLayout->mapVarToLayout.add(entryKey, newFieldLayout);
}
}
@@ -2705,8 +2705,9 @@ static RefPtr<TypeLayout> _createParameterGroupTypeLayout(
// We will first compute a layout for the element type of
// the parameter group.
//
- auto elementTypeLayout = createTypeLayout(
- context.with(elementTypeRules),
+ auto elementTypeLayout = createTypeLayoutWith(
+ context,
+ elementTypeRules,
elementType);
// Now we delegate to a routine that does the meat of
@@ -2830,8 +2831,9 @@ createStructuredBufferTypeLayout(
auto structuredBufferLayoutRules = context.getRulesFamily()->getStructuredBufferRules(context.targetReq);
// Create and save type layout for the buffer contents.
- auto elementTypeLayout = createTypeLayout(
- context.with(structuredBufferLayoutRules),
+ auto elementTypeLayout = createTypeLayoutWith(
+ context,
+ structuredBufferLayoutRules,
elementType);
return createStructuredBufferTypeLayout(
@@ -2849,7 +2851,7 @@ createStructuredBufferTypeLayout(
/// together as a `TypeLayoutResult`.
///
static TypeLayoutResult _createTypeLayout(
- TypeLayoutContext const& context,
+ TypeLayoutContext& context,
Type* type);
/// Create layout information for the given `type`, obeying any layout modifiers on the given declaration.
@@ -3131,10 +3133,8 @@ static RefPtr<TypeLayout> maybeAdjustLayoutForArrayElementType(
mapOriginalFieldToAdjusted.add(originalField, adjustedField);
}
- for( auto p : originalStructTypeLayout->mapVarToLayout )
+ for( auto [key, originalVal] : originalStructTypeLayout->mapVarToLayout )
{
- VarDeclBase* key = p.key;
- RefPtr<VarLayout> originalVal = p.value;
RefPtr<VarLayout> adjustedVal;
if( mapOriginalFieldToAdjusted.tryGetValue(originalVal, adjustedVal) )
{
@@ -3436,7 +3436,7 @@ static bool _isDescriptorSlotLike(
}
static TypeLayoutResult createArrayLikeTypeLayout(
- TypeLayoutContext const& context,
+ TypeLayoutContext& context,
Type* type,
Type* baseType,
IntVal* arrayLength
@@ -3607,23 +3607,23 @@ static TypeLayoutResult createArrayLikeTypeLayout(
return TypeLayoutResult(typeLayout, arrayUniformInfo);
}
-static void _addLayout(TypeLayoutContext const& context,
+static void _addLayout(TypeLayoutContext& context,
Type* type,
TypeLayout* layout)
{
// Add it *without info*.
// The info can be added with _updateLayout
- context.layoutMap[type] = TypeLayoutResult(layout, SimpleLayoutInfo());
+ context.layoutMap.set(type, TypeLayoutResult(layout, SimpleLayoutInfo()));
}
-static void _addLayout(TypeLayoutContext const& context,
+static void _addLayout(TypeLayoutContext& context,
Type* type,
const TypeLayoutResult& result)
{
context.layoutMap[type] = result;
}
-static TypeLayoutResult _updateLayout(TypeLayoutContext const& context,
+static TypeLayoutResult _updateLayout(TypeLayoutContext& context,
Type* type,
const TypeLayoutResult& result)
{
@@ -3641,7 +3641,7 @@ static TypeLayoutResult _updateLayout(TypeLayoutContext const& context,
}
static TypeLayoutResult _createTypeLayout(
- TypeLayoutContext const& context,
+ TypeLayoutContext& context,
Type* type)
{
if (auto layoutResultPtr = context.layoutMap.tryGetValue(type))
@@ -4226,7 +4226,7 @@ static TypeLayoutResult _createTypeLayout(
//
auto anyValueRules = context.getRulesFamily()->getAnyValueRules();
RefPtr<TypeLayout> concreteTypeAnyValueLayout =
- createTypeLayout(context.with(anyValueRules), concreteType);
+ createTypeLayoutWith(context, anyValueRules, concreteType);
// We will look at the resource usage of the concrete type
// to determine if it "fits" in the reserved space.
@@ -4547,12 +4547,22 @@ RefPtr<TypeLayout> getSimpleVaryingParameterTypeLayout(
}
RefPtr<TypeLayout> createTypeLayout(
- TypeLayoutContext const& context,
+ TypeLayoutContext& context,
Type* type)
{
return _createTypeLayout(context, type).layout;
}
+RefPtr<TypeLayout> createTypeLayoutWith(
+ const TypeLayoutContext& context,
+ LayoutRulesImpl* rules,
+ Type* type)
+{
+ auto c = context.with(rules);
+ return createTypeLayout(c, type);
+}
+
+
void TypeLayout::removeResourceUsage(LayoutResourceKind kind)
{
Int infoCount = resourceInfos.getCount();
diff --git a/source/slang/slang-type-layout.h b/source/slang/slang-type-layout.h
index c800d0931..af07f3e73 100644
--- a/source/slang/slang-type-layout.h
+++ b/source/slang/slang-type-layout.h
@@ -1264,7 +1264,14 @@ RefPtr<TypeLayout> getSimpleVaryingParameterTypeLayout(
// Create a full type-layout object for a type,
// according to the layout rules in `context`.
RefPtr<TypeLayout> createTypeLayout(
- TypeLayoutContext const& context,
+ TypeLayoutContext& context,
+ Type* type);
+
+// A wrapper for createTypeLayout which copies the context applying the
+// provided rules with TypeLayoutContext::with
+RefPtr<TypeLayout> createTypeLayoutWith(
+ const TypeLayoutContext& context,
+ LayoutRulesImpl* rules,
Type* type);
//
diff --git a/source/slang/slang-workspace-version.cpp b/source/slang/slang-workspace-version.cpp
index 2ac079047..ed568b470 100644
--- a/source/slang/slang-workspace-version.cpp
+++ b/source/slang/slang-workspace-version.cpp
@@ -299,9 +299,9 @@ RefPtr<WorkspaceVersion> Workspace::createWorkspaceVersion()
else
{
HashSet<String> set;
- for (auto& p : openedDocuments)
+ for (const auto& [docPath, _] : openedDocuments)
{
- auto dir = Path::getParentDirectory(p.key.getBuffer());
+ auto dir = Path::getParentDirectory(docPath.getBuffer());
if (set.add(dir))
searchPathsRaw.add(dir.getBuffer());
}
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 1edf62a38..71c705246 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -407,11 +407,8 @@ SlangResult Session::saveStdLib(SlangArchiveType archiveType, ISlangBlob** outBl
SLANG_AST_BUILDER_RAII(m_builtinLinkage->getASTBuilder());
- for (auto& pair : m_builtinLinkage->mapNameToLoadedModules)
+ for (const auto& [moduleName, module] : m_builtinLinkage->mapNameToLoadedModules)
{
- const Name* moduleName = pair.key;
- Module* module = pair.value;
-
// Set up options
SerialContainerUtil::WriteOptions options;
@@ -943,10 +940,8 @@ Linkage::Linkage(Session* session, ASTBuilder* astBuilder, Linkage* builtinLinka
// Copy of the built in linkages modules
if (builtinLinkage)
{
- for (const auto& pair : builtinLinkage->mapNameToLoadedModules)
- {
- mapNameToLoadedModules.add(pair.key, pair.value);
- }
+ for (const auto& nameToMod : builtinLinkage->mapNameToLoadedModules)
+ mapNameToLoadedModules.add(nameToMod);
}
{
@@ -1387,10 +1382,10 @@ void Linkage::buildHash(DigestBuilder<SHA1>& builder, SlangInt targetIndex)
}
// Add the preprocessor definitions to the hash
- for (auto& key : preprocessorDefinitions)
+ for (const auto& [defName, defVal] : preprocessorDefinitions)
{
- builder.append(key.key);
- builder.append(key.value);
+ builder.append(defName);
+ builder.append(defVal);
}
// Add the target specified by targetIndex
@@ -2074,9 +2069,9 @@ static void _calcViewInitiatingHierarchy(SourceManager* sourceManager, ViewIniti
// Order all the children, by their raw SourceLocs. This is desirable, so that a trivial traversal
// will traverse children in the order they are initiated in the parent source.
// This assumes they increase in SourceLoc implies an later within a source file - this is true currently.
- for (auto& pair : outHierarchy)
+ for (auto& [_, value] : outHierarchy)
{
- pair.value.sort([](SourceView* a, SourceView* b) -> bool { return a->getInitiatingSourceLoc().getRaw() < b->getInitiatingSourceLoc().getRaw(); });
+ value.sort([](SourceView* a, SourceView* b) -> bool { return a->getInitiatingSourceLoc().getRaw() < b->getInitiatingSourceLoc().getRaw(); });
}
}
@@ -2233,12 +2228,12 @@ void FrontEndCompileRequest::parseTranslationUnit(
// Note! that a adding a define twice will cause an exception in debug builds
// that may be desirable or not...
Dictionary<String, String> combinedPreprocessorDefinitions;
- for(auto& def : getLinkage()->preprocessorDefinitions)
- combinedPreprocessorDefinitions.add(def.key, def.value);
- for(auto& def : preprocessorDefinitions)
- combinedPreprocessorDefinitions.add(def.key, def.value);
- for(auto& def : translationUnit->preprocessorDefinitions)
- combinedPreprocessorDefinitions.add(def.key, def.value);
+ for(const auto& def : getLinkage()->preprocessorDefinitions)
+ combinedPreprocessorDefinitions.add(def);
+ for(const auto& def : preprocessorDefinitions)
+ combinedPreprocessorDefinitions.add(def);
+ for(const auto& def : translationUnit->preprocessorDefinitions)
+ combinedPreprocessorDefinitions.add(def);
// Define standard macros, if not already defined. This style assumes using `#if __SOME_VAR` style, as in
//