静态分析-死代码检测


对应南京大学的软件分析课程作业。死代码包括不可达代码和无用赋值

一、不可达代码

不可达代码包括控制流不可达以及分支不可达
控制流不可达只需要遍历一遍所有的可达语句(通过cfg中的node之间的关系),不属于可达语句的便是不可达
分支不可达只需要获取条件变量的常量值,额外的分支就是不可达

二、无用赋值

一个变量被赋值,但是在后面的语句中没有再次被使用,那么这个赋值就是无用的

三、代码

通过作业1和作业2,可以得到每个node的常量IN和OUT以及存活变量IN和OUT,因此这里只展示将二者综合分析的代码,即DeadCodeDection的analyze函数。

代码如下(示例):

    @Override
    public Set<Stmt> analyze(IR ir) {
        // obtain CFG
        CFG<Stmt> cfg = ir.getResult(CFGBuilder.ID);
        // obtain result of constant propagation 作业2
        DataflowResult<Stmt, CPFact> constants =
                ir.getResult(ConstantPropagation.ID);
        // obtain result of live variable analysis 作业1
        DataflowResult<Stmt, SetFact<Var>> liveVars =
                ir.getResult(LiveVariableAnalysis.ID);
        // keep statements (dead code) sorted in the resulting set
        Set<Stmt> deadCode = new TreeSet<>(Comparator.comparing(Stmt::getIndex));
        // TODO - finish me
      	 //首先获取所有的控制流可达代码
        Set<Stmt> reachnableCode=new HashSet<>();
        for (Stmt stmt:cfg){
            for (Stmt succ:cfg.getSuccsOf(stmt)){
                reachnableCode.add(succ);
            }
        }
        // Your task is to recognize dead code in ir and add it to deadCode
        for(Stmt stmt:cfg){
            //不可达代码
            //如果是控制流不可达
            if (!reachnableCode.contains(stmt)&&!cfg.isEntry(stmt)){
                deadCode.add(stmt);
                continue;
            }
            //分支不可达
            //如果是if语句
            if (stmt instanceof If){
                If ifStmt=(If) stmt;
                Var conditionVar=ifStmt.getCondition().getOperand1();
                if (constants.getOutFact(stmt).get(conditionVar).isConstant()){
                    if (constants.getOutFact(stmt).get(conditionVar).getConstant()==0){
                        for(Edge<Stmt> edge:cfg.getOutEdgesOf(stmt)){
                            if (edge.getKind()==Edge.Kind.IF_TRUE){
                                deadCode.add(edge.getTarget());
                            }
                        }
                    }else {
                        for(Edge<Stmt> edge:cfg.getOutEdgesOf(stmt)){
                            if (edge.getKind()==Edge.Kind.IF_FALSE){
                                deadCode.add(edge.getTarget());
                            }
                        }
                    }
                }
            }
            //如果是Switch语句
            else if (stmt instanceof SwitchStmt){
                SwitchStmt switchStmt=(SwitchStmt) stmt;
                Var conditionVar=switchStmt.getVar();
                if (constants.getOutFact(stmt).get(conditionVar).isConstant()){
                    for (Edge<Stmt> edge:cfg.getOutEdgesOf(stmt)){
                        if (edge.getCaseValue()!=constants.getOutFact(stmt).get(conditionVar).getConstant()){
                            deadCode.add(edge.getTarget());
                        }
                    }
                }
            }
            //如果是赋值语句,无用赋值
            else if (stmt instanceof AssignStmt){
                LValue def=stmt.getDef().get();
                if (def instanceof Var){
                    Var defV=(Var) def;
                    if (!liveVars.getOutFact(stmt).contains(defV)){
                        deadCode.add(stmt);
                    }
                }
            }
        }
        return deadCode;
    }

四、运行结果

注意结果的输出顺序是每个函数->存活变量结果,常量传播结果,死代码结果。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值