svf-tools 1.0.289 → 1.0.293

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. package/README.md +1 -0
  2. package/SVF-doxygen/html/html/AndersenHCD_8cpp_source.html +2 -2
  3. package/SVF-doxygen/html/html/AndersenHLCD_8cpp_source.html +2 -2
  4. package/SVF-doxygen/html/html/AndersenLCD_8cpp_source.html +2 -2
  5. package/SVF-doxygen/html/html/AndersenSCD_8cpp_source.html +1 -1
  6. package/SVF-doxygen/html/html/AndersenSFR_8cpp_source.html +3 -3
  7. package/SVF-doxygen/html/html/AndersenSFR_8h_source.html +2 -2
  8. package/SVF-doxygen/html/html/AndersenStat_8cpp_source.html +1 -1
  9. package/SVF-doxygen/html/html/AndersenWaveDiffWithType_8cpp_source.html +5 -5
  10. package/SVF-doxygen/html/html/AndersenWaveDiff_8cpp_source.html +3 -3
  11. package/SVF-doxygen/html/html/Andersen_8cpp_source.html +45 -29
  12. package/SVF-doxygen/html/html/Andersen_8h_source.html +50 -50
  13. package/SVF-doxygen/html/html/BasicTypes_8h_source.html +2 -2
  14. package/SVF-doxygen/html/html/ConditionalPT_8h_source.html +9 -9
  15. package/SVF-doxygen/html/html/ConsG_8cpp_source.html +1 -1
  16. package/SVF-doxygen/html/html/ContextDDA_8cpp_source.html +1 -1
  17. package/SVF-doxygen/html/html/ContextDDA_8h_source.html +1 -1
  18. package/SVF-doxygen/html/html/DDAClient_8cpp_source.html +3 -3
  19. package/SVF-doxygen/html/html/DDAStat_8cpp_source.html +1 -1
  20. package/SVF-doxygen/html/html/DDAVFSolver_8h_source.html +2 -2
  21. package/SVF-doxygen/html/html/DoubleFreeChecker_8cpp_source.html +2 -2
  22. package/SVF-doxygen/html/html/FSMPTA_8cpp_source.html +5 -5
  23. package/SVF-doxygen/html/html/FileChecker_8cpp_source.html +2 -2
  24. package/SVF-doxygen/html/html/FlowDDA_8cpp_source.html +1 -1
  25. package/SVF-doxygen/html/html/FlowDDA_8h_source.html +1 -1
  26. package/SVF-doxygen/html/html/FlowSensitiveStat_8cpp_source.html +1 -1
  27. package/SVF-doxygen/html/html/FlowSensitiveTBHC_8cpp_source.html +22 -22
  28. package/SVF-doxygen/html/html/FlowSensitive_8cpp_source.html +52 -32
  29. package/SVF-doxygen/html/html/FlowSensitive_8h_source.html +58 -55
  30. package/SVF-doxygen/html/html/ICFG_8cpp_source.html +1 -1
  31. package/SVF-doxygen/html/html/LeakChecker_8cpp_source.html +2 -2
  32. package/SVF-doxygen/html/html/LockResultValidator_8cpp_source.html +1 -1
  33. package/SVF-doxygen/html/html/MTAAnnotator_8cpp_source.html +4 -4
  34. package/SVF-doxygen/html/html/MTA_8cpp_source.html +1 -1
  35. package/SVF-doxygen/html/html/MemRegion_8cpp_source.html +1 -1
  36. package/SVF-doxygen/html/html/MutablePointsToDS_8h_source.html +2 -2
  37. package/SVF-doxygen/html/html/NodeIDAllocator_8cpp_source.html +64 -11
  38. package/SVF-doxygen/html/html/NodeIDAllocator_8h.html +5 -1
  39. package/SVF-doxygen/html/html/NodeIDAllocator_8h_source.html +52 -15
  40. package/SVF-doxygen/html/html/PAG_8cpp_source.html +1 -1
  41. package/SVF-doxygen/html/html/PersistentPointsToDS_8h_source.html +2 -2
  42. package/SVF-doxygen/html/html/PointerAnalysisImpl_8cpp_source.html +2 -2
  43. package/SVF-doxygen/html/html/PointerAnalysisImpl_8h_source.html +1 -1
  44. package/SVF-doxygen/html/html/PointerAnalysis_8h_source.html +1 -1
  45. package/SVF-doxygen/html/html/PointsTo_8cpp_source.html +34 -33
  46. package/SVF-doxygen/html/html/PointsTo_8h_source.html +32 -32
  47. package/SVF-doxygen/html/html/ProgSlice_8cpp_source.html +4 -12
  48. package/SVF-doxygen/html/html/ProgSlice_8h_source.html +33 -35
  49. package/SVF-doxygen/html/html/SVFGOPT_8cpp_source.html +1 -1
  50. package/SVF-doxygen/html/html/SVFG_8cpp_source.html +31 -36
  51. package/SVF-doxygen/html/html/SVFG_8h_source.html +19 -19
  52. package/SVF-doxygen/html/html/SVFUtil_8cpp_source.html +15 -7
  53. package/SVF-doxygen/html/html/SVFUtil_8h.html +3 -0
  54. package/SVF-doxygen/html/html/SVFUtil_8h_source.html +10 -8
  55. package/SVF-doxygen/html/html/SaberAnnotator_8cpp_source.html +2 -2
  56. package/SVF-doxygen/html/html/SaberSVFGBuilder_8cpp_source.html +3 -3
  57. package/SVF-doxygen/html/html/SrcSnkDDA_8cpp_source.html +2 -2
  58. package/SVF-doxygen/html/html/SymbolTableInfo_8cpp_source.html +1 -1
  59. package/SVF-doxygen/html/html/TypeBasedHeapCloning_8cpp_source.html +3 -3
  60. package/SVF-doxygen/html/html/VFG_8cpp_source.html +17 -11
  61. package/SVF-doxygen/html/html/VersionedFlowSensitiveStat_8cpp_source.html +1 -1
  62. package/SVF-doxygen/html/html/VersionedFlowSensitive_8cpp_source.html +51 -43
  63. package/SVF-doxygen/html/html/VersionedFlowSensitive_8h_source.html +34 -33
  64. package/SVF-doxygen/html/html/WPAPass_8cpp_source.html +5 -5
  65. package/SVF-doxygen/html/html/annotated.html +2 -1
  66. package/SVF-doxygen/html/html/classSVF_1_1AddrPE.html +1 -1
  67. package/SVF-doxygen/html/html/classSVF_1_1AddrVFGNode-members.html +1 -1
  68. package/SVF-doxygen/html/html/classSVF_1_1AddrVFGNode.html +3 -3
  69. package/SVF-doxygen/html/html/classSVF_1_1Andersen-members.html +213 -212
  70. package/SVF-doxygen/html/html/classSVF_1_1Andersen.html +124 -72
  71. package/SVF-doxygen/html/html/classSVF_1_1AndersenBase.html +2 -2
  72. package/SVF-doxygen/html/html/classSVF_1_1AndersenHCD-members.html +223 -222
  73. package/SVF-doxygen/html/html/classSVF_1_1AndersenHCD.html +36 -34
  74. package/SVF-doxygen/html/html/classSVF_1_1AndersenHLCD-members.html +232 -231
  75. package/SVF-doxygen/html/html/classSVF_1_1AndersenHLCD.html +21 -19
  76. package/SVF-doxygen/html/html/classSVF_1_1AndersenLCD-members.html +220 -219
  77. package/SVF-doxygen/html/html/classSVF_1_1AndersenLCD.html +38 -36
  78. package/SVF-doxygen/html/html/classSVF_1_1AndersenSCD-members.html +221 -220
  79. package/SVF-doxygen/html/html/classSVF_1_1AndersenSCD.html +11 -9
  80. package/SVF-doxygen/html/html/classSVF_1_1AndersenSFR-members.html +232 -231
  81. package/SVF-doxygen/html/html/classSVF_1_1AndersenSFR.html +6 -4
  82. package/SVF-doxygen/html/html/classSVF_1_1AndersenStat.html +1 -1
  83. package/SVF-doxygen/html/html/classSVF_1_1AndersenWaveDiff-members.html +220 -219
  84. package/SVF-doxygen/html/html/classSVF_1_1AndersenWaveDiff.html +21 -19
  85. package/SVF-doxygen/html/html/classSVF_1_1AndersenWaveDiffWithType-members.html +227 -226
  86. package/SVF-doxygen/html/html/classSVF_1_1AndersenWaveDiffWithType.html +26 -24
  87. package/SVF-doxygen/html/html/classSVF_1_1ArgumentVFGNode.html +2 -3
  88. package/SVF-doxygen/html/html/classSVF_1_1BVDataPTAImpl.html +2 -2
  89. package/SVF-doxygen/html/html/classSVF_1_1BinaryOPPE.html +1 -1
  90. package/SVF-doxygen/html/html/classSVF_1_1BinaryOPVFGNode.html +3 -4
  91. package/SVF-doxygen/html/html/classSVF_1_1CallBlockNode.html +1 -1
  92. package/SVF-doxygen/html/html/classSVF_1_1CallPE.html +1 -1
  93. package/SVF-doxygen/html/html/classSVF_1_1CmpPE.html +1 -1
  94. package/SVF-doxygen/html/html/classSVF_1_1CmpVFGNode.html +3 -4
  95. package/SVF-doxygen/html/html/classSVF_1_1ContextDDA.html +2 -2
  96. package/SVF-doxygen/html/html/classSVF_1_1CopyPE.html +1 -1
  97. package/SVF-doxygen/html/html/classSVF_1_1CopyVFGNode-members.html +1 -1
  98. package/SVF-doxygen/html/html/classSVF_1_1CopyVFGNode.html +3 -3
  99. package/SVF-doxygen/html/html/classSVF_1_1DDAStat.html +1 -1
  100. package/SVF-doxygen/html/html/classSVF_1_1DDAVFSolver.html +1 -1
  101. package/SVF-doxygen/html/html/classSVF_1_1DoubleFreeChecker.html +2 -2
  102. package/SVF-doxygen/html/html/classSVF_1_1FIObjPN.html +1 -1
  103. package/SVF-doxygen/html/html/classSVF_1_1FSMPTA-members.html +110 -107
  104. package/SVF-doxygen/html/html/classSVF_1_1FSMPTA.html +12 -4
  105. package/SVF-doxygen/html/html/classSVF_1_1FileChecker.html +2 -2
  106. package/SVF-doxygen/html/html/classSVF_1_1FlowDDA.html +2 -2
  107. package/SVF-doxygen/html/html/classSVF_1_1FlowSensitive-members.html +109 -106
  108. package/SVF-doxygen/html/html/classSVF_1_1FlowSensitive.html +286 -157
  109. package/SVF-doxygen/html/html/classSVF_1_1FlowSensitiveStat.html +30 -30
  110. package/SVF-doxygen/html/html/classSVF_1_1FlowSensitiveTBHC-members.html +121 -118
  111. package/SVF-doxygen/html/html/classSVF_1_1FlowSensitiveTBHC.html +36 -28
  112. package/SVF-doxygen/html/html/classSVF_1_1FormalOUTSVFGNode.html +2 -2
  113. package/SVF-doxygen/html/html/classSVF_1_1FunptrDDAClient.html +3 -3
  114. package/SVF-doxygen/html/html/classSVF_1_1GepObjPN.html +1 -1
  115. package/SVF-doxygen/html/html/classSVF_1_1GepPE.html +1 -1
  116. package/SVF-doxygen/html/html/classSVF_1_1GepVFGNode-members.html +1 -1
  117. package/SVF-doxygen/html/html/classSVF_1_1GepVFGNode.html +3 -3
  118. package/SVF-doxygen/html/html/classSVF_1_1GepValPN.html +1 -1
  119. package/SVF-doxygen/html/html/classSVF_1_1InterPHIVFGNode.html +1 -1
  120. package/SVF-doxygen/html/html/classSVF_1_1IntraBlockNode.html +1 -1
  121. package/SVF-doxygen/html/html/classSVF_1_1IntraPHIVFGNode.html +1 -1
  122. package/SVF-doxygen/html/html/classSVF_1_1LeakChecker.html +2 -2
  123. package/SVF-doxygen/html/html/classSVF_1_1LoadPE.html +1 -1
  124. package/SVF-doxygen/html/html/classSVF_1_1LoadVFGNode-members.html +1 -1
  125. package/SVF-doxygen/html/html/classSVF_1_1LoadVFGNode.html +3 -3
  126. package/SVF-doxygen/html/html/classSVF_1_1LockResultValidator.html +1 -1
  127. package/SVF-doxygen/html/html/classSVF_1_1MRGenerator.html +2 -2
  128. package/SVF-doxygen/html/html/classSVF_1_1MTA.html +1 -1
  129. package/SVF-doxygen/html/html/classSVF_1_1MTAAnnotator.html +4 -4
  130. package/SVF-doxygen/html/html/classSVF_1_1MTASVFGBuilder.html +5 -5
  131. package/SVF-doxygen/html/html/classSVF_1_1MutablePTData.html +2 -2
  132. package/SVF-doxygen/html/html/classSVF_1_1NodeIDAllocator-members.html +11 -10
  133. package/SVF-doxygen/html/html/classSVF_1_1NodeIDAllocator.html +74 -34
  134. package/SVF-doxygen/html/html/classSVF_1_1NodeIDAllocator_1_1Clusterer-members.html +109 -0
  135. package/SVF-doxygen/html/html/classSVF_1_1NodeIDAllocator_1_1Clusterer.html +1188 -0
  136. package/SVF-doxygen/html/html/classSVF_1_1NormalGepPE.html +1 -1
  137. package/SVF-doxygen/html/html/classSVF_1_1ObjPN.html +1 -1
  138. package/SVF-doxygen/html/html/classSVF_1_1PHIVFGNode.html +3 -4
  139. package/SVF-doxygen/html/html/classSVF_1_1PersistentIncDFPTData.html +2 -2
  140. package/SVF-doxygen/html/html/classSVF_1_1PersistentPTData.html +2 -2
  141. package/SVF-doxygen/html/html/classSVF_1_1PointsTo.html +77 -66
  142. package/SVF-doxygen/html/html/classSVF_1_1PointsTo_1_1PointsToIterator.html +32 -26
  143. package/SVF-doxygen/html/html/classSVF_1_1ProgSlice-members.html +36 -37
  144. package/SVF-doxygen/html/html/classSVF_1_1ProgSlice.html +121 -153
  145. package/SVF-doxygen/html/html/classSVF_1_1RetBlockNode.html +1 -1
  146. package/SVF-doxygen/html/html/classSVF_1_1RetPE.html +1 -1
  147. package/SVF-doxygen/html/html/classSVF_1_1SVFFunction.html +4 -4
  148. package/SVF-doxygen/html/html/classSVF_1_1SVFG.html +49 -49
  149. package/SVF-doxygen/html/html/classSVF_1_1SVFGBuilder.html +3 -3
  150. package/SVF-doxygen/html/html/classSVF_1_1SVFGOPT.html +9 -9
  151. package/SVF-doxygen/html/html/classSVF_1_1SaberAnnotator.html +2 -2
  152. package/SVF-doxygen/html/html/classSVF_1_1SaberSVFGBuilder.html +6 -6
  153. package/SVF-doxygen/html/html/classSVF_1_1SrcSnkDDA.html +2 -2
  154. package/SVF-doxygen/html/html/classSVF_1_1StmtVFGNode-members.html +1 -1
  155. package/SVF-doxygen/html/html/classSVF_1_1StmtVFGNode.html +8 -9
  156. package/SVF-doxygen/html/html/classSVF_1_1StorePE.html +1 -1
  157. package/SVF-doxygen/html/html/classSVF_1_1StoreVFGNode-members.html +1 -1
  158. package/SVF-doxygen/html/html/classSVF_1_1StoreVFGNode.html +3 -3
  159. package/SVF-doxygen/html/html/classSVF_1_1SymbolTableInfo.html +1 -1
  160. package/SVF-doxygen/html/html/classSVF_1_1TDForkPE.html +1 -1
  161. package/SVF-doxygen/html/html/classSVF_1_1TDJoinPE.html +1 -1
  162. package/SVF-doxygen/html/html/classSVF_1_1TypeBasedHeapCloning.html +4 -4
  163. package/SVF-doxygen/html/html/classSVF_1_1UnaryOPPE.html +1 -1
  164. package/SVF-doxygen/html/html/classSVF_1_1UnaryOPVFGNode.html +1 -1
  165. package/SVF-doxygen/html/html/classSVF_1_1VFGNode.html +1 -1
  166. package/SVF-doxygen/html/html/classSVF_1_1ValPN.html +1 -1
  167. package/SVF-doxygen/html/html/classSVF_1_1VariantGepPE.html +1 -1
  168. package/SVF-doxygen/html/html/classSVF_1_1VersionedFlowSensitive-members.html +132 -129
  169. package/SVF-doxygen/html/html/classSVF_1_1VersionedFlowSensitive.html +171 -116
  170. package/SVF-doxygen/html/html/classSVF_1_1VersionedFlowSensitiveStat.html +37 -37
  171. package/SVF-doxygen/html/html/classSVF_1_1WPAPass.html +5 -5
  172. package/SVF-doxygen/html/html/classes.html +62 -62
  173. package/SVF-doxygen/html/html/functions_b.html +10 -5
  174. package/SVF-doxygen/html/html/functions_c.html +36 -22
  175. package/SVF-doxygen/html/html/functions_d.html +12 -0
  176. package/SVF-doxygen/html/html/functions_e.html +9 -3
  177. package/SVF-doxygen/html/html/functions_f.html +21 -18
  178. package/SVF-doxygen/html/html/functions_func_c.html +19 -10
  179. package/SVF-doxygen/html/html/functions_func_d.html +3 -0
  180. package/SVF-doxygen/html/html/functions_func_e.html +3 -0
  181. package/SVF-doxygen/html/html/functions_func_g.html +16 -10
  182. package/SVF-doxygen/html/html/functions_func_p.html +6 -2
  183. package/SVF-doxygen/html/html/functions_func_r.html +7 -1
  184. package/SVF-doxygen/html/html/functions_func_t.html +3 -0
  185. package/SVF-doxygen/html/html/functions_g.html +15 -9
  186. package/SVF-doxygen/html/html/functions_l.html +10 -7
  187. package/SVF-doxygen/html/html/functions_n.html +21 -3
  188. package/SVF-doxygen/html/html/functions_o.html +16 -8
  189. package/SVF-doxygen/html/html/functions_p.html +23 -17
  190. package/SVF-doxygen/html/html/functions_r.html +13 -6
  191. package/SVF-doxygen/html/html/functions_s.html +9 -9
  192. package/SVF-doxygen/html/html/functions_t.html +18 -9
  193. package/SVF-doxygen/html/html/functions_type_d.html +3 -0
  194. package/SVF-doxygen/html/html/functions_v.html +3 -3
  195. package/SVF-doxygen/html/html/functions_vars_b.html +3 -0
  196. package/SVF-doxygen/html/html/functions_vars_c.html +3 -0
  197. package/SVF-doxygen/html/html/functions_vars_d.html +6 -0
  198. package/SVF-doxygen/html/html/functions_vars_e.html +3 -0
  199. package/SVF-doxygen/html/html/functions_vars_f.html +3 -0
  200. package/SVF-doxygen/html/html/functions_vars_l.html +3 -0
  201. package/SVF-doxygen/html/html/functions_vars_n.html +18 -0
  202. package/SVF-doxygen/html/html/functions_vars_o.html +6 -0
  203. package/SVF-doxygen/html/html/functions_vars_r.html +3 -0
  204. package/SVF-doxygen/html/html/functions_vars_t.html +6 -0
  205. package/SVF-doxygen/html/html/functions_w.html +8 -6
  206. package/SVF-doxygen/html/html/globals_f.html +3 -3
  207. package/SVF-doxygen/html/html/hierarchy.html +413 -412
  208. package/SVF-doxygen/html/html/menudata.js +2 -0
  209. package/SVF-doxygen/html/html/namespaceSVF.html +8 -8
  210. package/SVF-doxygen/html/html/namespaceSVF_1_1SVFUtil.html +47 -16
  211. package/SVF-doxygen/html/html/namespacemembers_func.html +17 -10
  212. package/SVF-doxygen/html/html/namespacemembers_h.html +76 -0
  213. package/SVF-doxygen/html/html/search/all_10.js +9 -8
  214. package/SVF-doxygen/html/html/search/all_12.js +5 -2
  215. package/SVF-doxygen/html/html/search/all_13.js +7 -7
  216. package/SVF-doxygen/html/html/search/all_14.js +8 -5
  217. package/SVF-doxygen/html/html/search/all_15.js +1 -1
  218. package/SVF-doxygen/html/html/search/all_16.js +1 -1
  219. package/SVF-doxygen/html/html/search/all_17.js +1 -1
  220. package/SVF-doxygen/html/html/search/all_2.js +1 -0
  221. package/SVF-doxygen/html/html/search/all_3.js +4 -0
  222. package/SVF-doxygen/html/html/search/all_4.js +4 -0
  223. package/SVF-doxygen/html/html/search/all_5.js +2 -0
  224. package/SVF-doxygen/html/html/search/all_6.js +4 -3
  225. package/SVF-doxygen/html/html/search/all_7.js +4 -2
  226. package/SVF-doxygen/html/html/search/all_8.js +1 -0
  227. package/SVF-doxygen/html/html/search/all_c.js +4 -3
  228. package/SVF-doxygen/html/html/search/all_d.js +1 -1
  229. package/SVF-doxygen/html/html/search/all_e.js +9 -4
  230. package/SVF-doxygen/html/html/search/all_f.js +4 -2
  231. package/SVF-doxygen/html/html/search/classes_2.js +1 -0
  232. package/SVF-doxygen/html/html/search/functions_10.js +1 -1
  233. package/SVF-doxygen/html/html/search/functions_11.js +1 -0
  234. package/SVF-doxygen/html/html/search/functions_2.js +2 -0
  235. package/SVF-doxygen/html/html/search/functions_3.js +1 -0
  236. package/SVF-doxygen/html/html/search/functions_4.js +1 -0
  237. package/SVF-doxygen/html/html/search/functions_6.js +4 -2
  238. package/SVF-doxygen/html/html/search/functions_7.js +1 -0
  239. package/SVF-doxygen/html/html/search/functions_e.js +3 -2
  240. package/SVF-doxygen/html/html/search/functions_f.js +2 -0
  241. package/SVF-doxygen/html/html/search/typedefs_3.js +1 -0
  242. package/SVF-doxygen/html/html/search/variables_12.js +1 -0
  243. package/SVF-doxygen/html/html/search/variables_14.js +3 -1
  244. package/SVF-doxygen/html/html/search/variables_15.js +1 -1
  245. package/SVF-doxygen/html/html/search/variables_2.js +1 -0
  246. package/SVF-doxygen/html/html/search/variables_3.js +1 -0
  247. package/SVF-doxygen/html/html/search/variables_4.js +2 -0
  248. package/SVF-doxygen/html/html/search/variables_5.js +1 -0
  249. package/SVF-doxygen/html/html/search/variables_6.js +1 -0
  250. package/SVF-doxygen/html/html/search/variables_c.js +1 -0
  251. package/SVF-doxygen/html/html/search/variables_d.js +1 -1
  252. package/SVF-doxygen/html/html/search/variables_e.js +7 -2
  253. package/SVF-doxygen/html/html/search/variables_f.js +2 -0
  254. package/SVF-doxygen/html/html/structllvm_1_1DOTGraphTraits_3_01ConstraintGraph_01_5_01_4.html +1 -1
  255. package/SVF-doxygen/html/html/structllvm_1_1DOTGraphTraits_3_01ICFG_01_5_01_4.html +1 -1
  256. package/SVF-doxygen/html/html/structllvm_1_1DOTGraphTraits_3_01SVFG_01_5_01_4.html +20 -20
  257. package/SVF-doxygen/html/html/structllvm_1_1DOTGraphTraits_3_01VFG_01_5_01_4.html +18 -18
  258. package/SVF-doxygen/html/html/structstd_1_1hash_3_01SVF_1_1PointsTo_01_4.html +1 -1
  259. package/include/SABER/ProgSlice.h +0 -3
  260. package/include/Util/NodeIDAllocator.h +94 -0
  261. package/include/Util/SVFUtil.h +3 -0
  262. package/include/WPA/Andersen.h +4 -0
  263. package/include/WPA/FlowSensitive.h +9 -0
  264. package/include/WPA/VersionedFlowSensitive.h +3 -0
  265. package/lib/Graphs/SVFG.cpp +0 -20
  266. package/lib/Graphs/VFG.cpp +18 -0
  267. package/lib/MemoryModel/PointsTo.cpp +76 -19
  268. package/lib/SABER/ProgSlice.cpp +0 -37
  269. package/lib/SABER/SaberAnnotator.cpp +1 -1
  270. package/lib/Util/NodeIDAllocator.cpp +548 -1
  271. package/lib/Util/SVFUtil.cpp +19 -0
  272. package/lib/WPA/Andersen.cpp +34 -0
  273. package/lib/WPA/FlowSensitive.cpp +70 -0
  274. package/lib/WPA/VersionedFlowSensitive.cpp +20 -0
  275. package/package.json +1 -1
