对应南京大学的软件分析课程作业。死代码包括不可达代码和无用赋值
一、不可达代码
不可达代码包括控制流不可达以及分支不可达
控制流不可达只需要遍历一遍所有的可达语句(通过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;
}
四、运行结果
注意结果的输出顺序是每个函数->存活变量结果,常量传播结果,死代码结果。