1/* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. 4 * You may obtain a copy of the License at 5 * 6 * http://www.apache.org/licenses/LICENSE-2.0 7 * 8 * Unless required by applicable law or agreed to in writing, software 9 * distributed under the License is distributed on an "AS IS" BASIS, 10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 * See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15import { Constant } from '../../core/base/Constant'; 16import { AbstractExpr, AbstractInvokeExpr } from '../../core/base/Expr'; 17import { AbstractFieldRef } from '../../core/base/Ref'; 18import { ArkAssignStmt, ArkInvokeStmt, ArkIfStmt, ArkReturnStmt, ArkThrowStmt, Stmt, ArkReturnVoidStmt, ArkAliasTypeDefineStmt } from '../../core/base/Stmt'; 19import { Value } from '../../core/base/Value'; 20import { DummyStmt } from '../../core/common/ArkIRTransformer'; 21import { MFPDataFlowSolver } from '../../core/dataflow/GenericDataFlow'; 22import { ReachingDefProblem } from '../../core/dataflow/ReachingDef'; 23import { NodeID } from '../../core/graph/BaseExplicitGraph'; 24import { ArkMethod } from '../../core/model/ArkMethod'; 25import { FieldSignature } from '../../core/model/ArkSignature'; 26import { Scene } from '../../Scene'; 27import { DVFG, DVFGNode } from '../DVFG'; 28 29export class DVFGBuilder { 30 private dvfg: DVFG; 31 private scene: Scene; 32 33 constructor(dvfg: DVFG, s: Scene) { 34 this.dvfg = dvfg; 35 this.scene = s; 36 } 37 38 public build(): void { 39 this.scene.getMethods().forEach(m => { 40 if (m.getCfg()) { 41 this.buildForSingleMethod(m); 42 } 43 }); 44 } 45 46 public buildForSingleMethod(m: ArkMethod): void { 47 let problem = new ReachingDefProblem(m); 48 let solver = new MFPDataFlowSolver(); 49 let solution = solver.calculateMopSolutionForwards(problem); 50 51 let defMap = new Map<Value | FieldSignature, Set<Stmt>>(); 52 m.getCfg()! 53 .getStmts() 54 .forEach(s => { 55 let def: Value | FieldSignature | null = s.getDef(); 56 if (def != null) { 57 if (def instanceof AbstractFieldRef) { 58 def = def.getFieldSignature(); 59 } 60 let defStmts = defMap.get(def) ?? new Set<Stmt>(); 61 defStmts.add(s); 62 defMap.set(def, defStmts); 63 } 64 }); 65 66 solution.in.forEach((defs, reach) => { 67 let addNewNodes = (defId: NodeID, def: Stmt, reach: Stmt): void => { 68 if (defs.test(defId)) { 69 let srcNode = this.dvfg.getOrNewDVFGNode(def); 70 let dstNode = this.dvfg.getOrNewDVFGNode(reach); 71 this.dvfg.addDVFGEdge(srcNode, dstNode); 72 } 73 }; 74 75 const reachStmt = problem.flowGraph.getNode(reach); 76 this.getStmtUsedValues(reachStmt).forEach(use => { 77 let target: Value | FieldSignature = use; 78 if (target instanceof AbstractFieldRef) { 79 target = target.getFieldSignature(); 80 } 81 defMap.get(target)?.forEach(defStmt => { 82 let defId = problem.flowGraph.getNodeID(defStmt); 83 addNewNodes(defId, defStmt, reachStmt); 84 }); 85 }); 86 }); 87 } 88 89 private getStmtUsedValues(stmt: Stmt): Value[] { 90 if (stmt instanceof ArkAssignStmt) { 91 return this.getUsedValues(stmt.getRightOp()); 92 } else if (stmt instanceof ArkInvokeStmt) { 93 return this.getUsedValues(stmt.getInvokeExpr()); 94 } else if (stmt instanceof ArkIfStmt) { 95 return this.getUsedValues(stmt.getConditionExpr()); 96 } else if (stmt instanceof ArkReturnStmt) { 97 return this.getUsedValues(stmt.getOp()); 98 } else if (stmt instanceof ArkThrowStmt) { 99 return this.getUsedValues(stmt.getOp()); 100 } else if (stmt instanceof ArkReturnVoidStmt || stmt instanceof ArkAliasTypeDefineStmt || stmt instanceof DummyStmt) { 101 return []; 102 } else { 103 throw new Error('unsupported stmt'); 104 } 105 } 106 107 private getUsedValues(val: Value): Value[] { 108 if (val instanceof AbstractExpr) { 109 if (val instanceof AbstractInvokeExpr) { 110 return val.getArgs().flatMap(current => { 111 return this.getUsedValues(current); 112 }, []); 113 } else { 114 return val.getUses().flatMap(current => { 115 return this.getUsedValues(current); 116 }, []); 117 } 118 } 119 if (val instanceof Constant) { 120 return []; 121 } 122 return [val]; 123 } 124 125 public getOrNewDVFGNode(stmt: Stmt): DVFGNode { 126 return this.dvfg.getOrNewDVFGNode(stmt); 127 } 128 129 public addDVFGNodes(): void {} 130 131 public addDVFGEdges(): void {} 132} 133