Package compiler.imcode

Source Code of compiler.imcode.IMCodeGenerator

package compiler.imcode;

import java.util.LinkedList;

import compiler.abstree.AbsArrTyp;
import compiler.abstree.AbsAtomExpr;
import compiler.abstree.AbsAtomTyp;
import compiler.abstree.AbsBinExpr;
import compiler.abstree.AbsDecl;
import compiler.abstree.AbsDecls;
import compiler.abstree.AbsForStmt;
import compiler.abstree.AbsFunDecl;
import compiler.abstree.AbsFunName;
import compiler.abstree.AbsIfStmt;
import compiler.abstree.AbsLetExpr;
import compiler.abstree.AbsPtrTyp;
import compiler.abstree.AbsRecTyp;
import compiler.abstree.AbsStmt;
import compiler.abstree.AbsStmts;
import compiler.abstree.AbsTypDecl;
import compiler.abstree.AbsTypName;
import compiler.abstree.AbsUnExpr;
import compiler.abstree.AbsValExpr;
import compiler.abstree.AbsValStmt;
import compiler.abstree.AbsVarDecl;
import compiler.abstree.AbsVarName;
import compiler.abstree.AbsWhileStmt;
import compiler.abstree.Visitor;
import compiler.frames.ArgAccess;
import compiler.frames.CmpAccess;
import compiler.frames.Frame;
import compiler.frames.Label;
import compiler.frames.LocAccess;
import compiler.frames.VarAccess;
import compiler.report.Report;
import compiler.semanal.SemAtomTyp;
import compiler.semanal.SemFunTyp;
import compiler.semanal.SemPtrTyp;
import compiler.semanal.SemRecTyp;

public class IMCodeGenerator implements Visitor
{
  public LinkedList<ImcChunk> chunks = new LinkedList<ImcChunk>();
  private int scopeLevel = 0;
  private Frame currentFrame = null;
 
  @Override
  public Object visit(AbsArrTyp node)
  {
    // Nothing TBD
    return null;
  }

  @Override
  public Object visit(AbsAtomExpr node)
  {
    switch(node.typ_desc)
    {
      case AbsAtomExpr.STRING:
        ImcConstChunk stringConst = new ImcConstChunk(Label.newLabel(), node.value);
        chunks.add(stringConst);
       
        return new ImcNAME(stringConst.label);
       
      case AbsAtomExpr.BOOL:
        int boolvalue = 0;
       
        if (node.value.equals("true"))
          boolvalue = 1;
        else
          boolvalue = 0;
       
        return new ImcCONST(boolvalue);
     
      case AbsAtomExpr.INT:
        return new ImcCONST(Integer.parseInt(node.value));
     
      case AbsAtomExpr.PTR:
      case AbsAtomExpr.VOID:
        return new ImcCONST(0);
     
      case AbsAtomExpr.CHAR:
        // Check for escaped chars
        int charValue = 0;
       
        if (node.value.length() > 3)
        {
          if (node.value.equals("'\\n'"))
            charValue = Character.valueOf('\n').charValue();
          else if (node.value.equals("'\\''"))
            charValue = Character.valueOf('\'').charValue();
          else if (node.value.equals("'\\\\'"))
            charValue = Character.valueOf('\\').charValue();
        }
        else
        {
          charValue = (int)node.value.charAt(1);
        }
       
        return new ImcCONST(charValue);
     
      default:
        return null;
    }
  }

  @Override
  public Object visit(AbsAtomTyp node)
  {
    // Nothing TBD
    return null;
  }

