Package backend

Source Code of backend.StmtCodeGenerator

package backend;

import java.util.HashMap;

import soot.Unit;
import soot.Value;
import soot.jimple.IntConstant;
import soot.jimple.Jimple;
import soot.jimple.NopStmt;
import soot.util.Chain;
import ast.ASTNode;
import ast.Block;
import ast.BreakStmt;
import ast.ExprStmt;
import ast.IfStmt;
import ast.ReturnStmt;
import ast.Stmt;
import ast.Visitor;
import ast.WhileStmt;

/**
* This class is in charge of creating Jimple code for a given statement (and its nested
* statements, if applicable).
*/
/**
* TODO
* @author Danyang
* The statement code generator is a visitor class, with different methods performing code generation for
different kinds of statements. Note that the visitor type parameter is Void, representing the fact that the statement
code generator returns no values; it simply appends the statements it generates to the statement list in field units.
(For somewhat silly reasons, the visitor methods still need to return null, however.) You are asked to supply the
missing implementations of the visitor methods for ExprStmt, BreakStmt, and WhileStmt; the TODO comments
will get you started, and Figure 1 below lists all the API methods you will need.
*/
public class StmtCodeGenerator extends Visitor<Void> {
  /** Cache Jimple singleton for convenience. */
  private final Jimple j = Jimple.v();
 
  /** The {@link FunctionCodeGenerator} that created this object. */
  private final FunctionCodeGenerator fcg;
 
  /** The statement list of the enclosing function body. */
  private final Chain<Unit> units;
 
  /** A map from while statements to their break target. */
  private final HashMap<WhileStmt, Unit> breakTargets = new HashMap<WhileStmt, Unit>();
 
  public StmtCodeGenerator(FunctionCodeGenerator fcg) {
    this.fcg = fcg;
    this.units = fcg.getBody().getUnits();
  }
 
  /** Generates code for an expression statement. */
  @Override
  public Void visitExprStmt(ExprStmt nd) {
    /* DONE: generate code for expression statement (hint: use ExprCodeGenerator.generate) */
    ExprCodeGenerator.generate(nd.getExpr(), this.fcg);
    return null; // dummy
  }
 
  /** Generates code for a break statement. */
  @Override
  public Void visitBreakStmt(BreakStmt nd) {
    /* DONE: generate code for break statement (hint: use ASTNode.getEnclosingLoop and breakTargets;
     *       use units.add() to insert the statement into the surrounding method) */
    WhileStmt whileStmt = nd.getEnclosingLoop();
    Unit breakTargetUnit = this.breakTargets.get(whileStmt);
    this.units.add(j.newGotoStmt(breakTargetUnit));
    return null; // dummy
  }

  /** Generates code for a block of statements. */
  @Override
  public Void visitBlock(Block nd) {
    for(Stmt stmt : nd.getStmts())
      stmt.accept(this);
    return null;
  }
 
  /** Generates code for a return statement. */
  @Override
  public Void visitReturnStmt(ReturnStmt nd) {
    Unit stmt;
    if(nd.hasExpr())
      stmt = j.newReturnStmt(ExprCodeGenerator.generate(nd.getExpr(), fcg));
    else
      stmt = j.newReturnVoidStmt();
    units.add(stmt);
    return null;
  }
 
  /** Generates code for an if statement. */
  @Override
  public Void visitIfStmt(IfStmt nd) {
    Value cond = ExprCodeGenerator.generate(nd.getExpr(), fcg);
    NopStmt join = j.newNopStmt();
    units.add(j.newIfStmt(j.newEqExpr(cond, IntConstant.v(0)), join));
    nd.getThen().accept(this);
    if(nd.hasElse()) {
      NopStmt els = join;
      join = j.newNopStmt();
      units.add(j.newGotoStmt(join));
      units.add(els);
      nd.getElse().accept(this);
    }
    units.add(join);
    return null;
  }
   
  /** Generates code for a while statement. */
  @Override
  public Void visitWhileStmt(WhileStmt nd) {
    /* DONE: generate code for while statement as discussed in lecture; add the NOP statement you
     *       generate as the break target to the breakTargets map
     */
    /* Structure of While Statements
    label0:
    // compute value of cond
    c = �
    if c == 0 goto label1
    // code for body
    goto label0
    label1:
     */
    NopStmt label0 = j.newNopStmt();
    this.units.add(label0);
   
    Value cond = ExprCodeGenerator.generate(nd.getExpr(), this.fcg);
    NopStmt label1 = j.newNopStmt();
    this.units.add(
        j.newIfStmt(
            j.newEqExpr(cond, IntConstant.v(0)),
            label1
            )
          );
    this.breakTargets.put(nd, label1); // break // must put before accept
    nd.getBody().accept(this);
    this.units.add(j.newGotoStmt(label0));
    this.units.add(label1);
    return null; // dummy
  }
}
TOP

Related Classes of backend.StmtCodeGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.