summaryrefslogtreecommitdiff
path: root/submit/ast/Call.java
blob: 25ab2ea5fb4da401c7afa240ba71c886a0831b09 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * Code formatter project
 * CS 4481
 */
package submit.ast;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import submit.MIPSResult;
import submit.RegisterAllocator;
import submit.SymbolTable;

/**
 *
 * @author edwajohn
 */
public class Call implements Expression {

  private final String id;
  private final List<Expression> args;

  public Call(String id, List<Expression> args) {
    this.id = id;
    this.args = new ArrayList<>(args);
  }

  private void println(List<MIPSResult> mipsResults, StringBuilder code,
                       StringBuilder data, SymbolTable symbolTable,
                       RegisterAllocator regAllocator) {
    code.append("# println\n");

    for (MIPSResult result : mipsResults) {
      if (result.getRegister() == null && result.getAddress() != null) {
        if (result.getAddress().startsWith("$")) {
          // Hack - might be a register
          regAllocator.loadIntoRegister(result, code, "$a0");
        } else {
          code.append(String.format("la $a0 %s\n", result.getAddress()));
        }
      } else if (result.getRegister() != null) {
        code.append(String.format("move $a0 %s\n", result.getRegister()));
      }

      if (result.getType() == VarType.INT) {
        code.append("li $v0 1\n");
      } else if (result.getType() == VarType.CHAR) {
        code.append("li $v0 11\n");
      } else {
        code.append("li $v0 4\n");
      }
      code.append("syscall\n");
    }

    // End line with newline
    code.append(String.format("la $a0 %s\n", "newline"));
    code.append("li $v0 4\n");
    code.append("syscall\n");
  }

  @Override
  public void toCminus(StringBuilder builder, String prefix) {
    builder.append(id).append("(");
    for (Expression arg : args) {
      arg.toCminus(builder, prefix);
      builder.append(", ");
    }
    if (!args.isEmpty()) {
      builder.setLength(builder.length() - 2);
    }
    builder.append(")");
  }

  @Override
  public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
                           SymbolTable symbolTable,
                           RegisterAllocator regAllocator) {
    List<MIPSResult> argMips;
    String resultRegister = null;

    if (this.id.equals("println")) {
      argMips =
          args.stream()
              .map(e -> e.toMIPS(code, data, symbolTable, regAllocator))
              .collect(Collectors.toList());
      this.println(argMips, code, data, symbolTable, regAllocator);
    } else {
      argMips = new ArrayList<MIPSResult>();
      String returnAddr = regAllocator.getAny();
      code.append(String.format("move %s $ra\n", returnAddr));
      int savedRegistersOffset = regAllocator.saveRestore(
          code, -symbolTable.getOffset(), false, true);

      int argsOffset = symbolTable.getOffset() - savedRegistersOffset;
      int i = argsOffset;
      for (Expression expression : args) {
        MIPSResult mipsResult =
            expression.toMIPS(code, data, symbolTable, regAllocator);
        argMips.add(mipsResult);
        i -= 4;

        String reg =
            regAllocator.getRegisterOrLoadIntoRegister(mipsResult, code);
        code.append(String.format("sw %s %d($sp)\n", reg, i));

        regAllocator.clear(reg);
      }

      code.append(String.format("add $sp $sp %d\n", argsOffset));

      code.append(String.format("jal %s\n", id));

      code.append(String.format("add $sp $sp %d\n", -argsOffset));

      regAllocator.saveRestore(code, -symbolTable.getOffset(), false,
                                    false);
      code.append(String.format("# symbol table size - %d\n", i));

      resultRegister = regAllocator.getAny();
      regAllocator.loadIntoRegisterWithOffset(
          MIPSResult.createAddressResult("$sp", VarType.INT), code,
          resultRegister, i - 4);

      code.append(String.format("move $ra %s\n", returnAddr));
      regAllocator.clear(returnAddr);
    }

    for (MIPSResult arg : argMips)
      if (arg.getRegister() != null)
        regAllocator.clear(arg.getRegister());

    if (resultRegister != null) {
      VarType returnType = symbolTable.find(id).getType();
      return MIPSResult.createRegisterResult(resultRegister, returnType);
    }

    return MIPSResult.createVoidResult();
  }
}