  @Override
  public Object visit(AbsBinExpr node)
  {
    switch(node.op)
    {
      case AbsBinExpr.ADD:
        return new ImcBINOP(ImcBINOP.ADD, (ImcExpr)node.lsub.accept(this), (ImcExpr)node.rsub.accept(this));
     
      case AbsBinExpr.SUB:
        return new ImcBINOP(ImcBINOP.SUB, (ImcExpr)node.lsub.accept(this), (ImcExpr)node.rsub.accept(this));
     
      case AbsBinExpr.MUL:
        return new ImcBINOP(ImcBINOP.MUL, (ImcExpr)node.lsub.accept(this), (ImcExpr)node.rsub.accept(this));
     
      case AbsBinExpr.DIV:
        return new ImcBINOP(ImcBINOP.DIV, (ImcExpr)node.lsub.accept(this), (ImcExpr)node.rsub.accept(this));
     
      case AbsBinExpr.EQU:
        return new ImcBINOP(ImcBINOP.EQU, (ImcExpr)node.lsub.accept(this), (ImcExpr)node.rsub.accept(this));
       
      case AbsBinExpr.GTH:
        return new ImcBINOP(ImcBINOP.GTH, (ImcExpr)node.lsub.accept(this), (ImcExpr)node.rsub.accept(this));
     
      case AbsBinExpr.GEQ:
        return new ImcBINOP(ImcBINOP.GEQ, (ImcExpr)node.lsub.accept(this), (ImcExpr)node.rsub.accept(this));
       
      case AbsBinExpr.LTH:
        return new ImcBINOP(ImcBINOP.LTH, (ImcExpr)node.lsub.accept(this), (ImcExpr)node.rsub.accept(this));
       
      case AbsBinExpr.LEQ:
        return new ImcBINOP(ImcBINOP.LEQ, (ImcExpr)node.lsub.accept(this), (ImcExpr)node.rsub.accept(this));
       
      case AbsBinExpr.NEQ:
        return new ImcBINOP(ImcBINOP.NEQ, (ImcExpr)node.lsub.accept(this), (ImcExpr)node.rsub.accept(this));
     
      case AbsBinExpr.AND:
        return new ImcBINOP(ImcBINOP.AND, (ImcExpr)node.lsub.accept(this), (ImcExpr)node.rsub.accept(this));
     
      case AbsBinExpr.OR:
        return new ImcBINOP(ImcBINOP.OR, (ImcExpr)node.lsub.accept(this), (ImcExpr)node.rsub.accept(this));
       
      case AbsBinExpr.IS:
        return new ImcMOVE((ImcExpr)node.lsub.accept(this), (ImcExpr)node.rsub.accept(this));
     
      case AbsBinExpr.DOT:
        // Get record var access tree
        ImcExpr expr = (ImcExpr) node.lsub.accept(this);
       
        // Right hand component
        AbsVarName comp = (AbsVarName)node.rsub;
       
        CmpAccess access = null;
       
        // Get access from component list
        for (AbsVarDecl cmp : ((SemRecTyp)node.lsub.semTyp.actual()).comps)
        {
          if (cmp.name.equals(comp.name))
          {
            // Found component, assign access
            access = (CmpAccess) cmp.access;
            break;
          }
        }
       
        // Create result
        return new ImcMEM(new ImcBINOP(ImcBINOP.ADD, expr, new ImcCONST(access.offset)));
       
      case AbsBinExpr.ARR:
        // Get basic array access data
        ImcMEM arrayAccess = (ImcMEM) node.lsub.accept(this);
       
        // Create addition operation meaning rsub * CONST type_size
        ImcExpr add = new ImcBINOP(ImcBINOP.ADD, arrayAccess, new ImcBINOP(ImcBINOP.MUL, (ImcExpr)node.rsub.accept(this), new ImcCONST(node.semTyp.size())));
       
        return new ImcMEM(add);
       
      default:
        Report.error("Switch value not implemented!", 100);
     
    }
   
    return null;
  }

  @Override
  public Object visit(AbsDecls node)
  {
    // Iterate over declarations and add their chunks to list
    for (AbsDecl decl : node.decls)
    {
      decl.accept(this);
    }
     
    return chunks;
  }