@@ -153,4 +153,551 @@ namespace SVF
153
153
  numSymbols = numNodes;
154
154
  }
155
155
 
156
- } // namespace SVF.
156
+ const std::string NodeIDAllocator::Clusterer::NumObjects = "NumObjects";
157
+ const std::string NodeIDAllocator::Clusterer::RegioningTime = "RegioningTime";
158
+ const std::string NodeIDAllocator::Clusterer::DistanceMatrixTime = "DistanceMatrixTime";
159
+ const std::string NodeIDAllocator::Clusterer::FastClusterTime = "FastClusterTime";
160
+ const std::string NodeIDAllocator::Clusterer::DendrogramTraversalTime = "DendrogramTravTime";
161
+ const std::string NodeIDAllocator::Clusterer::EvalTime = "EvalTime";
162
+ const std::string NodeIDAllocator::Clusterer::TotalTime = "TotalTime";
163
+ const std::string NodeIDAllocator::Clusterer::TheoreticalNumWords = "TheoreticalWords";
164
+ const std::string NodeIDAllocator::Clusterer::OriginalBvNumWords = "OriginalBvWords";
165
+ const std::string NodeIDAllocator::Clusterer::OriginalSbvNumWords = "OriginalSbvWords";
166
+ const std::string NodeIDAllocator::Clusterer::NewBvNumWords = "NewBvWords";
167
+ const std::string NodeIDAllocator::Clusterer::NewSbvNumWords = "NewSbvWords";
168
+ const std::string NodeIDAllocator::Clusterer::NumRegions = "NumRegions";
169
+ const std::string NodeIDAllocator::Clusterer::NumGtIntRegions = "NumGtIntRegions";
170
+ const std::string NodeIDAllocator::Clusterer::LargestRegion = "LargestRegion";
171
+ const std::string NodeIDAllocator::Clusterer::BestCandidate = "BestCandidate";
172
+ const std::string NodeIDAllocator::Clusterer::NumNonTrivialRegionObjects = "NumNonTrivObj";
173
+
174
+ std::vector<NodeID> NodeIDAllocator::Clusterer::cluster(BVDataPTAImpl *pta, const std::vector<std::pair<NodeID, unsigned>> keys, std::vector<std::pair<hclust_fast_methods, std::vector<NodeID>>> &candidates, std::string evalSubtitle)
175
+ {
176
+ assert(pta != nullptr && "Clusterer::cluster: given null BVDataPTAImpl");
177
+ assert(Options::NodeAllocStrat == Strategy::DENSE && "Clusterer::cluster: only dense allocation clustering currently supported");
178
+
179
+ Map<std::string, std::string> overallStats;
180
+ double totalTime = 0.0;
181
+ double fastClusterTime = 0.0;
182
+ double distanceMatrixTime = 0.0;
183
+ double dendrogramTraversalTime = 0.0;
184
+ double regioningTime = 0.0;
185
+ double evalTime = 0.0;
186
+
187
+ // Pair of nodes to their (minimum) distance and the number of occurrences of that distance.
188
+ Map<std::pair<NodeID, NodeID>, std::pair<unsigned, unsigned>> distances;
189
+
190
+ double clkStart = PTAStat::getClk(true);
191
+
192
+ // Map points-to sets to occurrences.
193
+ Map<PointsTo, unsigned> pointsToSets;
194
+
195
+ // Objects each object shares at least a points-to set with.
196
+ Map<NodeID, Set<NodeID>> coPointeeGraph;
197
+ for (const std::pair<NodeID, unsigned> &keyOcc : keys)
198
+ {
199
+ const PointsTo &pts = pta->getPts(keyOcc.first);
200
+ const size_t oldSize = pointsToSets.size();
201
+ pointsToSets[pts] += keyOcc.second;;
202
+
203
+ // Edges in this graph have no weight or uniqueness, so we only need to
204
+ // do this for each points-to set once.
205
+ if (oldSize != pointsToSets.size())
206
+ {
207
+ NodeID firstO = !pts.empty() ? *(pts.begin()) : 0;
208
+ Set<NodeID> &firstOsNeighbours = coPointeeGraph[firstO];
209
+ for (const NodeID o : pts)
210
+ {
211
+ if (o != firstO)
212
+ {
213
+ firstOsNeighbours.insert(o);
214
+ coPointeeGraph[o].insert(firstO);
215
+ }
216
+ }
217
+ }
218
+ }
219
+
220
+ size_t numObjects = NodeIDAllocator::get()->numObjects;
221
+ overallStats[NumObjects] = std::to_string(numObjects);
222
+
223
+ size_t numRegions = 0;
224
+ std::vector<unsigned> objectsRegion;
225
+ if (Options::RegionedClustering)
226
+ {
227
+ objectsRegion = regionObjects(coPointeeGraph, numObjects, numRegions);
228
+ }
229
+ else
230
+ {
231
+ // Just a single big region (0).
232
+ objectsRegion.insert(objectsRegion.end(), numObjects, 0);
233
+ numRegions = 1;
234
+ }
235
+
236
+ // Set needs to be ordered because getDistanceMatrix, in its n^2 iteration, expects
237
+ // sets to be ordered (we are building a condensed matrix, not a full matrix, so it
238
+ // matters). In getDistanceMatrix, doing regionReverseMapping for oi and oj, where
239
+ // oi < oj, and getting a result moi > moj gives incorrect results.
240
+ // In the condensed matrix, [b][a] where b >= a, is incorrect.
241
+ std::vector<OrderedSet<NodeID>> regionsObjects(numRegions);
242
+ for (NodeID o = 0; o < numObjects; ++o) regionsObjects[objectsRegion[o]].insert(o);
243
+
244
+ // Size of the return node mapping. It is potentially larger than the number of
245
+ // objects because we align each region to NATIVE_INT_SIZE.
246
+ size_t numMappings = 0;
247
+
248
+ // Maps a region to a mapping which maps 0 to n to all objects
249
+ // in that region.
250
+ std::vector<std::vector<NodeID>> regionMappings(numRegions);
251
+ // The reverse: region to mapping of objects to a 0 to n from above.
252
+ std::vector<Map<NodeID, unsigned>> regionReverseMappings(numRegions);
253
+ // We can thus use 0 to n for each region to create smaller distance matrices.
254
+ for (unsigned region = 0; region < numRegions; ++region)
255
+ {
256
+ size_t curr = 0;
257
+ // With the OrderedSet above, o1 < o2 => map[o1] < map[o2].
258
+ for (NodeID o : regionsObjects[region])
259
+ {
260
+ // push_back here is just like p...[region][curr] = o.
261
+ regionMappings[region].push_back(o);
262
+ regionReverseMappings[region][o] = curr++;
263
+ }
264
+
265
+ // curr is the number of objects. A region with no objects makes no sense.
266
+ assert(curr != 0);
267
+
268
+ // Number of bits needed for this region if we were
269
+ // to start assigning from 0 rounded up to the fewest needed
270
+ // native ints. This is added to the number of mappings since
271
+ // we align each region to a native int.
272
+ numMappings += requiredBits(regionsObjects[region].size());
273
+ }
274
+
275
+ // Points-to sets which are relevant to a region, i.e., those whose elements
276
+ // belong to that region. Pair is for occurences.
277
+ std::vector<std::vector<std::pair<const PointsTo *, unsigned>>> regionsPointsTos(numRegions);
278
+ for (const Map<PointsTo, unsigned>::value_type &ptocc : pointsToSets)
279
+ {
280
+ const PointsTo &pt = ptocc.first;
281
+ const unsigned occ = ptocc.second;
282
+ if (pt.empty()) continue;
283
+ // Guaranteed that begin() != end() because of the continue above. All objects in pt
284
+ // will be relevant to the same region.
285
+ unsigned region = objectsRegion[*(pt.begin())];
286
+ // In our "graph", objects in the same points-to set have an edge between them,
287
+ // so they are all in the same connected component/region.
288
+ regionsPointsTos[region].push_back(std::make_pair(&pt, occ));
289
+ }
290
+
291
+ double clkEnd = PTAStat::getClk(true);
292
+ regioningTime = (clkEnd - clkStart) / TIMEINTERVAL;
293
+ overallStats[RegioningTime] = std::to_string(regioningTime);
294
+ overallStats[NumRegions] = std::to_string(numRegions);
295
+
296
+ std::vector<hclust_fast_methods> methods;
297
+ if (Options::ClusterMethod == HCLUST_METHOD_SVF_BEST)
298
+ {
299
+ methods.push_back(HCLUST_METHOD_SINGLE);
300
+ methods.push_back(HCLUST_METHOD_COMPLETE);
301
+ methods.push_back(HCLUST_METHOD_AVERAGE);
302
+ }
303
+ else
304
+ {
305
+ methods.push_back(Options::ClusterMethod);
306
+ }
307
+
308
+ for (const hclust_fast_methods method : methods)
309
+ {
310
+ std::vector<NodeID> nodeMap(numObjects, UINT_MAX);
311
+
312
+ unsigned numGtIntRegions = 0;
313
+ unsigned largestRegion = 0;
314
+ unsigned nonTrivialRegionObjects = 0;
315
+ unsigned allocCounter = 0;
316
+ for (unsigned region = 0; region < numRegions; ++region)
317
+ {
318
+ const size_t regionNumObjects = regionsObjects[region].size();
319
+ // Round up to next Word: ceiling of current allocation to get how
320
+ // many words and multiply to get the number of bits; if we're aligning.
321
+ if (Options::RegionAlign)
322
+ {
323
+ allocCounter =
324
+ ((allocCounter + NATIVE_INT_SIZE - 1) / NATIVE_INT_SIZE) * NATIVE_INT_SIZE;
325
+ }
326
+
327
+ if (regionNumObjects > largestRegion) largestRegion = regionNumObjects;
328
+
329
+ // For regions with fewer than 64 objects, we can just allocate them
330
+ // however as they will be in the one int regardless..
331
+ if (regionNumObjects < NATIVE_INT_SIZE)
332
+ {
333
+ for (NodeID o : regionsObjects[region]) nodeMap[o] = allocCounter++;
334
+ continue;
335
+ }
336
+
337
+ ++numGtIntRegions;
338
+ nonTrivialRegionObjects += regionNumObjects;
339
+
340
+ double *distMatrix = getDistanceMatrix(regionsPointsTos[region], regionNumObjects,
341
+ regionReverseMappings[region], distanceMatrixTime);
342
+
343
+ clkStart = PTAStat::getClk(true);
344
+ int *dendrogram = new int[2 * (regionNumObjects - 1)];
345
+ double *height = new double[regionNumObjects - 1];
346
+ hclust_fast(regionNumObjects, distMatrix, method, dendrogram, height);
347
+ delete[] distMatrix;
348
+ delete[] height;
349
+ clkEnd = PTAStat::getClk(true);
350
+ fastClusterTime += (clkEnd - clkStart) / TIMEINTERVAL;
351
+
352
+ clkStart = PTAStat::getClk(true);
353
+ Set<int> visited;
354
+ traverseDendrogram(nodeMap, dendrogram, regionNumObjects, allocCounter,
355
+ visited, regionNumObjects - 1, regionMappings[region]);
356
+ delete[] dendrogram;
357
+ clkEnd = PTAStat::getClk(true);
358
+ dendrogramTraversalTime += (clkEnd - clkStart) / TIMEINTERVAL;
359
+ }
360
+
361
+ candidates.push_back(std::make_pair(method, nodeMap));
362
+
363
+ // Though we "update" these in the loop, they will be the same every iteration.
364
+ overallStats[NumGtIntRegions] = std::to_string(numGtIntRegions);
365
+ overallStats[LargestRegion] = std::to_string(largestRegion);
366
+ overallStats[NumNonTrivialRegionObjects] = std::to_string(nonTrivialRegionObjects);
367
+ }
368
+
369
+ // Work out which of the mappings we generated looks best.
370
+ std::pair<hclust_fast_methods, std::vector<NodeID>> bestMapping = determineBestMapping(candidates, pointsToSets,
371
+ evalSubtitle, evalTime);
372
+
373
+ overallStats[DistanceMatrixTime] = std::to_string(distanceMatrixTime);
374
+ overallStats[DendrogramTraversalTime] = std::to_string(dendrogramTraversalTime);
375
+ overallStats[FastClusterTime] = std::to_string(fastClusterTime);
376
+ overallStats[EvalTime] = std::to_string(evalTime);
377
+ overallStats[TotalTime] = std::to_string(distanceMatrixTime + dendrogramTraversalTime + fastClusterTime + regioningTime + evalTime);
378
+
379
+ overallStats[BestCandidate] = SVFUtil::hclustMethodToString(bestMapping.first);
380
+ printStats(evalSubtitle + ": overall", overallStats);
381
+
382
+ return bestMapping.second;
383
+ }
384
+
385
+ std::vector<NodeID> NodeIDAllocator::Clusterer::getReverseNodeMapping(const std::vector<NodeID> &nodeMapping)
386
+ {
387
+ // nodeMapping.size() may not be big enough because we leave some gaps, but it's a start.
388
+ std::vector<NodeID> reverseNodeMapping(nodeMapping.size(), UINT_MAX);
389
+ for (size_t i = 0; i < nodeMapping.size(); ++i)
390
+ {
391
+ const NodeID mapsTo = nodeMapping.at(i);
392
+ if (mapsTo >= reverseNodeMapping.size()) reverseNodeMapping.resize(mapsTo + 1, UINT_MAX);
393
+ reverseNodeMapping.at(mapsTo) = i;
394
+ }
395
+
396
+ return reverseNodeMapping;
397
+ }
398
+
399
+ size_t NodeIDAllocator::Clusterer::condensedIndex(size_t n, size_t i, size_t j)
400
+ {
401
+ // From https://stackoverflow.com/a/14839010
402
+ return n*(n-1)/2 - (n-i)*(n-i-1)/2 + j - i - 1;
403
+ }
404
+
405
+ unsigned NodeIDAllocator::Clusterer::requiredBits(const PointsTo &pts)
406
+ {
407
+ return requiredBits(pts.count());
408
+ }
409
+
410
+ unsigned NodeIDAllocator::Clusterer::requiredBits(const size_t n)
411
+ {
412
+ if (n == 0) return 0;
413
+ // Ceiling of number of bits amongst each native integer gives needed native ints,
414
+ // so we then multiply again by the number of bits in each native int.
415
+ return ((n - 1) / NATIVE_INT_SIZE + 1) * NATIVE_INT_SIZE;
416
+ }
417
+
418
+ double *NodeIDAllocator::Clusterer::getDistanceMatrix(const std::vector<std::pair<const PointsTo *, unsigned>> pointsToSets,
419
+ const size_t numObjects, const Map<NodeID, unsigned> &nodeMap,
420
+ double &distanceMatrixTime)
421
+ {
422
+ const double clkStart = PTAStat::getClk(true);
423
+ size_t condensedSize = (numObjects * (numObjects - 1)) / 2;
424
+ double *distMatrix = new double[condensedSize];
425
+ for (size_t i = 0; i < condensedSize; ++i) distMatrix[i] = numObjects * numObjects;
426
+
427
+ // TODO: maybe use machine epsilon?
428
+ // For reducing distance due to extra occurrences.
429
+ // Can differentiate ~9999 occurrences.
430
+ double occurrenceEpsilon = 0.0001;
431
+
432
+ for (const std::pair<const PointsTo *, unsigned> &ptsOcc : pointsToSets)
433
+ {
434
+ const PointsTo *pts = ptsOcc.first;
435
+ assert(pts != nullptr);
436
+ const unsigned occ = ptsOcc.second;
437
+
438
+ // Distance between each element of pts.
439
+ unsigned distance = requiredBits(*pts) / NATIVE_INT_SIZE;
440
+
441
+ // Use a vector so we can index into pts.
442
+ std::vector<NodeID> ptsVec;
443
+ for (const NodeID o : *pts) ptsVec.push_back(o);
444
+ for (size_t i = 0; i < ptsVec.size(); ++i)
445
+ {
446
+ const NodeID oi = ptsVec[i];
447
+ const Map<NodeID, unsigned>::const_iterator moi = nodeMap.find(oi);
448
+ assert(moi != nodeMap.end());
449
+ for (size_t j = i + 1; j < ptsVec.size(); ++j)
450
+ {
451
+ const NodeID oj = ptsVec[j];
452
+ const Map<NodeID, unsigned>::const_iterator moj = nodeMap.find(oj);
453
+ assert(moj != nodeMap.end());
454
+ double &existingDistance = distMatrix[condensedIndex(numObjects, moi->second, moj->second)];
455
+
456
+ // Subtract extra occurrenceEpsilon to make upcoming logic simpler.
457
+ // When existingDistance is never whole, it is always between two distances.
458
+ if (distance < existingDistance) existingDistance = distance - occurrenceEpsilon;
459
+
460
+ if (distance == std::ceil(existingDistance))
461
+ {
462
+ // We have something like distance == x, existingDistance == x - e, for some e < 1
463
+ // (potentially even set during this iteration).
464
+ // So, the new distance is an occurrence the existingDistance being tracked, it just
465
+ // had some reductions because of multiple occurences.
466
+ // If there is not room within this distance to reduce more (increase priority),
467
+ // just ignore it. TODO: maybe warn?
468
+ if (existingDistance - occ * occurrenceEpsilon > std::floor(existingDistance))
469
+ {
470
+ existingDistance -= occ * occurrenceEpsilon;
471
+ }
472
+ else
473
+ {
474
+ // Reached minimum.
475
+ existingDistance = std::floor(existingDistance) + occurrenceEpsilon;
476
+ }
477
+ }
478
+ }
479
+ }
480
+
481
+ }
482
+
483
+ const double clkEnd = PTAStat::getClk(true);
484
+ distanceMatrixTime += (clkEnd - clkStart) / TIMEINTERVAL;
485
+
486
+ return distMatrix;
487
+ }
488
+
489
+ void NodeIDAllocator::Clusterer::traverseDendrogram(std::vector<NodeID> &nodeMap, const int *dendrogram, const size_t numObjects, unsigned &allocCounter, Set<int> &visited, const int index, const std::vector<NodeID> &regionNodeMap)
490
+ {
491
+ if (visited.find(index) != visited.end()) return;
492
+ visited.insert(index);
493
+
494
+ int left = dendrogram[index - 1];
495
+ if (left < 0)
496
+ {
497
+ // Reached a leaf.
498
+ // -1 because the items start from 1 per fastcluster (TODO).
499
+ nodeMap[regionNodeMap[std::abs(left) - 1]] = allocCounter;
500
+ ++allocCounter;
501
+ }
502
+ else
503
+ {
504
+ traverseDendrogram(nodeMap, dendrogram, numObjects, allocCounter, visited, left, regionNodeMap);
505
+ }
506
+
507
+ // Repeat for the right child.
508
+ int right = dendrogram[(numObjects - 1) + index - 1];
509
+ if (right < 0)
510
+ {
511
+ nodeMap[regionNodeMap[std::abs(right) - 1]] = allocCounter;
512
+ ++allocCounter;
513
+ }
514
+ else
515
+ {
516
+ traverseDendrogram(nodeMap, dendrogram, numObjects, allocCounter, visited, right, regionNodeMap);
517
+ }
518
+ }
519
+
520
+ std::vector<NodeID> NodeIDAllocator::Clusterer::regionObjects(const Map<NodeID, Set<NodeID>> &graph, size_t numObjects, size_t &numLabels)
521
+ {
522
+ unsigned label = UINT_MAX;
523
+ std::vector<NodeID> labels(numObjects, UINT_MAX);
524
+ Set<NodeID> labelled;
525
+ for (const Map<NodeID, Set<NodeID>>::value_type &oos : graph)
526
+ {
527
+ const NodeID o = oos.first;
528
+ if (labels[o] != UINT_MAX) continue;
529
+ std::queue<NodeID> bfsQueue;
530
+ bfsQueue.push(o);
531
+ ++label;
532
+ while (!bfsQueue.empty())
533
+ {
534
+ const NodeID o = bfsQueue.front();
535
+ bfsQueue.pop();
536
+ if (labels[o] != UINT_MAX)
537
+ {
538
+ assert(labels[o] == label);
539
+ continue;
540
+ }
541
+
542
+ labels[o] = label;
543
+ Map<NodeID, Set<NodeID>>::const_iterator neighboursIt = graph.find(o);
544
+ assert(neighboursIt != graph.end());
545
+ for (const NodeID neighbour : neighboursIt->second) bfsQueue.push(neighbour);
546
+ }
547
+ }
548
+
549
+ // The remaining objects have no relation with others: they get their own label.
550
+ for (size_t o = 0; o < numObjects; ++o)
551
+ {
552
+ if (labels[o] == UINT_MAX) labels[o] = ++label;
553
+ }
554
+
555
+ numLabels = label + 1;
556
+
557
+ return labels;
558
+ }
559
+
560
+ void NodeIDAllocator::Clusterer::evaluate(const std::vector<NodeID> &nodeMap, const Map<PointsTo, unsigned> pointsToSets, Map<std::string, std::string> &stats, bool accountForOcc)
561
+ {
562
+ u64_t totalTheoretical = 0;
563
+ u64_t totalOriginalSbv = 0;
564
+ u64_t totalOriginalBv = 0;
565
+ u64_t totalNewSbv = 0;
566
+ u64_t totalNewBv = 0;
567
+
568
+ for (const Map<PointsTo, unsigned>::value_type &ptsOcc : pointsToSets)
569
+ {
570
+ const PointsTo &pts = ptsOcc.first;
571
+ const unsigned occ = ptsOcc.second;
572
+ if (pts.count() == 0) continue;
573
+
574
+ u64_t theoretical = requiredBits(pts) / NATIVE_INT_SIZE;
575
+ if (accountForOcc) theoretical *= occ;
576
+
577
+ // Check number of words for original SBV.
578
+ Set<unsigned> words;
579
+ // TODO: nasty hardcoding.
580
+ for (const NodeID o : pts) words.insert(o / 128);
581
+ u64_t originalSbv = words.size() * 2;
582
+ if (accountForOcc) originalSbv *= occ;
583
+
584
+ // Check number of words for original BV.
585
+ NodeID min = UINT_MAX;
586
+ NodeID max = 0;
587
+ for (NodeID o : pts)
588
+ {
589
+ if (o < min) min = o;
590
+ if (o > max) max = o;
591
+ }
592
+ words.clear();
593
+ for (NodeID b = min; b <= max; ++b)
594
+ {
595
+ words.insert(b / NATIVE_INT_SIZE);
596
+ }
597
+ u64_t originalBv = words.size();
598
+ if (accountForOcc) originalBv *= occ;
599
+
600
+ // Check number of words for new SBV.
601
+ words.clear();
602
+ // TODO: nasty hardcoding.
603
+ for (const NodeID o : pts) words.insert(nodeMap[o] / 128);
604
+ u64_t newSbv = words.size() * 2;
605
+ if (accountForOcc) newSbv *= occ;
606
+
607
+ // Check number of words for new BV.
608
+ min = UINT_MAX;
609
+ max = 0;
610
+ for (const NodeID o : pts)
611
+ {
612
+ const NodeID mappedO = nodeMap[o];
613
+ if (mappedO < min) min = mappedO;
614
+ if (mappedO > max) max = mappedO;
615
+ }
616
+
617
+ words.clear();
618
+ // No nodeMap[b] because min and max and from nodeMap.
619
+ for (NodeID b = min; b <= max; ++b) words.insert(b / NATIVE_INT_SIZE);
620
+ u64_t newBv = words.size();
621
+ if (accountForOcc) newBv *= occ;
622
+
623
+ totalTheoretical += theoretical;
624
+ totalOriginalSbv += originalSbv;
625
+ totalOriginalBv += originalBv;
626
+ totalNewSbv += newSbv;
627
+ totalNewBv += newBv;
628
+ }
629
+
630
+ stats[TheoreticalNumWords] = std::to_string(totalTheoretical);
631
+ stats[OriginalSbvNumWords] = std::to_string(totalOriginalSbv);
632
+ stats[OriginalBvNumWords] = std::to_string(totalOriginalBv);
633
+ stats[NewSbvNumWords] = std::to_string(totalNewSbv);
634
+ stats[NewBvNumWords] = std::to_string(totalNewBv);
635
+ }
636
+
637
+ // Work out which of the mappings we generated looks best.
638
+ std::pair<hclust_fast_methods, std::vector<NodeID>> NodeIDAllocator::Clusterer::determineBestMapping(
639
+ const std::vector<std::pair<hclust_fast_methods, std::vector<NodeID>>> &candidates,
640
+ Map<PointsTo, unsigned> pointsToSets, const std::string &evalSubtitle, double &evalTime)
641
+ {
642
+ // In case we're not comparing anything, set to first "candidate".
643
+ std::pair<hclust_fast_methods, std::vector<NodeID>> bestMapping = candidates[0];
644
+ // Number of bits required for the best candidate.
645
+ size_t bestWords = std::numeric_limits<size_t>::max();
646
+ if (evalSubtitle != "" || Options::ClusterMethod == HCLUST_METHOD_SVF_BEST)
647
+ {
648
+ for (const std::pair<hclust_fast_methods, std::vector<NodeID>> &candidate : candidates)
649
+ {
650
+ Map<std::string, std::string> candidateStats;
651
+ hclust_fast_methods candidateMethod = candidate.first;
652
+ std::string candidateMethodName = SVFUtil::hclustMethodToString(candidateMethod);
653
+ std::vector<NodeID> candidateMapping = candidate.second;
654
+
655
+ // TODO: parameterise final arg.
656
+ const double clkStart = PTAStat::getClk(true);
657
+ evaluate(candidateMapping, pointsToSets, candidateStats, true);
658
+ const double clkEnd = PTAStat::getClk(true);
659
+ evalTime += (clkEnd - clkStart) / TIMEINTERVAL;
660
+ printStats(evalSubtitle + ": candidate " + candidateMethodName, candidateStats);
661
+
662
+ size_t candidateWords = 0;
663
+ if (Options::PtType == PointsTo::SBV) candidateWords = std::stoull(candidateStats[NewSbvNumWords]);
664
+ else if (Options::PtType == PointsTo::CBV) candidateWords = std::stoull(candidateStats[NewBvNumWords]);
665
+ else assert(false && "Clusterer::cluster: unsupported BV type for clustering.");
666
+
667
+ if (candidateWords < bestWords)
668
+ {
669
+ bestWords = candidateWords;
670
+ bestMapping = candidate;
671
+ }
672
+ }
673
+ }
674
+
675
+ return bestMapping;
676
+ }
677
+
678
+ void NodeIDAllocator::Clusterer::printStats(std::string subtitle, Map<std::string, std::string> &stats)
679
+ {
680
+ // When not in order, it is too hard to compare original/new SBV/BV words, so this array forces an order.
681
+ const static std::array<std::string, 17> statKeys =
682
+ { NumObjects, TheoreticalNumWords, OriginalSbvNumWords, OriginalBvNumWords,
683
+ NewSbvNumWords, NewBvNumWords, NumRegions, NumGtIntRegions,
684
+ NumNonTrivialRegionObjects, LargestRegion, RegioningTime,
685
+ DistanceMatrixTime, FastClusterTime, DendrogramTraversalTime,
686
+ EvalTime, TotalTime, BestCandidate };
687
+
688
+ const unsigned fieldWidth = 20;
689
+ std::cout.flags(std::ios::left);
690
+ std::cout << "****Clusterer Statistics: " << subtitle << "****\n";
691
+ for (const std::string &statKey : statKeys)
692
+ {
693
+ Map<std::string, std::string>::const_iterator stat = stats.find(statKey);
694
+ if (stat != stats.end())
695
+ {
696
+ std::cout << std::setw(fieldWidth) << statKey << " " << stat->second << "\n";
697
+ }
698
+ }
699
+
700
+ std::cout.flush();
701
+ }
702
+
703
+ }; // namespace SVF.
@@ -362,6 +362,25 @@ std::string SVFUtil::getSourceLoc(const Value* val)
362
362
  return rawstr.str();
