arkanalyzer 1.0.20 → 1.0.21

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 (279) hide show
  1. package/lib/Config.d.ts +70 -70
  2. package/lib/Config.js +198 -198
  3. package/lib/Scene.d.ts +316 -316
  4. package/lib/Scene.js +1316 -1316
  5. package/lib/callgraph/algorithm/AbstractAnalysis.d.ts +28 -28
  6. package/lib/callgraph/algorithm/AbstractAnalysis.js +144 -144
  7. package/lib/callgraph/algorithm/ClassHierarchyAnalysis.d.ts +10 -10
  8. package/lib/callgraph/algorithm/ClassHierarchyAnalysis.js +69 -69
  9. package/lib/callgraph/algorithm/RapidTypeAnalysis.d.ts +15 -15
  10. package/lib/callgraph/algorithm/RapidTypeAnalysis.js +146 -146
  11. package/lib/callgraph/common/Statistics.d.ts +57 -57
  12. package/lib/callgraph/common/Statistics.js +228 -228
  13. package/lib/callgraph/model/CallGraph.d.ts +96 -96
  14. package/lib/callgraph/model/CallGraph.js +354 -354
  15. package/lib/callgraph/model/builder/CallGraphBuilder.d.ts +15 -15
  16. package/lib/callgraph/model/builder/CallGraphBuilder.js +106 -106
  17. package/lib/callgraph/pointerAnalysis/Context.d.ts +37 -37
  18. package/lib/callgraph/pointerAnalysis/Context.js +155 -155
  19. package/lib/callgraph/pointerAnalysis/DummyCallCreator.d.ts +22 -22
  20. package/lib/callgraph/pointerAnalysis/DummyCallCreator.js +104 -104
  21. package/lib/callgraph/pointerAnalysis/PTAUtils.d.ts +5 -5
  22. package/lib/callgraph/pointerAnalysis/PTAUtils.js +46 -46
  23. package/lib/callgraph/pointerAnalysis/Pag.d.ts +261 -261
  24. package/lib/callgraph/pointerAnalysis/Pag.js +930 -930
  25. package/lib/callgraph/pointerAnalysis/PagBuilder.d.ts +157 -157
  26. package/lib/callgraph/pointerAnalysis/PagBuilder.js +1399 -1399
  27. package/lib/callgraph/pointerAnalysis/PointerAnalysis.d.ts +72 -72
  28. package/lib/callgraph/pointerAnalysis/PointerAnalysis.js +573 -573
  29. package/lib/callgraph/pointerAnalysis/PointerAnalysisConfig.d.ts +15 -15
  30. package/lib/callgraph/pointerAnalysis/PointerAnalysisConfig.js +81 -81
  31. package/lib/callgraph/pointerAnalysis/PtsDS.d.ts +80 -80
  32. package/lib/callgraph/pointerAnalysis/PtsDS.js +308 -308
  33. package/lib/core/base/Constant.d.ts +48 -48
  34. package/lib/core/base/Constant.js +103 -103
  35. package/lib/core/base/Decorator.d.ts +15 -15
  36. package/lib/core/base/Decorator.js +46 -46
  37. package/lib/core/base/DefUseChain.d.ts +8 -8
  38. package/lib/core/base/DefUseChain.js +25 -25
  39. package/lib/core/base/Expr.d.ts +340 -340
  40. package/lib/core/base/Expr.js +917 -917
  41. package/lib/core/base/Local.d.ts +104 -104
  42. package/lib/core/base/Local.js +176 -176
  43. package/lib/core/base/Position.d.ts +30 -30
  44. package/lib/core/base/Position.js +147 -147
  45. package/lib/core/base/Ref.d.ts +173 -173
  46. package/lib/core/base/Ref.js +374 -374
  47. package/lib/core/base/Stmt.d.ts +237 -237
  48. package/lib/core/base/Stmt.js +525 -525
  49. package/lib/core/base/Trap.d.ts +8 -8
  50. package/lib/core/base/Trap.js +30 -30
  51. package/lib/core/base/Type.d.ts +308 -308
  52. package/lib/core/base/Type.js +639 -639
  53. package/lib/core/base/TypeExpr.d.ts +71 -71
  54. package/lib/core/base/TypeExpr.js +155 -155
  55. package/lib/core/base/Value.d.ts +32 -32
  56. package/lib/core/base/Value.js +16 -16
  57. package/lib/core/common/ArkError.d.ts +14 -14
  58. package/lib/core/common/ArkError.js +28 -28
  59. package/lib/core/common/ArkIRTransformer.d.ts +67 -67
  60. package/lib/core/common/ArkIRTransformer.js +690 -690
  61. package/lib/core/common/ArkValueTransformer.d.ts +89 -89
  62. package/lib/core/common/ArkValueTransformer.js +1478 -1478
  63. package/lib/core/common/Builtin.d.ts +36 -36
  64. package/lib/core/common/Builtin.js +81 -81
  65. package/lib/core/common/Const.d.ts +21 -21
  66. package/lib/core/common/Const.js +43 -43
  67. package/lib/core/common/DummyMainCreater.d.ts +46 -46
  68. package/lib/core/common/DummyMainCreater.js +319 -319
  69. package/lib/core/common/EtsConst.d.ts +73 -73
  70. package/lib/core/common/EtsConst.js +1021 -1021
  71. package/lib/core/common/ExprUseReplacer.d.ts +21 -21
  72. package/lib/core/common/ExprUseReplacer.js +124 -124
  73. package/lib/core/common/IRInference.d.ts +36 -36
  74. package/lib/core/common/IRInference.d.ts.map +1 -1
  75. package/lib/core/common/IRInference.js +651 -648
  76. package/lib/core/common/IRUtils.d.ts +18 -18
  77. package/lib/core/common/IRUtils.js +141 -141
  78. package/lib/core/common/ModelUtils.d.ts +70 -70
  79. package/lib/core/common/ModelUtils.js +712 -712
  80. package/lib/core/common/RefUseReplacer.d.ts +13 -13
  81. package/lib/core/common/RefUseReplacer.js +52 -52
  82. package/lib/core/common/SdkUtils.d.ts +8 -8
  83. package/lib/core/common/SdkUtils.js +105 -105
  84. package/lib/core/common/StmtDefReplacer.d.ts +12 -12
  85. package/lib/core/common/StmtDefReplacer.js +41 -41
  86. package/lib/core/common/StmtUseReplacer.d.ts +16 -16
  87. package/lib/core/common/StmtUseReplacer.js +108 -108
  88. package/lib/core/common/TSConst.d.ts +18 -18
  89. package/lib/core/common/TSConst.js +36 -36
  90. package/lib/core/common/TypeInference.d.ts +102 -102
  91. package/lib/core/common/TypeInference.js +748 -748
  92. package/lib/core/common/ValueUtil.d.ts +12 -12
  93. package/lib/core/common/ValueUtil.js +54 -54
  94. package/lib/core/common/VisibleValue.d.ts +36 -36
  95. package/lib/core/common/VisibleValue.js +212 -212
  96. package/lib/core/dataflow/DataflowProblem.d.ts +20 -20
  97. package/lib/core/dataflow/DataflowProblem.js +20 -20
  98. package/lib/core/dataflow/DataflowResult.d.ts +7 -7
  99. package/lib/core/dataflow/DataflowResult.js +26 -26
  100. package/lib/core/dataflow/DataflowSolver.d.ts +43 -43
  101. package/lib/core/dataflow/DataflowSolver.js +307 -307
  102. package/lib/core/dataflow/Edge.d.ts +11 -11
  103. package/lib/core/dataflow/Edge.js +31 -31
  104. package/lib/core/dataflow/Fact.d.ts +6 -6
  105. package/lib/core/dataflow/Fact.js +24 -24
  106. package/lib/core/dataflow/GenericDataFlow.d.ts +142 -142
  107. package/lib/core/dataflow/GenericDataFlow.js +109 -109
  108. package/lib/core/dataflow/ReachingDef.d.ts +62 -62
  109. package/lib/core/dataflow/ReachingDef.js +168 -168
  110. package/lib/core/dataflow/UndefinedVariable.d.ts +45 -45
  111. package/lib/core/dataflow/UndefinedVariable.js +288 -288
  112. package/lib/core/dataflow/Util.d.ts +9 -9
  113. package/lib/core/dataflow/Util.js +64 -64
  114. package/lib/core/graph/BaseExplicitGraph.d.ts +58 -58
  115. package/lib/core/graph/BaseExplicitGraph.js +157 -157
  116. package/lib/core/graph/BaseImplicitGraph.d.ts +77 -77
  117. package/lib/core/graph/BaseImplicitGraph.js +78 -78
  118. package/lib/core/graph/BasicBlock.d.ts +104 -104
  119. package/lib/core/graph/BasicBlock.js +280 -280
  120. package/lib/core/graph/Cfg.d.ts +59 -59
  121. package/lib/core/graph/Cfg.js +282 -282
  122. package/lib/core/graph/DependsGraph.d.ts +35 -35
  123. package/lib/core/graph/DependsGraph.js +87 -87
  124. package/lib/core/graph/DominanceFinder.d.ts +15 -15
  125. package/lib/core/graph/DominanceFinder.js +121 -121
  126. package/lib/core/graph/DominanceTree.d.ts +12 -12
  127. package/lib/core/graph/DominanceTree.js +70 -70
  128. package/lib/core/graph/GraphTraits.d.ts +7 -7
  129. package/lib/core/graph/GraphTraits.js +16 -16
  130. package/lib/core/graph/Scc.d.ts +61 -61
  131. package/lib/core/graph/Scc.js +222 -222
  132. package/lib/core/graph/ViewTree.d.ts +114 -114
  133. package/lib/core/graph/ViewTree.js +16 -16
  134. package/lib/core/graph/builder/CfgBuilder.d.ts +176 -176
  135. package/lib/core/graph/builder/CfgBuilder.js +1139 -1139
  136. package/lib/core/graph/builder/ConditionBuilder.d.ts +15 -15
  137. package/lib/core/graph/builder/ConditionBuilder.js +252 -252
  138. package/lib/core/graph/builder/LoopBuilder.d.ts +20 -20
  139. package/lib/core/graph/builder/LoopBuilder.js +251 -251
  140. package/lib/core/graph/builder/SwitchBuilder.d.ts +11 -11
  141. package/lib/core/graph/builder/SwitchBuilder.js +152 -152
  142. package/lib/core/graph/builder/TrapBuilder.d.ts +16 -16
  143. package/lib/core/graph/builder/TrapBuilder.js +272 -272
  144. package/lib/core/graph/builder/ViewTreeBuilder.d.ts +203 -203
  145. package/lib/core/graph/builder/ViewTreeBuilder.js +1055 -1055
  146. package/lib/core/model/ArkBaseModel.d.ts +59 -59
  147. package/lib/core/model/ArkBaseModel.js +274 -274
  148. package/lib/core/model/ArkBody.d.ts +24 -24
  149. package/lib/core/model/ArkBody.js +65 -65
  150. package/lib/core/model/ArkClass.d.ts +206 -206
  151. package/lib/core/model/ArkClass.js +439 -439
  152. package/lib/core/model/ArkExport.d.ts +72 -72
  153. package/lib/core/model/ArkExport.js +147 -147
  154. package/lib/core/model/ArkField.d.ts +62 -62
  155. package/lib/core/model/ArkField.js +113 -113
  156. package/lib/core/model/ArkFile.d.ts +131 -131
  157. package/lib/core/model/ArkFile.js +267 -267
  158. package/lib/core/model/ArkImport.d.ts +44 -44
  159. package/lib/core/model/ArkImport.js +108 -108
  160. package/lib/core/model/ArkMetadata.d.ts +31 -31
  161. package/lib/core/model/ArkMetadata.js +55 -55
  162. package/lib/core/model/ArkMethod.d.ts +261 -261
  163. package/lib/core/model/ArkMethod.js +592 -592
  164. package/lib/core/model/ArkNamespace.d.ts +66 -66
  165. package/lib/core/model/ArkNamespace.js +209 -209
  166. package/lib/core/model/ArkSignature.d.ts +162 -162
  167. package/lib/core/model/ArkSignature.js +379 -379
  168. package/lib/core/model/builder/ArkClassBuilder.d.ts +12 -12
  169. package/lib/core/model/builder/ArkClassBuilder.js +454 -454
  170. package/lib/core/model/builder/ArkExportBuilder.d.ts +24 -24
  171. package/lib/core/model/builder/ArkExportBuilder.js +210 -210
  172. package/lib/core/model/builder/ArkFieldBuilder.d.ts +8 -8
  173. package/lib/core/model/builder/ArkFieldBuilder.js +193 -193
  174. package/lib/core/model/builder/ArkFileBuilder.d.ts +9 -9
  175. package/lib/core/model/builder/ArkFileBuilder.js +165 -165
  176. package/lib/core/model/builder/ArkImportBuilder.d.ts +4 -4
  177. package/lib/core/model/builder/ArkImportBuilder.js +128 -128
  178. package/lib/core/model/builder/ArkMethodBuilder.d.ts +63 -63
  179. package/lib/core/model/builder/ArkMethodBuilder.js +486 -486
  180. package/lib/core/model/builder/ArkNamespaceBuilder.d.ts +5 -5
  181. package/lib/core/model/builder/ArkNamespaceBuilder.js +205 -205
  182. package/lib/core/model/builder/ArkSignatureBuilder.d.ts +8 -8
  183. package/lib/core/model/builder/ArkSignatureBuilder.js +40 -40
  184. package/lib/core/model/builder/BodyBuilder.d.ts +55 -30
  185. package/lib/core/model/builder/BodyBuilder.d.ts.map +1 -1
  186. package/lib/core/model/builder/BodyBuilder.js +542 -371
  187. package/lib/core/model/builder/builderUtils.d.ts +18 -18
  188. package/lib/core/model/builder/builderUtils.js +558 -558
  189. package/lib/index.d.ts +82 -80
  190. package/lib/index.d.ts.map +1 -1
  191. package/lib/index.js +201 -196
  192. package/lib/save/ArkStream.d.ts +23 -23
  193. package/lib/save/ArkStream.js +83 -83
  194. package/lib/save/DotPrinter.d.ts +43 -43
  195. package/lib/save/DotPrinter.js +170 -170
  196. package/lib/save/GraphPrinter.d.ts +16 -16
  197. package/lib/save/GraphPrinter.js +134 -134
  198. package/lib/save/JsonPrinter.d.ts +30 -30
  199. package/lib/save/JsonPrinter.js +580 -580
  200. package/lib/save/Printer.d.ts +12 -12
  201. package/lib/save/Printer.js +27 -27
  202. package/lib/save/PrinterBuilder.d.ts +53 -53
  203. package/lib/save/PrinterBuilder.js +145 -145
  204. package/lib/save/ViewTreePrinter.d.ts +14 -14
  205. package/lib/save/ViewTreePrinter.js +123 -123
  206. package/lib/save/arkir/ArkIRClassPrinter.d.ts +13 -13
  207. package/lib/save/arkir/ArkIRClassPrinter.js +92 -92
  208. package/lib/save/arkir/ArkIRFieldPrinter.d.ts +11 -11
  209. package/lib/save/arkir/ArkIRFieldPrinter.js +64 -64
  210. package/lib/save/arkir/ArkIRFilePrinter.d.ts +12 -12
  211. package/lib/save/arkir/ArkIRFilePrinter.js +54 -54
  212. package/lib/save/arkir/ArkIRMethodPrinter.d.ts +16 -16
  213. package/lib/save/arkir/ArkIRMethodPrinter.js +159 -159
  214. package/lib/save/arkir/ArkIRNamespacePrinter.d.ts +11 -11
  215. package/lib/save/arkir/ArkIRNamespacePrinter.js +66 -66
  216. package/lib/save/base/BasePrinter.d.ts +23 -23
  217. package/lib/save/base/BasePrinter.js +70 -70
  218. package/lib/save/base/ExportPrinter.d.ts +8 -8
  219. package/lib/save/base/ExportPrinter.js +67 -67
  220. package/lib/save/base/ImportPrinter.d.ts +9 -9
  221. package/lib/save/base/ImportPrinter.js +92 -92
  222. package/lib/save/base/PrinterUtils.d.ts +24 -24
  223. package/lib/save/base/PrinterUtils.js +208 -208
  224. package/lib/save/serializeArkIR.d.ts +8 -8
  225. package/lib/save/serializeArkIR.js +294 -294
  226. package/lib/save/source/SourceBase.d.ts +22 -22
  227. package/lib/save/source/SourceBase.js +64 -64
  228. package/lib/save/source/SourceBody.d.ts +58 -58
  229. package/lib/save/source/SourceBody.js +296 -296
  230. package/lib/save/source/SourceClass.d.ts +25 -25
  231. package/lib/save/source/SourceClass.js +187 -187
  232. package/lib/save/source/SourceField.d.ts +13 -13
  233. package/lib/save/source/SourceField.js +73 -73
  234. package/lib/save/source/SourceFilePrinter.d.ts +12 -12
  235. package/lib/save/source/SourceFilePrinter.js +69 -69
  236. package/lib/save/source/SourceMethod.d.ts +22 -22
  237. package/lib/save/source/SourceMethod.d.ts.map +1 -1
  238. package/lib/save/source/SourceMethod.js +196 -193
  239. package/lib/save/source/SourceNamespace.d.ts +11 -11
  240. package/lib/save/source/SourceNamespace.js +83 -83
  241. package/lib/save/source/SourceStmt.d.ts +178 -178
  242. package/lib/save/source/SourceStmt.js +838 -838
  243. package/lib/save/source/SourceTransformer.d.ts +46 -46
  244. package/lib/save/source/SourceTransformer.js +446 -446
  245. package/lib/transformer/FunctionTransformer.d.ts +2 -2
  246. package/lib/transformer/FunctionTransformer.js +17 -17
  247. package/lib/transformer/SceneTransformer.d.ts +2 -2
  248. package/lib/transformer/SceneTransformer.js +17 -17
  249. package/lib/transformer/StaticSingleAssignmentFormer.d.ts +12 -12
  250. package/lib/transformer/StaticSingleAssignmentFormer.js +259 -259
  251. package/lib/transformer/Transformer.d.ts +6 -6
  252. package/lib/transformer/Transformer.js +22 -22
  253. package/lib/utils/AstTreeUtils.d.ts +4 -4
  254. package/lib/utils/AstTreeUtils.js +26 -26
  255. package/lib/utils/CfgStructualAnalysis.d.ts +110 -110
  256. package/lib/utils/CfgStructualAnalysis.js +1277 -1277
  257. package/lib/utils/FileUtils.d.ts +18 -18
  258. package/lib/utils/FileUtils.js +135 -135
  259. package/lib/utils/SparseBitVector.d.ts +100 -100
  260. package/lib/utils/SparseBitVector.js +445 -445
  261. package/lib/utils/callGraphUtils.d.ts +30 -30
  262. package/lib/utils/callGraphUtils.js +205 -205
  263. package/lib/utils/crypto_utils.d.ts +5 -5
  264. package/lib/utils/crypto_utils.js +57 -57
  265. package/lib/utils/entryMethodUtils.d.ts +13 -13
  266. package/lib/utils/entryMethodUtils.js +110 -110
  267. package/lib/utils/getAllFiles.d.ts +9 -9
  268. package/lib/utils/getAllFiles.js +90 -90
  269. package/lib/utils/json5parser.d.ts +6 -6
  270. package/lib/utils/json5parser.js +146 -146
  271. package/lib/utils/logger.d.ts +18 -18
  272. package/lib/utils/logger.d.ts.map +1 -1
  273. package/lib/utils/logger.js +97 -90
  274. package/lib/utils/pathTransfer.d.ts +1 -1
  275. package/lib/utils/pathTransfer.js +25 -25
  276. package/node_modules/json5/lib/cli.js +0 -0
  277. package/node_modules/ohos-typescript/bin/tsc +0 -0
  278. package/node_modules/ohos-typescript/bin/tsserver +0 -0
  279. package/package.json +3 -3