  @Override
  public Object visit(AbsForStmt node)
  {
    // For sequence
    ImcSEQ forSequence = new ImcSEQ();
   
    ImcExpr var = (ImcExpr)node.expr.accept(this);
    ImcExpr lo = (ImcExpr)node.lo.accept(this);
    ImcExpr hi = (ImcExpr)node.hi.accept(this);
   
    // Initialize variable with starting value with MOVE
    ImcMOVE init = new ImcMOVE(var, lo);
   
    ImcLABEL lblCondition = new ImcLABEL(Label.newLabel());
    ImcLABEL lblStatements = new ImcLABEL(Label.newLabel());
    ImcLABEL lblEnd = new ImcLABEL(Label.newLabel());
   
    // Condition value check
    ImcCJUMP condition = new ImcCJUMP(new ImcBINOP(ImcBINOP.GTH, var, hi), lblEnd.label, lblStatements.label);
   
    // Collect sequence together
    forSequence.stmts.add(init);
    forSequence.stmts.add(lblCondition);
    forSequence.stmts.add(condition);
    forSequence.stmts.add(lblStatements);
    forSequence.stmts.add((ImcStmt) node.stmts.accept(this));
    // Increment loop counter
    forSequence.stmts.add(new ImcMOVE(var, new ImcBINOP(ImcBINOP.ADD, var, new ImcCONST(1))));
    // Jump back to condition
    forSequence.stmts.add(new ImcJUMP(lblCondition.label));
    // End label
    forSequence.stmts.add(lblEnd);
   
    return forSequence;
  }

  @Override
  public Object visit(AbsFunDecl node)
  {
    // Change valid scope level
    scopeLevel++;
   
    Frame oldFrame = currentFrame;
    currentFrame = node.frame;
   
    // Evaluate function code, then check if the result is an expression
    // Because void functions can have non-expressions as code we need to check that and wrap them into
    // ESEQ call with 0 result
    ImcExpr functionCode = null;
    Object code = node.val.accept(this);
   
    if (code instanceof ImcExpr)
    {
      functionCode = (ImcExpr) code;
    }
    else
    {
      ImcESEQ eseq = new ImcESEQ((ImcStmt) code, new ImcCONST(0));
      functionCode = eseq;
    }
   
    // Restore valid scope level
    scopeLevel--;
   
    // Restore currentframe
    currentFrame = oldFrame;
   
    ImcCodeChunk codeChunk = null;
   
    // Void function
    if (((SemFunTyp)node.semTyp).result instanceof SemAtomTyp &&
      ((SemAtomTyp)((SemFunTyp)node.semTyp).result).typ_desc == SemAtomTyp.VOID)
    {
      ImcESEQ eseq = (ImcESEQ)functionCode;
      codeChunk = new ImcCodeChunk(node.frame, eseq.stmt);
    }
    else
    {
      ImcMOVE moveResult = new ImcMOVE(new ImcTEMP(node.frame.RV), functionCode);
     
      // Add data chunk
      codeChunk = new ImcCodeChunk(node.frame, moveResult);
    }
 
    chunks.add(codeChunk);
   
    return codeChunk;
  }

  @Override
  public Object visit(AbsFunName node)
  {
    ImcCALL functionCall = new ImcCALL(node.decl.frame.label);
   
    functionCall.args.add(new ImcTEMP(currentFrame.FP));
   
    // Intercept new call and replace argument with size of the datatype
    if (node.decl.frame.label.name().equals("_new"))
    {
      // Intercept new function call and turn it into a pointer assignment sequence
      functionCall.args.add(new ImcCONST(((SemPtrTyp)node.args.get(0).semTyp.actual()).base.size()));
     
      // Pointer assignment
      ImcMOVE ptr = new ImcMOVE((ImcExpr) node.args.get(0).accept(this), functionCall);
     
      return ptr;
    }
   
    // Evaulate arguments
    if (node.args != null)
    {
      for (AbsValExpr args : node.args)
      {
        functionCall.args.add((ImcExpr) args.accept(this));
      }
    }
   
    // Void functions require expression node above
    if (((SemFunTyp)node.decl.semTyp).result.actual() instanceof SemAtomTyp &&
      ((SemAtomTyp)((SemFunTyp)node.decl.semTyp).result.actual()).typ_desc == SemAtomTyp.VOID)
    {
      return new ImcEXP(functionCall);
    }
    else
    {
      return functionCall;
    }
  }

