Write your liveness analysis in the file cs6340srcLivenessAn

Write your liveness analysis in the file cs6340/src/LivenessAnalysis.java and your reaching definitions analysis in the file cs6340/src/ReachDefAnalysis.java .

Follow the instructions in those files for how to write the analyses.

LivenessAnalysis.java

import chord.project.Chord;
import joeq.Compiler.Quad.RegisterFactory.Register;

@Chord(name=\"liveness\")
public class LivenessAnalysis extends DataflowAnalysis<Register> {
   @Override
   public void doAnalysis() {
       // Implement your liveness dataflow analysis here.
       //
       // File DataflowAnalysis.java defines instance fields main, inMap, and
       // outMap, which will serve as the inputs and outputs of your analysis:
       //
       // INPUT: Method main.
       //
       // OUTPUT: Populate maps inMap and outMap with the results of your
       // liveness analysis of method main.
       //
       // Specifically, for each Quad q in the control-flow graph of main,
       // inMap(q) and outMap(q) must contain the sets of all Registers that
       // may be live on entry and on exit, respectively, of q. You can leave
       // a set either null or empty if it does not contain any registers.
       //
       // Your analysis will be graded for the following aspects in decreasing
       // order of importance:
       // 1. Correctness of the results produced by the analysis.
       // 2. Efficiency of the analysis, in particular, the number of times you
       // revisit each quad.
       //
       // Add helper instance methods to this class if necessary. All your
       // code must be in this class itself, and it must be written in Java.
       //
       // Note: This is a single procedure analysis; you do not need to
       // consult any pointer analysis, call graph, or any method of the given
       // program besides the provided main method.
   }
}

ReachDefAnalysis.java

import chord.project.Chord;
import chord.util.tuple.object.Pair;
import joeq.Compiler.Quad.Quad;
import joeq.Compiler.Quad.RegisterFactory.Register;

@Chord(name=\"reachdef\")
public class ReachDefAnalysis extends DataflowAnalysis<Pair<Quad, Register>> {
   @Override
   public void doAnalysis() {
       // Implement your reaching definitions dataflow analysis here.
       //
       // File DataflowAnalysis.java defines instance fields main, inMap, and
       // outMap, which will serve as the inputs and outputs of your analysis:
       //
       // INPUT: Method main.
       //
       // OUTPUT: Populate maps inMap and outMap with the results of your
       // reaching definitions analysis of method main.
       //
       // Specifically, for each Quad q in the control-flow graph of main,
       // inMap(q) and outMap(q) must contain the sets of all <Quad, Register>
       // definitions that may reach the entry and the exit, respectively, of
       // q. You can leave a set either null or empty if it does not contain
       // any reaching definitions.
       //
       // Your analysis will be graded for the following aspects in decreasing
       // order of importance:
       //
       // 1. Correctness of the results produced by the analysis.
       // 2. Efficiency of the analysis, in particular, the number of times you
       // revisit each quad.
       //
       // Add helper instance methods to this class if necessary. All your
       // code must be in this class itself, and it must be written in Java.
       //
       // Note: This is a single procedure analysis; you do not need to
       // consult any pointer analysis, call graph, or any method of the given
       // program besides the provided main method.
   }
}

Solution

LivenessAnalysis.java

import chord.project.Chord;
import chord.project.analyses.JavaAnalysis;
import chord.program.Program;

import joeq.Class.jq_Method;
import joeq.Compiler.Quad.*;
import joeq.Compiler.Quad.RegisterFactory.Register;
import joeq.Compiler.Quad.Operand.RegisterOperand;

import java.util.*;

@Chord(name=\"liveness\")
public class LivenessAnalysis extends DataflowAnalysis<Register> {
   @Override
   public void doAnalysis() {
       // Implement your liveness dataflow analysis here.
       //
       // File DataflowAnalysis.java defines instance fields main, inMap, and
       // outMap, which will serve as the inputs and outputs of your analysis:
       //
       // INPUT: Method main.
       //
       // OUTPUT: Populate maps inMap and outMap with the results of your
       // liveness analysis of method main.
       //
       // Specifically, for each Quad q in the control-flow graph of main,
       // inMap(q) and outMap(q) must contain the sets of all Registers that
       // may be live on entry and on exit, respectively, of q. You can leave
       // a set either null or empty if it does not contain any registers.
       //
       // Your analysis will be graded for the following aspects in decreasing
       // order of importance:
       // 1. Correctness of the results produced by the analysis.
       // 2. Efficiency of the analysis, in particular, the number of times you
       // revisit each quad.
       // 3. Clarity of your source code. While we will run automatic tests
       // to evaluate correctness, we might need to read your source code to
       // evaluate the efficiency of your analysis. So, it is important that
       // your code be concise and readable. Adding comments is not required
       // but it won\'t hurt if you comment your code.
       //
       // Add helper instance methods to this class if necessary. All your
       // code must be in this class itself, and it must be written in Java
       // (for instance, you cannot use Datalog).
       //
       // Note: This is a single procedure analysis; you do not need to
       // consult any pointer analysis, call graph, or any method of the given
       // program besides the provided main method.
      
       main = Program.g().getMainMethod();
       if (main.isAbstract())
           throw new RuntimeException(\"Method \" + main + \" is abstract\");
       ControlFlowGraph cfg = main.getCFG();
      
       int count = 0;
       boolean changed = true;
       boolean last = true;
       List<Quad> quads;
       Set<Register> in, out;
      
       System.out.println(\"Begin analysis...\");
       while(changed) {
           count++;
           changed = false;
           System.out.println(\"Iteration \" + count + \"...\");
          
           // Backwards traversal
           for(BasicBlock bb : cfg.reversePostOrderOnReverseGraph()) {
              
               quads = bb.getQuads();
               last = true;
               for(int i = quads.size() - 1; i >= 0; i--) {
                   Quad q = quads.get(i);
                   Set<Quad> succs = getSuccessors(q, bb, last, i);
                   last = false;
                  
                   out = new HashSet<Register>();
                   in = new HashSet<Register>();
                  
                   // Union of entry of successors
                   for(Quad succ_q : succs) {
                       Set<Register> set = inMap.get(succ_q);
                       if(set != null)
                           out.addAll(set);
                   }
                  
                   List<RegisterOperand> def = q.getDefinedRegisters();
                   List<RegisterOperand> used = q.getUsedRegisters();
                  
                   in.addAll(out);
                   // Remove kill set
                   for(RegisterOperand ro : def)
                       in.remove(ro.getRegister());
                  
                   // Add gen set
                   for(RegisterOperand ro : used)
                       in.add(ro.getRegister());
                  
                   Set<Register> prev_in = inMap.put(q, in);
                   Set<Register> prev_out = outMap.put(q, out);
                  
                   // Reiterate over everything if changes occurred
                   if(!changed && (prev_in == null || (prev_in != null && !prev_in.equals(in)) ||
                           prev_out == null || (prev_out != null && !prev_out.equals(out))))
                       changed = true;
               }
           }
       }
       System.out.println(\"Analysis finished after \" + count + \" iterations.\");
   }
  
   private Set<Quad> getSuccessors(Quad q, BasicBlock bb, boolean last, int index) {
      
       Set<Quad> succs = new HashSet<Quad>();
      
       if(last) {
           for(BasicBlock succ_bb : bb.getSuccessors())
               if(succ_bb.size() > 0)
                   succs.add(succ_bb.getQuad(0));
          
           return succs;
       }
      
       succs.add(bb.getQuad(index + 1));
       return succs;
   }
}

ReachDefAnalysis.java

import java.util.*;

import chord.project.Chord;
import chord.util.tuple.object.Pair;
import chord.project.analyses.JavaAnalysis;
import chord.program.Program;

import joeq.Class.jq_Method;
import joeq.Compiler.Quad.*;
import joeq.Compiler.Quad.RegisterFactory.Register;
import joeq.Compiler.Quad.Operand.RegisterOperand;

@Chord(name=\"reachdef\")
public class ReachDefAnalysis extends DataflowAnalysis<Pair<Quad, Register>> {
   @Override
   public void doAnalysis() {
       // Implement your reaching definitions dataflow analysis here.
       //
       // File DataflowAnalysis.java defines instance fields main, inMap, and
       // outMap, which will serve as the inputs and outputs of your analysis:
       //
       // INPUT: Method main.
       //
       // OUTPUT: Populate maps inMap and outMap with the results of your
       // reaching definitions analysis of method main.
       //
       // Specifically, for each Quad q in the control-flow graph of main,
       // inMap(q) and outMap(q) must contain the sets of all <Quad, Register>
       // definitions that may reach the entry and the exit, respectively, of
       // q. You can leave a set either null or empty if it does not contain
       // any reaching definitions.
       //
       // Your analysis will be graded for the following aspects in decreasing
       // order of importance:
       //
       // 1. Correctness of the results produced by the analysis.
       // 2. Efficiency of the analysis, in particular, the number of times you
       // revisit each quad.
       // 3. Clarity of your source code. While we will run automatic tests
       // to evaluate correctness, we might need to read your source code to
       // evaluate the efficiency of your analysis. So, it is important that
       // your code be concise and readable. Adding comments is not required
       // but it won\'t hurt if you comment your code.
       //
       // Add helper instance methods to this class if necessary. All your
       // code must be in this class itself, and it must be written in Java
       // (for instance, you cannot use Datalog).
       //
       // Note: This is a single procedure analysis; you do not need to
       // consult any pointer analysis, call graph, or any method of the given
       // program besides the provided main method.
      
       main = Program.g().getMainMethod();
       if (main.isAbstract())
           throw new RuntimeException(\"Method \" + main + \" is abstract\");
       ControlFlowGraph cfg = main.getCFG();
      
       int count = 0;
       boolean changed = true;
       boolean last = true;
       List<Quad> quads;
       Set<Pair<Quad,Register>> in, out;
      
       System.out.println(\"Begin analysis...\");
       while(changed) {
           count++;
           changed = false;
           System.out.println(\"Iteration \" + count + \"...\");
          
           // Forward traversal
           for(BasicBlock bb : cfg.reversePostOrder()) {
               for(Quad q : bb.getQuads()) {
                  
                   Set<Quad> preds = getPredecessors(q, bb);
                  
                   in = new HashSet<Pair<Quad,Register>>();
                   out = new HashSet<Pair<Quad,Register>>();
                  
                   // Union of exit of predecessors
                   for(Quad pred_q : preds) {
                       Set<Pair<Quad,Register>> set = outMap.get(pred_q);
                       if(set != null)
                           in.addAll(set);
                   }
                  
                   List<RegisterOperand> def = q.getDefinedRegisters();
                  
                   out.addAll(in);
                   // Remove kill set
                   out = removeKilled(out, def);
                  
                   // Add gen set
                   for(RegisterOperand ro : def) {
                       out.add(new Pair(q,ro.getRegister()));
                   }
                  
                   Set<Pair<Quad,Register>> prev_in = inMap.put(q, in);
                   Set<Pair<Quad,Register>> prev_out = outMap.put(q, out);
                  
                   // Reiterate over everything if changes occurred
                   if(!changed && (prev_in == null || (prev_in != null && !prev_in.equals(in)) ||
                           prev_out == null || (prev_out != null && !prev_out.equals(out))))
                       changed = true;
               }
           }
       }
       System.out.println(\"Analysis finished after \" + count + \" iterations.\");
   }
  
   private Set<Quad> getPredecessors(Quad q, BasicBlock bb) {
      
       int index = bb.getQuadIndex(q);
       Set<Quad> preds = new HashSet<Quad>();
      
       if(index == 0) {
           for(BasicBlock pred_bb : bb.getPredecessors())
               if(pred_bb.size() > 0)
                   preds.add(bb.getLastQuad());
          
           return preds;
       }
      
       preds.add(bb.getQuad(index - 1));
       return preds;
   }
  
   private Set<Pair<Quad,Register>> removeKilled(Set<Pair<Quad,Register>> set, List<RegisterOperand> def) {
      
       Set<Pair<Quad,Register>> ret = new HashSet<Pair<Quad,Register>>();
      
       boolean add;
       for(Pair p : set) {
           add = true;
           for(RegisterOperand ro : def) {
               if(p.val1.equals(ro.getRegister())) {
                   add = false;
                   break;
               }
           }
           if(add)
               ret.add(p);
       }
      
       return ret;
   }
}

Write your liveness analysis in the file cs6340/src/LivenessAnalysis.java and your reaching definitions analysis in the file cs6340/src/ReachDefAnalysis.java .
Write your liveness analysis in the file cs6340/src/LivenessAnalysis.java and your reaching definitions analysis in the file cs6340/src/ReachDefAnalysis.java .
Write your liveness analysis in the file cs6340/src/LivenessAnalysis.java and your reaching definitions analysis in the file cs6340/src/ReachDefAnalysis.java .
Write your liveness analysis in the file cs6340/src/LivenessAnalysis.java and your reaching definitions analysis in the file cs6340/src/ReachDefAnalysis.java .
Write your liveness analysis in the file cs6340/src/LivenessAnalysis.java and your reaching definitions analysis in the file cs6340/src/ReachDefAnalysis.java .
Write your liveness analysis in the file cs6340/src/LivenessAnalysis.java and your reaching definitions analysis in the file cs6340/src/ReachDefAnalysis.java .

Get Help Now

Submit a Take Down Notice

Tutor
Tutor: Dr Jack
Most rated tutor on our site