arkanalyzer 1.0.6 → 1.0.8

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 (224) hide show
  1. package/config/arkanalyzer.json +8 -0
  2. package/docs/IR2ts-stmt.md +81 -0
  3. package/docs/IR2ts.md +82 -0
  4. package/lib/Config.d.ts +29 -1
  5. package/lib/Config.d.ts.map +1 -1
  6. package/lib/Config.js +44 -11
  7. package/lib/Scene.d.ts +152 -9
  8. package/lib/Scene.d.ts.map +1 -1
  9. package/lib/Scene.js +233 -66
  10. package/lib/callgraph/algorithm/AbstractAnalysis.d.ts +2 -1
  11. package/lib/callgraph/algorithm/AbstractAnalysis.d.ts.map +1 -1
  12. package/lib/callgraph/algorithm/AbstractAnalysis.js +14 -7
  13. package/lib/callgraph/algorithm/ClassHierarchyAnalysis.d.ts.map +1 -1
  14. package/lib/callgraph/algorithm/ClassHierarchyAnalysis.js +2 -4
  15. package/lib/callgraph/algorithm/RapidTypeAnalysis.d.ts.map +1 -1
  16. package/lib/callgraph/algorithm/RapidTypeAnalysis.js +2 -3
  17. package/lib/callgraph/common/Statistics.js +1 -1
  18. package/lib/callgraph/model/BaseGraph.js +2 -2
  19. package/lib/callgraph/model/CallGraph.d.ts +3 -2
  20. package/lib/callgraph/model/CallGraph.d.ts.map +1 -1
  21. package/lib/callgraph/model/CallGraph.js +23 -14
  22. package/lib/callgraph/model/builder/CallGraphBuilder.d.ts +2 -2
  23. package/lib/callgraph/model/builder/CallGraphBuilder.js +3 -3
  24. package/lib/callgraph/pointerAnalysis/Context.d.ts.map +1 -1
  25. package/lib/callgraph/pointerAnalysis/Context.js +0 -1
  26. package/lib/callgraph/pointerAnalysis/Pag.d.ts +36 -9
  27. package/lib/callgraph/pointerAnalysis/Pag.d.ts.map +1 -1
  28. package/lib/callgraph/pointerAnalysis/Pag.js +130 -37
  29. package/lib/callgraph/pointerAnalysis/PagBuilder.d.ts +34 -5
  30. package/lib/callgraph/pointerAnalysis/PagBuilder.d.ts.map +1 -1
  31. package/lib/callgraph/pointerAnalysis/PagBuilder.js +479 -126
  32. package/lib/callgraph/pointerAnalysis/PointerAnalysis.d.ts +6 -0
  33. package/lib/callgraph/pointerAnalysis/PointerAnalysis.d.ts.map +1 -1
  34. package/lib/callgraph/pointerAnalysis/PointerAnalysis.js +107 -45
  35. package/lib/callgraph/pointerAnalysis/PtsDS.d.ts.map +1 -1
  36. package/lib/callgraph/pointerAnalysis/PtsDS.js +0 -2
  37. package/lib/core/base/Constant.d.ts +37 -5
  38. package/lib/core/base/Constant.d.ts.map +1 -1
  39. package/lib/core/base/Constant.js +58 -8
  40. package/lib/core/base/Expr.d.ts +98 -13
  41. package/lib/core/base/Expr.d.ts.map +1 -1
  42. package/lib/core/base/Expr.js +295 -127
  43. package/lib/core/base/Local.d.ts +70 -5
  44. package/lib/core/base/Local.d.ts.map +1 -1
  45. package/lib/core/base/Local.js +77 -4
  46. package/lib/core/base/Ref.d.ts +79 -5
  47. package/lib/core/base/Ref.d.ts.map +1 -1
  48. package/lib/core/base/Ref.js +143 -38
  49. package/lib/core/base/Stmt.d.ts +126 -12
  50. package/lib/core/base/Stmt.d.ts.map +1 -1
  51. package/lib/core/base/Stmt.js +135 -28
  52. package/lib/core/base/Type.d.ts +11 -2
  53. package/lib/core/base/Type.d.ts.map +1 -1
  54. package/lib/core/base/Type.js +47 -42
  55. package/lib/core/base/Value.d.ts +24 -2
  56. package/lib/core/base/Value.d.ts.map +1 -1
  57. package/lib/core/common/ArkError.d.ts +15 -0
  58. package/lib/core/common/ArkError.d.ts.map +1 -0
  59. package/lib/core/common/ArkError.js +28 -0
  60. package/lib/core/common/ArkIRTransformer.d.ts +12 -5
  61. package/lib/core/common/ArkIRTransformer.d.ts.map +1 -1
  62. package/lib/core/common/ArkIRTransformer.js +90 -45
  63. package/lib/core/common/BodyBuilder.d.ts +2 -0
  64. package/lib/core/common/BodyBuilder.d.ts.map +1 -1
  65. package/lib/core/common/BodyBuilder.js +5 -2
  66. package/lib/core/common/Builtin.js +1 -1
  67. package/lib/core/common/CfgBuilder.d.ts +12 -7
  68. package/lib/core/common/CfgBuilder.d.ts.map +1 -1
  69. package/lib/core/common/CfgBuilder.js +336 -140
  70. package/lib/core/common/Const.d.ts +15 -10
  71. package/lib/core/common/Const.d.ts.map +1 -1
  72. package/lib/core/common/Const.js +18 -11
  73. package/lib/core/common/DummyMainCreater.d.ts +5 -4
  74. package/lib/core/common/DummyMainCreater.d.ts.map +1 -1
  75. package/lib/core/common/DummyMainCreater.js +43 -28
  76. package/lib/core/common/EtsConst.d.ts +1 -0
  77. package/lib/core/common/EtsConst.d.ts.map +1 -1
  78. package/lib/core/common/EtsConst.js +2 -1
  79. package/lib/core/common/ExprUseReplacer.js +8 -8
  80. package/lib/core/common/IRUtils.d.ts +7 -0
  81. package/lib/core/common/IRUtils.d.ts.map +1 -1
  82. package/lib/core/common/IRUtils.js +34 -2
  83. package/lib/core/common/ModelUtils.d.ts +1 -0
  84. package/lib/core/common/ModelUtils.d.ts.map +1 -1
  85. package/lib/core/common/ModelUtils.js +39 -36
  86. package/lib/core/common/RefUseReplacer.js +3 -3
  87. package/lib/core/common/StmtUseReplacer.js +4 -4
  88. package/lib/core/common/TSConst.d.ts +10 -3
  89. package/lib/core/common/TSConst.d.ts.map +1 -1
  90. package/lib/core/common/TSConst.js +11 -4
  91. package/lib/core/common/TypeInference.d.ts +8 -2
  92. package/lib/core/common/TypeInference.d.ts.map +1 -1
  93. package/lib/core/common/TypeInference.js +222 -90
  94. package/lib/core/common/ValueUtil.d.ts +0 -4
  95. package/lib/core/common/ValueUtil.d.ts.map +1 -1
  96. package/lib/core/common/ValueUtil.js +10 -27
  97. package/lib/core/common/VisibleValue.js +1 -1
  98. package/lib/core/dataflow/DataflowProblem.d.ts +1 -0
  99. package/lib/core/dataflow/DataflowProblem.d.ts.map +1 -1
  100. package/lib/core/dataflow/DataflowProblem.js +4 -4
  101. package/lib/core/dataflow/DataflowSolver.d.ts +20 -16
  102. package/lib/core/dataflow/DataflowSolver.d.ts.map +1 -1
  103. package/lib/core/dataflow/DataflowSolver.js +67 -78
  104. package/lib/core/dataflow/TiantAnalysis.d.ts +1 -0
  105. package/lib/core/dataflow/TiantAnalysis.d.ts.map +1 -1
  106. package/lib/core/dataflow/TiantAnalysis.js +42 -28
  107. package/lib/core/dataflow/UndefinedVariable.d.ts +15 -1
  108. package/lib/core/dataflow/UndefinedVariable.d.ts.map +1 -1
  109. package/lib/core/dataflow/UndefinedVariable.js +122 -76
  110. package/lib/core/dataflow/Util.d.ts +5 -1
  111. package/lib/core/dataflow/Util.d.ts.map +1 -1
  112. package/lib/core/dataflow/Util.js +43 -22
  113. package/lib/core/graph/BasicBlock.d.ts +72 -0
  114. package/lib/core/graph/BasicBlock.d.ts.map +1 -1
  115. package/lib/core/graph/BasicBlock.js +165 -3
  116. package/lib/core/graph/Cfg.d.ts +30 -1
  117. package/lib/core/graph/Cfg.d.ts.map +1 -1
  118. package/lib/core/graph/Cfg.js +131 -11
  119. package/lib/core/graph/DominanceFinder.js +7 -7
  120. package/lib/core/graph/DominanceTree.js +4 -4
  121. package/lib/core/graph/builder/ViewTreeBuilder.d.ts.map +1 -1
  122. package/lib/core/graph/builder/ViewTreeBuilder.js +6 -5
  123. package/lib/core/model/ArkBaseModel.d.ts +59 -0
  124. package/lib/core/model/ArkBaseModel.d.ts.map +1 -0
  125. package/lib/core/model/ArkBaseModel.js +271 -0
  126. package/lib/core/model/ArkBody.d.ts +3 -9
  127. package/lib/core/model/ArkBody.d.ts.map +1 -1
  128. package/lib/core/model/ArkBody.js +3 -14
  129. package/lib/core/model/ArkClass.d.ts +107 -13
  130. package/lib/core/model/ArkClass.d.ts.map +1 -1
  131. package/lib/core/model/ArkClass.js +152 -54
  132. package/lib/core/model/ArkExport.d.ts +8 -7
  133. package/lib/core/model/ArkExport.d.ts.map +1 -1
  134. package/lib/core/model/ArkExport.js +16 -18
  135. package/lib/core/model/ArkField.d.ts +16 -13
  136. package/lib/core/model/ArkField.d.ts.map +1 -1
  137. package/lib/core/model/ArkField.js +18 -62
  138. package/lib/core/model/ArkFile.d.ts +42 -0
  139. package/lib/core/model/ArkFile.d.ts.map +1 -1
  140. package/lib/core/model/ArkFile.js +58 -0
  141. package/lib/core/model/ArkImport.d.ts +9 -7
  142. package/lib/core/model/ArkImport.d.ts.map +1 -1
  143. package/lib/core/model/ArkImport.js +11 -12
  144. package/lib/core/model/ArkMetadata.d.ts +20 -0
  145. package/lib/core/model/ArkMetadata.d.ts.map +1 -0
  146. package/lib/core/model/ArkMetadata.js +44 -0
  147. package/lib/core/model/ArkMethod.d.ts +195 -17
  148. package/lib/core/model/ArkMethod.d.ts.map +1 -1
  149. package/lib/core/model/ArkMethod.js +363 -46
  150. package/lib/core/model/ArkNamespace.d.ts +6 -8
  151. package/lib/core/model/ArkNamespace.d.ts.map +1 -1
  152. package/lib/core/model/ArkNamespace.js +16 -20
  153. package/lib/core/model/ArkSignature.d.ts +41 -0
  154. package/lib/core/model/ArkSignature.d.ts.map +1 -1
  155. package/lib/core/model/ArkSignature.js +76 -19
  156. package/lib/core/model/builder/ArkClassBuilder.d.ts.map +1 -1
  157. package/lib/core/model/builder/ArkClassBuilder.js +60 -49
  158. package/lib/core/model/builder/ArkExportBuilder.d.ts.map +1 -1
  159. package/lib/core/model/builder/ArkExportBuilder.js +12 -6
  160. package/lib/core/model/builder/ArkFieldBuilder.d.ts.map +1 -1
  161. package/lib/core/model/builder/ArkFieldBuilder.js +13 -9
  162. package/lib/core/model/builder/ArkFileBuilder.js +1 -3
  163. package/lib/core/model/builder/ArkImportBuilder.d.ts +2 -1
  164. package/lib/core/model/builder/ArkImportBuilder.d.ts.map +1 -1
  165. package/lib/core/model/builder/ArkImportBuilder.js +16 -13
  166. package/lib/core/model/builder/ArkMethodBuilder.d.ts +3 -1
  167. package/lib/core/model/builder/ArkMethodBuilder.d.ts.map +1 -1
  168. package/lib/core/model/builder/ArkMethodBuilder.js +105 -45
  169. package/lib/core/model/builder/ArkNamespaceBuilder.d.ts.map +1 -1
  170. package/lib/core/model/builder/ArkNamespaceBuilder.js +4 -5
  171. package/lib/core/model/builder/builderUtils.d.ts +2 -1
  172. package/lib/core/model/builder/builderUtils.d.ts.map +1 -1
  173. package/lib/core/model/builder/builderUtils.js +63 -43
  174. package/lib/index.d.ts +2 -1
  175. package/lib/index.d.ts.map +1 -1
  176. package/lib/index.js +4 -3
  177. package/lib/save/ArkStream.js +1 -1
  178. package/lib/save/DotPrinter.d.ts.map +1 -1
  179. package/lib/save/DotPrinter.js +1 -15
  180. package/lib/save/GraphPrinter.d.ts.map +1 -1
  181. package/lib/save/GraphPrinter.js +4 -2
  182. package/lib/save/JsonPrinter.js +5 -5
  183. package/lib/save/ViewTreePrinter.d.ts +16 -0
  184. package/lib/save/ViewTreePrinter.d.ts.map +1 -0
  185. package/lib/save/ViewTreePrinter.js +130 -0
  186. package/lib/save/source/SourceBase.d.ts +2 -2
  187. package/lib/save/source/SourceBase.d.ts.map +1 -1
  188. package/lib/save/source/SourceBase.js +6 -13
  189. package/lib/save/source/SourceBody.d.ts.map +1 -1
  190. package/lib/save/source/SourceBody.js +27 -14
  191. package/lib/save/source/SourceClass.d.ts.map +1 -1
  192. package/lib/save/source/SourceClass.js +12 -8
  193. package/lib/save/source/SourceField.d.ts.map +1 -1
  194. package/lib/save/source/SourceField.js +6 -2
  195. package/lib/save/source/SourceMethod.d.ts.map +1 -1
  196. package/lib/save/source/SourceMethod.js +10 -3
  197. package/lib/save/source/SourceModule.d.ts.map +1 -1
  198. package/lib/save/source/SourceModule.js +16 -10
  199. package/lib/save/source/SourceNamespace.d.ts.map +1 -1
  200. package/lib/save/source/SourceNamespace.js +4 -0
  201. package/lib/save/source/SourceStmt.d.ts +1 -1
  202. package/lib/save/source/SourceStmt.d.ts.map +1 -1
  203. package/lib/save/source/SourceStmt.js +37 -25
  204. package/lib/save/source/SourceTransformer.d.ts +6 -0
  205. package/lib/save/source/SourceTransformer.d.ts.map +1 -1
  206. package/lib/save/source/SourceTransformer.js +82 -51
  207. package/lib/save/source/SourceUtils.d.ts.map +1 -1
  208. package/lib/save/source/SourceUtils.js +12 -11
  209. package/lib/transformer/StaticSingleAssignmentFormer.js +3 -3
  210. package/lib/utils/CfgStructualAnalysis.d.ts +1 -0
  211. package/lib/utils/CfgStructualAnalysis.d.ts.map +1 -1
  212. package/lib/utils/CfgStructualAnalysis.js +103 -72
  213. package/lib/utils/callGraphUtils.d.ts.map +1 -1
  214. package/lib/utils/callGraphUtils.js +7 -10
  215. package/lib/utils/crypto_utils.d.ts +6 -0
  216. package/lib/utils/crypto_utils.d.ts.map +1 -0
  217. package/lib/utils/crypto_utils.js +57 -0
  218. package/lib/utils/entryMethodUtils.d.ts.map +1 -1
  219. package/lib/utils/entryMethodUtils.js +27 -26
  220. package/lib/utils/getAllFiles.d.ts +1 -1
  221. package/lib/utils/getAllFiles.d.ts.map +1 -1
  222. package/lib/utils/getAllFiles.js +4 -5
  223. package/lib/utils/logger.js +2 -2
  224. package/package.json +3 -2
