================
@@ -232,27 +233,86 @@ class RegionBindingsRef : public 
llvm::ImmutableMapRef<const MemRegion *,
 
   void printJson(raw_ostream &Out, const char *NL = "\n",
                  unsigned int Space = 0, bool IsDot = false) const {
-    for (iterator I = begin(), E = end(); I != E; ++I) {
-      // TODO: We might need a .printJson for I.getKey() as well.
+    using namespace llvm;
+    DenseMap<const MemRegion *, std::string> StringifyCache;
+    auto ToString = [&StringifyCache](const MemRegion *R) {
+      auto [Place, Inserted] = StringifyCache.try_emplace(R);
+      if (!Inserted)
+        return Place->second;
+      std::string Res;
+      raw_string_ostream OS(Res);
+      OS << R;
+      Place->second = Res;
+      return Res;
+    };
+
+    using Cluster =
+        std::pair<const MemRegion *, ImmutableMap<BindingKey, SVal>>;
+    using Binding = std::pair<BindingKey, SVal>;
+
+    const auto MemSpaceBeforeRegionName = [&ToString](const Cluster *L,
+                                                      const Cluster *R) {
+      if (isa<MemSpaceRegion>(L->first) && !isa<MemSpaceRegion>(R->first))
+        return true;
+      if (!isa<MemSpaceRegion>(L->first) && isa<MemSpaceRegion>(R->first))
+        return false;
+      return ToString(L->first) < ToString(R->first);
+    };
+
+    const auto SymbolicBeforeOffset = [&ToString](const BindingKey &L,
+                                                  const BindingKey &R) {
+      if (L.hasSymbolicOffset() && !R.hasSymbolicOffset())
+        return true;
+      if (!L.hasSymbolicOffset() && R.hasSymbolicOffset())
+        return false;
+      if (L.hasSymbolicOffset() && R.hasSymbolicOffset())
+        return ToString(L.getRegion()) < ToString(R.getRegion());
+      return L.getOffset() < R.getOffset();
+    };
+
+    const auto DefaultBindingBeforeDirectBindings =
+        [&SymbolicBeforeOffset](const Binding *LPtr, const Binding *RPtr) {
+          const BindingKey &L = LPtr->first;
+          const BindingKey &R = RPtr->first;
+          if (L.isDefault() && !R.isDefault())
+            return true;
+          if (!L.isDefault() && R.isDefault())
+            return false;
+          assert(L.isDefault() == R.isDefault());
+          return SymbolicBeforeOffset(L, R);
+        };
+
----------------
NagyDonat wrote:

I think it the implementation of these comparison function could be made 
clearer if you introduce them as the lexicographical ordering of some tuples 
derived from the sorted values. For example, to sort the bindings, you could 
write something like 
```cpp
// Tweak the definition of ToString to ensure that ToString(nullptr) does not 
crash.
const auto BindingSortKey[&ToString](const Binding *BPtr) {
  const BindingKey &BK = BP->first;
  return std::make_tuple(BK.isDirect(), !BK.hasSymbolicOffset(), 
ToString(BK.getRegion()), BK.getOffset());
}
const auto CompareBindings[&BindingSortKey](const Binding *LPtr, const Binding 
*RPtr) {
  return BindingSortKey(LPtr) < BindingSortKey(RPtr);
}
```
and this `CompareBindings` is equivalent to your lambda 
`DefaultBindingBeforeDirectBindings` with a significantly shorter code 
(disclaimer: untested code, you might need to tweak it if I miscalculated 
something in my head).

I presume that the compiler will be able to inline these definitions, so this 
implementation won't be slower than your hand-unrolled lexicographical 
comparison.

https://github.com/llvm/llvm-project/pull/115615
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to