@@ -1,1277 +1,1277 @@
1
- "use strict";
2
- /*
3
- * Copyright (c) 2024 Huawei Device Co., Ltd.
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.AbstractFlowGraph = exports.CodeBlockType = void 0;
18
- const Stmt_1 = require("../core/base/Stmt");
19
- var CodeBlockType;
20
- (function (CodeBlockType) {
21
- CodeBlockType[CodeBlockType["NORMAL"] = 0] = "NORMAL";
22
- CodeBlockType[CodeBlockType["IF"] = 1] = "IF";
23
- CodeBlockType[CodeBlockType["ELSE"] = 2] = "ELSE";
24
- CodeBlockType[CodeBlockType["BREAK"] = 3] = "BREAK";
25
- CodeBlockType[CodeBlockType["CONTINUE"] = 4] = "CONTINUE";
26
- CodeBlockType[CodeBlockType["DO"] = 5] = "DO";
27
- CodeBlockType[CodeBlockType["DO_WHILE"] = 6] = "DO_WHILE";
28
- CodeBlockType[CodeBlockType["WHILE"] = 7] = "WHILE";
29
- CodeBlockType[CodeBlockType["FOR"] = 8] = "FOR";
30
- CodeBlockType[CodeBlockType["COMPOUND_END"] = 9] = "COMPOUND_END";
31
- CodeBlockType[CodeBlockType["TRY"] = 10] = "TRY";
32
- CodeBlockType[CodeBlockType["CATCH"] = 11] = "CATCH";
33
- CodeBlockType[CodeBlockType["FINALLY"] = 12] = "FINALLY";
34
- })(CodeBlockType = exports.CodeBlockType || (exports.CodeBlockType = {}));
35
- class AbstractFlowGraph {
36
- constructor(cfg, traps) {
37
- this.nodes = [];
38
- this.structOf = new Map();
39
- this.structTypes = new Map();
40
- this.structBlocks = new Map();
41
- this.loopMap = new Map();
42
- this.block2NodeMap = new Map();
43
- for (const bb of cfg.getBlocks()) {
44
- let an = new AbstractNode();
45
- an.setBlock(bb);
46
- this.block2NodeMap.set(bb, an);
47
- }
48
- for (const bb of cfg.getBlocks()) {
49
- let an = this.block2NodeMap.get(bb);
50
- for (const succ of bb.getSuccessors()) {
51
- an.addSucc(this.block2NodeMap.get(succ));
52
- }
53
- for (const pred of bb.getPredecessors()) {
54
- an.addPred(this.block2NodeMap.get(pred));
55
- }
56
- }
57
- let trapRegions = this.buildTrap(traps);
58
- this.searchTrapFinallyNodes(trapRegions);
59
- this.trapsStructuralAnalysis(trapRegions);
60
- this.entry = this.block2NodeMap.get(cfg.getStartingBlock());
61
- this.entry = this.structuralAnalysis(this.entry);
62
- }
63
- getEntry() {
64
- return this.entry;
65
- }
66
- getForIncBlock(block) {
67
- let node = this.block2NodeMap.get(block);
68
- let loop = this.loopMap.get(node);
69
- return loop.inc.getBlock();
70
- }
71
- preOrder(node, callback, visitor = new Set()) {
72
- visitor.add(node);
73
- node.traversal(callback, CodeBlockType.NORMAL);
74
- for (const succ of node.getSucc()) {
75
- if (!visitor.has(succ)) {
76
- this.preOrder(succ, callback, visitor);
77
- }
78
- }
79
- }
80
- structuralAnalysis(entry, scope) {
81
- let preds = entry.getPred();
82
- let entryBak = entry;
83
- this.nodes = this.dfsPostOrder(entry, scope);
84
- this.entry = entry;
85
- this.buildCyclicStructural();
86
- // acyclic structural
87
- let postMax = this.nodes.length;
88
- let change = true;
89
- while (postMax > 1 && change) {
90
- change = false;
91
- for (let i = 0; i < postMax; i++) {
92
- let node = this.nodes[i];
93
- let nset = new Set();
94
- let rtype = this.identifyRegionType(node, nset, scope);
95
- if (!rtype) {
96
- continue;
97
- }
98
- let p = this.reduce(rtype, nset);
99
- if (!p) {
100
- continue;
101
- }
102
- scope === null || scope === void 0 ? void 0 : scope.add(p);
103
- if (nset.has(entry)) {
104
- entry = p;
105
- }
106
- this.nodes = this.dfsPostOrder(entry, scope);
107
- change = postMax !== this.nodes.length;
108
- postMax = this.nodes.length;
109
- }
110
- }
111
- for (const pred of preds) {
112
- pred.replaceSucc(entryBak, entry);
113
- entry.addPred(pred);
114
- }
115
- return entry;
116
- }
117
- dfsPostOrder(node, scope, visitor = new Set(), postOrder = []) {
118
- visitor.add(node);
119
- for (const succ of node.getSucc()) {
120
- if (visitor.has(succ)) {
121
- continue;
122
- }
123
- if (scope && !scope.has(succ)) {
124
- continue;
125
- }
126
- this.dfsPostOrder(succ, scope, visitor, postOrder);
127
- }
128
- postOrder.push(node);
129
- return postOrder;
130
- }
131
- buildCyclicStructural() {
132
- for (const loop of this.prepareBuildLoops()) {
133
- let nset = new Set();
134
- for (const n of loop) {
135
- if (this.structOf.has(n)) {
136
- nset.add(this.structOf.get(n));
137
- }
138
- else {
139
- nset.add(n);
140
- }
141
- }
142
- let rtype = this.cyclicRegionType(nset);
143
- let region = this.createRegion(rtype, nset);
144
- region.revise();
145
- this.structTypes.set(region, rtype);
146
- let blocks = new Set();
147
- for (const s of nset) {
148
- if (!this.structOf.has(s)) {
149
- this.structOf.set(s, region);
150
- }
151
- if (this.structBlocks.has(s)) {
152
- for (const b of this.structBlocks.get(s)) {
153
- blocks.add(b);
154
- }
155
- }
156
- else {
157
- blocks.add(s);
158
- }
159
- }
160
- this.structBlocks.set(region, blocks);
161
- this.loopMap.set(region.header, region);
162
- }
163
- }
164
- prepareBuildLoops() {
165
- let dom = this.buildDominator();
166
- let loops = [];
167
- for (const header of this.nodes) {
168
- let innermost;
169
- let longest = 0;
170
- let backEdges = this.getBackEdges(dom, header);
171
- if (backEdges.size === 0) {
172
- continue;
173
- }
174
- if (this.isSelfLoopNode(header)) {
175
- loops.push(new Set([header]));
176
- }
177
- for (const start of backEdges) {
178
- let loop = this.naturalLoop(start, header);
179
- if (!innermost || loop.size > longest) {
180
- innermost = loop;
181
- longest = loop.size;
182
- }
183
- }
184
- loops.push(innermost);
185
- }
186
- loops.sort((a, b) => a.size - b.size);
187
- return loops;
188
- }
189
- buildDominator() {
190
- let domin = new Map();
191
- domin.set(this.entry, new Set([this.entry]));
192
- for (const node of this.nodes) {
193
- if (node !== this.entry) {
194
- domin.set(node, new Set(this.nodes));
195
- }
196
- }
197
- let change = true;
198
- while (change) {
199
- change = false;
200
- for (const node of this.nodes) {
201
- if (node === this.entry) {
202
- continue;
203
- }
204
- let t = new Set(domin.get(node));
205
- for (const p of node.getPred()) {
206
- t = this.setIntersect(t, domin.get(p));
207
- }
208
- t.add(node);
209
- if (!this.isSetEqual(t, domin.get(node))) {
210
- change = true;
211
- domin.set(node, t);
212
- }
213
- }
214
- }
215
- return domin;
216
- }
217
- getBackEdges(dom, header) {
218
- var _a;
219
- let backEdges = new Set();
220
- for (const n of header.getPred()) {
221
- // h dom n && n -> h
222
- if ((_a = dom.get(n)) === null || _a === void 0 ? void 0 : _a.has(header)) {
223
- backEdges.add(n);
224
- }
225
- }
226
- return backEdges;
227
- }
228
- naturalLoop(backEdgeStart, backEdgeEnd) {
229
- let stack = [];
230
- let loop = new Set([backEdgeEnd, backEdgeStart]);
231
- stack.push(backEdgeStart);
232
- while (stack.length > 0) {
233
- let m = stack.shift();
234
- for (const pred of m.getPred()) {
235
- if (loop.has(pred)) {
236
- continue;
237
- }
238
- loop.add(pred);
239
- stack.push(pred);
240
- }
241
- }
242
- return loop;
243
- }
244
- isSelfLoopNode(node) {
245
- let inSucc = false;
246
- let inPred = false;
247
- for (const pred of node.getPred()) {
248
- if (pred === node) {
249
- inPred = true;
250
- }
251
- }
252
- for (const succ of node.getSucc()) {
253
- if (succ === node) {
254
- inSucc = true;
255
- }
256
- }
257
- return inSucc && inPred;
258
- }
259
- isForLoopIncNode(node) {
260
- for (const loop of this.loopMap.values()) {
261
- if (loop.getType() === RegionType.FOR_LOOP_REGION) {
262
- if (node === loop.inc) {
263
- return true;
264
- }
265
- }
266
- }
267
- return false;
268
- }
269
- isValidInBlocks(node, scope) {
270
- if (this.isForLoopIncNode(node) || node.hasIfStmt()) {
271
- return false;
272
- }
273
- if (scope && !scope.has(node)) {
274
- return false;
275
- }
276
- return true;
277
- }
278
- isIfRegion(node, nodeSet) {
279
- nodeSet.clear();
280
- if (node.getSucc().length !== 2) {
281
- return false;
282
- }
283
- let m = node.getSucc()[0];
284
- let n = node.getSucc()[1];
285
- if (m.getSucc().length === 1 && m.getSucc()[0] === n) {
286
- nodeSet.add(node).add(m);
287
- return true;
288
- }
289
- return false;
290
- }
291
- isIfExitRegion(node, nodeSet) {
292
- nodeSet.clear();
293
- if (node.getSucc().length !== 2) {
294
- return false;
295
- }
296
- let m = node.getSucc()[0];
297
- if (m.hasReturnStmt()) {
298
- nodeSet.add(node).add(m);
299
- return true;
300
- }
301
- return false;
302
- }
303
- isIfElseRegion(node, nodeSet) {
304
- nodeSet.clear();
305
- if (node.getSucc().length !== 2) {
306
- return false;
307
- }
308
- let m = node.getSucc()[0];
309
- let n = node.getSucc()[1];
310
- if ((m.getSucc().length === 1 &&
311
- n.getSucc().length === 1 &&
312
- m.getPred().length === 1 &&
313
- n.getPred().length === 1 &&
314
- m.getSucc()[0] === n.getSucc()[0]) ||
315
- (m.getSucc().length === 0 && n.getSucc().length === 0)) {
316
- nodeSet.add(node).add(m).add(n);
317
- return true;
318
- }
319
- return false;
320
- }
321
- isBlockRegion(node, nodeSet, scope) {
322
- let n = node;
323
- let p = true;
324
- let s = n.getSucc().length === 1;
325
- nodeSet.clear();
326
- let blocks = [];
327
- while (p && s && !nodeSet.has(n) && this.isValidInBlocks(n, scope)) {
328
- nodeSet.add(n);
329
- blocks.push(n);
330
- n = n.getSucc()[0];
331
- p = n.getPred().length === 1;
332
- s = n.getSucc().length === 1;
333
- }
334
- if (p && this.isValidInBlocks(n, scope)) {
335
- if (!nodeSet.has(n)) {
336
- blocks.push(n);
337
- }
338
- nodeSet.add(n);
339
- }
340
- n = node;
341
- p = n.getPred().length === 1;
342
- s = true;
343
- while (p && s && this.isValidInBlocks(n, scope)) {
344
- if (!nodeSet.has(n)) {
345
- blocks.unshift(n);
346
- }
347
- nodeSet.add(n);
348
- n = n.getPred()[0];
349
- if (nodeSet.has(n)) {
350
- break;
351
- }
352
- p = n.getPred().length === 1;
353
- s = n.getSucc().length === 1;
354
- }
355
- if (s && this.isValidInBlocks(n, scope)) {
356
- if (!nodeSet.has(n)) {
357
- blocks.unshift(n);
358
- }
359
- nodeSet.add(n);
360
- }
361
- nodeSet.clear();
362
- for (const n of blocks) {
363
- nodeSet.add(n);
364
- }
365
- if (nodeSet.size >= 2) {
366
- return true;
367
- }
368
- return false;
369
- }
370
- isIfBreakRegion(node, nodeSet, loop) {
371
- let m = node.getSucc()[0];
372
- nodeSet.clear();
373
- if (this.isExitLoop(m, this.structBlocks.get(loop))) {
374
- nodeSet.add(node);
375
- return true;
376
- }
377
- if (m.getSucc().length === 1 && this.isExitLoop(m.getSucc()[0], this.structBlocks.get(loop))) {
378
- nodeSet.add(node).add(m);
379
- return true;
380
- }
381
- return false;
382
- }
383
- isIfContinueRegion(node, nodeSet, loop) {
384
- nodeSet.clear();
385
- let m = node.getSucc()[0];
386
- let n = node.getSucc()[1];
387
- if (loop.control.has(m)) {
388
- nodeSet.add(node);
389
- return true;
390
- }
391
- if (m.getSucc().length === 1 &&
392
- loop.control.has(m.getSucc()[0]) &&
393
- !loop.control.has(n) &&
394
- !this.isIfElseRegion(node, nodeSet)) {
395
- nodeSet.add(node).add(m);
396
- return true;
397
- }
398
- return false;
399
- }
400
- isWhileRegion(node, nodeSet, loop) {
401
- nodeSet.clear();
402
- let m = node.getSucc()[0];
403
- if (loop.header === node && m.getSucc().length === 1 && m.getPred().length === 1 && m.getSucc()[0] === node) {
404
- nodeSet.add(node).add(m);
405
- return true;
406
- }
407
- return false;
408
- }
409
- isForRegion(node, nodeSet, loop) {
410
- nodeSet.clear();
411
- if (loop.header === node && loop.getType() === RegionType.FOR_LOOP_REGION) {
412
- let forLoop = loop;
413
- let blocks = node.getSucc()[0];
414
- if (forLoop.inc.getPred().length === 1 &&
415
- forLoop.inc.getPred()[0] === blocks &&
416
- blocks.getSucc().length === 1) {
417
- nodeSet.add(node).add(forLoop.inc).add(blocks);
418
- return true;
419
- }
420
- }
421
- return false;
422
- }
423
- isDoWhileRegion(node, nodeSet, loop) {
424
- nodeSet.clear();
425
- if (loop.back === node && loop.getType() === RegionType.DO_WHILE_LOOP_REGION) {
426
- let blocks = node.getPred()[0];
427
- if (blocks.getSucc().length === 1 && blocks.getSucc()[0] === node && node.getSucc()[0] === blocks) {
428
- nodeSet.add(blocks).add(node);
429
- return true;
430
- }
431
- }
432
- return false;
433
- }
434
- identifyRegionType(node, nodeSet, scope) {
435
- if (this.isBlockRegion(node, nodeSet, scope)) {
436
- return RegionType.BLOCK_REGION;
437
- }
438
- let inLoop = false;
439
- let region = this.structOf.get(node);
440
- if (region && LOOP_TYPES.has(region === null || region === void 0 ? void 0 : region.getType())) {
441
- inLoop = true;
442
- }
443
- if (new Set(node.getPred()).has(node) && new Set(node.getSucc()).has(node)) {
444
- nodeSet.add(node);
445
- if (inLoop) {
446
- return region === null || region === void 0 ? void 0 : region.getType();
447
- }
448
- return RegionType.SELF_LOOP_REGION;
449
- }
450
- if (node.getSucc().length !== 2) {
451
- return undefined;
452
- }
453
- if (inLoop) {
454
- let loop = region;
455
- if (!loop.control.has(node)) {
456
- if (this.isIfBreakRegion(node, nodeSet, loop)) {
457
- return RegionType.IF_THEN_BREAK_REGION;
458
- }
459
- if (this.isIfContinueRegion(node, nodeSet, loop)) {
460
- return RegionType.IF_THEN_CONTINUE_REGION;
461
- }
462
- }
463
- if (this.isWhileRegion(node, nodeSet, loop)) {
464
- return RegionType.WHILE_LOOP_REGION;
465
- }
466
- if (this.isForRegion(node, nodeSet, loop)) {
467
- return RegionType.FOR_LOOP_REGION;
468
- }
469
- if (this.isDoWhileRegion(node, nodeSet, loop)) {
470
- return RegionType.DO_WHILE_LOOP_REGION;
471
- }
472
- }
473
- // check for if
474
- if (this.isIfExitRegion(node, nodeSet)) {
475
- return RegionType.IF_THEN_EXIT_REGION;
476
- }
477
- if (this.isIfRegion(node, nodeSet)) {
478
- return RegionType.IF_REGION;
479
- }
480
- // check for an if else
481
- if (this.isIfElseRegion(node, nodeSet)) {
482
- return RegionType.IF_ELSE_REGION;
483
- }
484
- return undefined;
485
- }
486
- cyclicRegionType(nodeSet) {
487
- var _a, _b, _c;
488
- let nodes = Array.from(nodeSet);
489
- let header = nodes[0];
490
- if (nodeSet.size === 1) {
491
- let tail = (_a = nodes[0].getBlock()) === null || _a === void 0 ? void 0 : _a.getTail();
492
- if (tail instanceof Stmt_1.ArkIfStmt) {
493
- return RegionType.DO_WHILE_LOOP_REGION;
494
- }
495
- return RegionType.WHILE_LOOP_REGION;
496
- }
497
- let back = nodes[1];
498
- // exit loop from back
499
- if (!this.hasExitLoopSucc(header, nodeSet) && this.hasExitLoopSucc(back, nodeSet)) {
500
- return RegionType.DO_WHILE_LOOP_REGION;
501
- }
502
- if (this.hasExitLoopSucc(header, nodeSet) && this.hasExitLoopSucc(back, nodeSet)) {
503
- // header true exit loop --> exit is break
504
- if (!nodeSet.has(header.getSucc()[0])) {
505
- return RegionType.DO_WHILE_LOOP_REGION;
506
- }
507
- }
508
- // for
509
- if (back.getSucc().length === 1 && ((_c = (_b = back.getBlock()) === null || _b === void 0 ? void 0 : _b.getStmts()) === null || _c === void 0 ? void 0 : _c.length) === 1) {
510
- let isForLoop = true;
511
- for (const pred of header.getPred()) {
512
- if (nodeSet.has(pred) && pred !== back) {
513
- isForLoop = false;
514
- }
515
- }
516
- if (isForLoop) {
517
- return RegionType.FOR_LOOP_REGION;
518
- }
519
- }
520
- return RegionType.WHILE_LOOP_REGION;
521
- }
522
- hasExitLoopSucc(node, nodeSet) {
523
- for (const succ of node.getSucc()) {
524
- if (!nodeSet.has(succ)) {
525
- return true;
526
- }
527
- }
528
- return false;
529
- }
530
- isExitLoop(node, nodeSet) {
531
- if (this.structBlocks.has(node)) {
532
- for (const n of this.structBlocks.get(node)) {
533
- if (!nodeSet.has(n)) {
534
- return true;
535
- }
536
- }
537
- }
538
- else {
539
- if (!nodeSet.has(node)) {
540
- return true;
541
- }
542
- }
543
- return false;
544
- }
545
- createRegion(rtype, nodeSet) {
546
- let node;
547
- if (rtype === RegionType.BLOCK_REGION) {
548
- node = new BlockRegion(nodeSet);
549
- }
550
- else if (rtype === RegionType.IF_ELSE_REGION) {
551
- node = new IfElseRegion(nodeSet);
552
- }
553
- else if (rtype === RegionType.IF_REGION) {
554
- node = new IfRegion(nodeSet);
555
- }
556
- else if (rtype === RegionType.IF_THEN_EXIT_REGION) {
557
- node = new IfExitRegion(nodeSet);
558
- }
559
- else if (rtype === RegionType.IF_THEN_BREAK_REGION) {
560
- node = new IfBreakRegion(nodeSet);
561
- }
562
- else if (rtype === RegionType.IF_THEN_CONTINUE_REGION) {
563
- node = new IfContinueRegion(nodeSet);
564
- }
565
- else if (rtype === RegionType.SELF_LOOP_REGION) {
566
- node = new SelfLoopRegion(nodeSet);
567
- }
568
- else if (rtype === RegionType.WHILE_LOOP_REGION) {
569
- let whileLoop = new WhileLoopRegion(nodeSet);
570
- this.loopMap.set(whileLoop.header, whileLoop);
571
- node = whileLoop;
572
- }
573
- else if (rtype === RegionType.FOR_LOOP_REGION) {
574
- let forLoop = new ForLoopRegion(nodeSet);
575
- this.loopMap.set(forLoop.header, forLoop);
576
- node = forLoop;
577
- }
578
- else if (rtype === RegionType.DO_WHILE_LOOP_REGION) {
579
- let doWhileLoop = new DoWhileLoopRegion(nodeSet);
580
- this.loopMap.set(doWhileLoop.header, doWhileLoop);
581
- node = doWhileLoop;
582
- }
583
- else if (rtype === RegionType.TRY_CATCH_REGION ||
584
- rtype === RegionType.TRY_FINALLY_REGION ||
585
- rtype === RegionType.TRY_CATCH_FINALLY_REGION) {
586
- node = new TrapRegion(nodeSet, rtype);
587
- }
588
- return node;
589
- }
590
- reduce(rtype, nodeSet) {
591
- let region = this.createRegion(rtype, nodeSet);
592
- region === null || region === void 0 ? void 0 : region.replace();
593
- if (region) {
594
- this.structTypes.set(region, rtype);
595
- let blocks = new Set();
596
- for (const s of nodeSet) {
597
- this.structOf.set(s, region);
598
- if (this.structBlocks.has(s)) {
599
- for (const b of this.structBlocks.get(s)) {
600
- blocks.add(b);
601
- }
602
- }
603
- else {
604
- blocks.add(s);
605
- }
606
- }
607
- this.structBlocks.set(region, blocks);
608
- }
609
- return region;
610
- }
611
- setIntersect(a, b) {
612
- let r = new Set();
613
- if (!b) {
614
- return r;
615
- }
616
- for (const n of b) {
617
- if (a.has(n)) {
618
- r.add(n);
619
- }
620
- }
621
- return r;
622
- }
623
- isSetEqual(a, b) {
624
- if (a.size !== b.size) {
625
- return false;
626
- }
627
- return this.setIntersect(a, b).size === a.size;
628
- }
629
- buildTrap(traps) {
630
- if (!traps) {
631
- return [];
632
- }
633
- traps.sort((a, b) => a.getTryBlocks().length +
634
- a.getCatchBlocks().length -
635
- (b.getTryBlocks().length + b.getCatchBlocks().length));
636
- let trapRegions = [];
637
- for (const trap of traps) {
638
- let region = new NaturalTrapRegion(trap, this.block2NodeMap);
639
- let findTrapRegion = this.getNaturalTrapRegion(region);
640
- if (!findTrapRegion) {
641
- for (const n of region.getNodes()) {
642
- this.structOf.set(n, region);
643
- }
644
- trapRegions.push(region);
645
- continue;
646
- }
647
- if (findTrapRegion.type === RegionType.TRY_FINALLY_REGION) {
648
- findTrapRegion.trySet = region.trySet;
649
- findTrapRegion.catchSet = region.catchSet;
650
- region = findTrapRegion;
651
- }
652
- else {
653
- findTrapRegion.finallySet = region.finallySet;
654
- region = findTrapRegion;
655
- }
656
- for (const n of region.getNodes()) {
657
- this.structOf.set(n, region);
658
- }
659
- region.type = RegionType.TRY_CATCH_FINALLY_REGION;
660
- }
661
- this.structOf.clear();
662
- return trapRegions;
663
- }
664
- searchTrapFinallyNodes(trapRegions) {
665
- // search finally
666
- for (const region of trapRegions) {
667
- if (region.type === RegionType.TRY_CATCH_REGION) {
668
- continue;
669
- }
670
- this.bfs(region);
671
- }
672
- }
673
- bfs(region) {
674
- let finallyNodes = new Set();
675
- let count = region.finallySet.size;
676
- let queue = [region.getSucc()[0]];
677
- while (queue.length > 0 && finallyNodes.size < count) {
678
- let node = queue[0];
679
- queue.splice(0, 1);
680
- finallyNodes.add(node);
681
- region.identifyFinallySet.add(node);
682
- for (const succ of node.getSucc()) {
683
- if (!finallyNodes.has(succ)) {
684
- queue.push(succ);
685
- }
686
- }
687
- }
688
- }
689
- getNaturalTrapRegion(trap) {
690
- let findTrap = this.findNaturalTrapRegion(trap.trySet);
691
- if (findTrap) {
692
- return findTrap;
693
- }
694
- if (trap.catchSet) {
695
- findTrap = this.findNaturalTrapRegion(trap.catchSet);
696
- }
697
- if (findTrap) {
698
- return findTrap;
699
- }
700
- if (trap.finallySet) {
701
- findTrap = this.findNaturalTrapRegion(trap.finallySet);
702
- }
703
- return findTrap;
704
- }
705
- findNaturalTrapRegion(nodes) {
706
- let findTrap;
707
- for (const node of nodes) {
708
- if (!this.structOf.has(node)) {
709
- return undefined;
710
- }
711
- if (!findTrap) {
712
- findTrap = this.structOf.get(node);
713
- continue;
714
- }
715
- if (findTrap !== this.structOf.get(node)) {
716
- return undefined;
717
- }
718
- }
719
- return findTrap;
720
- }
721
- trapsStructuralAnalysis(trapRegions) {
722
- trapRegions.sort((a, b) => a.size() - b.size());
723
- for (const trap of trapRegions) {
724
- let tryNode = this.trapsSubStructuralAnalysis(trap.trySet);
725
- let catchNode = this.trapsSubStructuralAnalysis(trap.catchSet);
726
- let finnallyNode = this.trapsSubStructuralAnalysis(trap.identifyFinallySet);
727
- if (catchNode === undefined) {
728
- this.reduce(RegionType.TRY_FINALLY_REGION, new Set([tryNode, finnallyNode]));
729
- }
730
- else if (finnallyNode === undefined) {
731
- this.reduce(RegionType.TRY_CATCH_REGION, new Set([tryNode, catchNode]));
732
- }
733
- else {
734
- this.reduce(RegionType.TRY_CATCH_FINALLY_REGION, new Set([tryNode, catchNode, finnallyNode]));
735
- }
736
- }
737
- }
738
- trapsSubStructuralAnalysis(nodes) {
739
- if (!nodes) {
740
- return undefined;
741
- }
742
- let entry = Array.from(nodes)[0];
743
- if (nodes.size <= 1) {
744
- return entry;
745
- }
746
- for (const node of nodes) {
747
- if (this.structOf.has(node)) {
748
- nodes.add(this.structOf.get(node));
749
- }
750
- }
751
- return this.structuralAnalysis(entry, nodes);
752
- }
753
- }
754
- exports.AbstractFlowGraph = AbstractFlowGraph;
755
- var RegionType;
756
- (function (RegionType) {
757
- RegionType[RegionType["ABSTRACT_NODE"] = 0] = "ABSTRACT_NODE";
758
- RegionType[RegionType["TRY_NODE"] = 1] = "TRY_NODE";
759
- RegionType[RegionType["CATCH_NODE"] = 2] = "CATCH_NODE";
760
- RegionType[RegionType["FINALLY_NODE"] = 3] = "FINALLY_NODE";
761
- /* Sequence of blocks. */
762
- RegionType[RegionType["BLOCK_REGION"] = 4] = "BLOCK_REGION";
763
- RegionType[RegionType["IF_REGION"] = 5] = "IF_REGION";
764
- RegionType[RegionType["IF_ELSE_REGION"] = 6] = "IF_ELSE_REGION";
765
- RegionType[RegionType["IF_THEN_EXIT_REGION"] = 7] = "IF_THEN_EXIT_REGION";
766
- RegionType[RegionType["IF_THEN_BREAK_REGION"] = 8] = "IF_THEN_BREAK_REGION";
767
- RegionType[RegionType["IF_THEN_CONTINUE_REGION"] = 9] = "IF_THEN_CONTINUE_REGION";
768
- RegionType[RegionType["SELF_LOOP_REGION"] = 10] = "SELF_LOOP_REGION";
769
- RegionType[RegionType["NATURAL_LOOP_REGION"] = 11] = "NATURAL_LOOP_REGION";
770
- RegionType[RegionType["WHILE_LOOP_REGION"] = 12] = "WHILE_LOOP_REGION";
771
- RegionType[RegionType["DO_WHILE_LOOP_REGION"] = 13] = "DO_WHILE_LOOP_REGION";
772
- RegionType[RegionType["FOR_LOOP_REGION"] = 14] = "FOR_LOOP_REGION";
773
- RegionType[RegionType["CASE_REGION"] = 15] = "CASE_REGION";
774
- RegionType[RegionType["SWITCH_REGION"] = 16] = "SWITCH_REGION";
775
- RegionType[RegionType["TRY_CATCH_REGION"] = 17] = "TRY_CATCH_REGION";
776
- RegionType[RegionType["TRY_FINALLY_REGION"] = 18] = "TRY_FINALLY_REGION";
777
- RegionType[RegionType["TRY_CATCH_FINALLY_REGION"] = 19] = "TRY_CATCH_FINALLY_REGION";
778
- })(RegionType || (RegionType = {}));
779
- const LOOP_TYPES = new Set([
780
- RegionType.SELF_LOOP_REGION,
781
- RegionType.NATURAL_LOOP_REGION,
782
- RegionType.WHILE_LOOP_REGION,
783
- RegionType.FOR_LOOP_REGION,
784
- RegionType.DO_WHILE_LOOP_REGION,
785
- ]);
786
- class AbstractNode {
787
- constructor() {
788
- this.predNodes = [];
789
- this.succNodes = [];
790
- this.type = RegionType.ABSTRACT_NODE;
791
- }
792
- traversal(callback, type) {
793
- callback(this.bb, type);
794
- }
795
- getType() {
796
- return this.type;
797
- }
798
- getSucc() {
799
- return this.succNodes;
800
- }
801
- addSucc(node) {
802
- this.succNodes.push(node);
803
- }
804
- replaceSucc(src, dst) {
805
- for (let i = 0; i < this.succNodes.length; i++) {
806
- if (this.succNodes[i] === src) {
807
- this.succNodes[i] = dst;
808
- break;
809
- }
810
- }
811
- }
812
- removeSucc(src) {
813
- for (let i = 0; i < this.predNodes.length; i++) {
814
- if (this.succNodes[i] === src) {
815
- this.succNodes.splice(i, 1);
816
- break;
817
- }
818
- }
819
- }
820
- getPred() {
821
- return this.predNodes;
822
- }
823
- addPred(block) {
824
- let set = new Set(this.predNodes);
825
- if (set.has(block)) {
826
- return;
827
- }
828
- this.predNodes.push(block);
829
- }
830
- replacePred(src, dst) {
831
- for (let i = 0; i < this.predNodes.length; i++) {
832
- if (this.predNodes[i] === src) {
833
- this.predNodes[i] = dst;
834
- break;
835
- }
836
- }
837
- }
838
- removePred(src) {
839
- for (let i = 0; i < this.predNodes.length; i++) {
840
- if (this.predNodes[i] === src) {
841
- this.predNodes.splice(i, 1);
842
- break;
843
- }
844
- }
845
- }
846
- setBlock(bb) {
847
- this.bb = bb;
848
- }
849
- getBlock() {
850
- return this.bb;
851
- }
852
- hasIfStmt() {
853
- if (!this.bb) {
854
- return false;
855
- }
856
- for (let stmt of this.bb.getStmts()) {
857
- if (stmt instanceof Stmt_1.ArkIfStmt) {
858
- return true;
859
- }
860
- }
861
- return false;
862
- }
863
- hasReturnStmt() {
864
- if (!this.bb) {
865
- return false;
866
- }
867
- for (let stmt of this.bb.getStmts()) {
868
- if (stmt instanceof Stmt_1.ArkReturnStmt) {
869
- return true;
870
- }
871
- }
872
- return false;
873
- }
874
- }
875
- class Region extends AbstractNode {
876
- constructor(nset, type) {
877
- super();
878
- this.nset = nset;
879
- this.type = type;
880
- }
881
- getBlock() {
882
- if (this.nset.size === 0) {
883
- return undefined;
884
- }
885
- return Array.from(this.nset)[0].getBlock();
886
- }
887
- }
888
- class BlockRegion extends Region {
889
- constructor(nset) {
890
- super(nset, RegionType.BLOCK_REGION);
891
- this.blocks = Array.from(nset);
892
- }
893
- replace() {
894
- for (let pred of this.blocks[0].getPred()) {
895
- pred.replaceSucc(this.blocks[0], this);
896
- this.addPred(pred);
897
- }
898
- for (let succ of this.blocks[this.blocks.length - 1].getSucc()) {
899
- succ.replacePred(this.blocks[this.blocks.length - 1], this);
900
- this.addSucc(succ);
901
- }
902
- }
903
- traversal(callback) {
904
- for (const node of this.blocks) {
905
- node.traversal(callback, CodeBlockType.NORMAL);
906
- }
907
- }
908
- }
909
- class NaturalLoopRegion extends Region {
910
- constructor(nset, type = RegionType.NATURAL_LOOP_REGION) {
911
- super(nset, type);
912
- let nodes = Array.from(nset);
913
- this.header = nodes[0];
914
- if (nset.size > 1) {
915
- this.back = nodes[1];
916
- }
917
- else {
918
- this.back = nodes[0];
919
- }
920
- this.control = new Set([this.header]);
921
- }
922
- replace() {
923
- for (let pred of this.header.getPred()) {
924
- if (!this.nset.has(pred)) {
925
- pred.replaceSucc(this.header, this);
926
- this.addPred(pred);
927
- }
928
- }
929
- let succNodes = new Set();
930
- for (let node of this.nset) {
931
- for (let succ of node.getSucc()) {
932
- if (!this.nset.has(succ)) {
933
- succNodes.add(succ);
934
- }
935
- }
936
- }
937
- if (succNodes.size === 0) {
938
- return;
939
- }
940
- let pred = Array.from(succNodes)[0];
941
- let replaced = false;
942
- for (let succ of pred.getPred()) {
943
- if (this.nset.has(succ)) {
944
- if (!replaced) {
945
- pred.replacePred(succ, this);
946
- this.addSucc(pred);
947
- replaced = true;
948
- }
949
- else {
950
- pred.removePred(succ);
951
- }
952
- }
953
- }
954
- }
955
- revise() {
956
- // add node to loop sets
957
- for (const node of this.nset) {
958
- for (const succ of node.getSucc()) {
959
- if (!this.nset.has(succ) &&
960
- succ !== this.getExitNode() &&
961
- succ.getSucc().length === 1 &&
962
- succ.getSucc()[0] === this.getExitNode()) {
963
- this.nset.add(succ);
964
- }
965
- }
966
- }
967
- }
968
- }
969
- class SelfLoopRegion extends NaturalLoopRegion {
970
- constructor(nset) {
971
- super(nset, RegionType.SELF_LOOP_REGION);
972
- this.back = this.header;
973
- }
974
- replace() {
975
- for (let pred of this.header.getPred()) {
976
- if (pred !== this.header) {
977
- pred.replaceSucc(this.header, this);
978
- this.addPred(pred);
979
- }
980
- }
981
- for (let succ of this.header.getSucc()) {
982
- if (succ !== this.header) {
983
- succ.replacePred(this.header, this);
984
- this.addSucc(succ);
985
- }
986
- }
987
- }
988
- getExitNode() {
989
- return this.header.getSucc()[1];
990
- }
991
- }
992
- class WhileLoopRegion extends NaturalLoopRegion {
993
- constructor(nset) {
994
- super(nset, RegionType.WHILE_LOOP_REGION);
995
- }
996
- traversal(callback) {
997
- this.header.traversal(callback, CodeBlockType.WHILE);
998
- if (this.header !== this.back) {
999
- this.back.traversal(callback, CodeBlockType.NORMAL);
1000
- }
1001
- callback(undefined, CodeBlockType.COMPOUND_END);
1002
- }
1003
- getExitNode() {
1004
- return this.header.getSucc()[1];
1005
- }
1006
- }
1007
- class DoWhileLoopRegion extends NaturalLoopRegion {
1008
- constructor(nset) {
1009
- super(nset, RegionType.DO_WHILE_LOOP_REGION);
1010
- this.control.clear();
1011
- this.control.add(this.back);
1012
- }
1013
- traversal(callback) {
1014
- callback(undefined, CodeBlockType.DO);
1015
- if (this.header !== this.back) {
1016
- this.header.traversal(callback, CodeBlockType.NORMAL);
1017
- }
1018
- this.back.traversal(callback, CodeBlockType.DO_WHILE);
1019
- }
1020
- getExitNode() {
1021
- return this.back.getSucc()[1];
1022
- }
1023
- }
1024
- class ForLoopRegion extends NaturalLoopRegion {
1025
- constructor(nset) {
1026
- super(nset, RegionType.FOR_LOOP_REGION);
1027
- this.inc = this.back;
1028
- this.control.add(this.inc);
1029
- }
1030
- traversal(callback) {
1031
- this.header.traversal(callback, CodeBlockType.FOR);
1032
- for (const node of this.nset) {
1033
- if (node !== this.header && node !== this.inc) {
1034
- node.traversal(callback, CodeBlockType.NORMAL);
1035
- }
1036
- }
1037
- callback(undefined, CodeBlockType.COMPOUND_END);
1038
- }
1039
- getExitNode() {
1040
- return this.header.getSucc()[1];
1041
- }
1042
- }
1043
- class IfRegion extends Region {
1044
- constructor(nset) {
1045
- super(nset, RegionType.IF_REGION);
1046
- let nodes = Array.from(nset);
1047
- this.contition = nodes[0];
1048
- this.then = nodes[1];
1049
- }
1050
- replace() {
1051
- this.replaceContitionPred();
1052
- for (let succ of this.then.getSucc()) {
1053
- if (succ !== this.then) {
1054
- succ.replacePred(this.then, this);
1055
- succ.removePred(this.contition);
1056
- this.addSucc(succ);
1057
- }
1058
- }
1059
- }
1060
- traversal(callback) {
1061
- this.contition.traversal(callback, CodeBlockType.IF);
1062
- this.then.traversal(callback, CodeBlockType.NORMAL);
1063
- callback(undefined, CodeBlockType.COMPOUND_END);
1064
- }
1065
- replaceContitionPred() {
1066
- for (let pred of this.contition.getPred()) {
1067
- if (pred !== this.contition) {
1068
- pred.replaceSucc(this.contition, this);
1069
- this.addPred(pred);
1070
- }
1071
- }
1072
- }
1073
- }
1074
- class IfExitRegion extends IfRegion {
1075
- constructor(nset) {
1076
- super(nset);
1077
- this.type = RegionType.IF_THEN_EXIT_REGION;
1078
- }
1079
- replace() {
1080
- this.replaceContitionPred();
1081
- let succ = this.contition.getSucc()[1];
1082
- succ.replacePred(this.contition, this);
1083
- this.addSucc(succ);
1084
- }
1085
- }
1086
- class IfBreakRegion extends IfRegion {
1087
- constructor(nset) {
1088
- super(nset);
1089
- this.type = RegionType.IF_THEN_BREAK_REGION;
1090
- }
1091
- replace() {
1092
- this.replaceContitionPred();
1093
- let succ = this.contition.getSucc()[1];
1094
- succ.replacePred(this.contition, this);
1095
- this.addSucc(succ);
1096
- if (this.then) {
1097
- succ = this.then.getSucc()[0];
1098
- succ.removePred(this.then);
1099
- }
1100
- else {
1101
- succ = this.contition.getSucc()[0];
1102
- succ.removePred(this.contition);
1103
- }
1104
- }
1105
- traversal(callback) {
1106
- var _a;
1107
- this.contition.traversal(callback, CodeBlockType.IF);
1108
- (_a = this.then) === null || _a === void 0 ? void 0 : _a.traversal(callback, CodeBlockType.NORMAL);
1109
- callback(undefined, CodeBlockType.BREAK);
1110
- callback(undefined, CodeBlockType.COMPOUND_END);
1111
- }
1112
- }
1113
- class IfContinueRegion extends IfBreakRegion {
1114
- constructor(nset) {
1115
- super(nset);
1116
- this.type = RegionType.IF_THEN_CONTINUE_REGION;
1117
- }
1118
- traversal(callback) {
1119
- var _a;
1120
- this.contition.traversal(callback, CodeBlockType.IF);
1121
- (_a = this.then) === null || _a === void 0 ? void 0 : _a.traversal(callback, CodeBlockType.NORMAL);
1122
- callback(undefined, CodeBlockType.CONTINUE);
1123
- callback(undefined, CodeBlockType.COMPOUND_END);
1124
- }
1125
- }
1126
- class IfElseRegion extends Region {
1127
- constructor(nset) {
1128
- super(nset, RegionType.IF_ELSE_REGION);
1129
- let nodes = Array.from(nset);
1130
- this.contition = nodes[0];
1131
- this.then = nodes[1];
1132
- this.else = nodes[2];
1133
- }
1134
- replace() {
1135
- for (let pred of this.contition.getPred()) {
1136
- if (pred !== this.contition) {
1137
- pred.replaceSucc(this.contition, this);
1138
- this.addPred(pred);
1139
- }
1140
- }
1141
- for (let succ of this.then.getSucc()) {
1142
- if (succ !== this.then) {
1143
- succ.replacePred(this.then, this);
1144
- succ.removePred(this.else);
1145
- this.addSucc(succ);
1146
- }
1147
- }
1148
- }
1149
- traversal(callback) {
1150
- this.contition.traversal(callback, CodeBlockType.IF);
1151
- this.then.traversal(callback, CodeBlockType.NORMAL);
1152
- callback(undefined, CodeBlockType.ELSE);
1153
- this.else.traversal(callback, CodeBlockType.NORMAL);
1154
- callback(undefined, CodeBlockType.COMPOUND_END);
1155
- }
1156
- }
1157
- class TrapRegion extends Region {
1158
- constructor(nset, type) {
1159
- super(nset, type);
1160
- let nodes = Array.from(nset);
1161
- this.tryNode = nodes[0];
1162
- if (type === RegionType.TRY_CATCH_REGION) {
1163
- this.catchNode = nodes[1];
1164
- }
1165
- else if (type === RegionType.TRY_FINALLY_REGION) {
1166
- this.finallyNode = nodes[1];
1167
- }
1168
- else {
1169
- this.catchNode = nodes[1];
1170
- this.finallyNode = nodes[2];
1171
- }
1172
- }
1173
- replace() {
1174
- for (let pred of this.tryNode.getPred()) {
1175
- if (pred !== this.tryNode) {
1176
- pred.replaceSucc(this.tryNode, this);
1177
- this.addPred(pred);
1178
- }
1179
- }
1180
- if (this.finallyNode) {
1181
- for (let succ of this.finallyNode.getSucc()) {
1182
- if (succ !== this.finallyNode) {
1183
- succ.replacePred(this.finallyNode, this);
1184
- this.addSucc(succ);
1185
- }
1186
- }
1187
- }
1188
- else {
1189
- for (let succ of this.tryNode.getSucc()) {
1190
- if (succ !== this.tryNode) {
1191
- succ.replacePred(this.tryNode, this);
1192
- this.addSucc(succ);
1193
- }
1194
- }
1195
- }
1196
- }
1197
- traversal(callback) {
1198
- var _a, _b;
1199
- callback(undefined, CodeBlockType.TRY);
1200
- this.tryNode.traversal(callback, CodeBlockType.NORMAL);
1201
- if (this.catchNode) {
1202
- callback(this.catchNode.getBlock(), CodeBlockType.CATCH);
1203
- (_a = this.catchNode) === null || _a === void 0 ? void 0 : _a.traversal(callback, CodeBlockType.NORMAL);
1204
- }
1205
- if (this.finallyNode) {
1206
- callback(undefined, CodeBlockType.FINALLY);
1207
- (_b = this.finallyNode) === null || _b === void 0 ? void 0 : _b.traversal(callback, CodeBlockType.NORMAL);
1208
- }
1209
- callback(undefined, CodeBlockType.COMPOUND_END);
1210
- }
1211
- }
1212
- class NaturalTrapRegion extends Region {
1213
- constructor(trap, block2NodeMap) {
1214
- super(new Set(), RegionType.TRY_CATCH_FINALLY_REGION);
1215
- this.trySet = new Set();
1216
- this.catchSet = new Set();
1217
- this.identifyFinallySet = new Set();
1218
- for (const block of trap.getTryBlocks()) {
1219
- this.trySet.add(block2NodeMap.get(block));
1220
- }
1221
- for (const block of trap.getCatchBlocks()) {
1222
- this.catchSet.add(block2NodeMap.get(block));
1223
- }
1224
- if (this.isFinallyNode(Array.from(this.catchSet)[this.catchSet.size - 1])) {
1225
- this.type = RegionType.TRY_FINALLY_REGION;
1226
- this.finallySet = this.catchSet;
1227
- this.catchSet = undefined;
1228
- }
1229
- else {
1230
- this.type = RegionType.TRY_CATCH_REGION;
1231
- }
1232
- }
1233
- isFinallyNode(node) {
1234
- let block = node.getBlock();
1235
- if (!block) {
1236
- return false;
1237
- }
1238
- let stmtLen = block.getStmts().length;
1239
- if (stmtLen < 1) {
1240
- return false;
1241
- }
1242
- let stmtLast = block.getStmts()[stmtLen - 1];
1243
- return stmtLast instanceof Stmt_1.ArkThrowStmt;
1244
- }
1245
- size() {
1246
- let size = this.trySet.size;
1247
- if (this.catchSet) {
1248
- size += this.catchSet.size;
1249
- }
1250
- if (this.finallySet) {
1251
- size += this.finallySet.size;
1252
- }
1253
- return size;
1254
- }
1255
- replace() { }
1256
- getNodes() {
1257
- let nodes = Array.from(this.trySet);
1258
- if (this.catchSet) {
1259
- nodes.push(...this.catchSet);
1260
- }
1261
- if (this.finallySet) {
1262
- nodes.push(...this.finallySet);
1263
- }
1264
- return nodes;
1265
- }
1266
- getSucc() {
1267
- let succ = new Set();
1268
- for (const node of this.trySet) {
1269
- for (const s of node.getSucc()) {
1270
- if (!this.trySet.has(s)) {
1271
- succ.add(s);
1272
- }
1273
- }
1274
- }
1275
- return Array.from(succ);
1276
- }
1277
- }
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2024 Huawei Device Co., Ltd.
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.AbstractFlowGraph = exports.CodeBlockType = void 0;
18
+ const Stmt_1 = require("../core/base/Stmt");
19
+ var CodeBlockType;
20
+ (function (CodeBlockType) {
21
+ CodeBlockType[CodeBlockType["NORMAL"] = 0] = "NORMAL";
22
+ CodeBlockType[CodeBlockType["IF"] = 1] = "IF";
23
+ CodeBlockType[CodeBlockType["ELSE"] = 2] = "ELSE";
24
+ CodeBlockType[CodeBlockType["BREAK"] = 3] = "BREAK";
25
+ CodeBlockType[CodeBlockType["CONTINUE"] = 4] = "CONTINUE";
26
+ CodeBlockType[CodeBlockType["DO"] = 5] = "DO";
27
+ CodeBlockType[CodeBlockType["DO_WHILE"] = 6] = "DO_WHILE";
28
+ CodeBlockType[CodeBlockType["WHILE"] = 7] = "WHILE";
29
+ CodeBlockType[CodeBlockType["FOR"] = 8] = "FOR";
30
+ CodeBlockType[CodeBlockType["COMPOUND_END"] = 9] = "COMPOUND_END";
31
+ CodeBlockType[CodeBlockType["TRY"] = 10] = "TRY";
32
+ CodeBlockType[CodeBlockType["CATCH"] = 11] = "CATCH";
33
+ CodeBlockType[CodeBlockType["FINALLY"] = 12] = "FINALLY";
34
+ })(CodeBlockType = exports.CodeBlockType || (exports.CodeBlockType = {}));
35
+ class AbstractFlowGraph {
36
+ constructor(cfg, traps) {
37
+ this.nodes = [];
38
+ this.structOf = new Map();
39
+ this.structTypes = new Map();
40
+ this.structBlocks = new Map();
41
+ this.loopMap = new Map();
42
+ this.block2NodeMap = new Map();
43
+ for (const bb of cfg.getBlocks()) {
44
+ let an = new AbstractNode();
45
+ an.setBlock(bb);
46
+ this.block2NodeMap.set(bb, an);
47
+ }
48
+ for (const bb of cfg.getBlocks()) {
49
+ let an = this.block2NodeMap.get(bb);
50
+ for (const succ of bb.getSuccessors()) {
51
+ an.addSucc(this.block2NodeMap.get(succ));
52
+ }
53
+ for (const pred of bb.getPredecessors()) {
54
+ an.addPred(this.block2NodeMap.get(pred));
55
+ }
56
+ }
57
+ let trapRegions = this.buildTrap(traps);
58
+ this.searchTrapFinallyNodes(trapRegions);
59
+ this.trapsStructuralAnalysis(trapRegions);
60
+ this.entry = this.block2NodeMap.get(cfg.getStartingBlock());
61
+ this.entry = this.structuralAnalysis(this.entry);
62
+ }
63
+ getEntry() {
64
+ return this.entry;
65
+ }
66
+ getForIncBlock(block) {
67
+ let node = this.block2NodeMap.get(block);
68
+ let loop = this.loopMap.get(node);
69
+ return loop.inc.getBlock();
70
+ }
71
+ preOrder(node, callback, visitor = new Set()) {
72
+ visitor.add(node);
73
+ node.traversal(callback, CodeBlockType.NORMAL);
74
+ for (const succ of node.getSucc()) {
75
+ if (!visitor.has(succ)) {
76
+ this.preOrder(succ, callback, visitor);
77
+ }
78
+ }
79
+ }
80
+ structuralAnalysis(entry, scope) {
81
+ let preds = entry.getPred();
82
+ let entryBak = entry;
83
+ this.nodes = this.dfsPostOrder(entry, scope);
84
+ this.entry = entry;
85
+ this.buildCyclicStructural();
86
+ // acyclic structural
87
+ let postMax = this.nodes.length;
88
+ let change = true;
89
+ while (postMax > 1 && change) {
90
+ change = false;
91
+ for (let i = 0; i < postMax; i++) {
92
+ let node = this.nodes[i];
93
+ let nset = new Set();
94
+ let rtype = this.identifyRegionType(node, nset, scope);
95
+ if (!rtype) {
96
+ continue;
97
+ }
98
+ let p = this.reduce(rtype, nset);
99
+ if (!p) {
100
+ continue;
101
+ }
102
+ scope === null || scope === void 0 ? void 0 : scope.add(p);
103
+ if (nset.has(entry)) {
104
+ entry = p;
105
+ }
106
+ this.nodes = this.dfsPostOrder(entry, scope);
107
+ change = postMax !== this.nodes.length;
108
+ postMax = this.nodes.length;
109
+ }
110
+ }
111
+ for (const pred of preds) {
112
+ pred.replaceSucc(entryBak, entry);
113
+ entry.addPred(pred);
114
+ }
115
+ return entry;
116
+ }
117
+ dfsPostOrder(node, scope, visitor = new Set(), postOrder = []) {
118
+ visitor.add(node);
119
+ for (const succ of node.getSucc()) {
120
+ if (visitor.has(succ)) {
121
+ continue;
122
+ }
123
+ if (scope && !scope.has(succ)) {
124
+ continue;
125
+ }
126
+ this.dfsPostOrder(succ, scope, visitor, postOrder);
127
+ }
128
+ postOrder.push(node);
129
+ return postOrder;
130
+ }
131
+ buildCyclicStructural() {
132
+ for (const loop of this.prepareBuildLoops()) {
133
+ let nset = new Set();
134
+ for (const n of loop) {
135
+ if (this.structOf.has(n)) {
136
+ nset.add(this.structOf.get(n));
137
+ }
138
+ else {
139
+ nset.add(n);
140
+ }
141
+ }
142
+ let rtype = this.cyclicRegionType(nset);
143
+ let region = this.createRegion(rtype, nset);
144
+ region.revise();
145
+ this.structTypes.set(region, rtype);
146
+ let blocks = new Set();
147
+ for (const s of nset) {
148
+ if (!this.structOf.has(s)) {
149
+ this.structOf.set(s, region);
150
+ }
151
+ if (this.structBlocks.has(s)) {
152
+ for (const b of this.structBlocks.get(s)) {
153
+ blocks.add(b);
154
+ }
155
+ }
156
+ else {
157
+ blocks.add(s);
158
+ }
159
+ }
160
+ this.structBlocks.set(region, blocks);
161
+ this.loopMap.set(region.header, region);
162
+ }
163
+ }
164
+ prepareBuildLoops() {
165
+ let dom = this.buildDominator();
166
+ let loops = [];
167
+ for (const header of this.nodes) {
168
+ let innermost;
169
+ let longest = 0;
170
+ let backEdges = this.getBackEdges(dom, header);
171
+ if (backEdges.size === 0) {
172
+ continue;
173
+ }
174
+ if (this.isSelfLoopNode(header)) {
175
+ loops.push(new Set([header]));
176
+ }
177
+ for (const start of backEdges) {
178
+ let loop = this.naturalLoop(start, header);
179
+ if (!innermost || loop.size > longest) {
180
+ innermost = loop;
181
+ longest = loop.size;
182
+ }
183
+ }
184
+ loops.push(innermost);
185
+ }
186
+ loops.sort((a, b) => a.size - b.size);
187
+ return loops;
188
+ }
189
+ buildDominator() {
190
+ let domin = new Map();
191
+ domin.set(this.entry, new Set([this.entry]));
192
+ for (const node of this.nodes) {
193
+ if (node !== this.entry) {
194
+ domin.set(node, new Set(this.nodes));
195
+ }
196
+ }
197
+ let change = true;
198
+ while (change) {
199
+ change = false;
200
+ for (const node of this.nodes) {
201
+ if (node === this.entry) {
202
+ continue;
203
+ }
204
+ let t = new Set(domin.get(node));
205
+ for (const p of node.getPred()) {
206
+ t = this.setIntersect(t, domin.get(p));
207
+ }
208
+ t.add(node);
209
+ if (!this.isSetEqual(t, domin.get(node))) {
210
+ change = true;
211
+ domin.set(node, t);
212
+ }
213
+ }
214
+ }
215
+ return domin;
216
+ }
217
+ getBackEdges(dom, header) {
218
+ var _a;
219
+ let backEdges = new Set();
220
+ for (const n of header.getPred()) {
221
+ // h dom n && n -> h
222
+ if ((_a = dom.get(n)) === null || _a === void 0 ? void 0 : _a.has(header)) {
223
+ backEdges.add(n);
224
+ }
225
+ }
226
+ return backEdges;
227
+ }
228
+ naturalLoop(backEdgeStart, backEdgeEnd) {
229
+ let stack = [];
230
+ let loop = new Set([backEdgeEnd, backEdgeStart]);
231
+ stack.push(backEdgeStart);
232
+ while (stack.length > 0) {
233
+ let m = stack.shift();
234
+ for (const pred of m.getPred()) {
235
+ if (loop.has(pred)) {
236
+ continue;
237
+ }
238
+ loop.add(pred);
239
+ stack.push(pred);
240
+ }
241
+ }
242
+ return loop;
243
+ }
244
+ isSelfLoopNode(node) {
245
+ let inSucc = false;
246
+ let inPred = false;
247
+ for (const pred of node.getPred()) {
248
+ if (pred === node) {
249
+ inPred = true;
250
+ }
251
+ }
252
+ for (const succ of node.getSucc()) {
253
+ if (succ === node) {
254
+ inSucc = true;
255
+ }
256
+ }
257
+ return inSucc && inPred;
258
+ }
259
+ isForLoopIncNode(node) {
260
+ for (const loop of this.loopMap.values()) {
261
+ if (loop.getType() === RegionType.FOR_LOOP_REGION) {
262
+ if (node === loop.inc) {
263
+ return true;
264
+ }
265
+ }
266
+ }
267
+ return false;
268
+ }
269
+ isValidInBlocks(node, scope) {
270
+ if (this.isForLoopIncNode(node) || node.hasIfStmt()) {
271
+ return false;
272
+ }
273
+ if (scope && !scope.has(node)) {
274
+ return false;
275
+ }
276
+ return true;
277
+ }
278
+ isIfRegion(node, nodeSet) {
279
+ nodeSet.clear();
280
+ if (node.getSucc().length !== 2) {
281
+ return false;
282
+ }
283
+ let m = node.getSucc()[0];
284
+ let n = node.getSucc()[1];
285
+ if (m.getSucc().length === 1 && m.getSucc()[0] === n) {
286
+ nodeSet.add(node).add(m);
287
+ return true;
288
+ }
289
+ return false;
290
+ }
291
+ isIfExitRegion(node, nodeSet) {
292
+ nodeSet.clear();
293
+ if (node.getSucc().length !== 2) {
294
+ return false;
295
+ }
296
+ let m = node.getSucc()[0];
297
+ if (m.hasReturnStmt()) {
298
+ nodeSet.add(node).add(m);
299
+ return true;
300
+ }
301
+ return false;
302
+ }
303
+ isIfElseRegion(node, nodeSet) {
304
+ nodeSet.clear();
305
+ if (node.getSucc().length !== 2) {
306
+ return false;
307
+ }
308
+ let m = node.getSucc()[0];
309
+ let n = node.getSucc()[1];
310
+ if ((m.getSucc().length === 1 &&
311
+ n.getSucc().length === 1 &&
312
+ m.getPred().length === 1 &&
313
+ n.getPred().length === 1 &&
314
+ m.getSucc()[0] === n.getSucc()[0]) ||
315
+ (m.getSucc().length === 0 && n.getSucc().length === 0)) {
316
+ nodeSet.add(node).add(m).add(n);
317
+ return true;
318
+ }
319
+ return false;
320
+ }
321
+ isBlockRegion(node, nodeSet, scope) {
322
+ let n = node;
323
+ let p = true;
324
+ let s = n.getSucc().length === 1;
325
+ nodeSet.clear();
326
+ let blocks = [];
327
+ while (p && s && !nodeSet.has(n) && this.isValidInBlocks(n, scope)) {
328
+ nodeSet.add(n);
329
+ blocks.push(n);
330
+ n = n.getSucc()[0];
331
+ p = n.getPred().length === 1;
332
+ s = n.getSucc().length === 1;
333
+ }
334
+ if (p && this.isValidInBlocks(n, scope)) {
335
+ if (!nodeSet.has(n)) {
336
+ blocks.push(n);
337
+ }
338
+ nodeSet.add(n);
339
+ }
340
+ n = node;
341
+ p = n.getPred().length === 1;
342
+ s = true;
343
+ while (p && s && this.isValidInBlocks(n, scope)) {
344
+ if (!nodeSet.has(n)) {
345
+ blocks.unshift(n);
346
+ }
347
+ nodeSet.add(n);
348
+ n = n.getPred()[0];
349
+ if (nodeSet.has(n)) {
350
+ break;
351
+ }
352
+ p = n.getPred().length === 1;
353
+ s = n.getSucc().length === 1;
354
+ }
355
+ if (s && this.isValidInBlocks(n, scope)) {
356
+ if (!nodeSet.has(n)) {
357
+ blocks.unshift(n);
358
+ }
359
+ nodeSet.add(n);
360
+ }
361
+ nodeSet.clear();
362
+ for (const n of blocks) {
363
+ nodeSet.add(n);
364
+ }
365
+ if (nodeSet.size >= 2) {
366
+ return true;
367
+ }
368
+ return false;
369
+ }
370
+ isIfBreakRegion(node, nodeSet, loop) {
371
+ let m = node.getSucc()[0];
372
+ nodeSet.clear();
373
+ if (this.isExitLoop(m, this.structBlocks.get(loop))) {
374
+ nodeSet.add(node);
375
+ return true;
376
+ }
377
+ if (m.getSucc().length === 1 && this.isExitLoop(m.getSucc()[0], this.structBlocks.get(loop))) {
378
+ nodeSet.add(node).add(m);
379
+ return true;
380
+ }
381
+ return false;
382
+ }
383
+ isIfContinueRegion(node, nodeSet, loop) {
384
+ nodeSet.clear();
385
+ let m = node.getSucc()[0];
386
+ let n = node.getSucc()[1];
387
+ if (loop.control.has(m)) {
388
+ nodeSet.add(node);
389
+ return true;
390
+ }
391
+ if (m.getSucc().length === 1 &&
392
+ loop.control.has(m.getSucc()[0]) &&
393
+ !loop.control.has(n) &&
394
+ !this.isIfElseRegion(node, nodeSet)) {
395
+ nodeSet.add(node).add(m);
396
+ return true;
397
+ }
398
+ return false;
399
+ }
400
+ isWhileRegion(node, nodeSet, loop) {
401
+ nodeSet.clear();
402
+ let m = node.getSucc()[0];
403
+ if (loop.header === node && m.getSucc().length === 1 && m.getPred().length === 1 && m.getSucc()[0] === node) {
404
+ nodeSet.add(node).add(m);
405
+ return true;
406
+ }
407
+ return false;
408
+ }
409
+ isForRegion(node, nodeSet, loop) {
410
+ nodeSet.clear();
411
+ if (loop.header === node && loop.getType() === RegionType.FOR_LOOP_REGION) {
412
+ let forLoop = loop;
413
+ let blocks = node.getSucc()[0];
414
+ if (forLoop.inc.getPred().length === 1 &&
415
+ forLoop.inc.getPred()[0] === blocks &&
416
+ blocks.getSucc().length === 1) {
417
+ nodeSet.add(node).add(forLoop.inc).add(blocks);
418
+ return true;
419
+ }
420
+ }
421
+ return false;
422
+ }
423
+ isDoWhileRegion(node, nodeSet, loop) {
424
+ nodeSet.clear();
425
+ if (loop.back === node && loop.getType() === RegionType.DO_WHILE_LOOP_REGION) {
426
+ let blocks = node.getPred()[0];
427
+ if (blocks.getSucc().length === 1 && blocks.getSucc()[0] === node && node.getSucc()[0] === blocks) {
428
+ nodeSet.add(blocks).add(node);
429
+ return true;
430
+ }
431
+ }
432
+ return false;
433
+ }
434
+ identifyRegionType(node, nodeSet, scope) {
435
+ if (this.isBlockRegion(node, nodeSet, scope)) {
436
+ return RegionType.BLOCK_REGION;
437
+ }
438
+ let inLoop = false;
439
+ let region = this.structOf.get(node);
440
+ if (region && LOOP_TYPES.has(region === null || region === void 0 ? void 0 : region.getType())) {
441
+ inLoop = true;
442
+ }
443
+ if (new Set(node.getPred()).has(node) && new Set(node.getSucc()).has(node)) {
444
+ nodeSet.add(node);
445
+ if (inLoop) {
446
+ return region === null || region === void 0 ? void 0 : region.getType();
447
+ }
448
+ return RegionType.SELF_LOOP_REGION;
449
+ }
450
+ if (node.getSucc().length !== 2) {
451
+ return undefined;
452
+ }
453
+ if (inLoop) {
454
+ let loop = region;
455
+ if (!loop.control.has(node)) {
456
+ if (this.isIfBreakRegion(node, nodeSet, loop)) {
457
+ return RegionType.IF_THEN_BREAK_REGION;
458
+ }
459
+ if (this.isIfContinueRegion(node, nodeSet, loop)) {
460
+ return RegionType.IF_THEN_CONTINUE_REGION;
461
+ }
462
+ }
463
+ if (this.isWhileRegion(node, nodeSet, loop)) {
464
+ return RegionType.WHILE_LOOP_REGION;
465
+ }
466
+ if (this.isForRegion(node, nodeSet, loop)) {
467
+ return RegionType.FOR_LOOP_REGION;
468
+ }
469
+ if (this.isDoWhileRegion(node, nodeSet, loop)) {
470
+ return RegionType.DO_WHILE_LOOP_REGION;
471
+ }
472
+ }
473
+ // check for if
474
+ if (this.isIfExitRegion(node, nodeSet)) {
475
+ return RegionType.IF_THEN_EXIT_REGION;
476
+ }
477
+ if (this.isIfRegion(node, nodeSet)) {
478
+ return RegionType.IF_REGION;
479
+ }
480
+ // check for an if else
481
+ if (this.isIfElseRegion(node, nodeSet)) {
482
+ return RegionType.IF_ELSE_REGION;
483
+ }
484
+ return undefined;
485
+ }
486
+ cyclicRegionType(nodeSet) {
487
+ var _a, _b, _c;
488
+ let nodes = Array.from(nodeSet);
489
+ let header = nodes[0];
490
+ if (nodeSet.size === 1) {
491
+ let tail = (_a = nodes[0].getBlock()) === null || _a === void 0 ? void 0 : _a.getTail();
492
+ if (tail instanceof Stmt_1.ArkIfStmt) {
493
+ return RegionType.DO_WHILE_LOOP_REGION;
494
+ }
495
+ return RegionType.WHILE_LOOP_REGION;
496
+ }
497
+ let back = nodes[1];
498
+ // exit loop from back
499
+ if (!this.hasExitLoopSucc(header, nodeSet) && this.hasExitLoopSucc(back, nodeSet)) {
500
+ return RegionType.DO_WHILE_LOOP_REGION;
501
+ }
502
+ if (this.hasExitLoopSucc(header, nodeSet) && this.hasExitLoopSucc(back, nodeSet)) {
503
+ // header true exit loop --> exit is break
504
+ if (!nodeSet.has(header.getSucc()[0])) {
505
+ return RegionType.DO_WHILE_LOOP_REGION;
506
+ }
507
+ }
508
+ // for
509
+ if (back.getSucc().length === 1 && ((_c = (_b = back.getBlock()) === null || _b === void 0 ? void 0 : _b.getStmts()) === null || _c === void 0 ? void 0 : _c.length) === 1) {
510
+ let isForLoop = true;
511
+ for (const pred of header.getPred()) {
512
+ if (nodeSet.has(pred) && pred !== back) {
513
+ isForLoop = false;
514
+ }
515
+ }
516
+ if (isForLoop) {
517
+ return RegionType.FOR_LOOP_REGION;
518
+ }
519
+ }
520
+ return RegionType.WHILE_LOOP_REGION;
521
+ }
522
+ hasExitLoopSucc(node, nodeSet) {
523
+ for (const succ of node.getSucc()) {
524
+ if (!nodeSet.has(succ)) {
525
+ return true;
526
+ }
527
+ }
528
+ return false;
529
+ }
530
+ isExitLoop(node, nodeSet) {
531
+ if (this.structBlocks.has(node)) {
532
+ for (const n of this.structBlocks.get(node)) {
533
+ if (!nodeSet.has(n)) {
534
+ return true;
535
+ }
536
+ }
537
+ }
538
+ else {
539
+ if (!nodeSet.has(node)) {
540
+ return true;
541
+ }
542
+ }
543
+ return false;
544
+ }
545
+ createRegion(rtype, nodeSet) {
546
+ let node;
547
+ if (rtype === RegionType.BLOCK_REGION) {
548
+ node = new BlockRegion(nodeSet);
549
+ }
550
+ else if (rtype === RegionType.IF_ELSE_REGION) {
551
+ node = new IfElseRegion(nodeSet);
552
+ }
553
+ else if (rtype === RegionType.IF_REGION) {
554
+ node = new IfRegion(nodeSet);
555
+ }
556
+ else if (rtype === RegionType.IF_THEN_EXIT_REGION) {
557
+ node = new IfExitRegion(nodeSet);
558
+ }
559
+ else if (rtype === RegionType.IF_THEN_BREAK_REGION) {
560
+ node = new IfBreakRegion(nodeSet);
561
+ }
562
+ else if (rtype === RegionType.IF_THEN_CONTINUE_REGION) {
563
+ node = new IfContinueRegion(nodeSet);
564
+ }
565
+ else if (rtype === RegionType.SELF_LOOP_REGION) {
566
+ node = new SelfLoopRegion(nodeSet);
567
+ }
568
+ else if (rtype === RegionType.WHILE_LOOP_REGION) {
569
+ let whileLoop = new WhileLoopRegion(nodeSet);
570
+ this.loopMap.set(whileLoop.header, whileLoop);
571
+ node = whileLoop;
572
+ }
573
+ else if (rtype === RegionType.FOR_LOOP_REGION) {
574
+ let forLoop = new ForLoopRegion(nodeSet);
575
+ this.loopMap.set(forLoop.header, forLoop);
576
+ node = forLoop;
577
+ }
578
+ else if (rtype === RegionType.DO_WHILE_LOOP_REGION) {
579
+ let doWhileLoop = new DoWhileLoopRegion(nodeSet);
580
+ this.loopMap.set(doWhileLoop.header, doWhileLoop);
581
+ node = doWhileLoop;
582
+ }
583
+ else if (rtype === RegionType.TRY_CATCH_REGION ||
584
+ rtype === RegionType.TRY_FINALLY_REGION ||
585
+ rtype === RegionType.TRY_CATCH_FINALLY_REGION) {
586
+ node = new TrapRegion(nodeSet, rtype);
587
+ }
588
+ return node;
589
+ }
590
+ reduce(rtype, nodeSet) {
591
+ let region = this.createRegion(rtype, nodeSet);
592
+ region === null || region === void 0 ? void 0 : region.replace();
593
+ if (region) {
594
+ this.structTypes.set(region, rtype);
595
+ let blocks = new Set();
596
+ for (const s of nodeSet) {
597
+ this.structOf.set(s, region);
598
+ if (this.structBlocks.has(s)) {
599
+ for (const b of this.structBlocks.get(s)) {
600
+ blocks.add(b);
601
+ }
602
+ }
603
+ else {
604
+ blocks.add(s);
605
+ }
606
+ }
607
+ this.structBlocks.set(region, blocks);
608
+ }
609
+ return region;
610
+ }
611
+ setIntersect(a, b) {
612
+ let r = new Set();
613
+ if (!b) {
614
+ return r;
615
+ }
616
+ for (const n of b) {
617
+ if (a.has(n)) {
618
+ r.add(n);
619
+ }
620
+ }
621
+ return r;
622
+ }
623
+ isSetEqual(a, b) {
624
+ if (a.size !== b.size) {
625
+ return false;
626
+ }
627
+ return this.setIntersect(a, b).size === a.size;
628
+ }
629
+ buildTrap(traps) {
630
+ if (!traps) {
631
+ return [];
632
+ }
633
+ traps.sort((a, b) => a.getTryBlocks().length +
634
+ a.getCatchBlocks().length -
635
+ (b.getTryBlocks().length + b.getCatchBlocks().length));
636
+ let trapRegions = [];
637
+ for (const trap of traps) {
638
+ let region = new NaturalTrapRegion(trap, this.block2NodeMap);
639
+ let findTrapRegion = this.getNaturalTrapRegion(region);
640
+ if (!findTrapRegion) {
641
+ for (const n of region.getNodes()) {
642
+ this.structOf.set(n, region);
643
+ }
644
+ trapRegions.push(region);
645
+ continue;
646
+ }
647
+ if (findTrapRegion.type === RegionType.TRY_FINALLY_REGION) {
648
+ findTrapRegion.trySet = region.trySet;
649
+ findTrapRegion.catchSet = region.catchSet;
650
+ region = findTrapRegion;
651
+ }
652
+ else {
653
+ findTrapRegion.finallySet = region.finallySet;
654
+ region = findTrapRegion;
655
+ }
656
+ for (const n of region.getNodes()) {
657
+ this.structOf.set(n, region);
658
+ }
659
+ region.type = RegionType.TRY_CATCH_FINALLY_REGION;
660
+ }
661
+ this.structOf.clear();
662
+ return trapRegions;
663
+ }
664
+ searchTrapFinallyNodes(trapRegions) {
665
+ // search finally
666
+ for (const region of trapRegions) {
667
+ if (region.type === RegionType.TRY_CATCH_REGION) {
668
+ continue;
669
+ }
670
+ this.bfs(region);
671
+ }
672
+ }
673
+ bfs(region) {
674
+ let finallyNodes = new Set();
675
+ let count = region.finallySet.size;
676
+ let queue = [region.getSucc()[0]];
677
+ while (queue.length > 0 && finallyNodes.size < count) {
678
+ let node = queue[0];
679
+ queue.splice(0, 1);
680
+ finallyNodes.add(node);
681
+ region.identifyFinallySet.add(node);
682
+ for (const succ of node.getSucc()) {
683
+ if (!finallyNodes.has(succ)) {
684
+ queue.push(succ);
685
+ }
686
+ }
687
+ }
688
+ }
689
+ getNaturalTrapRegion(trap) {
690
+ let findTrap = this.findNaturalTrapRegion(trap.trySet);
691
+ if (findTrap) {
692
+ return findTrap;
693
+ }
694
+ if (trap.catchSet) {
695
+ findTrap = this.findNaturalTrapRegion(trap.catchSet);
696
+ }
697
+ if (findTrap) {
698
+ return findTrap;
699
+ }
700
+ if (trap.finallySet) {
701
+ findTrap = this.findNaturalTrapRegion(trap.finallySet);
702
+ }
703
+ return findTrap;
704
+ }
705
+ findNaturalTrapRegion(nodes) {
706
+ let findTrap;
707
+ for (const node of nodes) {
708
+ if (!this.structOf.has(node)) {
709
+ return undefined;
710
+ }
711
+ if (!findTrap) {
712
+ findTrap = this.structOf.get(node);
713
+ continue;
714
+ }
715
+ if (findTrap !== this.structOf.get(node)) {
716
+ return undefined;
717
+ }
718
+ }
719
+ return findTrap;
720
+ }
721
+ trapsStructuralAnalysis(trapRegions) {
722
+ trapRegions.sort((a, b) => a.size() - b.size());
723
+ for (const trap of trapRegions) {
724
+ let tryNode = this.trapsSubStructuralAnalysis(trap.trySet);
725
+ let catchNode = this.trapsSubStructuralAnalysis(trap.catchSet);
726
+ let finnallyNode = this.trapsSubStructuralAnalysis(trap.identifyFinallySet);
727
+ if (catchNode === undefined) {
728
+ this.reduce(RegionType.TRY_FINALLY_REGION, new Set([tryNode, finnallyNode]));
729
+ }
730
+ else if (finnallyNode === undefined) {
731
+ this.reduce(RegionType.TRY_CATCH_REGION, new Set([tryNode, catchNode]));
732
+ }
733
+ else {
734
+ this.reduce(RegionType.TRY_CATCH_FINALLY_REGION, new Set([tryNode, catchNode, finnallyNode]));
735
+ }
736
+ }
737
+ }
738
+ trapsSubStructuralAnalysis(nodes) {
739
+ if (!nodes) {
740
+ return undefined;
741
+ }
742
+ let entry = Array.from(nodes)[0];
743
+ if (nodes.size <= 1) {
744
+ return entry;
745
+ }
746
+ for (const node of nodes) {
747
+ if (this.structOf.has(node)) {
748
+ nodes.add(this.structOf.get(node));
749
+ }
750
+ }
751
+ return this.structuralAnalysis(entry, nodes);
752
+ }
753
+ }
754
+ exports.AbstractFlowGraph = AbstractFlowGraph;
755
+ var RegionType;
756
+ (function (RegionType) {
757
+ RegionType[RegionType["ABSTRACT_NODE"] = 0] = "ABSTRACT_NODE";
758
+ RegionType[RegionType["TRY_NODE"] = 1] = "TRY_NODE";
759
+ RegionType[RegionType["CATCH_NODE"] = 2] = "CATCH_NODE";
760
+ RegionType[RegionType["FINALLY_NODE"] = 3] = "FINALLY_NODE";
761
+ /* Sequence of blocks. */
762
+ RegionType[RegionType["BLOCK_REGION"] = 4] = "BLOCK_REGION";
763
+ RegionType[RegionType["IF_REGION"] = 5] = "IF_REGION";
764
+ RegionType[RegionType["IF_ELSE_REGION"] = 6] = "IF_ELSE_REGION";
765
+ RegionType[RegionType["IF_THEN_EXIT_REGION"] = 7] = "IF_THEN_EXIT_REGION";
766
+ RegionType[RegionType["IF_THEN_BREAK_REGION"] = 8] = "IF_THEN_BREAK_REGION";
767
+ RegionType[RegionType["IF_THEN_CONTINUE_REGION"] = 9] = "IF_THEN_CONTINUE_REGION";
768
+ RegionType[RegionType["SELF_LOOP_REGION"] = 10] = "SELF_LOOP_REGION";
769
+ RegionType[RegionType["NATURAL_LOOP_REGION"] = 11] = "NATURAL_LOOP_REGION";
770
+ RegionType[RegionType["WHILE_LOOP_REGION"] = 12] = "WHILE_LOOP_REGION";
771
+ RegionType[RegionType["DO_WHILE_LOOP_REGION"] = 13] = "DO_WHILE_LOOP_REGION";
772
+ RegionType[RegionType["FOR_LOOP_REGION"] = 14] = "FOR_LOOP_REGION";
773
+ RegionType[RegionType["CASE_REGION"] = 15] = "CASE_REGION";
774
+ RegionType[RegionType["SWITCH_REGION"] = 16] = "SWITCH_REGION";
775
+ RegionType[RegionType["TRY_CATCH_REGION"] = 17] = "TRY_CATCH_REGION";
776
+ RegionType[RegionType["TRY_FINALLY_REGION"] = 18] = "TRY_FINALLY_REGION";
777
+ RegionType[RegionType["TRY_CATCH_FINALLY_REGION"] = 19] = "TRY_CATCH_FINALLY_REGION";
778
+ })(RegionType || (RegionType = {}));
779
+ const LOOP_TYPES = new Set([
780
+ RegionType.SELF_LOOP_REGION,
781
+ RegionType.NATURAL_LOOP_REGION,
782
+ RegionType.WHILE_LOOP_REGION,
783
+ RegionType.FOR_LOOP_REGION,
784
+ RegionType.DO_WHILE_LOOP_REGION,
785
+ ]);
786
+ class AbstractNode {
787
+ constructor() {
788
+ this.predNodes = [];
789
+ this.succNodes = [];
790
+ this.type = RegionType.ABSTRACT_NODE;
791
+ }
792
+ traversal(callback, type) {
793
+ callback(this.bb, type);
794
+ }
795
+ getType() {
796
+ return this.type;
797
+ }
798
+ getSucc() {
799
+ return this.succNodes;
800
+ }
801
+ addSucc(node) {
802
+ this.succNodes.push(node);
803
+ }
804
+ replaceSucc(src, dst) {
805
+ for (let i = 0; i < this.succNodes.length; i++) {
806
+ if (this.succNodes[i] === src) {
807
+ this.succNodes[i] = dst;
808
+ break;
809
+ }
810
+ }
811
+ }
812
+ removeSucc(src) {
813
+ for (let i = 0; i < this.predNodes.length; i++) {
814
+ if (this.succNodes[i] === src) {
815
+ this.succNodes.splice(i, 1);
816
+ break;
817
+ }
818
+ }
819
+ }
820
+ getPred() {
821
+ return this.predNodes;
822
+ }
823
+ addPred(block) {
824
+ let set = new Set(this.predNodes);
825
+ if (set.has(block)) {
826
+ return;
827
+ }
828
+ this.predNodes.push(block);
829
+ }
830
+ replacePred(src, dst) {
831
+ for (let i = 0; i < this.predNodes.length; i++) {
832
+ if (this.predNodes[i] === src) {
833
+ this.predNodes[i] = dst;
834
+ break;
835
+ }
836
+ }
837
+ }
838
+ removePred(src) {
839
+ for (let i = 0; i < this.predNodes.length; i++) {
840
+ if (this.predNodes[i] === src) {
841
+ this.predNodes.splice(i, 1);
842
+ break;
843
+ }
844
+ }
845
+ }
846
+ setBlock(bb) {
847
+ this.bb = bb;
848
+ }
849
+ getBlock() {
850
+ return this.bb;
851
+ }
852
+ hasIfStmt() {
853
+ if (!this.bb) {
854
+ return false;
855
+ }
856
+ for (let stmt of this.bb.getStmts()) {
857
+ if (stmt instanceof Stmt_1.ArkIfStmt) {
858
+ return true;
859
+ }
860
+ }
861
+ return false;
862
+ }
863
+ hasReturnStmt() {
864
+ if (!this.bb) {
865
+ return false;
866
+ }
867
+ for (let stmt of this.bb.getStmts()) {
868
+ if (stmt instanceof Stmt_1.ArkReturnStmt) {
869
+ return true;
870
+ }
871
+ }
872
+ return false;
873
+ }
874
+ }
875
+ class Region extends AbstractNode {
876
+ constructor(nset, type) {
877
+ super();
878
+ this.nset = nset;
879
+ this.type = type;
880
+ }
881
+ getBlock() {
882
+ if (this.nset.size === 0) {
883
+ return undefined;
884
+ }
885
+ return Array.from(this.nset)[0].getBlock();
886
+ }
887
+ }
888
+ class BlockRegion extends Region {
889
+ constructor(nset) {
890
+ super(nset, RegionType.BLOCK_REGION);
891
+ this.blocks = Array.from(nset);
892
+ }
893
+ replace() {
894
+ for (let pred of this.blocks[0].getPred()) {
895
+ pred.replaceSucc(this.blocks[0], this);
896
+ this.addPred(pred);
897
+ }
898
+ for (let succ of this.blocks[this.blocks.length - 1].getSucc()) {
899
+ succ.replacePred(this.blocks[this.blocks.length - 1], this);
900
+ this.addSucc(succ);
901
+ }
902
+ }
903
+ traversal(callback) {
904
+ for (const node of this.blocks) {
905
+ node.traversal(callback, CodeBlockType.NORMAL);
906
+ }
907
+ }
908
+ }
909
+ class NaturalLoopRegion extends Region {
910
+ constructor(nset, type = RegionType.NATURAL_LOOP_REGION) {
911
+ super(nset, type);
912
+ let nodes = Array.from(nset);
913
+ this.header = nodes[0];
914
+ if (nset.size > 1) {
915
+ this.back = nodes[1];
916
+ }
917
+ else {
918
+ this.back = nodes[0];
919
+ }
920
+ this.control = new Set([this.header]);
921
+ }
922
+ replace() {
923
+ for (let pred of this.header.getPred()) {
924
+ if (!this.nset.has(pred)) {
925
+ pred.replaceSucc(this.header, this);
926
+ this.addPred(pred);
927
+ }
928
+ }
929
+ let succNodes = new Set();
930
+ for (let node of this.nset) {
931
+ for (let succ of node.getSucc()) {
932
+ if (!this.nset.has(succ)) {
933
+ succNodes.add(succ);
934
+ }
935
+ }
936
+ }
937
+ if (succNodes.size === 0) {
938
+ return;
939
+ }
940
+ let pred = Array.from(succNodes)[0];
941
+ let replaced = false;
942
+ for (let succ of pred.getPred()) {
943
+ if (this.nset.has(succ)) {
944
+ if (!replaced) {
945
+ pred.replacePred(succ, this);
946
+ this.addSucc(pred);
947
+ replaced = true;
948
+ }
949
+ else {
950
+ pred.removePred(succ);
951
+ }
952
+ }
953
+ }
954
+ }
955
+ revise() {
956
+ // add node to loop sets
957
+ for (const node of this.nset) {
958
+ for (const succ of node.getSucc()) {
959
+ if (!this.nset.has(succ) &&
960
+ succ !== this.getExitNode() &&
961
+ succ.getSucc().length === 1 &&
962
+ succ.getSucc()[0] === this.getExitNode()) {
963
+ this.nset.add(succ);
964
+ }
965
+ }
966
+ }
967
+ }
968
+ }
969
+ class SelfLoopRegion extends NaturalLoopRegion {
970
+ constructor(nset) {
971
+ super(nset, RegionType.SELF_LOOP_REGION);
972
+ this.back = this.header;
973
+ }
974
+ replace() {
975
+ for (let pred of this.header.getPred()) {
976
+ if (pred !== this.header) {
977
+ pred.replaceSucc(this.header, this);
978
+ this.addPred(pred);
979
+ }
980
+ }
981
+ for (let succ of this.header.getSucc()) {
982
+ if (succ !== this.header) {
983
+ succ.replacePred(this.header, this);
984
+ this.addSucc(succ);
985
+ }
986
+ }
987
+ }
988
+ getExitNode() {
989
+ return this.header.getSucc()[1];
990
+ }
991
+ }
992
+ class WhileLoopRegion extends NaturalLoopRegion {
993
+ constructor(nset) {
994
+ super(nset, RegionType.WHILE_LOOP_REGION);
995
+ }
996
+ traversal(callback) {
997
+ this.header.traversal(callback, CodeBlockType.WHILE);
998
+ if (this.header !== this.back) {
999
+ this.back.traversal(callback, CodeBlockType.NORMAL);
1000
+ }
1001
+ callback(undefined, CodeBlockType.COMPOUND_END);
1002
+ }
1003
+ getExitNode() {
1004
+ return this.header.getSucc()[1];
1005
+ }
1006
+ }
1007
+ class DoWhileLoopRegion extends NaturalLoopRegion {
1008
+ constructor(nset) {
1009
+ super(nset, RegionType.DO_WHILE_LOOP_REGION);
1010
+ this.control.clear();
1011
+ this.control.add(this.back);
1012
+ }
1013
+ traversal(callback) {
1014
+ callback(undefined, CodeBlockType.DO);
1015
+ if (this.header !== this.back) {
1016
+ this.header.traversal(callback, CodeBlockType.NORMAL);
1017
+ }
1018
+ this.back.traversal(callback, CodeBlockType.DO_WHILE);
1019
+ }
1020
+ getExitNode() {
1021
+ return this.back.getSucc()[1];
1022
+ }
1023
+ }
1024
+ class ForLoopRegion extends NaturalLoopRegion {
1025
+ constructor(nset) {
1026
+ super(nset, RegionType.FOR_LOOP_REGION);
1027
+ this.inc = this.back;
1028
+ this.control.add(this.inc);
1029
+ }
1030
+ traversal(callback) {
1031
+ this.header.traversal(callback, CodeBlockType.FOR);
1032
+ for (const node of this.nset) {
1033
+ if (node !== this.header && node !== this.inc) {
1034
+ node.traversal(callback, CodeBlockType.NORMAL);
1035
+ }
1036
+ }
1037
+ callback(undefined, CodeBlockType.COMPOUND_END);
1038
+ }
1039
+ getExitNode() {
1040
+ return this.header.getSucc()[1];
1041
+ }
1042
+ }
1043
+ class IfRegion extends Region {
1044
+ constructor(nset) {
1045
+ super(nset, RegionType.IF_REGION);
1046
+ let nodes = Array.from(nset);
1047
+ this.contition = nodes[0];
1048
+ this.then = nodes[1];
1049
+ }
1050
+ replace() {
1051
+ this.replaceContitionPred();
1052
+ for (let succ of this.then.getSucc()) {
1053
+ if (succ !== this.then) {
1054
+ succ.replacePred(this.then, this);
1055
+ succ.removePred(this.contition);
1056
+ this.addSucc(succ);
1057
+ }
1058
+ }
1059
+ }
1060
+ traversal(callback) {
1061
+ this.contition.traversal(callback, CodeBlockType.IF);
1062
+ this.then.traversal(callback, CodeBlockType.NORMAL);
1063
+ callback(undefined, CodeBlockType.COMPOUND_END);
1064
+ }
1065
+ replaceContitionPred() {
1066
+ for (let pred of this.contition.getPred()) {
1067
+ if (pred !== this.contition) {
1068
+ pred.replaceSucc(this.contition, this);
1069
+ this.addPred(pred);
1070
+ }
1071
+ }
1072
+ }
1073
+ }
1074
+ class IfExitRegion extends IfRegion {
1075
+ constructor(nset) {
1076
+ super(nset);
1077
+ this.type = RegionType.IF_THEN_EXIT_REGION;
1078
+ }
1079
+ replace() {
1080
+ this.replaceContitionPred();
1081
+ let succ = this.contition.getSucc()[1];
1082
+ succ.replacePred(this.contition, this);
1083
+ this.addSucc(succ);
1084
+ }
1085
+ }
1086
+ class IfBreakRegion extends IfRegion {
1087
+ constructor(nset) {
1088
+ super(nset);
1089
+ this.type = RegionType.IF_THEN_BREAK_REGION;
1090
+ }
1091
+ replace() {
1092
+ this.replaceContitionPred();
1093
+ let succ = this.contition.getSucc()[1];
1094
+ succ.replacePred(this.contition, this);
1095
+ this.addSucc(succ);
1096
+ if (this.then) {
1097
+ succ = this.then.getSucc()[0];
1098
+ succ.removePred(this.then);
1099
+ }
1100
+ else {
1101
+ succ = this.contition.getSucc()[0];
1102
+ succ.removePred(this.contition);
1103
+ }
1104
+ }
1105
+ traversal(callback) {
1106
+ var _a;
1107
+ this.contition.traversal(callback, CodeBlockType.IF);
1108
+ (_a = this.then) === null || _a === void 0 ? void 0 : _a.traversal(callback, CodeBlockType.NORMAL);
1109
+ callback(undefined, CodeBlockType.BREAK);
1110
+ callback(undefined, CodeBlockType.COMPOUND_END);
1111
+ }
1112
+ }
1113
+ class IfContinueRegion extends IfBreakRegion {
1114
+ constructor(nset) {
1115
+ super(nset);
1116
+ this.type = RegionType.IF_THEN_CONTINUE_REGION;
1117
+ }
1118
+ traversal(callback) {
1119
+ var _a;
1120
+ this.contition.traversal(callback, CodeBlockType.IF);
1121
+ (_a = this.then) === null || _a === void 0 ? void 0 : _a.traversal(callback, CodeBlockType.NORMAL);
1122
+ callback(undefined, CodeBlockType.CONTINUE);
1123
+ callback(undefined, CodeBlockType.COMPOUND_END);
1124
+ }
1125
+ }
1126
+ class IfElseRegion extends Region {
1127
+ constructor(nset) {
1128
+ super(nset, RegionType.IF_ELSE_REGION);
1129
+ let nodes = Array.from(nset);
1130
+ this.contition = nodes[0];
1131
+ this.then = nodes[1];
1132
+ this.else = nodes[2];
1133
+ }
1134
+ replace() {
1135
+ for (let pred of this.contition.getPred()) {
1136
+ if (pred !== this.contition) {
1137
+ pred.replaceSucc(this.contition, this);
1138
+ this.addPred(pred);
1139
+ }
1140
+ }
1141
+ for (let succ of this.then.getSucc()) {
1142
+ if (succ !== this.then) {
1143
+ succ.replacePred(this.then, this);
1144
+ succ.removePred(this.else);
1145
+ this.addSucc(succ);
1146
+ }
1147
+ }
1148
+ }
1149
+ traversal(callback) {
1150
+ this.contition.traversal(callback, CodeBlockType.IF);
1151
+ this.then.traversal(callback, CodeBlockType.NORMAL);
1152
+ callback(undefined, CodeBlockType.ELSE);
1153
+ this.else.traversal(callback, CodeBlockType.NORMAL);
1154
+ callback(undefined, CodeBlockType.COMPOUND_END);
1155
+ }
1156
+ }
1157
+ class TrapRegion extends Region {
1158
+ constructor(nset, type) {
1159
+ super(nset, type);
1160
+ let nodes = Array.from(nset);
1161
+ this.tryNode = nodes[0];
1162
+ if (type === RegionType.TRY_CATCH_REGION) {
1163
+ this.catchNode = nodes[1];
1164
+ }
1165
+ else if (type === RegionType.TRY_FINALLY_REGION) {
1166
+ this.finallyNode = nodes[1];
1167
+ }
1168
+ else {
1169
+ this.catchNode = nodes[1];
1170
+ this.finallyNode = nodes[2];
1171
+ }
1172
+ }
1173
+ replace() {
1174
+ for (let pred of this.tryNode.getPred()) {
1175
+ if (pred !== this.tryNode) {
1176
+ pred.replaceSucc(this.tryNode, this);
1177
+ this.addPred(pred);
1178
+ }
1179
+ }
1180
+ if (this.finallyNode) {
1181
+ for (let succ of this.finallyNode.getSucc()) {
1182
+ if (succ !== this.finallyNode) {
1183
+ succ.replacePred(this.finallyNode, this);
1184
+ this.addSucc(succ);
1185
+ }
1186
+ }
1187
+ }
1188
+ else {
1189
+ for (let succ of this.tryNode.getSucc()) {
1190
+ if (succ !== this.tryNode) {
1191
+ succ.replacePred(this.tryNode, this);
1192
+ this.addSucc(succ);
1193
+ }
1194
+ }
1195
+ }
1196
+ }
1197
+ traversal(callback) {
1198
+ var _a, _b;
1199
+ callback(undefined, CodeBlockType.TRY);
1200
+ this.tryNode.traversal(callback, CodeBlockType.NORMAL);
1201
+ if (this.catchNode) {
1202
+ callback(this.catchNode.getBlock(), CodeBlockType.CATCH);
1203
+ (_a = this.catchNode) === null || _a === void 0 ? void 0 : _a.traversal(callback, CodeBlockType.NORMAL);
1204
+ }
1205
+ if (this.finallyNode) {
1206
+ callback(undefined, CodeBlockType.FINALLY);
1207
+ (_b = this.finallyNode) === null || _b === void 0 ? void 0 : _b.traversal(callback, CodeBlockType.NORMAL);
1208
+ }
1209
+ callback(undefined, CodeBlockType.COMPOUND_END);
1210
+ }
1211
+ }
1212
+ class NaturalTrapRegion extends Region {
1213
+ constructor(trap, block2NodeMap) {
1214
+ super(new Set(), RegionType.TRY_CATCH_FINALLY_REGION);
1215
+ this.trySet = new Set();
1216
+ this.catchSet = new Set();
1217
+ this.identifyFinallySet = new Set();
1218
+ for (const block of trap.getTryBlocks()) {
1219
+ this.trySet.add(block2NodeMap.get(block));
1220
+ }
1221
+ for (const block of trap.getCatchBlocks()) {
1222
+ this.catchSet.add(block2NodeMap.get(block));
1223
+ }
1224
+ if (this.isFinallyNode(Array.from(this.catchSet)[this.catchSet.size - 1])) {
1225
+ this.type = RegionType.TRY_FINALLY_REGION;
1226
+ this.finallySet = this.catchSet;
1227
+ this.catchSet = undefined;
1228
+ }
1229
+ else {
1230
+ this.type = RegionType.TRY_CATCH_REGION;
1231
+ }
1232
+ }
1233
+ isFinallyNode(node) {
1234
+ let block = node.getBlock();
1235
+ if (!block) {
1236
+ return false;
1237
+ }
1238
+ let stmtLen = block.getStmts().length;
1239
+ if (stmtLen < 1) {
1240
+ return false;
1241
+ }
1242
+ let stmtLast = block.getStmts()[stmtLen - 1];
1243
+ return stmtLast instanceof Stmt_1.ArkThrowStmt;
1244
+ }
1245
+ size() {
1246
+ let size = this.trySet.size;
1247
+ if (this.catchSet) {
1248
+ size += this.catchSet.size;
1249
+ }
1250
+ if (this.finallySet) {
1251
+ size += this.finallySet.size;
1252
+ }
1253
+ return size;
1254
+ }
1255
+ replace() { }
1256
+ getNodes() {
1257
+ let nodes = Array.from(this.trySet);
1258
+ if (this.catchSet) {
1259
+ nodes.push(...this.catchSet);
1260
+ }
1261
+ if (this.finallySet) {
1262
+ nodes.push(...this.finallySet);
1263
+ }
1264
+ return nodes;
1265
+ }
1266
+ getSucc() {
1267
+ let succ = new Set();
1268
+ for (const node of this.trySet) {
1269
+ for (const s of node.getSucc()) {
1270
+ if (!this.trySet.has(s)) {
1271
+ succ.add(s);
1272
+ }
1273
+ }
1274
+ }
1275
+ return Array.from(succ);
1276
+ }
1277
+ }