@@ -39,6 +39,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.CfgBuilder = void 0;
41
41
  const ts = __importStar(require("ohos-typescript"));
42
+ const Local_1 = require("../base/Local");
42
43
  const Stmt_1 = require("../base/Stmt");
43
44
  const BasicBlock_1 = require("../graph/BasicBlock");
44
45
  const Cfg_1 = require("../graph/Cfg");
@@ -180,7 +181,7 @@ class CfgBuilder {
180
181
  walkAST(lastStatement, nextStatement, nodes) {
181
182
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
182
183
  function judgeLastType(s) {
183
- if (lastStatement.type == 'ifStatement') {
184
+ if (lastStatement.type === 'ifStatement') {
184
185
  let lastIf = lastStatement;
185
186
  if (lastIf.nextT == null) {
186
187
  lastIf.nextT = s;
@@ -191,12 +192,12 @@ class CfgBuilder {
191
192
  s.lasts.add(lastIf);
192
193
  }
193
194
  }
194
- else if (lastStatement.type == 'loopStatement') {
195
+ else if (lastStatement.type === 'loopStatement') {
195
196
  let lastLoop = lastStatement;
196
197
  lastLoop.nextT = s;
197
198
  s.lasts.add(lastLoop);
198
199
  }
199
- else if (lastStatement.type == 'catchOrNot') {
200
+ else if (lastStatement.type === 'catchOrNot') {
200
201
  let lastLoop = lastStatement;
201
202
  lastLoop.nextT = s;
202
203
  s.lasts.add(lastLoop);
@@ -209,7 +210,7 @@ class CfgBuilder {
209
210
  this.scopeLevel++;
210
211
  let scope = new Scope(this.scopes.length, new Set(), this.scopeLevel);
211
212
  for (let i = this.scopes.length - 1; i >= 0; i--) {
212
- if (this.scopes[i].level == this.scopeLevel - 1) {
213
+ if (this.scopes[i].level === this.scopeLevel - 1) {
213
214
  scope.parent = this.scopes[i];
214
215
  break;
215
216
  }
@@ -222,6 +223,11 @@ class CfgBuilder {
222
223
  judgeLastType(s);
223
224
  lastStatement = s;
224
225
  }
226
+ else if (!this.declaringMethod.isDefaultArkMethod() && ts.isFunctionDeclaration(c)) {
227
+ let s = new StatementBuilder('functionDeclarationStatement', c.getText(this.sourceFile), c, scope.id);
228
+ judgeLastType(s);
229
+ lastStatement = s;
230
+ }
225
231
  else if (ts.isReturnStatement(c)) {
226
232
  let s = new StatementBuilder('returnStatement', c.getText(this.sourceFile), c, scope.id);
227
233
  judgeLastType(s);
@@ -367,7 +373,7 @@ class CfgBuilder {
367
373
  this.walkAST(lastStatement, loopstm, [c.statement]);
368
374
  }
369
375
  let lastType = lastStatement.type;
370
- if (lastType == 'ifStatement' || lastType == 'loopStatement') {
376
+ if (lastType === 'ifStatement' || lastType === 'loopStatement') {
371
377
  let lastCondition = lastStatement;
372
378
  loopstm.nextT = lastCondition.nextT;
373
379
  (_f = lastCondition.nextT) === null || _f === void 0 ? void 0 : _f.lasts.add(loopstm);
@@ -376,7 +382,7 @@ class CfgBuilder {
376
382
  loopstm.nextT = lastStatement.next;
377
383
  (_g = lastStatement.next) === null || _g === void 0 ? void 0 : _g.lasts.add(loopstm);
378
384
  }
379
- if (loopstm.nextT && loopstm.nextT != loopstm) {
385
+ if (loopstm.nextT && loopstm.nextT !== loopstm) {
380
386
  loopstm.nextT.isDoWhile = true;
381
387
  loopstm.doStatement = loopstm.nextT;
382
388
  }
@@ -424,7 +430,7 @@ class CfgBuilder {
424
430
  (_h = casestm.next) === null || _h === void 0 ? void 0 : _h.lasts.add(lastCaseExit);
425
431
  }
426
432
  lastCaseExit = caseExit;
427
- if (i == c.caseBlock.clauses.length - 1) {
433
+ if (i === c.caseBlock.clauses.length - 1) {
428
434
  caseExit.next = switchExit;
429
435
  switchExit.lasts.add(caseExit);
430
436
  }
@@ -488,13 +494,13 @@ class CfgBuilder {
488
494
  }
489
495
  }
490
496
  this.scopeLevel--;
491
- if (lastStatement.type != 'breakStatement' && lastStatement.type != 'continueStatement' && lastStatement.type != 'returnStatement') {
497
+ if (lastStatement.type !== 'breakStatement' && lastStatement.type !== 'continueStatement' && lastStatement.type !== 'returnStatement') {
492
498
  lastStatement.next = nextStatement;
493
499
  nextStatement.lasts.add(lastStatement);
494
500
  }
495
501
  }
496
502
  addReturnInEmptyMethod() {
497
- if (this.entry.next == this.exit) {
503
+ if (this.entry.next === this.exit) {
498
504
  const ret = new StatementBuilder('returnStatement', 'return;', null, this.entry.scopeID);
499
505
  this.entry.next = ret;
500
506
  ret.lasts.add(this.entry);
@@ -506,13 +512,13 @@ class CfgBuilder {
506
512
  for (const exit of this.exits) {
507
513
  for (const last of [...exit.lasts]) {
508
514
  if (last instanceof ConditionStatementBuilder) {
509
- if (last.nextT == exit) {
515
+ if (last.nextT === exit) {
510
516
  last.nextT = exit.next;
511
517
  const lasts = exit.next.lasts;
512
518
  lasts.delete(exit);
513
519
  lasts.add(last);
514
520
  }
515
- else if (last.nextF == exit) {
521
+ else if (last.nextF === exit) {
516
522
  last.nextF = exit.next;
517
523
  const lasts = exit.next.lasts;
518
524
  lasts.delete(exit);
@@ -522,7 +528,7 @@ class CfgBuilder {
522
528
  else if (last instanceof SwitchStatementBuilder) {
523
529
  for (let i = 0; i < last.nexts.length; i++) {
524
530
  const stmt = last.nexts[i];
525
- if (stmt == exit) {
531
+ if (stmt === exit) {
526
532
  last.nexts[i] = exit.next;
527
533
  const lasts = exit.next.lasts;
528
534
  lasts.delete(exit);
@@ -559,7 +565,7 @@ class CfgBuilder {
559
565
  const block = new Block(this.blocks.length, []);
560
566
  this.blocks.push(block);
561
567
  while (stmt && !handledStmts.has(stmt)) {
562
- if (stmt.type == 'loopStatement' && block.stmts.length > 0 && !stmt.isDoWhile) {
568
+ if (stmt.type === 'loopStatement' && block.stmts.length > 0 && !stmt.isDoWhile) {
563
569
  stmtQueue.push(stmt);
564
570
  break;
565
571
  }
@@ -599,15 +605,15 @@ class CfgBuilder {
599
605
  }
600
606
  else {
601
607
  if (stmt.next) {
602
- if ((stmt.type == 'continueStatement' || stmt.next.type == 'loopStatement') && stmt.next.block) {
608
+ if ((stmt.type === 'continueStatement' || stmt.next.type === 'loopStatement') && stmt.next.block) {
603
609
  break;
604
610
  }
605
611
  if (stmt.next.type.includes('exit')) {
606
612
  break;
607
613
  }
608
614
  stmt.next.passTmies++;
609
- if (stmt.next.passTmies == stmt.next.lasts.size || (stmt.next.type == 'loopStatement') || stmt.next.isDoWhile) {
610
- if (stmt.next.scopeID != stmt.scopeID && !(stmt.next instanceof ConditionStatementBuilder && stmt.next.doStatement)
615
+ if (stmt.next.passTmies === stmt.next.lasts.size || (stmt.next.type === 'loopStatement') || stmt.next.isDoWhile) {
616
+ if (stmt.next.scopeID !== stmt.scopeID && !(stmt.next instanceof ConditionStatementBuilder && stmt.next.doStatement)
611
617
  && !(ts.isCaseClause(stmt.astNode) || ts.isDefaultClause(stmt.astNode))) {
612
618
  stmtQueue.push(stmt.next);
613
619
  break;
@@ -623,15 +629,15 @@ class CfgBuilder {
623
629
  var _a, _b, _c, _d, _e, _f;
624
630
  for (let block of this.blocks) {
625
631
  for (let originStatement of block.stmts) {
626
- let lastStatement = (block.stmts.indexOf(originStatement) == block.stmts.length - 1);
632
+ let lastStatement = (block.stmts.indexOf(originStatement) === block.stmts.length - 1);
627
633
  if (originStatement instanceof ConditionStatementBuilder) {
628
634
  let nextT = (_a = originStatement.nextT) === null || _a === void 0 ? void 0 : _a.block;
629
- if (nextT && (lastStatement || nextT != block) && !((_b = originStatement.nextT) === null || _b === void 0 ? void 0 : _b.type.includes(' exit'))) {
635
+ if (nextT && (lastStatement || nextT !== block) && !((_b = originStatement.nextT) === null || _b === void 0 ? void 0 : _b.type.includes(' exit'))) {
630
636
  block.nexts.push(nextT);
631
637
  nextT.lasts.push(block);
632
638
  }
633
639
  let nextF = (_c = originStatement.nextF) === null || _c === void 0 ? void 0 : _c.block;
634
- if (nextF && (lastStatement || nextF != block) && !((_d = originStatement.nextF) === null || _d === void 0 ? void 0 : _d.type.includes(' exit'))) {
640
+ if (nextF && (lastStatement || nextF !== block) && !((_d = originStatement.nextF) === null || _d === void 0 ? void 0 : _d.type.includes(' exit'))) {
635
641
  block.nexts.push(nextF);
636
642
  nextF.lasts.push(block);
637
643
  }
@@ -639,7 +645,7 @@ class CfgBuilder {
639
645
  else if (originStatement instanceof SwitchStatementBuilder) {
640
646
  for (const next of originStatement.nexts) {
641
647
  const nextBlock = next.block;
642
- if (nextBlock && (lastStatement || nextBlock != block)) {
648
+ if (nextBlock && (lastStatement || nextBlock !== block)) {
643
649
  block.nexts.push(nextBlock);
644
650
  nextBlock.lasts.push(block);
645
651
  }
@@ -647,7 +653,7 @@ class CfgBuilder {
647
653
  }
648
654
  else {
649
655
  let next = (_e = originStatement.next) === null || _e === void 0 ? void 0 : _e.block;
650
- if (next && (lastStatement || next != block) && !((_f = originStatement.next) === null || _f === void 0 ? void 0 : _f.type.includes(' exit'))) {
656
+ if (next && (lastStatement || next !== block) && !((_f = originStatement.next) === null || _f === void 0 ? void 0 : _f.type.includes(' exit'))) {
651
657
  block.nexts.push(next);
652
658
  next.lasts.push(block);
653
659
  }
@@ -659,7 +665,7 @@ class CfgBuilder {
659
665
  var _a, _b, _c, _d;
660
666
  let notReturnStmts = [];
661
667
  for (let stmt of [...this.exit.lasts]) {
662
- if (stmt.type != 'returnStatement') {
668
+ if (stmt.type !== 'returnStatement') {
663
669
  notReturnStmts.push(stmt);
664
670
  }
665
671
  }
@@ -668,7 +674,7 @@ class CfgBuilder {
668
674
  }
669
675
  const returnStatement = new StatementBuilder('returnStatement', 'return;', null, this.exit.scopeID);
670
676
  let tryExit = false;
671
- if (notReturnStmts.length == 1 && notReturnStmts[0].block) {
677
+ if (notReturnStmts.length === 1 && notReturnStmts[0].block) {
672
678
  for (const stmt of notReturnStmts[0].block.stmts) {
673
679
  if (stmt instanceof TryStatementBuilder) {
674
680
  tryExit = true;
@@ -676,7 +682,7 @@ class CfgBuilder {
676
682
  }
677
683
  }
678
684
  }
679
- if (notReturnStmts.length == 1 && !(notReturnStmts[0] instanceof ConditionStatementBuilder) && !tryExit) {
685
+ if (notReturnStmts.length === 1 && !(notReturnStmts[0] instanceof ConditionStatementBuilder) && !tryExit) {
680
686
  const notReturnStmt = notReturnStmts[0];
681
687
  notReturnStmt.next = returnStatement;
682
688
  returnStatement.lasts = new Set([notReturnStmt]);
@@ -693,11 +699,11 @@ class CfgBuilder {
693
699
  this.blocks.push(returnBlock);
694
700
  for (const notReturnStmt of notReturnStmts) {
695
701
  if (notReturnStmt instanceof ConditionStatementBuilder) {
696
- if (this.exit == notReturnStmt.nextT) {
702
+ if (this.exit === notReturnStmt.nextT) {
697
703
  notReturnStmt.nextT = returnStatement;
698
704
  (_b = notReturnStmt.block) === null || _b === void 0 ? void 0 : _b.nexts.splice(0, 0, returnBlock);
699
705
  }
700
- else if (this.exit == notReturnStmt.nextF) {
706
+ else if (this.exit === notReturnStmt.nextF) {
701
707
  notReturnStmt.nextF = returnStatement;
702
708
  (_c = notReturnStmt.block) === null || _c === void 0 ? void 0 : _c.nexts.push(returnBlock);
703
709
  }
@@ -736,7 +742,7 @@ class CfgBuilder {
736
742
  stmt.index = this.statementArray.length;
737
743
  if (!stmt.type.includes(' exit'))
738
744
  this.statementArray.push(stmt);
739
- if (stmt.type == 'ifStatement' || stmt.type == 'loopStatement' || stmt.type == 'catchOrNot') {
745
+ if (stmt.type === 'ifStatement' || stmt.type === 'loopStatement' || stmt.type === 'catchOrNot') {
740
746
  let cstm = stmt;
741
747
  if (cstm.nextT == null || cstm.nextF == null) {
742
748
  this.errorTest(cstm);
@@ -745,13 +751,13 @@ class CfgBuilder {
745
751
  this.CfgBuilder2Array(cstm.nextF);
746
752
  this.CfgBuilder2Array(cstm.nextT);
747
753
  }
748
- else if (stmt.type == 'switchStatement') {
754
+ else if (stmt.type === 'switchStatement') {
749
755
  let sstm = stmt;
750
756
  for (let ss of sstm.nexts) {
751
757
  this.CfgBuilder2Array(ss);
752
758
  }
753
759
  }
754
- else if (stmt.type == 'tryStatement') {
760
+ else if (stmt.type === 'tryStatement') {
755
761
  let trystm = stmt;
756
762
  if (trystm.tryFirst) {
757
763
  this.CfgBuilder2Array(trystm.tryFirst);
@@ -772,12 +778,12 @@ class CfgBuilder {
772
778
  }
773
779
  }
774
780
  getDotEdges(stmt) {
775
- if (this.statementArray.length == 0)
781
+ if (this.statementArray.length === 0)
776
782
  this.CfgBuilder2Array(this.entry);
777
783
  if (stmt.walked)
778
784
  return;
779
785
  stmt.walked = true;
780
- if (stmt.type == 'ifStatement' || stmt.type == 'loopStatement' || stmt.type == 'catchOrNot') {
786
+ if (stmt.type === 'ifStatement' || stmt.type === 'loopStatement' || stmt.type === 'catchOrNot') {
781
787
  let cstm = stmt;
782
788
  if (cstm.nextT == null || cstm.nextF == null) {
783
789
  this.errorTest(cstm);
@@ -790,7 +796,7 @@ class CfgBuilder {
790
796
  this.getDotEdges(cstm.nextF);
791
797
  this.getDotEdges(cstm.nextT);
792
798
  }
793
- else if (stmt.type == 'switchStatement') {
799
+ else if (stmt.type === 'switchStatement') {
794
800
  let sstm = stmt;
795
801
  for (let ss of sstm.nexts) {
796
802
  let edge = [sstm.index, ss.index];
@@ -823,12 +829,12 @@ class CfgBuilder {
823
829
  }
824
830
  for (let bi = 0; bi < this.blocks.length; bi++) {
825
831
  let block = this.blocks[bi];
826
- if (bi != 0)
832
+ if (bi !== 0)
827
833
  text += 'label' + block.id + ':\n';
828
834
  let length = block.stmts.length;
829
835
  for (let i = 0; i < length; i++) {
830
836
  let stmt = block.stmts[i];
831
- if (stmt.type == 'ifStatement' || stmt.type == 'loopStatement' || stmt.type == 'catchOrNot') {
837
+ if (stmt.type === 'ifStatement' || stmt.type === 'loopStatement' || stmt.type === 'catchOrNot') {
832
838
  let cstm = stmt;
833
839
  if (cstm.nextT == null || cstm.nextF == null) {
834
840
  this.errorTest(cstm);
@@ -839,13 +845,13 @@ class CfgBuilder {
839
845
  return text;
840
846
  }
841
847
  stmt.code = 'if !(' + cstm.condition + ') goto label' + cstm.nextF.block.id;
842
- if (i == length - 1 && bi + 1 < this.blocks.length && this.blocks[bi + 1].id != cstm.nextT.block.id) {
848
+ if (i === length - 1 && bi + 1 < this.blocks.length && this.blocks[bi + 1].id !== cstm.nextT.block.id) {
843
849
  let gotoStm = new StatementBuilder('gotoStatement', 'goto label' + cstm.nextT.block.id, null, block.stmts[0].scopeID);
844
850
  block.stmts.push(gotoStm);
845
851
  length++;
846
852
  }
847
853
  }
848
- else if (stmt.type == 'breakStatement' || stmt.type == 'continueStatement') {
854
+ else if (stmt.type === 'breakStatement' || stmt.type === 'continueStatement') {
849
855
  if (!((_b = stmt.next) === null || _b === void 0 ? void 0 : _b.block)) {
850
856
  this.errorTest(stmt);
851
857
  return text;
@@ -853,13 +859,13 @@ class CfgBuilder {
853
859
  stmt.code = 'goto label' + ((_c = stmt.next) === null || _c === void 0 ? void 0 : _c.block.id);
854
860
  }
855
861
  else {
856
- if (i == length - 1 && ((_d = stmt.next) === null || _d === void 0 ? void 0 : _d.block) && (bi + 1 < this.blocks.length && this.blocks[bi + 1].id != stmt.next.block.id || bi + 1 == this.blocks.length)) {
862
+ if (i === length - 1 && ((_d = stmt.next) === null || _d === void 0 ? void 0 : _d.block) && (bi + 1 < this.blocks.length && this.blocks[bi + 1].id !== stmt.next.block.id || bi + 1 === this.blocks.length)) {
857
863
  let gotoStm = new StatementBuilder('StatementBuilder', 'goto label' + ((_e = stmt.next) === null || _e === void 0 ? void 0 : _e.block.id), null, block.stmts[0].scopeID);
858
864
  block.stmts.push(gotoStm);
859
865
  length++;
860
866
  }
861
867
  }
862
- if (stmt.addressCode3.length == 0) {
868
+ if (stmt.addressCode3.length === 0) {
863
869
  text += ' ' + stmt.code + '\n';
864
870
  }
865
871
  else {
@@ -931,7 +937,7 @@ class CfgBuilder {
931
937
  this.CfgBuilder2Array(this.entry);
932
938
  this.addStmtBuilderPosition();
933
939
  this.buildBlocks();
934
- this.blocks = this.blocks.filter((b) => b.stmts.length != 0);
940
+ this.blocks = this.blocks.filter((b) => b.stmts.length !== 0);
935
941
  this.buildBlocksNextLast();
936
942
  this.addReturnBlock();
937
943
  }
@@ -976,7 +982,6 @@ class CfgBuilder {
976
982
  expressionBodyStmts.push(returnStmt);
977
983
  arkIRTransformer.mapStmtsToTsStmt(expressionBodyStmts, expressionBodyNode);
978
984
  stmts.push(...expressionBodyStmts);
979
- const stmtToOriginalStmt = arkIRTransformer.getStmtToOriginalStmt();
980
985
  const cfg = new Cfg_1.Cfg();
981
986
  const blockInCfg = new BasicBlock_1.BasicBlock();
982
987
  blockInCfg.setId(0);
@@ -986,15 +991,8 @@ class CfgBuilder {
986
991
  });
987
992
  cfg.addBlock(blockInCfg);
988
993
  cfg.setStartingStmt(stmts[0]);
989
- const originalCfg = new Cfg_1.Cfg();
990
- const blockInOriginalCfg = new BasicBlock_1.BasicBlock();
991
- blockInOriginalCfg.setId(0);
992
- originalCfg.addBlock(blockInOriginalCfg);
993
- originalCfg.setStartingStmt(stmtToOriginalStmt.get(stmts[0]));
994
994
  return {
995
995
  cfg: cfg,
996
- originalCfg: originalCfg,
997
- stmtToOriginalStmt: stmtToOriginalStmt,
998
996
  locals: arkIRTransformer.getLocals(),
999
997
  aliasTypeMap: arkIRTransformer.getAliasTypeMap()
1000
998
  };
@@ -1003,10 +1001,7 @@ class CfgBuilder {
1003
1001
  const cfg = new Cfg_1.Cfg();
1004
1002
  const blockBuilderToCfgBlock = new Map();
1005
1003
  let isStartingStmtInCfgBlock = true;
1006
- const stmtsInOriginalCfg = [];
1007
- const stmtSetInOriginalCfg = new Set();
1008
1004
  const arkIRTransformer = new ArkIRTransformer_1.ArkIRTransformer(this.sourceFile, this.declaringMethod);
1009
- const stmtToOriginalStmt = arkIRTransformer.getStmtToOriginalStmt();
1010
1005
  const blocksContainLoopCondition = new Set();
1011
1006
  for (let i = 0; i < this.blocks.length; i++) {
1012
1007
  // build block in Cfg
@@ -1015,10 +1010,10 @@ class CfgBuilder {
1015
1010
  stmtsInBlock.push(...arkIRTransformer.prebuildStmts());
1016
1011
  }
1017
1012
  for (const statementBuilder of this.blocks[i].stmts) {
1018
- if (statementBuilder.type == 'loopStatement') {
1013
+ if (statementBuilder.type === 'loopStatement') {
1019
1014
  blocksContainLoopCondition.add(this.blocks[i]);
1020
1015
  }
1021
- if (statementBuilder.astNode && statementBuilder.code != '') {
1016
+ if (statementBuilder.astNode && statementBuilder.code !== '') {
1022
1017
  stmtsInBlock.push(...arkIRTransformer.tsNodeToStmts(statementBuilder.astNode));
1023
1018
  }
1024
1019
  else if (statementBuilder.code.startsWith('return')) {
@@ -1036,19 +1031,33 @@ class CfgBuilder {
1036
1031
  }
1037
1032
  cfg.addBlock(blockInCfg);
1038
1033
  blockBuilderToCfgBlock.set(this.blocks[i], blockInCfg);
1039
- // collect stmts in OriginalCfg
1040
- for (const stmt of stmtsInBlock) {
1041
- const originalStmt = stmtToOriginalStmt.get(stmt);
1042
- if (originalStmt) {
1043
- if (!stmtSetInOriginalCfg.has(originalStmt)) {
1044
- stmtSetInOriginalCfg.add(originalStmt);
1045
- stmtsInOriginalCfg.push(originalStmt);
1046
- }
1047
- }
1048
- }
1049
1034
  }
1050
1035
  let currBlockId = this.blocks.length;
1051
- // link blocks
1036
+ this.linkBasicBlocks(blockBuilderToCfgBlock);
1037
+ this.rebuildBlocksInLoop(blockBuilderToCfgBlock, blocksContainLoopCondition, cfg);
1038
+ this.rebuildBlocksInConditionalOperator(cfg);
1039
+ for (const blockBuilder of this.blocks) {
1040
+ if (blockBuilder.id === -1) {
1041
+ blockBuilder.id = currBlockId++;
1042
+ const block = blockBuilderToCfgBlock.get(blockBuilder);
1043
+ block.setId(blockBuilder.id);
1044
+ }
1045
+ }
1046
+ for (const block of cfg.getBlocks()) {
1047
+ if (block.getId() === -1) {
1048
+ block.setId(currBlockId++);
1049
+ }
1050
+ }
1051
+ for (const stmt of cfg.getStmts()) {
1052
+ stmt.setCfg(cfg);
1053
+ }
1054
+ return {
1055
+ cfg: cfg,
1056
+ locals: arkIRTransformer.getLocals(),
1057
+ aliasTypeMap: arkIRTransformer.getAliasTypeMap(),
1058
+ };
1059
+ }
1060
+ linkBasicBlocks(blockBuilderToCfgBlock) {
1052
1061
  for (const [blockBuilder, cfgBlock] of blockBuilderToCfgBlock) {
1053
1062
  for (const successorBlockBuilder of blockBuilder.nexts) {
1054
1063
  if (!blockBuilderToCfgBlock.get(successorBlockBuilder)) {
@@ -1065,7 +1074,204 @@ class CfgBuilder {
1065
1074
  cfgBlock.addPredecessorBlock(predecessorBlock);
1066
1075
  }
1067
1076
  }
1068
- // put statements within loop in right position
1077
+ }
1078
+ rebuildBlocksInConditionalOperator(cfg) {
1079
+ var _a;
1080
+ for (const basicBlock of cfg.getBlocks()) {
1081
+ const stmts = Array.from(basicBlock.getStmts());
1082
+ const stmtCnt = stmts.length;
1083
+ let endPos = -1;
1084
+ for (let i = stmtCnt - 1; i >= 0; i--) {
1085
+ const stmt = stmts[i];
1086
+ if (stmt instanceof ArkIRTransformer_1.DummyStmt && ((_a = stmt.toString()) === null || _a === void 0 ? void 0 : _a.startsWith(ArkIRTransformer_1.ArkIRTransformer.DUMMY_CONDITIONAL_OPERATOR_END_STMT))) {
1087
+ endPos = i;
1088
+ break;
1089
+ }
1090
+ }
1091
+ if (endPos === -1) {
1092
+ continue;
1093
+ }
1094
+ const { topBlock, bottomBlocks, allBlocks, } = this.traverseAndRebuildConditionalOperator(stmts, 0, endPos);
1095
+ basicBlock.getStmts().splice(topBlock.getStmts().length);
1096
+ const succBlocksOfIfBlock = topBlock.getSuccessors();
1097
+ succBlocksOfIfBlock.forEach((block) => {
1098
+ block.setPredecessorBlock(0, basicBlock);
1099
+ });
1100
+ const conditionalOperatorBlockSet = new Set(allBlocks);
1101
+ this.adjustSuccessorOfConditionalOperator(basicBlock, succBlocksOfIfBlock, stmts, bottomBlocks, endPos, conditionalOperatorBlockSet);
1102
+ conditionalOperatorBlockSet.forEach((block) => {
1103
+ if (block !== topBlock) {
1104
+ cfg.addBlock(block);
1105
+ }
1106
+ });
1107
+ }
1108
+ }
1109
+ traverseAndRebuildConditionalOperator(stmts, beginPos, endPos) {
1110
+ const { ifTruePos, ifFalsePos, conditionalOperatorEndPos } = this.findConditionalOperator(stmts, beginPos, endPos);
1111
+ if (ifTruePos === -1) {
1112
+ const block = new BasicBlock_1.BasicBlock();
1113
+ block.getStmts().push(...stmts.slice(beginPos, endPos + 1));
1114
+ return { topBlock: block, bottomBlocks: [], allBlocks: [block] };
1115
+ }
1116
+ const allBlocks = [];
1117
+ const topBlock = new BasicBlock_1.BasicBlock();
1118
+ topBlock.getStmts().push(...stmts.slice(beginPos, ifTruePos));
1119
+ allBlocks.push(topBlock);
1120
+ const { topBlock: ifTrueTopBlock, bottomBlocks: ifTrueBottomBlocks, allBlocks: ifTrueAllBlocks, } = this.traverseAndRebuildConditionalOperator(stmts, ifTruePos + 1, ifFalsePos - 1);
1121
+ allBlocks.push(...ifTrueAllBlocks);
1122
+ const { topBlock: ifFalseTopBlock, bottomBlocks: ifFalseBottomBlocks, allBlocks: ifFalseAllBlocks, } = this.traverseAndRebuildConditionalOperator(stmts, ifFalsePos + 1, conditionalOperatorEndPos - 1);
1123
+ allBlocks.push(...ifFalseAllBlocks);
1124
+ topBlock.addSuccessorBlock(ifTrueTopBlock);
1125
+ topBlock.addSuccessorBlock(ifFalseTopBlock);
1126
+ ifTrueTopBlock.addPredecessorBlock(topBlock);
1127
+ ifFalseTopBlock.addPredecessorBlock(topBlock);
1128
+ let bottomBlocks = [];
1129
+ bottomBlocks.push(...(ifTrueBottomBlocks.length > 0 ? ifTrueBottomBlocks : [ifTrueTopBlock]));
1130
+ bottomBlocks.push(...(ifFalseBottomBlocks.length > 0 ? ifFalseBottomBlocks : [ifFalseTopBlock]));
1131
+ if (conditionalOperatorEndPos !== endPos) {
1132
+ const bottomBlock = new BasicBlock_1.BasicBlock();
1133
+ bottomBlock.getStmts().push(...stmts.slice(conditionalOperatorEndPos + 1, endPos + 1));
1134
+ bottomBlocks.forEach(block => {
1135
+ block.addSuccessorBlock(bottomBlock);
1136
+ bottomBlock.addPredecessorBlock(block);
1137
+ });
1138
+ bottomBlocks = [bottomBlock];
1139
+ allBlocks.push(bottomBlock);
1140
+ }
1141
+ return { topBlock: topBlock, bottomBlocks: bottomBlocks, allBlocks: allBlocks };
1142
+ }
1143
+ findConditionalOperator(stmts, beginPos, endPos) {
1144
+ let ifTruePos = -1;
1145
+ let ifFalsePos = -1;
1146
+ let conditionalOperatorEndPos = -1;
1147
+ let currConditionalOperatorNo = '';
1148
+ for (let i = beginPos; i <= endPos; i++) {
1149
+ const stmt = stmts[i];
1150
+ if (stmt instanceof ArkIRTransformer_1.DummyStmt) {
1151
+ if (stmt.toString()
1152
+ .startsWith(ArkIRTransformer_1.ArkIRTransformer.DUMMY_CONDITIONAL_OPERATOR_IF_TRUE_STMT) && ifTruePos === -1) {
1153
+ ifTruePos = i;
1154
+ currConditionalOperatorNo =
1155
+ stmt.toString().replace(ArkIRTransformer_1.ArkIRTransformer.DUMMY_CONDITIONAL_OPERATOR_IF_TRUE_STMT, '');
1156
+ }
1157
+ else if (stmt.toString() === ArkIRTransformer_1.ArkIRTransformer.DUMMY_CONDITIONAL_OPERATOR_IF_FALSE_STMT + currConditionalOperatorNo) {
1158
+ ifFalsePos = i;
1159
+ }
1160
+ else if (stmt.toString() === ArkIRTransformer_1.ArkIRTransformer.DUMMY_CONDITIONAL_OPERATOR_END_STMT + currConditionalOperatorNo) {
1161
+ conditionalOperatorEndPos = i;
1162
+ }
1163
+ }
1164
+ }
1165
+ return { ifTruePos: ifTruePos, ifFalsePos: ifFalsePos, conditionalOperatorEndPos: conditionalOperatorEndPos };
1166
+ }
1167
+ adjustSuccessorOfConditionalOperator(currBasicBlock, succBlocksOfIfBlock, stmts, bottomBlocks, conditionalOperatorEndPos, conditionalOperatorBlockSet) {
1168
+ const oldSuccBlocks = Array.from(currBasicBlock.getSuccessors());
1169
+ currBasicBlock.getSuccessors().splice(0, oldSuccBlocks.length, ...succBlocksOfIfBlock);
1170
+ oldSuccBlocks.forEach((succBlock) => {
1171
+ const originalPreds = succBlock.getPredecessors();
1172
+ for (let i = 0; i < originalPreds.length; i++) {
1173
+ if (originalPreds[i] === currBasicBlock) {
1174
+ succBlock.getPredecessors().splice(i, 1);
1175
+ break;
1176
+ }
1177
+ }
1178
+ });
1179
+ if (conditionalOperatorEndPos === stmts.length - 1) {
1180
+ oldSuccBlocks.forEach((oldSuccBlock) => {
1181
+ bottomBlocks.forEach((bottomBlock) => {
1182
+ bottomBlock.addSuccessorBlock(oldSuccBlock);
1183
+ oldSuccBlock.addSuccessorBlock(bottomBlock);
1184
+ });
1185
+ });
1186
+ }
1187
+ else {
1188
+ const insertSuccBlock = new BasicBlock_1.BasicBlock();
1189
+ insertSuccBlock.getStmts().push(...stmts.slice(conditionalOperatorEndPos + 1, stmts.length));
1190
+ oldSuccBlocks.forEach((oldSuccBlock) => {
1191
+ insertSuccBlock.addSuccessorBlock(oldSuccBlock);
1192
+ oldSuccBlock.addPredecessorBlock(insertSuccBlock);
1193
+ });
1194
+ bottomBlocks.forEach((bottomBlock) => {
1195
+ bottomBlock.addSuccessorBlock(insertSuccBlock);
1196
+ insertSuccBlock.addPredecessorBlock(bottomBlock);
1197
+ });
1198
+ conditionalOperatorBlockSet.add(insertSuccBlock);
1199
+ this.removeUnnecessaryBlocksInConditionalOperator(insertSuccBlock, conditionalOperatorBlockSet);
1200
+ }
1201
+ }
1202
+ removeUnnecessaryBlocksInConditionalOperator(bottomBlock, allBlocks) {
1203
+ const firstStmtInBottom = bottomBlock.getStmts()[0];
1204
+ if (!(firstStmtInBottom instanceof Stmt_1.ArkAssignStmt)) {
1205
+ return;
1206
+ }
1207
+ const targetValue = firstStmtInBottom.getLeftOp();
1208
+ const tempResultValue = firstStmtInBottom.getRightOp();
1209
+ if (!(targetValue instanceof Local_1.Local && IRUtils_1.IRUtils.isTempLocal(tempResultValue))) {
1210
+ return;
1211
+ }
1212
+ bottomBlock.remove(firstStmtInBottom);
1213
+ const oldPredecessors = bottomBlock.getPredecessors();
1214
+ const newPredecessors = [];
1215
+ for (const predecessor of oldPredecessors) {
1216
+ newPredecessors.push(...this.replaceTempResultcursively(predecessor, targetValue, tempResultValue, allBlocks));
1217
+ }
1218
+ bottomBlock.getPredecessors().splice(0, oldPredecessors.length, ...newPredecessors);
1219
+ newPredecessors.forEach((newPredecessor) => {
1220
+ newPredecessor.setSuccessorBlock(0, bottomBlock);
1221
+ });
1222
+ }
1223
+ replaceTempResultcursively(currBottomBlock, targetLocal, tempResultLocal, allBlocks) {
1224
+ const stmts = currBottomBlock.getStmts();
1225
+ const stmtsCnt = stmts.length;
1226
+ let tempResultReassignStmt = null;
1227
+ for (let i = stmtsCnt - 1; i >= 0; i--) {
1228
+ const stmt = stmts[i];
1229
+ if (stmt instanceof Stmt_1.ArkAssignStmt && stmt.getLeftOp() === tempResultLocal) {
1230
+ if (IRUtils_1.IRUtils.isTempLocal(stmt.getRightOp()) && this.isNewDefLocal(stmt.getRightOp(), stmts, i)) {
1231
+ tempResultReassignStmt = stmt;
1232
+ }
1233
+ else {
1234
+ stmt.setLeftOp(targetLocal);
1235
+ }
1236
+ }
1237
+ }
1238
+ let newBottomBlocks = [];
1239
+ if (tempResultReassignStmt) {
1240
+ const oldPredecessors = currBottomBlock.getPredecessors();
1241
+ const newPredecessors = [];
1242
+ const prevTempResultLocal = tempResultReassignStmt.getRightOp();
1243
+ for (const predecessor of oldPredecessors) {
1244
+ newPredecessors.push(...this.replaceTempResultcursively(predecessor, targetLocal, prevTempResultLocal, allBlocks));
1245
+ }
1246
+ currBottomBlock.remove(tempResultReassignStmt);
1247
+ if (currBottomBlock.getStmts().length === 0) {
1248
+ // remove this block
1249
+ newBottomBlocks = newPredecessors;
1250
+ allBlocks.delete(currBottomBlock);
1251
+ }
1252
+ else {
1253
+ currBottomBlock.getPredecessors().splice(0, oldPredecessors.length, ...newPredecessors);
1254
+ newPredecessors.forEach((newPredecessor) => {
1255
+ newPredecessor.setSuccessorBlock(0, currBottomBlock);
1256
+ });
1257
+ newBottomBlocks = [currBottomBlock];
1258
+ }
1259
+ }
1260
+ else {
1261
+ newBottomBlocks = [currBottomBlock];
1262
+ }
1263
+ return newBottomBlocks;
1264
+ }
1265
+ isNewDefLocal(local, stmts, pos) {
1266
+ for (let i = pos - 1; i >= 0; i++) {
1267
+ const stmt = stmts[i];
1268
+ if (stmt instanceof Stmt_1.ArkAssignStmt && stmt.getLeftOp() === local) {
1269
+ return false;
1270
+ }
1271
+ }
1272
+ return true;
1273
+ }
1274
+ rebuildBlocksInLoop(blockBuilderToCfgBlock, blocksContainLoopCondition, cfg) {
1069
1275
  for (const blockBuilder of blocksContainLoopCondition) {
1070
1276
  if (!blockBuilderToCfgBlock.get(blockBuilder)) {
1071
1277
  continue;
@@ -1074,38 +1280,11 @@ class CfgBuilder {
1074
1280
  const blockId = block.getId();
1075
1281
  const stmts = block.getStmts();
1076
1282
  const stmtsCnt = stmts.length;
1077
- let ifStmtIdx = -1;
1078
- let iteratorNextStmtIdx = -1;
1079
- let dummyInitializerStmtIdx = -1;
1080
- for (let i = 0; i < stmtsCnt; i++) {
1081
- const stmt = stmts[i];
1082
- if (stmt instanceof Stmt_1.ArkAssignStmt && stmt.getRightOp() instanceof Expr_1.AbstractInvokeExpr) {
1083
- const invokeExpr = stmt.getRightOp();
1084
- if (invokeExpr.getMethodSignature().getMethodSubSignature().getMethodName() == Builtin_1.Builtin.ITERATOR_NEXT) {
1085
- iteratorNextStmtIdx = i;
1086
- continue;
1087
- }
1088
- }
1089
- if (stmt.toString() == ArkIRTransformer_1.DUMMY_INITIALIZER_STMT) {
1090
- dummyInitializerStmtIdx = i;
1091
- continue;
1092
- }
1093
- if (stmt instanceof Stmt_1.ArkIfStmt) {
1094
- ifStmtIdx = i;
1095
- break;
1096
- }
1097
- }
1098
- if (iteratorNextStmtIdx != -1 || dummyInitializerStmtIdx != -1) {
1099
- // put statements into block before condition
1100
- const lastStmtIdxBeforeCondition = iteratorNextStmtIdx != -1 ? iteratorNextStmtIdx : dummyInitializerStmtIdx;
1283
+ const { ifStmtIdx, iteratorNextStmtIdx, dummyInitializerStmtIdx } = this.findIteratorIdx(stmts);
1284
+ if (iteratorNextStmtIdx !== -1 || dummyInitializerStmtIdx !== -1) {
1285
+ const lastStmtIdxBeforeCondition = iteratorNextStmtIdx !== -1 ? iteratorNextStmtIdx : dummyInitializerStmtIdx;
1101
1286
  const stmtsInsertBeforeCondition = stmts.slice(0, lastStmtIdxBeforeCondition);
1102
- let prevBlockBuilderContainsLoop = false;
1103
- for (const prevBlockBuilder of blockBuilder.lasts) {
1104
- if (prevBlockBuilder.id < blockId && blocksContainLoopCondition.has(prevBlockBuilder)) {
1105
- prevBlockBuilderContainsLoop = true;
1106
- break;
1107
- }
1108
- }
1287
+ let prevBlockBuilderContainsLoop = this.doesPrevBlockBuilderContainLoop(blockBuilder, blockId, blocksContainLoopCondition);
1109
1288
  if (prevBlockBuilderContainsLoop) {
1110
1289
  // should create an extra block when previous block contains loop condition
1111
1290
  this.insertBeforeConditionBlockBuilder(blockBuilderToCfgBlock, blockBuilder, stmtsInsertBeforeCondition, false, cfg);
@@ -1115,27 +1294,11 @@ class CfgBuilder {
1115
1294
  const blockBeforeCondition = blockBuilderToCfgBlock.get(blockBuilderBeforeCondition);
1116
1295
  blockBeforeCondition === null || blockBeforeCondition === void 0 ? void 0 : blockBeforeCondition.getStmts().push(...stmtsInsertBeforeCondition);
1117
1296
  }
1118
- if (dummyInitializerStmtIdx != -1 && ifStmtIdx != stmtsCnt - 1) {
1297
+ if (dummyInitializerStmtIdx !== -1 && ifStmtIdx !== stmtsCnt - 1) {
1119
1298
  // put incrementor statements into block which reenters condition
1120
- const stmtsReenterCondition = stmts.slice(ifStmtIdx + 1);
1121
- const blockBuildersReenterCondition = [];
1122
- for (const prevBlockBuilder of blockBuilder.lasts) {
1123
- const prevBlock = blockBuilderToCfgBlock.get(prevBlockBuilder);
1124
- if (prevBlock.getId() > blockId) {
1125
- blockBuildersReenterCondition.push(prevBlockBuilder);
1126
- }
1127
- }
1128
- if (blockBuildersReenterCondition.length > 1 || blocksContainLoopCondition.has(blockBuildersReenterCondition[0])) {
1129
- // put incrementor statements into an extra block
1130
- this.insertBeforeConditionBlockBuilder(blockBuilderToCfgBlock, blockBuilder, stmtsReenterCondition, true, cfg);
1131
- }
1132
- else {
1133
- // put incrementor statements into prev reenter block
1134
- const blockReenterCondition = blockBuilderToCfgBlock.get(blockBuildersReenterCondition[0]);
1135
- blockReenterCondition === null || blockReenterCondition === void 0 ? void 0 : blockReenterCondition.getStmts().push(...stmtsReenterCondition);
1136
- }
1299
+ this.adjustIncrementorStmts(stmts, ifStmtIdx, blockBuilder, blockId, blockBuilderToCfgBlock, blocksContainLoopCondition, cfg);
1137
1300
  }
1138
- else if (iteratorNextStmtIdx != -1) {
1301
+ else if (iteratorNextStmtIdx !== -1) {
1139
1302
  // put statements which get value of iterator into block after condition
1140
1303
  const blockBuilderAfterCondition = blockBuilder.nexts[0];
1141
1304
  const blockAfterCondition = blockBuilderToCfgBlock.get(blockBuilderAfterCondition);
@@ -1143,37 +1306,21 @@ class CfgBuilder {
1143
1306
  blockAfterCondition === null || blockAfterCondition === void 0 ? void 0 : blockAfterCondition.getStmts().splice(0, 0, ...stmtsAfterCondition);
1144
1307
  }
1145
1308
  // remove statements which should not in condition
1146
- const firstStmtIdxInCondition = iteratorNextStmtIdx != -1 ? iteratorNextStmtIdx : dummyInitializerStmtIdx + 1;
1309
+ const firstStmtIdxInCondition = iteratorNextStmtIdx !== -1 ? iteratorNextStmtIdx : dummyInitializerStmtIdx + 1;
1147
1310
  stmts.splice(0, firstStmtIdxInCondition);
1148
1311
  stmts.splice(ifStmtIdx - firstStmtIdxInCondition + 1);
1149
1312
  }
1150
1313
  }
1151
- for (const blockBuilder of this.blocks) {
1152
- if (blockBuilder.id == -1) {
1153
- blockBuilder.id = currBlockId++;
1154
- const block = blockBuilderToCfgBlock.get(blockBuilder);
1155
- block.setId(blockBuilder.id);
1156
- }
1157
- }
1158
- for (const stmt of cfg.getStmts()) {
1159
- stmt.setCfg(cfg);
1160
- }
1161
- const originalCfg = new Cfg_1.Cfg();
1162
- const originalCfgBlock = new BasicBlock_1.BasicBlock();
1163
- for (let i = 0; i < stmtsInOriginalCfg.length; i++) {
1164
- if (i === 0) {
1165
- originalCfg.setStartingStmt(stmtsInOriginalCfg[i]);
1314
+ }
1315
+ doesPrevBlockBuilderContainLoop(currBlockBuilder, currBlockId, blocksContainLoopCondition) {
1316
+ let prevBlockBuilderContainsLoop = false;
1317
+ for (const prevBlockBuilder of currBlockBuilder.lasts) {
1318
+ if (prevBlockBuilder.id < currBlockId && blocksContainLoopCondition.has(prevBlockBuilder)) {
1319
+ prevBlockBuilderContainsLoop = true;
1320
+ break;
1166
1321
  }
1167
- originalCfgBlock.addStmt(stmtsInOriginalCfg[i]);
1168
1322
  }
1169
- originalCfg.addBlock(originalCfgBlock);
1170
- return {
1171
- cfg: cfg,
1172
- originalCfg: originalCfg,
1173
- stmtToOriginalStmt: stmtToOriginalStmt,
1174
- locals: arkIRTransformer.getLocals(),
1175
- aliasTypeMap: arkIRTransformer.getAliasTypeMap(),
1176
- };
1323
+ return prevBlockBuilderContainsLoop;
1177
1324
  }
1178
1325
  insertBeforeConditionBlockBuilder(blockBuilderToCfgBlock, conditionBlockBuilder, stmtsInsertBeforeCondition, collectReenter, cfg) {
1179
1326
  const blockId = conditionBlockBuilder.id;
@@ -1213,7 +1360,7 @@ class CfgBuilder {
1213
1360
  for (const prevBlockBuilder of collectedBlockBuilders) {
1214
1361
  const prevBlock = blockBuilderToCfgBlock.get(prevBlockBuilder);
1215
1362
  for (let j = 0; j < prevBlockBuilder.nexts.length; j++) {
1216
- if (prevBlockBuilder.nexts[j] == conditionBlockBuilder) {
1363
+ if (prevBlockBuilder.nexts[j] === conditionBlockBuilder) {
1217
1364
  prevBlockBuilder.nexts[j] = blockBuilderInsertBeforeCondition;
1218
1365
  prevBlock.setSuccessorBlock(j, blockInsertBeforeCondition);
1219
1366
  break;
@@ -1237,5 +1384,54 @@ class CfgBuilder {
1237
1384
  cfg.addBlock(blockInsertBeforeCondition);
1238
1385
  blockBuilderToCfgBlock.set(blockBuilderInsertBeforeCondition, blockInsertBeforeCondition);
1239
1386
  }
1387
+ findIteratorIdx(stmts) {
1388
+ let ifStmtIdx = -1;
1389
+ let iteratorNextStmtIdx = -1;
1390
+ let dummyInitializerStmtIdx = -1;
1391
+ const stmtsCnt = stmts.length;
1392
+ for (let i = 0; i < stmtsCnt; i++) {
1393
+ const stmt = stmts[i];
1394
+ if (stmt instanceof Stmt_1.ArkAssignStmt && stmt.getRightOp() instanceof Expr_1.AbstractInvokeExpr) {
1395
+ const invokeExpr = stmt.getRightOp();
1396
+ if (invokeExpr.getMethodSignature().getMethodSubSignature()
1397
+ .getMethodName() === Builtin_1.Builtin.ITERATOR_NEXT) {
1398
+ iteratorNextStmtIdx = i;
1399
+ continue;
1400
+ }
1401
+ }
1402
+ if (stmt.toString() === ArkIRTransformer_1.ArkIRTransformer.DUMMY_LOOP_INITIALIZER_STMT) {
1403
+ dummyInitializerStmtIdx = i;
1404
+ continue;
1405
+ }
1406
+ if (stmt instanceof Stmt_1.ArkIfStmt) {
1407
+ ifStmtIdx = i;
1408
+ break;
1409
+ }
1410
+ }
1411
+ return {
1412
+ ifStmtIdx: ifStmtIdx,
1413
+ iteratorNextStmtIdx: iteratorNextStmtIdx,
1414
+ dummyInitializerStmtIdx: dummyInitializerStmtIdx,
1415
+ };
1416
+ }
1417
+ adjustIncrementorStmts(stmts, ifStmtIdx, currBlockBuilder, currBlockId, blockBuilderToCfgBlock, blocksContainLoopCondition, cfg) {
1418
+ const stmtsReenterCondition = stmts.slice(ifStmtIdx + 1);
1419
+ const blockBuildersReenterCondition = [];
1420
+ for (const prevBlockBuilder of currBlockBuilder.lasts) {
1421
+ const prevBlock = blockBuilderToCfgBlock.get(prevBlockBuilder);
1422
+ if (prevBlock.getId() > currBlockId) {
1423
+ blockBuildersReenterCondition.push(prevBlockBuilder);
1424
+ }
1425
+ }
1426
+ if (blockBuildersReenterCondition.length > 1 || blocksContainLoopCondition.has(blockBuildersReenterCondition[0])) {
1427
+ // put incrementor statements into an extra block
1428
+ this.insertBeforeConditionBlockBuilder(blockBuilderToCfgBlock, currBlockBuilder, stmtsReenterCondition, true, cfg);
1429
+ }
1430
+ else {
1431
+ // put incrementor statements into prev reenter block
1432
+ const blockReenterCondition = blockBuilderToCfgBlock.get(blockBuildersReenterCondition[0]);
1433
+ blockReenterCondition === null || blockReenterCondition === void 0 ? void 0 : blockReenterCondition.getStmts().push(...stmtsReenterCondition);
1434
+ }
1435
+ }
1240
1436
  }
1241
1437
  exports.CfgBuilder = CfgBuilder;