summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2023-04-20 13:42:20 -0400
committerGitHub <noreply@github.com>2023-04-20 13:42:20 -0400
commit088644c21c015eb60a41a59f417990023f1f4ef8 (patch)
tree596d224f99e35dcd3d66507cfe297bc25407336d /source
parent4e67cdedbef8f643c90b48172d5419d3dd1839db (diff)
Improve SourceMap coverage/testing (#2818)
* #include an absolute path didn't work - because paths were taken to always be relative. * WIP around more value like behavior for SourceMap/StringPool. * Use default impls on SourceMap ctor/assignment. * Handle comparison of SourceMaps. Some small fixes. Expand unit tests.
Diffstat (limited to 'source')
-rw-r--r--source/compiler-core/slang-json-source-map-util.cpp12
-rw-r--r--source/compiler-core/slang-source-map.cpp99
-rw-r--r--source/compiler-core/slang-source-map.h24
-rw-r--r--source/core/slang-string-slice-pool.cpp94
-rw-r--r--source/core/slang-string-slice-pool.h12
5 files changed, 238 insertions, 3 deletions
diff --git a/source/compiler-core/slang-json-source-map-util.cpp b/source/compiler-core/slang-json-source-map-util.cpp
index 193c812b7..30d722c4c 100644
--- a/source/compiler-core/slang-json-source-map-util.cpp
+++ b/source/compiler-core/slang-json-source-map-util.cpp
@@ -209,6 +209,7 @@ void _encode(Index v, StringBuilder& out)
cur = StringSlicePool::kNullHandle;
}
+ // Special case sourcesContent, because needs to be able to handle null or string
for (Index i = 0; i < sourcesContentCount; ++i)
{
auto value = native.sourcesContent[i];
@@ -223,6 +224,17 @@ void _encode(Index v, StringBuilder& out)
}
}
+ // Copy over the names
+ {
+ const auto namesCount = native.names.getCount();
+ outSourceMap.m_names.setCount(namesCount);
+
+ for (Index i = 0; i < namesCount; ++i)
+ {
+ outSourceMap.m_names[i] = outSourceMap.m_slicePool.add(native.names[i]);
+ }
+ }
+
List<UnownedStringSlice> lines;
StringUtil::split(native.mappings, ';', lines);
diff --git a/source/compiler-core/slang-source-map.cpp b/source/compiler-core/slang-source-map.cpp
index 7a6e368a4..43727838f 100644
--- a/source/compiler-core/slang-source-map.cpp
+++ b/source/compiler-core/slang-source-map.cpp
@@ -35,6 +35,105 @@ void SourceMap::swapWith(ThisType& rhs)
m_slicePool.swapWith(rhs.m_slicePool);
}
+static bool _areEqual(const List<StringSlicePool::Handle>& a, const List<StringSlicePool::Handle>& b, const List<Index>& bToAMap)
+{
+ const auto count = a.getCount();
+ if (count != b.getCount())
+ {
+ return false;
+ }
+
+ const auto* as = a.getBuffer();
+ const auto* bs = a.getBuffer();
+
+ for (Index i = 0; i < count; ++i)
+ {
+ if (StringSlicePool::asIndex(as[i]) != bToAMap[StringSlicePool::asIndex(bs[i])])
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool _areEqual(const SourceMap::Entry& a, const SourceMap::Entry& b, const List<Index>& bToAMap)
+{
+ return a.generatedColumn == b.generatedColumn &&
+ a.sourceLine == b.sourceLine &&
+ a.sourceColumn == b.sourceColumn &&
+ a.sourceFileIndex == bToAMap[b.sourceFileIndex] &&
+ a.nameIndex == bToAMap[b.nameIndex];
+}
+
+static bool _areEqual(const List<SourceMap::Entry>& a, const List<SourceMap::Entry>&b, const List<Index>& bToAMap)
+{
+ const auto count = a.getCount();
+ if (count != b.getCount())
+ {
+ return false;
+ }
+
+ for (Index i = 0; i < count; ++i)
+ {
+ if (!_areEqual(a[i], b[i], bToAMap))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool SourceMap::operator==(const ThisType& rhs) const
+{
+ if (this == &rhs)
+ {
+ return true;
+ }
+
+ if (m_file != rhs.m_file ||
+ m_sourceRoot != rhs.m_sourceRoot ||
+ m_lineStarts != rhs.m_lineStarts)
+ {
+ return false;
+ }
+
+ if (m_slicePool == rhs.m_slicePool)
+ {
+ // If the slice pools are the same we can just compare indices directly
+ return m_sources == rhs.m_sources &&
+ m_sourcesContent == rhs.m_sourcesContent &&
+ m_names == rhs.m_names &&
+ m_lineEntries == rhs.m_lineEntries;
+ }
+ else
+ {
+ // Otherwise we need to remap the indices
+ // Maps a pool handle from the rhs source map to the
+ List<Index> rhsMap;
+
+ Count count = rhs.m_slicePool.getSlicesCount();
+
+ rhsMap.setCount(count);
+
+ const auto startIndex = rhs.m_slicePool.getFirstAddedIndex();
+
+ // Work out the map
+ for (Index i = 0; i < startIndex; ++i)
+ {
+ const auto rhsSlice = rhs.m_slicePool.getSlice(StringSlicePool::Handle(i));
+ rhsMap[i] = (i < startIndex) ? i : m_slicePool.findIndex(rhsSlice);
+ }
+
+ // Do the comparison taking into account the mapping.
+ return _areEqual(m_sources, rhs.m_sources, rhsMap) &&
+ _areEqual(m_sourcesContent, rhs.m_sourcesContent, rhsMap) &&
+ _areEqual(m_names, rhs.m_names, rhsMap) &&
+ _areEqual(m_lineEntries, rhs.m_lineEntries, rhsMap);
+ }
+}
+
void SourceMap::advanceToLine(Index nextLineIndex)
{
const Count currentLineIndex = getGeneratedLineCount() - 1;
diff --git a/source/compiler-core/slang-source-map.h b/source/compiler-core/slang-source-map.h
index e0c8d065a..0c55d3a1a 100644
--- a/source/compiler-core/slang-source-map.h
+++ b/source/compiler-core/slang-source-map.h
@@ -19,6 +19,8 @@ public:
struct Entry
{
+ typedef Entry ThisType;
+
void init()
{
generatedColumn = 0;
@@ -28,6 +30,16 @@ public:
nameIndex = 0;
}
+ bool operator==(const ThisType& rhs) const
+ {
+ return generatedColumn == rhs.generatedColumn &&
+ sourceFileIndex == rhs.sourceFileIndex &&
+ sourceLine == rhs.sourceLine &&
+ sourceColumn == rhs.sourceColumn &&
+ nameIndex == rhs.nameIndex;
+ }
+ SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
+
// Note! All column/line are zero indexed
Index generatedColumn; ///< The generated column
Index sourceFileIndex; ///< The index into the source name/contents
@@ -71,12 +83,24 @@ public:
/// Swap this with rhs
void swapWith(ThisType& rhs);
+ /// ==
+ ///
+ /// Note that equality requires that entries for a line must be *in the same order*
+ /// even though strictly speaking with different orders could be considered equivalent.
+ bool operator==(const ThisType& rhs) const;
+ /// !=
+ bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
+
/// Ctor
SourceMap():
m_slicePool(StringSlicePool::Style::Default)
{
clear();
}
+ /// Copy Ctor
+ SourceMap(const ThisType& rhs) = default;
+ /// Assignment
+ ThisType& operator=(const ThisType& rhs) = default;
String m_file;
String m_sourceRoot;
diff --git a/source/core/slang-string-slice-pool.cpp b/source/core/slang-string-slice-pool.cpp
index 45cc811a3..5c4c7f61f 100644
--- a/source/core/slang-string-slice-pool.cpp
+++ b/source/core/slang-string-slice-pool.cpp
@@ -14,9 +14,103 @@ StringSlicePool::StringSlicePool(Style style) :
clear();
}
+StringSlicePool::StringSlicePool(const ThisType& rhs):
+ m_style(rhs.m_style),
+ m_arena(1024)
+{
+ // Set with rhs
+ _set(rhs);
+}
+
+void StringSlicePool::operator=(const ThisType& rhs)
+{
+ if (&rhs != this)
+ {
+ _set(rhs);
+ }
+}
+
+void StringSlicePool::_set(const ThisType& rhs)
+{
+ SLANG_ASSERT(this != &rhs);
+ m_style = rhs.m_style;
+
+ clear();
+
+ const Index startIndex = rhs.getFirstAddedIndex();
+ const Count count = rhs.m_slices.getCount();
+
+ // We need the same amount of slices
+ m_slices.setCount(count);
+
+ // Work out the total size to store all slices including terminating 0
+ // (which *isn't* part of the slice size)
+ size_t totalSize = 0;
+
+ for (Index i = startIndex; i < count; ++i)
+ {
+ const auto slice = rhs.m_slices[i];
+ totalSize += slice.getLength() + 1;
+ }
+
+ char* dst = (char*)m_arena.allocate(totalSize);
+
+ for (Index i = startIndex; i < count; ++i)
+ {
+ const auto srcSlice = rhs.m_slices[i];
+ const auto sliceSize = srcSlice.getLength();
+
+ // Copy over the src slices contents
+ ::memcpy(dst, srcSlice.begin(), sliceSize);
+ // Zero terminate
+ dst[sliceSize] = 0;
+
+ const UnownedStringSlice dstSlice(dst, sliceSize);
+ // Set the slice
+ m_slices[i] = dstSlice;
+
+ // Add to the map
+ m_map.Add(dstSlice, Handle(i));
+
+ // Skip to next slices storage
+ dst += sliceSize + 1;
+ }
+}
+
+bool StringSlicePool::operator==(const ThisType& rhs) const
+{
+ if (this == &rhs)
+ {
+ return true;
+ }
+
+ if (m_style != rhs.m_style)
+ {
+ return false;
+ }
+
+ const auto count = m_slices.getCount();
+
+ if (count != rhs.m_slices.getCount())
+ {
+ return false;
+ }
+
+ for (Index i = 0; i < count; ++i)
+ {
+ if (m_slices[i] != rhs.m_slices[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
void StringSlicePool::clear()
{
m_map.Clear();
+ m_arena.deallocateAll();
switch (m_style)
{
diff --git a/source/core/slang-string-slice-pool.h b/source/core/slang-string-slice-pool.h
index 90586a527..843556296 100644
--- a/source/core/slang-string-slice-pool.h
+++ b/source/core/slang-string-slice-pool.h
@@ -102,13 +102,19 @@ public:
/// Swap this with rhs
void swapWith(ThisType& rhs);
+ /// True if the pools are identical. Same style, same slices in the same order.
+ bool operator==(const ThisType& rhs) const;
+
+ /// Copy ctor
+ StringSlicePool(const ThisType& rhs);
+ /// Assignment
+ void operator=(const ThisType& rhs);
+
/// Ctor
explicit StringSlicePool(Style style);
protected:
- // Disable copy ctor and assignment
- StringSlicePool(const ThisType& rhs) = delete;
- void operator=(const ThisType& rhs) = delete;
+ void _set(const ThisType& rhs);
Style m_style;
List<UnownedStringSlice> m_slices;