363
363
  }
364
364
 
365
+ std::string SVFUtil::hclustMethodToString(hclust_fast_methods method)
366
+ {
367
+ switch (method)
368
+ {
369
+ case HCLUST_METHOD_SINGLE:
370
+ return "single";
371
+ case HCLUST_METHOD_COMPLETE:
372
+ return "complete";
373
+ case HCLUST_METHOD_AVERAGE:
374
+ return "average";
375
+ case HCLUST_METHOD_MEDIAN:
376
+ return "median";
377
+ case HCLUST_METHOD_SVF_BEST:
378
+ return "svf-best";
379
+ default:
380
+ assert(false && "SVFUtil::hclustMethodToString: unknown method");
381
+ }
382
+ }
383
+
365
384
  /*!
366
385
  * return string of an LLVM Value
367
386
  */
@@ -178,6 +178,9 @@ void Andersen::initialize()
178
178
  setDiffOpt(Options::PtsDiff);
179
179
  setPWCOpt(Options::MergePWC);
180
180
  AndersenBase::initialize();
181
+
182
+ if (Options::ClusterAnder) cluster();
183
+
181
184
  /// Initialize worklist
182
185
  processAllAddr();
183
186
  }
@@ -187,6 +190,18 @@ void Andersen::initialize()
187
190
  */
