// Ranjay but needs to be optimized private static Instruction handleArguments(CallIR call, TempTable tTable) { Instruction inst = new Instruction(); // Now that we have saved the caller-saved registers we get the tilings // for the arguments given to the function ArrayList<ExpressionInstruction> argumentTileLists = new ArrayList<ExpressionInstruction>(); for (int i = 1; i < call.getChildren().size(); i++) { argumentTileLists.add( (ExpressionInstruction) generateTile((SyntaxIR) call.getChildren().get(i), tTable)); } // Now that we have the arguments we must push them on the stack and or registers AddressingMode addr12 = new AddressingMode("r12"); AddressingMode addrR9 = new AddressingMode("r9"); AddressingMode addrR8 = new AddressingMode("r8"); AddressingMode addrRDX = new AddressingMode("rdx"); AddressingMode addrRCX = new AddressingMode("rcx"); AddressingMode addrRSI = new AddressingMode("rsi"); AddressingMode addrRDI = new AddressingMode("rdi"); int retsize = call.getretsize(); if (retsize > 1) { CallIR c = new CallIR(new NameIR("_I_alloc_i"), new ConstIR(8 * (retsize + 1))); c.setretsize(1); ExpressionInstruction ex = (ExpressionInstruction) generateTile(c, tTable); inst.addAll(ex.getTiles()); inst.add(new Tile(1, "movq", ex.getAddr(), new AddressingMode("rcx"))); inst.add(new Tile(1, "movq", new AddressingMode(retsize), new AddressingMode(0, "rcx"))); inst.add(new Tile(1, "add", new AddressingMode(8), new AddressingMode("rcx"))); } if ((argumentTileLists.size() <= 4 && retsize <= 1) || (argumentTileLists.size() <= 3 && retsize > 1)) { for (int i = 0; i < argumentTileLists.size(); i++) { inst.addAll(argumentTileLists.get(i).getTiles()); inst.add(new Tile(1, "pushq", argumentTileLists.get(i).getAddr(), null)); } } else { if (retsize > 1) { for (int i = argumentTileLists.size() - 1; i >= 3; i--) { inst.addAll(argumentTileLists.get(i).getTiles()); inst.add(new Tile(1, "pushq", argumentTileLists.get(i).getAddr(), null)); } for (int i = 0; i < 3; i++) { inst.addAll(argumentTileLists.get(i).getTiles()); inst.add(new Tile(1, "pushq", argumentTileLists.get(i).getAddr(), null)); } } else { for (int i = argumentTileLists.size() - 1; i >= 4; i--) { inst.addAll(argumentTileLists.get(i).getTiles()); inst.add(new Tile(1, "pushq", argumentTileLists.get(i).getAddr(), null)); } for (int i = 0; i < 4; i++) { inst.addAll(argumentTileLists.get(i).getTiles()); inst.add(new Tile(1, "pushq", argumentTileLists.get(i).getAddr(), null)); } } } switch (argumentTileLists.size()) { case 4: if (retsize <= 1) { inst.add(new Tile(1, "popq", addrR9, null)); } case 3: if (retsize > 1) { inst.add(new Tile(1, "popq", addrR9, null)); } else { inst.add(new Tile(1, "popq", addrR8, null)); } case 2: if (retsize > 1) { inst.add(new Tile(1, "popq", addrR8, null)); } else { inst.add(new Tile(1, "popq", addrRDX, null)); } case 1: if (retsize > 1) { inst.add(new Tile(1, "popq", addrRDX, null)); } else { inst.add(new Tile(1, "popq", addrRCX, null)); } case 0: // Do nothing break; default: // we have more than five arguments // push the first 6 arguments to registers // and we're not using RDI (not returning a tuple) if (retsize <= 1) { inst.add(new Tile(1, "popq", addrR9, null)); inst.add(new Tile(1, "popq", addrR8, null)); inst.add(new Tile(1, "popq", addrRDX, null)); inst.add(new Tile(1, "popq", addrRCX, null)); } // we're returning a tuple else { inst.add(new Tile(1, "popq", addrR9, null)); inst.add(new Tile(1, "popq", addrR8, null)); inst.add(new Tile(1, "popq", addrRDX, null)); } } return inst; }
// Ranjay public static ExpressionInstruction generateTile(OpIR op, TempTable tTable) { ExpressionInstruction inst = new ExpressionInstruction(); if (op.getChildren().size() > 1) { ExpressionInstruction child1 = (ExpressionInstruction) generateTile((SyntaxIR) op.getChildren().get(0), tTable); ExpressionInstruction child2 = (ExpressionInstruction) generateTile((SyntaxIR) op.getChildren().get(1), tTable); inst.addAll(child1.getTiles()); inst.add(new Tile(1, "pushq", child1.getAddr(), null)); inst.addAll(child2.getTiles()); inst.add(new Tile(1, "movq", child2.getAddr(), new AddressingMode("r12"))); inst.add(new Tile(1, "popq", new AddressingMode("r13"), null)); if (op.getOp() == opEnum.DIVIDE || op.getOp() == opEnum.MODULO) { inst.add(new Tile(1, "pushq", new AddressingMode("rdx"), null)); inst.add(new Tile(1, "pushq", new AddressingMode("rax"), null)); inst.add(new Tile(1, "movq", new AddressingMode("r13"), new AddressingMode("rax"))); // we need to sign extend r13 into rdx inst.add(new Tile(1, "cmp", new AddressingMode(0), new AddressingMode("r13"))); // if r12 is less than 0 we move FFFFFFFFFFFFFFFF to rdx otherwise move zero int div = tTable.getNewJumpLabel(); inst.add(new Tile(1, "jl", new AddressingMode("div" + div, true), null)); // fall through to moving zero inst.add(new Tile(1, "movq", new AddressingMode(0), new AddressingMode("rdx"))); inst.add(new Tile(1, "jmp", new AddressingMode("divEnd" + div, true), null)); inst.add(new Tile(1, "div" + div + ":", null, null)); inst.add(new Tile(1, "movq", new AddressingMode(-1), new AddressingMode("rdx"))); inst.add(new Tile(1, "divEnd" + div + ":", null, null)); inst.add(new Tile(1, "idiv", new AddressingMode("r12"), null)); // The result is put in RAX so we need to push that on the stack if (op.getOp() == opEnum.DIVIDE) inst.add(new Tile(1, "movq", new AddressingMode("rax"), new AddressingMode("r12"))); else inst.add(new Tile(1, "movq", new AddressingMode("rdx"), new AddressingMode("r12"))); inst.add(new Tile(1, "popq", new AddressingMode("rax"), null)); inst.add(new Tile(1, "popq", new AddressingMode("rdx"), null)); inst.setAddr(new AddressingMode("r12")); } else if (op.returnsBool() && op.getOp() != opEnum.AND && op.getOp() != opEnum.OR) { int x = tTable.getNewJumpLabel(); inst.add(new Tile(1, "cmp", new AddressingMode("r12"), new AddressingMode("r13"))); inst.add(new Tile(1, op.opToAssembly(), new AddressingMode("_true" + x, true), null)); inst.add(new Tile(1, "movq", new AddressingMode(0), new AddressingMode("r12"))); inst.add(new Tile(1, "jmp", new AddressingMode("_end" + x, true), null)); inst.add(new Tile(1, "_true" + x + ": ", null, null)); inst.add(new Tile(1, "movq", new AddressingMode(1), new AddressingMode("r12"))); inst.add(new Tile(1, "_end" + x + ": ", null, null)); inst.setAddr(new AddressingMode("r12")); } else if (op.getOp() == opEnum.LSHIFT || op.getOp() == opEnum.RSHIFT) { inst.add(new Tile(1, op.opToAssembly(), new AddressingMode(3), new AddressingMode("r13"))); inst.setAddr(new AddressingMode("r13")); } else { inst.add( new Tile(1, op.opToAssembly(), new AddressingMode("r12"), new AddressingMode("r13"))); inst.setAddr(new AddressingMode("r13")); } } else { ExpressionInstruction child = (ExpressionInstruction) generateTile((SyntaxIR) op.getChildren().get(0), tTable); inst.addAll(child.getTiles()); switch (op.getOp()) { case NOT: inst.add(new Tile(1, "btc", new AddressingMode(0), child.getAddr())); inst.setAddr(child.getAddr()); break; case UNARY_MINUS: inst.add(new Tile(1, "neg", child.getAddr(), null)); inst.setAddr(child.getAddr()); break; } } return inst; }