/* zweic -- a compiler for zwei * * Stephane Micheloud & LAMP * * $Id$ */ package zweic; import Operators._; class Generator(analyzer: Analyzer) { import RISC._; import scala.collection.mutable.{Map, HashMap}; val code = new Code(); private def genTmp(gen: Int => Unit) = { val tmpReg = code.getRegister(); gen(tmpReg); code.freeRegister(tmpReg); } def emitLoadConstant(r: Int, value: Int) = { code.emit(ADDI, r, ZERO, value, value.toString()); //TODO: immediats bigger than 2^16 have to be shifted } def gen(tree: Tree): Unit = tree match { case Program(classes, main) => val init = code.getLabel(); code.emit(BEQ,ZERO,init); // go initialize the VMTs // ... à compléter ... // generate class and function definitions // ... à compléter ... // generate main expression val start = code.getLabel(); code.anchorLabel(start); genTmp { tmpReg => genLoad(main, tmpReg) } // exit code.emit(RET, ZERO); // the following code is placed here because the space that // it occupies can be used after initialization. code.anchorLabel(init); // initialise stack pointer code.emit(SYSCALL, SP, 0, SYS_GET_TOTAL_MEM_SIZE); // initialise garbage collector: // the heap starts at init and // its size is 2/3 * (total_mem_size - init) words val r1 = code.getRegister(); val r2 = code.getRegister(); val r3 = code.getRegister(); emitLoadConstant(r1,init.getAnchor()); code.emit(SUB,r2,SP,r1); code.emit(DIVIU,r2,r2,3*WORD_SIZE); code.emit(LSHI,r2,r2,1); // r2 now contains the size of the heap emitLoadConstant(r3,SP << 27); code.emit(ADD, r2, r2, r3); code.emit(SYSCALL, r1, r2, SYS_GC_INIT); code.freeRegister(r3); code.freeRegister(r2); code.freeRegister(r1); // populate VMTs // ... à compléter ... // jump to main expression code.emit(BEQ, ZERO, start); case ClassDef(_, _, members) => // ... à compléter ... //TODO: case FieldDecl(_, _) => ; case FieldDecl(_) => ; case method @ MethodDef(name, params, _, body) => // ... à compléter ... case While(cond, stats) => // ... à compléter ... case Var(varname, _, init) => // ... à compléter ... case Set(name, expr) => // ... à compléter ... case Do(expr) => Console.println("DO"); genTmp { tempReg => genLoad(tree.asInstanceOf[Expr], tempReg) } case PrintInt(expr) => genTmp { tmpReg => genLoad(expr, tmpReg); code.emit(SYSCALL, tmpReg, ZERO, SYS_IO_WR_INT, "printInt"); code.emit(SYSCALL, ZERO, ZERO, SYS_IO_FLUSH, "flush"); } case PrintChar(expr) => genTmp { tempReg => genLoad(expr, tempReg); code.emit(SYSCALL, tempReg, ZERO, SYS_IO_WR_CHR, "printChar"); // TODO: do we flush all day long? code.emit(SYSCALL, ZERO, ZERO, SYS_IO_FLUSH, "flush"); } case _ => Console.println("gen __________________________________"); } // def gen(Tree): Unit def genLoad(tree: Expr, targetReg: Int): Unit = { def caseDefault(tree: Expr): Unit = genLoad( new If(tree, new IntLit(1), new IntLit(0)), targetReg); assert(code.usedRegisters()(targetReg), "invariant violated: target register R" + targetReg + " not allocated"); tree match { case NullLit() => // ... à compléter ... case IntLit(value) => emitLoadConstant(targetReg, value) case ReadInt() => code.emit(SYSCALL, targetReg, ZERO, SYS_IO_RD_INT, "readInt") case ReadChar() => code.emit(SYSCALL, targetReg, ZERO, SYS_IO_RD_CHR, "readChar") case Unop(op, expr) => op match { case NOT => //TODO case NEG => genTmp { tmpReg => genLoad(expr, tmpReg); code.emit(SUB, targetReg, ZERO, tmpReg, "-"); } case _ => Console.println("unop _________"); } case Binop(op, left, right) => // ... à compléter ... case Block(stats, main) => // ... à compléter ... case If(cond, thenp, elsep) => // ... à compléter ... case Ident(name) => // ... à compléter ... case New(name, args) => // ... à compléter ... case Select(prefix, selector) => // ... à compléter ... case Call(receiver, method, args) => // ... à compléter ... case _ => Console.println("LoadGen________________"); // ... à compléter ... } } // genLoad /** * Generates code for conditions, that is constructs * which jump somewhere on the result of a test. */ private def genCond(tree: Expr, targetLabel: code.Label, when: Boolean): Unit = { // ... à compléter ... tree match { case Binop(op, left, right) => ()//op match { // ... à compléter ... case Unop(op, expr) => () // ... à compléter ... case _ => () //TODO: caseDefault(tree) } } // genCond }