void MunchStm(TreeStm stm) { switch (stm) { case StmCJump cjump: { if (cjump.Left is ExpConst c) { Temp constTemp = new Temp(); Emit(new InstrBinary(InstrBinary.Kind.MOV, new Operand.Reg(constTemp), new Operand.Imm(c.Value))); Emit(new InstrBinary(InstrBinary.Kind.CMP, new Operand.Reg(constTemp), MunchExp(cjump.Right))); } else { Operand op1 = MunchExp(cjump.Left); Operand op2 = MunchExp(cjump.Right); if (op1 is Operand.Mem && op2 is Operand.Mem) { Operand.Reg memTemp = new Operand.Reg(new Temp()); Emit(new InstrBinary(InstrBinary.Kind.MOV, memTemp, op1)); Emit(new InstrBinary(InstrBinary.Kind.CMP, memTemp, op2)); } else { Emit(new InstrBinary(InstrBinary.Kind.CMP, op1, op2)); } //Emit(new InstrBinary(InstrBinary.Kind.CMP, MunchExp(cjump.Left), MunchExp(cjump.Right))); } InstrJump.Cond cond; switch (cjump.Rel) { case StmCJump.Relation.EQ: { cond = InstrJump.Cond.NE; break; } case StmCJump.Relation.GE: { cond = InstrJump.Cond.L; break; } case StmCJump.Relation.GT: { cond = InstrJump.Cond.LE; break; } case StmCJump.Relation.LE: { cond = InstrJump.Cond.G; break; } case StmCJump.Relation.LT: { cond = InstrJump.Cond.GE; break; } case StmCJump.Relation.NE: { cond = InstrJump.Cond.E; break; } default: throw new Exception("No Relation matched!"); } Emit(new InstrJump(cond, cjump.LabelFalse)); break; } case StmJump jump: { Emit(new InstrJump(InstrJump.Kind.JMP, jump.PossibleTargets[0])); break; } case StmLabel label: { Emit(new InstrLabel(label.Label)); break; } case StmMove move: { Operand op1 = MunchExp(move.Dest); Operand op2 = MunchExp(move.Source); if (op1 is Operand.Mem && op2 is Operand.Mem) { Operand.Reg t = new Operand.Reg(new Temp()); Emit(new InstrBinary(InstrBinary.Kind.MOV, t, op2)); Emit(new InstrBinary(InstrBinary.Kind.MOV, op1, t)); } else { Emit(new InstrBinary(InstrBinary.Kind.MOV, op1, op2)); } break; } case StmSeq seq: { throw new Exception("No Sequences allowed!"); } default: { throw new Exception("No case matched!"); } } }
Operand MunchExp(TreeExp exp) { switch (exp) { case ExpBinOp binop: { InstrBinary.Kind operation; switch (binop.Operator) { case ExpBinOp.Op.AND: { operation = InstrBinary.Kind.AND; break; } case ExpBinOp.Op.ARSHIFT: { operation = InstrBinary.Kind.SHR; break; } case ExpBinOp.Op.DIV: { Emit(new InstrBinary(InstrBinary.Kind.MOV, new Operand.Reg(EAX), MunchExp(binop.Left))); Operand op = MunchExp(binop.Right); Operand.Reg temp = new Operand.Reg(new Temp()); if (op is Operand.Reg) { Emit(new InstrNullary(InstrNullary.Kind.CDQ)); Emit(new InstrUnary(InstrUnary.Kind.IDIV, op)); } else { Emit(new InstrBinary(InstrBinary.Kind.MOV, temp, op)); Emit(new InstrNullary(InstrNullary.Kind.CDQ)); Emit(new InstrUnary(InstrUnary.Kind.IDIV, temp)); } return(new Operand.Reg(EAX)); } case ExpBinOp.Op.LSHIFT: { operation = InstrBinary.Kind.SHL; break; } case ExpBinOp.Op.MINUS: { operation = InstrBinary.Kind.SUB; break; } case ExpBinOp.Op.MUL: { operation = InstrBinary.Kind.IMUL; break; } case ExpBinOp.Op.OR: { operation = InstrBinary.Kind.OR; break; } case ExpBinOp.Op.PLUS: { operation = InstrBinary.Kind.ADD; break; } default: throw new Exception("not matched"); } Operand tempOp = new Operand.Reg(new Temp()); Emit(new InstrBinary(InstrBinary.Kind.MOV, tempOp, MunchExp(binop.Left))); Emit(new InstrBinary(operation, tempOp, MunchExp(binop.Right))); return(tempOp); } case ExpCall call: { ExpName name; if (call.Function is ExpName n) { name = n; } else { throw new Exception("No label"); } for (int i = 0; i < call.Args.Count; i++) { Temp argTemp = new Temp(); Emit(new InstrBinary(InstrBinary.Kind.MOV, new Operand.Reg(argTemp), MunchExp(call.Args[i]))); Emit(new InstrUnary(InstrUnary.Kind.PUSH, new Operand.Reg(argTemp))); } //Emit(new InstrBinary(InstrBinary.Kind.SUB, )) Emit(new InstrJump(InstrJump.Kind.CALL, name.Label, new List <RegTemp> { (RegTemp)EAX, (RegTemp)ECX, (RegTemp)EDX })); Emit(new InstrBinary(InstrBinary.Kind.ADD, new Operand.Reg(ESP), new Operand.Imm(call.Args.Count * 4))); return(new Operand.Reg(EAX)); } case ExpConst con: { return(new Operand.Imm(con.Value)); } case ExpMem mem: { // very confusing Temp bas = new Temp(); Temp index = new Temp(); Emit(new InstrBinary(InstrBinary.Kind.MOV, new Operand.Reg(bas), MunchExp(mem.Address))); return(new Operand.Mem(bas)); } case ExpName name: { Emit(new InstrLabel(name.Label)); return(new Operand.Reg(new Temp())); } case ExpParam param: { //Temp parTemp = new Temp(); //Emit(new InstrBinary(InstrBinary.Kind.MOV, new Operand.Reg(parTemp), new Operand.Mem(EBP, 0, null, (currentParamCount - param.Number) * 4 + 8))); //return new Operand.Reg(parTemp); return(new Operand.Mem(EBP, 0, null, (currentParamCount - param.Number) * 4 + 8)); } case ExpTemp temp: { return(new Operand.Reg(temp.Temp)); } default: throw new Exception("No expression matched."); } }