@@ -67,8 +67,8 @@ class BindingKey {
67
67
isa<ObjCIvarRegion, CXXDerivedObjectRegion>(r)) &&
68
68
" Not a base" );
69
69
}
70
- public:
71
70
71
+ public:
72
72
bool isDirect () const { return P.getInt () & Direct; }
73
73
bool hasSymbolicOffset () const { return P.getInt () & Symbolic; }
74
74
@@ -232,27 +232,75 @@ class RegionBindingsRef : public llvm::ImmutableMapRef<const MemRegion *,
232
232
233
233
void printJson (raw_ostream &Out, const char *NL = " \n " ,
234
234
unsigned int Space = 0 , bool IsDot = false ) const {
235
- for (iterator I = begin (), E = end (); I != E; ++I) {
236
- // TODO: We might need a .printJson for I.getKey() as well.
235
+ using namespace llvm ;
236
+ DenseMap<const MemRegion *, std::string> StringifyCache;
237
+ auto ToString = [&StringifyCache](const MemRegion *R) {
238
+ auto [Place, Inserted] = StringifyCache.try_emplace (R);
239
+ if (!Inserted)
240
+ return Place->second ;
241
+ std::string Res;
242
+ raw_string_ostream OS (Res);
243
+ OS << R;
244
+ Place->second = Res;
245
+ return Res;
246
+ };
247
+
248
+ using Cluster =
249
+ std::pair<const MemRegion *, ImmutableMap<BindingKey, SVal>>;
250
+ using Binding = std::pair<BindingKey, SVal>;
251
+
252
+ const auto ClusterSortKey = [&ToString](const Cluster *C) {
253
+ const MemRegion *Key = C->first ;
254
+ return std::tuple{isa<MemSpaceRegion>(Key), ToString (Key)};
255
+ };
256
+
257
+ const auto MemSpaceBeforeRegionName = [&ClusterSortKey](const Cluster *L,
258
+ const Cluster *R) {
259
+ return ClusterSortKey (L) < ClusterSortKey (R);
260
+ };
261
+
262
+ const auto BindingSortKey = [&ToString](const Binding *BPtr) {
263
+ const BindingKey &Key = BPtr->first ;
264
+ return std::tuple{Key.isDirect (), !Key.hasSymbolicOffset (),
265
+ ToString (Key.getRegion ()), Key.getOffset ()};
266
+ };
267
+
268
+ const auto DefaultBindingBeforeDirectBindings =
269
+ [&BindingSortKey](const Binding *LPtr, const Binding *RPtr) {
270
+ return BindingSortKey (LPtr) < BindingSortKey (RPtr);
271
+ };
272
+
273
+ const auto AddrOf = [](const auto &Item) { return &Item; };
274
+
275
+ std::vector<const Cluster *> SortedClusters;
276
+ SortedClusters.reserve (std::distance (begin (), end ()));
277
+ append_range (SortedClusters, map_range (*this , AddrOf));
278
+ llvm::sort (SortedClusters, MemSpaceBeforeRegionName);
279
+
280
+ for (auto [Idx, C] : llvm::enumerate (SortedClusters)) {
281
+ const auto &[BaseRegion, Bindings] = *C;
237
282
Indent (Out, Space, IsDot)
238
- << " { \" cluster\" : \" " << I.getKey () << " \" , \" pointer\" : \" "
239
- << (const void *)I.getKey () << " \" , \" items\" : [" << NL;
283
+ << " { \" cluster\" : \" " << BaseRegion << " \" , \" pointer\" : \" "
284
+ << (const void *)BaseRegion << " \" , \" items\" : [" << NL;
285
+
286
+ std::vector<const Binding *> SortedBindings;
287
+ SortedBindings.reserve (std::distance (Bindings.begin (), Bindings.end ()));
288
+ append_range (SortedBindings, map_range (Bindings, AddrOf));
289
+ llvm::sort (SortedBindings, DefaultBindingBeforeDirectBindings);
240
290
241
291
++Space;
242
- const ClusterBindings &CB = I.getData ();
243
- for (ClusterBindings::iterator CI = CB.begin (), CE = CB.end (); CI != CE;
244
- ++CI) {
245
- Indent (Out, Space, IsDot) << " { " << CI.getKey () << " , \" value\" : " ;
246
- CI.getData ().printJson (Out, /* AddQuotes=*/ true );
292
+ for (auto [Idx, B] : llvm::enumerate (SortedBindings)) {
293
+ const auto &[Key, Value] = *B;
294
+ Indent (Out, Space, IsDot) << " { " << Key << " , \" value\" : " ;
295
+ Value.printJson (Out, /* AddQuotes=*/ true );
247
296
Out << " }" ;
248
- if (std::next (CI) != CE )
297
+ if (Idx != SortedBindings. size () - 1 )
249
298
Out << ' ,' ;
250
299
Out << NL;
251
300
}
252
-
253
301
--Space;
254
302
Indent (Out, Space, IsDot) << " ]}" ;
255
- if (std::next (I) != E )
303
+ if (Idx != SortedClusters. size () - 1 )
256
304
Out << ' ,' ;
257
305
Out << NL;
258
306
}
0 commit comments