Package org.renjin.gcc.translate.var

Source Code of org.renjin.gcc.translate.var.PrimitivePtrVar$ArrayElementExpr

package org.renjin.gcc.translate.var;

import org.renjin.gcc.jimple.Jimple;
import org.renjin.gcc.jimple.JimpleExpr;
import org.renjin.gcc.jimple.JimpleType;
import org.renjin.gcc.translate.FunctionContext;
import org.renjin.gcc.translate.TypeChecker;
import org.renjin.gcc.translate.PrimitiveAssignment;
import org.renjin.gcc.translate.expr.*;
import org.renjin.gcc.translate.type.*;


public class PrimitivePtrVar extends AbstractImExpr implements Variable, ImIndirectExpr {


  private enum OffsetType {
    BYTES,
    ELEMENTS
  }

  private FunctionContext context;
  private String gimpleName;
  private final ImPrimitivePtrType type;
  private String jimpleArrayName;
  private String jimpleOffsetName;

  public PrimitivePtrVar(FunctionContext context, String gimpleName, ImPrimitivePtrType type) {
    this.context = context;
    this.gimpleName = gimpleName;
    this.type = type;
    this.jimpleArrayName = Jimple.id(gimpleName) + "_array";
    this.jimpleOffsetName = Jimple.id(gimpleName + "_offset");

    context.getBuilder().addVarDecl(type.getArrayClass(), jimpleArrayName);
    context.getBuilder().addVarDecl(JimpleType.INT, jimpleOffsetName);
  }

  private int sizeOf() {
    return type.getBaseType().getStorageSizeInBytes();
  }

  @Override
  public void writeAssignment(FunctionContext context, ImExpr rhs) {
    if(rhs.isNull()) {
      context.getBuilder().addStatement(jimpleArrayName + " = null");
    } else if(rhs instanceof ImIndirectExpr) {
      ArrayRef ptr = ((ImIndirectExpr) rhs).translateToArrayRef(context);
      context.getBuilder().addStatement(jimpleArrayName + " = " +  ptr.getArrayExpr());
      context.getBuilder().addStatement(jimpleOffsetName + " = " + ptr.getIndexExpr());
    } else {
      throw new UnsupportedOperationException(rhs.toString());
    }
  }

  @Override
  public ArrayRef translateToArrayRef(FunctionContext context) {
    return new ArrayRef(jimpleArrayName, jimpleOffsetName);
  }


  @Override
  public ImExpr memref() {
    return new ValueExpr();
  }

  @Override
  public ImPrimitivePtrType type() {
    return type;
  }

  @Override
  public ImExpr pointerPlus(ImExpr offset) {
    return new OffsetExpr(offset, OffsetType.BYTES);
  }

  @Override
  public String toString() {
    return gimpleName + ":" + type;
  }

  /**
   * An expression representing this pointer + an offset (p+4)
   *
   */
  public class OffsetExpr extends AbstractImExpr implements ImIndirectExpr {

    private ImExpr offset;
    private OffsetType offsetType;


    public OffsetExpr(ImExpr offset, OffsetType offsetType) {
      super();
      this.offset = offset;
      this.offsetType = offsetType;
    }

    @Override
    public ImIndirectType type() {
      return PrimitivePtrVar.this.type();
    }

    public PrimitivePtrVar variable() {
      return PrimitivePtrVar.this;
    }

    @Override
    public ArrayRef translateToArrayRef(FunctionContext context) {
      return new ArrayRef(jimpleArrayName, computeIndex());
    }

    private JimpleExpr computeIndex() {
      if(offsetType == OffsetType.BYTES) {
        JimpleExpr bytesToIncrement = offset.translateToPrimitive(context, ImPrimitiveType.INT);
        String positionsToIncrement = context.declareTemp(JimpleType.INT);
        context.getBuilder().addStatement(positionsToIncrement + " = " + bytesToIncrement + " / " + sizeOf());
        return new JimpleExpr(jimpleOffsetName + " + " + positionsToIncrement);   
      } else {
        return new JimpleExpr(jimpleOffsetName + " + " +
            offset.translateToPrimitive(context, ImPrimitiveType.INT));
      }
    }
  }

  /**
   * An expression representing the value of the pointer
   * (*x)
   *
   */
  public class ValueExpr extends AbstractImExpr implements PrimitiveLValue, ImLValue {


    @Override
    public ImExpr addressOf() {
      return PrimitivePtrVar.this;
    }

    @Override
    public JimpleExpr translateToPrimitive(FunctionContext context, ImPrimitiveType type) {
      return type.castIfNeeded(
          new JimpleExpr(jimpleArrayName + "[" + jimpleOffsetName + "]"),
          type());
    }

    @Override
    public ImPrimitiveType type() {
      return type.getBaseType();
    }

    @Override
    public void writePrimitiveAssignment(JimpleExpr expr) {
      context.getBuilder().addStatement(jimpleArrayName + "[" + jimpleOffsetName + "] = " + expr);
    }

    @Override
    public void writeAssignment(FunctionContext context, ImExpr rhs) {
      PrimitiveAssignment.assign(context, this, rhs);
    }

    @Override
    public ImExpr elementAt(ImExpr index) {
      return new ArrayElementExpr(index);
    }

  }

  public class ArrayElementExpr extends AbstractImExpr implements PrimitiveLValue, ImLValue {

    /**
     * Index of the array, with reference to the current offset.
     */
    private ImExpr index;

    public ArrayElementExpr(ImExpr index) {
      if(!TypeChecker.isInt(index.type())) {
        throw new UnsupportedOperationException();
      }
      this.index = index;
    }

    @Override
    public JimpleExpr translateToPrimitive(FunctionContext context, ImPrimitiveType type) {
      // get the overall index
      return type.castIfNeeded(
          new JimpleExpr(jimpleArrayName + "[" + computeOverallIndex(context) + "]"),
          this.type());
    }

   
    /**
     * Create a temporary variable storing the index of the element this expr references
     * with reference to the beginning of the array.
     * @return the name of the temporary variable
     */
    private String computeOverallIndex(FunctionContext context) {
      String overallIndex = context.declareTemp(JimpleType.INT);
      context.getBuilder().addStatement(overallIndex + " = " + jimpleOffsetName + " + " +
              index.translateToPrimitive(context, ImPrimitiveType.INT));
      return overallIndex;
    }


    @Override
    public ImExpr addressOf() {
      return new OffsetExpr(index, OffsetType.ELEMENTS);
    }

    @Override
    public ImPrimitiveType type() {
      return type.getBaseType();
    }

    @Override
    public void writePrimitiveAssignment(JimpleExpr expr) {
      context.getBuilder().addStatement(jimpleArrayName + "[" + computeOverallIndex(context) + "] = " + expr);
    }

    @Override
    public void writeAssignment(FunctionContext context, ImExpr rhs) {
      PrimitiveAssignment.assign(context, this, rhs);
    }
  }
}
TOP

Related Classes of org.renjin.gcc.translate.var.PrimitivePtrVar$ArrayElementExpr

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.