  @Override
  public Object visit(AbsIfStmt node)
  {
    // IF is a sequence of commands depending on the expression
    ImcSEQ ifSequence = new ImcSEQ();
   
    ImcLABEL thenLabel = new ImcLABEL(Label.newLabel());
    ImcLABEL endThenLabel = new ImcLABEL(Label.newLabel());
   
    ImcCJUMP condition = new ImcCJUMP((ImcExpr)node.cond.accept(this), thenLabel.label, endThenLabel.label);
   
    // No else statement
    if (node.else_stmts == null)
    {
      ifSequence.stmts.add(condition);
      ifSequence.stmts.add(thenLabel);
      ifSequence.stmts.add((ImcStmt) node.then_stmts.accept(this));
      ifSequence.stmts.add(endThenLabel);
    }
    else
    {
      ImcLABEL endElseLabel = new ImcLABEL(Label.newLabel());
     
      ifSequence.stmts.add(condition);
      ifSequence.stmts.add(thenLabel);
      ifSequence.stmts.add((ImcStmt) node.then_stmts.accept(this));
      ifSequence.stmts.add(new ImcJUMP(endElseLabel.label));
      ifSequence.stmts.add(endThenLabel);
      ifSequence.stmts.add((ImcStmt) node.else_stmts.accept(this));
      ifSequence.stmts.add(endElseLabel);
    }
   
    return ifSequence;
  }

  @Override
  public Object visit(AbsLetExpr node)
  {   
    ImcSEQ stmts = new ImcSEQ();
    // Get command sequence and finishing expression
    if (node.stmts != null)
    {
      stmts = (ImcSEQ) node.stmts.accept(this);
    }
   
    if (node.defs != null)
    {
      node.defs.accept(this);
    }
   
   
    ImcExpr expr = (ImcExpr)node.expr.accept(this);
   
    // Is this a void statement?
    /*if (node.semTyp.actual() instanceof SemAtomTyp &&
      ((SemAtomTyp)node.semTyp.actual()).typ_desc == SemAtomTyp.VOID)
    {
      return stmts;
    }*/
   
    // Let statement is just an expreesion sequence
    ImcESEQ letStmt = new ImcESEQ(stmts, expr);
   
    return letStmt;
  }

  @Override
  public Object visit(AbsPtrTyp node)
  {
    // Nothing TBD
    return null;
  }

  @Override
  public Object visit(AbsRecTyp node)
  {
    // Nothing TBD
    return null;
  }

  @Override
  public Object visit(AbsStmts node)
  {
    // Create sequence
    ImcSEQ statements = new ImcSEQ();
   
    for (AbsStmt statement : node.stmts)
    {
      Object stmtCode = statement.accept(this);
      ImcStmt stmt = null;
     
      if (stmtCode instanceof ImcStmt)
      {
        stmt = (ImcStmt)stmtCode;
      }
      else
      {
        stmt = ((ImcESEQ)stmtCode).stmt;
      }
     
      // DEBUG
      assert(stmt != null);
      statements.stmts.addFirst(stmt);
    }
   
    return statements;
  }

  @Override
  public Object visit(AbsTypDecl node)
  {
    // Nothing TBD
    return null;
  }

  @Override
  public Object visit(AbsTypName node)
  {
    // Nothing TBD
    return null;
  }

