summaryrefslogtreecommitdiff
path: root/submit/ast/Call.java
diff options
context:
space:
mode:
Diffstat (limited to 'submit/ast/Call.java')
-rw-r--r--submit/ast/Call.java104
1 files changed, 103 insertions, 1 deletions
diff --git a/submit/ast/Call.java b/submit/ast/Call.java
index b6e61ba..25ab2ea 100644
--- a/submit/ast/Call.java
+++ b/submit/ast/Call.java
@@ -6,12 +6,16 @@ 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 extends AbstractNode implements Expression {
+public class Call implements Expression {
private final String id;
private final List<Expression> args;
@@ -21,6 +25,39 @@ public class Call extends AbstractNode implements Expression {
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("(");
@@ -34,4 +71,69 @@ public class Call extends AbstractNode implements Expression {
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();
+ }
}