188
191
  void Andersen::finalize()
189
192
  {
193
+ // TODO: check -stat too.
194
+ // TODO: broken
195
+ if (Options::ClusterAnder)
196
+ {
197
+ Map<std::string, std::string> stats;
198
+ const PTDataTy *ptd = getPTDataTy();
199
+ // TODO: should we use liveOnly?
200
+ // TODO: parameterise final arg.
201
+ NodeIDAllocator::Clusterer::evaluate(*PointsTo::getCurrentBestNodeMapping(), ptd->getAllPts(true), stats, true);
202
+ NodeIDAllocator::Clusterer::printStats("post-main", stats);
203
+ }
204
+
190
205
  /// sanitize field insensitive obj
191
206
  /// TODO: Fields has been collapsed during Andersen::collapseField().
192
207
  // sanitizePts();
@@ -811,6 +826,25 @@ void Andersen::updateNodeRepAndSubs(NodeID nodeId, NodeID newRepId)
811
826
  consCG->resetSubs(nodeId);
812
827
  }
813
828
 
829
+ void Andersen::cluster(void) const
830
+ {
831
+ assert(Options::MaxFieldLimit == 0 && "Andersen::cluster: clustering for Andersen's is currently only supported in field-insesnsitive analysis");
832
+ Steensgaard *steens = Steensgaard::createSteensgaard(pag);
833
+ std::vector<std::pair<unsigned, unsigned>> keys;
834
+ for (PAG::iterator pit = pag->begin(); pit != pag->end(); ++pit)
835
+ {
836
+ keys.push_back(std::make_pair(pit->first, 1));
837
+ }
838
+
839
+ std::vector<std::pair<hclust_fast_methods, std::vector<NodeID>>> candidates;
840
+ PointsTo::MappingPtr nodeMapping =
841
+ std::make_shared<std::vector<NodeID>>(NodeIDAllocator::Clusterer::cluster(steens, keys, candidates, "aux-steens"));
842
+ PointsTo::MappingPtr reverseNodeMapping =
843
+ std::make_shared<std::vector<NodeID>>(NodeIDAllocator::Clusterer::getReverseNodeMapping(*nodeMapping));
844
+
845
+ PointsTo::setCurrentBestNodeMapping(nodeMapping, reverseNodeMapping);
846
+ }
847
+
814
848
  /*!
815
849
  * Print pag nodes' pts by an ascending order
816
850
  */