  @Override
  public Object visit(AbsUnExpr node)
  {
    switch(node.op)
    {
      case AbsUnExpr.ADD:
        return node.sub.accept(this);
     
      case AbsUnExpr.SUB:
        return new ImcBINOP(ImcBINOP.SUB, new ImcCONST(0), (ImcExpr) node.sub.accept(this));
     
      case AbsUnExpr.NOT:
        ImcExpr var = (ImcExpr) node.sub.accept(this);
       
        ImcSEQ flipSeq = new ImcSEQ();
       
        // Comparison expression
        ImcExpr cmpExpr = new ImcBINOP(ImcBINOP.EQU, var, new ImcCONST(0));
       
        // True
        ImcMOVE trueStmt = new ImcMOVE(var, new ImcCONST(1));
       
        // False
        ImcMOVE falseStmt = new ImcMOVE(var, new ImcCONST(0));
       
        ImcLABEL trueLbl = new ImcLABEL(Label.newLabel());
        ImcLABEL falseLbl = new ImcLABEL(Label.newLabel());
        ImcLABEL endLbl = new ImcLABEL(Label.newLabel());
       
        // Create comparison and flip sequence
       
        flipSeq.stmts.add(new ImcCJUMP(cmpExpr, trueLbl.label, falseLbl.label));
        flipSeq.stmts.add(trueLbl);
        flipSeq.stmts.add(trueStmt);
        flipSeq.stmts.add(new ImcJUMP(endLbl.label));
        flipSeq.stmts.add(falseLbl);
        flipSeq.stmts.add(falseStmt);
        flipSeq.stmts.add(endLbl);
       
        ImcESEQ notSeq = new ImcESEQ(flipSeq, var);
       
        return notSeq;
     
      case AbsUnExpr.VAL:
        ImcMEM varAccess = (ImcMEM) node.sub.accept(this);
        return new ImcMEM(varAccess.expr);
     
      case AbsUnExpr.REF:
        ImcMEM variableAccess = (ImcMEM) node.sub.accept(this);
        return variableAccess.expr;
    }
   
    return null;
  }

  @Override
  public Object visit(AbsValStmt node)
  {
    return node.expr.accept(this);
  }

  @Override
  public Object visit(AbsVarDecl node)
  {
    // Global variable
    if (node.access instanceof VarAccess)
    {
      chunks.add(new ImcDataChunk(((VarAccess)node.access).label, node.semTyp.size()));
    }
   
    return null;
  }

  @Override
  public Object visit(AbsVarName node)
  {
    // Check variable access
    if (node.decl.access instanceof VarAccess)
    {
      // Global variable
      VarAccess access = (VarAccess)node.decl.access;
      return new ImcMEM(new ImcNAME(access.label));
    }
    else if (node.decl.access instanceof ArgAccess)
    {
      ArgAccess access = (ArgAccess)node.decl.access;
      ImcExpr fpAccess = new ImcTEMP(access.frame.FP);
     
      // Count scope delta and add required amount of memory accesses
      for (int i = 0; i < (scopeLevel - 1) - access.frame.level; i++)
      {
        fpAccess = new ImcMEM(fpAccess);
      }
     
      return new ImcMEM(new ImcBINOP(ImcBINOP.ADD, fpAccess, new ImcCONST(access.offset)));
    }
    else
    {
      LocAccess access = (LocAccess)node.decl.access;
      ImcExpr fpAccess = new ImcTEMP(currentFrame.FP);
     
      // Count scope delta and add required amount of memory accesses
      for (int i = 0; i < (scopeLevel - 1) - access.frame.level; i++)
      {
        fpAccess = new ImcMEM(fpAccess);
      }
     
      // Add offset of varibale in frame to the frame pointer address
      return new ImcMEM(new ImcBINOP(ImcBINOP.ADD, fpAccess, new ImcCONST(access.offset)));
    }
  }

  @Override
  public Object visit(AbsWhileStmt node)
  {
    ImcLABEL startLabel = new ImcLABEL(Label.newLabel());
    ImcLABEL stmtsLabel = new ImcLABEL(Label.newLabel());
    ImcLABEL endLabel = new ImcLABEL(Label.newLabel());
   
    // Jump to end of code on false
    ImcCJUMP cJump = new ImcCJUMP((ImcExpr) node.cond.accept(this), stmtsLabel.label, endLabel.label);
   
    ImcSEQ whileSeq = new ImcSEQ();
   
    whileSeq.stmts.add(startLabel);
    whileSeq.stmts.add(cJump);
    whileSeq.stmts.add(stmtsLabel);
    whileSeq.stmts.add((ImcStmt) node.stmts.accept(this));
    // Jummp to condition
    whileSeq.stmts.add(new ImcJUMP(startLabel.label));
    whileSeq.stmts.add(endLabel);
   
    return whileSeq;
  }
 
}
TOP

Related Classes of compiler.imcode.IMCodeGenerator

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.