예제 #1
0
  /**
   * This method runs through the expression in order to generate the corresponding assembly code.
   * At the end of the run, the result is always stored in Register.RAX
   */
  public StringBuffer handleExpression(Expression e, Context context) throws Exception {
    StringBuffer sb = new StringBuffer();
    String lastReg;
    if (Parser.DEBUG) System.out.println("\nHandling expression: \"" + this.toString() + "\"");
    if (this.right == null) {
      // Handle leaf

      if (this instanceof Variable) {
        if (Parser.DEBUG) System.out.println("\tVariable caught: " + ((Variable) this).getValue());
        sb = ExpressionHelper.handleVariable(sb, (Variable) this, Register.RAX, context);
      } else if (this instanceof FunctionCall) {
        if (Parser.DEBUG)
          System.out.println("\tFunction-call caught: " + ((FunctionCall) this).getTag());
        sb = ExpressionHelper.handleFunctionCall(sb, (FunctionCall) this, context);
      }
      return sb;
    }

    sb.append(this.left.handleExpression(e, context));
    if (this.flag != null && this.flag.equals(Flag.UMINUS))
      sb.append(ExpressionHelper.asm(Assembly.NEG, Register.RAX));

    if (this.right.op != null && this.right.priority == false) {
      // Handle expression with three or more operands

      if (this.right.left.priority) {
        // Handle priority expression first (parentheses).
        this.right.left.priority = false;

        sb.append(context.virtualPush(Register.RAX.toString()));
        sb.append(this.right.left.handleExpression(e, context));
        sb.append(context.virtualPop(Register.RDX.toString()));
        sb = ExpressionHelper.handleOperation(sb, this.op, Register.RAX, Register.RDX);
        sb.append(context.virtualPush(Register.RAX.toString()));
        sb.append(this.right.right.handleExpression(e, context));
        sb.append(context.virtualPop(Register.RDX.toString()));
        sb = ExpressionHelper.handleOperation(sb, this.right.op, Register.RAX, Register.RDX);
      } else if (ExpressionHelper.getPrecedence(this.op.toString())
          > ExpressionHelper.getPrecedence(this.right.op.toString())) {
        // Handle operators of higher precedence first.

        if (this.right.left instanceof Variable)
          sb =
              ExpressionHelper.handleVariable(
                  sb, (Variable) this.right.left, Register.RDX, context);
        else {
          sb.append(ExpressionHelper.asm(Assembly.MOV, Register.RAX, Register.RDX));
          sb = ExpressionHelper.handleFunctionCall(sb, (FunctionCall) this.right.left, context);
        }

        sb = ExpressionHelper.handleOperation(sb, this.op, Register.RDX, Register.RAX);
        sb.append(context.virtualPush(Register.RAX.toString()));
        sb.append(this.right.right.handleExpression(e, context));
        sb.append(context.virtualPop(Register.RDX.toString()));
        sb = ExpressionHelper.handleOperation(sb, this.right.op, Register.RAX, Register.RDX);
      } else {
        sb.append(context.virtualPush(Register.RAX.toString()));
        sb.append(this.right.handleExpression(e, context));
        sb.append(ExpressionHelper.asm(Assembly.MOV, Register.RAX, Register.RDX));
        sb.append(context.virtualPop(Register.RAX.toString()));
        sb = ExpressionHelper.handleOperation(sb, this.op, Register.RAX, Register.RDX);
      }
    } else {
      // Handle simple node (l op r)

      if (this.right.priority) {
        sb.append(context.virtualPush(Register.RAX.toString()));
        sb.append(this.right.handleExpression(e, context));
        sb.append(context.virtualPop(Register.RDX.toString()));
        sb = ExpressionHelper.handleOperation(sb, this.op, Register.RAX, Register.RDX);
      } else if (this.right instanceof Variable) {

        if (((Variable) this.right).getValue() instanceof Integer) {
          if (this.right.flag != null && this.right.flag.equals(Flag.UMINUS))
            sb =
                ExpressionHelper.handleOperation(
                    sb, this.op, "$-" + ((Variable) this.right).getValue());
          else
            sb =
                ExpressionHelper.handleOperation(
                    sb, this.op, "$" + ((Variable) this.right).getValue());
        } else {

          if (((Variable) this.right).index != null)
            sb.append(context.virtualPush(Register.RAX.toString()));
          sb = ExpressionHelper.handleVariable(sb, (Variable) this.right, Register.RDX, context);

          if (((Variable) this.right).index != null) {
            sb.append(ExpressionHelper.asm(Assembly.MOV, Register.RAX, Register.RDX));
            sb.append(context.virtualPop(Register.RAX.toString()));
          }
          sb = ExpressionHelper.handleOperation(sb, this.op, Register.RDX, Register.RAX);
        }
      } else if (this.right instanceof FunctionCall) {
        sb.append(context.virtualPush(Register.RAX.toString()));
        sb = ExpressionHelper.handleFunctionCall(sb, (FunctionCall) this.right, context);
        sb.append(context.virtualPop(Register.RDX.toString()));
        sb = ExpressionHelper.handleOperation(sb, this.op, Register.RAX, Register.RDX);
        sb.append(ExpressionHelper.asm(Assembly.MOV, Register.RAX, Register.RDX));
      }
    }

    return sb;
  }