• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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