| |
---|
| | val init = code.getLabel(); |
---|
| | code.emit(BEQ,ZERO,init); |
---|
| | |
---|
| | // go initialize the VMTs |
---|
| | var offset = code.pc(); |
---|
| | for ( val c <- classes ) { |
---|
| | var offset = code.pc(); |
---|
| | for ( val c <- classes ) { |
---|
| | c.name.sym.offset = offset; |
---|
| | offset = offset + c.name.sym.asInstanceOf[ClassSymbol].allMethods.length*4; |
---|
| | //XXX: no +4 for empty top entry |
---|
| | for ( val m <- c.name.sym.asInstanceOf[ClassSymbol].allMethods ) { |
---|
| | code.emit(ADD, ZERO, ZERO, ZERO, c.name.name + "::" + m.name); |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | // generate class and function definitions |
---|
| | classes.foreach(gen); |
---|
| | |
---|
| | //TODO: what was that??? its writing some stuff in fromt of the program... |
---|
| | //TODO: allocation what???? |
---|
| | //genTmp { tmpReg => |
---|
| | // emitLoadConstant(tmpReg, offset); |
---|
| | // code.emit(SYSCALL, tmpReg, tmpReg, SYS_GC_ALLOC); |
---|
| | // } |
---|
| | code.emit(ADD, ZERO, ZERO, ZERO, c.name.name + "::" + m.name); |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | // generate class and function definitions |
---|
| | classes.foreach(gen); |
---|
| | |
---|
| | //TODO: what was that??? its writing some stuff in fromt of the program... |
---|
| | //TODO: allocation what???? |
---|
| | //genTmp { tmpReg => |
---|
| | // emitLoadConstant(tmpReg, offset); |
---|
| | // code.emit(SYSCALL, tmpReg, tmpReg, SYS_GC_ALLOC); |
---|
| | // } |
---|
| | |
---|
| | // generate main expression |
---|
| | val start = code.getLabel(); |
---|
| | code.anchorLabel(start); |
---|
| |
---|
| | code.freeRegister(r2); |
---|
| | code.freeRegister(r3); |
---|
| | |
---|
| | |
---|
| | // populate VMTs |
---|
| | genTmp { classHeader => |
---|
| | |
---|
| | for ( val ClassDef(cname, _, members) <- classes ) { |
---|
| | emitLoadConstant(classHeader, cname.sym.offset); |
---|
| | for ( val m <- cname.sym.asInstanceOf[ClassSymbol].allMethods ) { |
---|
| | //TODO: why use LNK here? don't we use a normal register??? |
---|
| | emitLoadConstant(LNK, m.address); |
---|
| | code.emit(STW, LNK, classHeader, m.offset, |
---|
| | cname.name + "::" + m.name); |
---|
| | // populate VMTs |
---|
| | genTmp { classHeader => |
---|
| | for ( val ClassDef(cname, _, members) <- classes ) { |
---|
| | emitLoadConstant(classHeader, cname.sym.offset); |
---|
| | for ( val m <- cname.sym.asInstanceOf[ClassSymbol].allMethods ) { |
---|
| | //TODO: why use LNK here? don't we use a normal register??? |
---|
| | emitLoadConstant(LNK, m.address); |
---|
| | code.emit(STW, LNK, classHeader, m.offset, |
---|
| | cname.name + "::" + m.name); |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | |
---|
| | |
---|
| | // jump to main expression |
---|
| | code.emit(BEQ, ZERO, start); |
---|
| | |
---|
| |
---|
| | } |
---|
| | |
---|
| | case New(name, args) => |
---|
| | val af = name.sym.asInstanceOf[ClassSymbol].allFields; |
---|
| | emitLoadConstant(targetReg, 4+af.length*4); |
---|
| | code.emit(SYSCALL, targetReg, targetReg, SYS_GC_ALLOC, "new "+name); |
---|
| | |
---|
| | emitLoadConstant(targetReg, 4+af.length*4); |
---|
| | code.emit(SYSCALL, targetReg, targetReg, SYS_GC_ALLOC, "new "+name); |
---|
| | |
---|
| | genTmp { tmpReg => |
---|
| | /* pointer to class header */ |
---|
| | emitLoadConstant(tmpReg, name.sym.offset); |
---|
| | code.emit(STW, tmpReg, targetReg, 0); |
---|
| |
---|
| | code.freeRegister(i); |
---|
| | freed = i::freed; |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | genTmp { thisReg => |
---|
| | // get 'receiver' and put it as 'this' on the stack |
---|
| | genLoad(receiver, thisReg); |
---|
| | |
---|
| | // check receiver != null |
---|
| | val okLabel = code.getLabel(); |
---|
| | code.emit(BNE, thisReg, okLabel); |
---|
| | emitLoadConstant(thisReg, 1); |
---|
| | code.emit(SYSCALL, thisReg, ZERO, SYS_EXIT); |
---|
| | code.anchorLabel(okLabel); |
---|
| | |
---|
| | //put 'this' on stack |
---|
| | code.emit(PSH, thisReg, SP, 4); |
---|
| | code.incFrameSize(4); |
---|
| | |
---|
| | // get 'receiver' and put it as 'this' on the stack |
---|
| | genLoad(receiver, targetReg); |
---|
| | |
---|
| | // check receiver != null |
---|
| | val okLabel = code.getLabel(); |
---|
| | code.emit(BNE, targetReg, okLabel); |
---|
| | emitLoadConstant(targetReg, 1); |
---|
| | code.emit(SYSCALL, targetReg, ZERO, SYS_EXIT); |
---|
| | code.anchorLabel(okLabel); |
---|
| | |
---|
| | code.emit(PSH, targetReg, SP, 4); |
---|
| | code.incFrameSize(4); |
---|
| | |
---|
| | // put args on stack |
---|
| | genTmp { tmpReg => |
---|
| | // put args on stack |
---|
| | genTmp { tmpReg => |
---|
| | for ( val a <- args ) { |
---|
| | genLoad(a, tmpReg); |
---|
| | code.emit(PSH, tmpReg, SP, 4); |
---|
| | code.incFrameSize(4); |
---|
| | genLoad(a, tmpReg); |
---|
| | code.emit(PSH, tmpReg, SP, 4); |
---|
| | code.incFrameSize(4); |
---|
| | } |
---|
| | } |
---|
| | //load method address |
---|
| | code.emit(LDW, targetReg, targetReg, method.sym.offset); |
---|
| | } |
---|
| | |
---|
| | |
---|
| | //TODO: bizarr: twice method.sym.offset.... |
---|
| | //load vmt pos |
---|
| | code.emit(LDW, thisReg, thisReg, method.sym.offset); |
---|
| | |
---|
| | //load method address |
---|
| | code.emit(LDW, targetReg, thisReg, method.sym.offset); |
---|
| | } |
---|
| | |
---|
| | // //TODO |
---|
| | // // check receiver.method() != null |
---|
| | // val okLabel2 = code.getLabel(); |
---|
| | // code.emit(BNE, targetReg, okLabel2); |
---|
| | // emitLoadConstant(targetReg, 1); |
---|
| | // code.emit(SYSCALL, targetReg, ZERO, SYS_EXIT); |
---|
| | // code.anchorLabel(okLabel2); |
---|
| | |
---|
| | //call function |
---|
| | code.emit(ADD, 1, ZERO, ZERO, "call " + |
---|
| | method.sym.name.toString() + " offset:" + method.sym.offset.toString()); |
---|
| | code.emit(RET, targetReg); |
---|
| | |
---|
| | //store return value |
---|
| | code.emit(ADD, targetReg, ZERO, RES, "store return value to target reg"); |
---|
| | |
---|
| | code.decFrameSize(args.length*4+4); // fs = oldframesize - params - this |
---|
| | |
---|
| | |
---|
| | //save current position + 8 (after RET) |
---|
| | code.emit(ORIU, LNK, ZERO, code.pc() + 8, "call " + |
---|
| | method.sym.name.toString() + " offset:" + method.sym.offset.toString()); |
---|
| | |
---|
| | //call function |
---|
| | code.emit(RET, targetReg); |
---|
| | |
---|
| | // //TODO store return value |
---|
| | // code.emit(ADD, targetReg, ZERO, RES, "store return value to target reg"); |
---|
| | |
---|
| | code.decFrameSize(args.length*4+4); // fs = oldframesize - params - this |
---|
| | |
---|
| | // retrieve all registers from stack |
---|
| | for ( val j <- freed ) { |
---|
| | code.getRegister(j); |
---|
| |
---|
| | |