public override Reg CGenValue(Env env, CGenState state) { // 1. Get the address of expr. // // regs: // %eax = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // expr.CGenAddress(env, state); // 2. Push address. // // regs: // %eax = &expr // // stack: // +-------+ // | ..... | // +-------+ // | &expr | <- %esp // +-------+ // Int32 stack_size = state.CGenPushLong(Reg.EAX); // 3. Get current value of expr. // // 1) If expr is an integral or pointer: // // regs: // %eax = expr // // stack: // +-------+ // | ..... | // +-------+ // | &expr | <- %esp // +-------+ // // // 2) If expr is a float: // // regs: // %eax = &expr // // stack: // +-------+ // | ..... | // +-------+ // | &expr | <- %esp // +-------+ // // float stack: // +-------+ // | expr | <- %st(0) // +-------+ // Reg ret = expr.CGenValue(env, state); switch (ret) { case Reg.EAX: // expr is an integral or pointer. // 4. Pop address to %ecx. // // regs: // %eax = expr // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // state.CGenPopLong(stack_size, Reg.ECX); // 5. Cache current value of expr in %ebx. // // regs: // %eax = expr // %ebx = expr // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // state.MOVL(Reg.EAX, Reg.EBX); // 6. Calculate the new value in %ebx or %eax and save. // Set %eax to be the return value. // // regs: // %eax = expr or (expr +- 1) // %ebx = (expr +- 1) or expr // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // switch (expr.type.kind) { case ExprType.Kind.CHAR: case ExprType.Kind.UCHAR: CalcAndSaveByte(state); return Reg.EAX; case ExprType.Kind.SHORT: case ExprType.Kind.USHORT: CalcAndSaveWord(state); return Reg.EAX; case ExprType.Kind.LONG: case ExprType.Kind.ULONG: CalcAndSaveByte(state); return Reg.EAX; case ExprType.Kind.POINTER: CalcAndSavePtr(state); return Reg.EAX; default: throw new InvalidProgramException(); } case Reg.ST0: // expr is a float. // 4. Pop address to %ecx. // // regs: // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // state.CGenPopLong(stack_size, Reg.ECX); // 5. Load 1.0 to FPU stack. // // regs: // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // // float stack: // +-------+ // | expr | <- %st(1) // +-------+ // | 1.0 | <- %st(0) // +-------+ // state.FLD1(); // 6. Calculate the new value and save back. // Set %st(0) to be the new or original value. // // regs: // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // // float stack: // +---------------------+ // | expr or (epxr +- 1) | <- %st(0) // +---------------------+ // switch (expr.type.kind) { case ExprType.Kind.FLOAT: CalcAndSaveFloat(state); return Reg.ST0; case ExprType.Kind.DOUBLE: CalcAndSaveDouble(state); return Reg.ST0; default: throw new InvalidProgramException(); } default: throw new InvalidProgramException(); } }
public override sealed Reg CGenValue(CGenState state) { // 1. Get the address of expr. // // regs: // %eax = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // this.Expr.CGenAddress(state); // 2. Push address. // // regs: // %eax = &expr // // stack: // +-------+ // | ..... | // +-------+ // | &expr | <- %esp // +-------+ // Int32 stack_size = state.CGenPushLong(Reg.EAX); // 3. Get current Value of expr. // // 1) If expr is an integral or pointer: // // regs: // %eax = expr // // stack: // +-------+ // | ..... | // +-------+ // | &expr | <- %esp // +-------+ // // // 2) If expr is a float: // // regs: // %eax = &expr // // stack: // +-------+ // | ..... | // +-------+ // | &expr | <- %esp // +-------+ // // float stack: // +-------+ // | expr | <- %st(0) // +-------+ // Reg ret = this.Expr.CGenValue(state); switch (ret) { case Reg.EAX: // expr is an integral or pointer. // 4. Pop address to %ecx. // // regs: // %eax = expr // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // state.CGenPopLong(stack_size, Reg.ECX); // 5. Cache current Value of Expr in %ebx. // // regs: // %eax = expr // %ebx = expr // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // state.MOVL(Reg.EAX, Reg.EBX); // 6. Calculate the new value in %ebx or %eax and save. // Set %eax to be the return Value. // // regs: // %eax = expr or (expr +- 1) // %ebx = (expr +- 1) or expr // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // switch (this.Expr.Type.Kind) { case ExprTypeKind.CHAR: case ExprTypeKind.UCHAR: CalcAndSaveByte(state); return(Reg.EAX); case ExprTypeKind.SHORT: case ExprTypeKind.USHORT: CalcAndSaveWord(state); return(Reg.EAX); case ExprTypeKind.LONG: case ExprTypeKind.ULONG: CalcAndSaveByte(state); return(Reg.EAX); case ExprTypeKind.POINTER: CalcAndSavePtr(state); return(Reg.EAX); default: throw new InvalidProgramException(); } case Reg.ST0: // Expr is a float. // 4. Pop address to %ecx. // // regs: // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // state.CGenPopLong(stack_size, Reg.ECX); // 5. Load 1.0 to FPU stack. // // regs: // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // // float stack: // +-------+ // | expr | <- %st(1) // +-------+ // | 1.0 | <- %st(0) // +-------+ // state.FLD1(); // 6. Calculate the new value and save back. // Set %st(0) to be the new or original Value. // // regs: // %ecx = &Expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // // float stack: // +---------------------+ // | expr or (epxr +- 1) | <- %st(0) // +---------------------+ // switch (this.Expr.Type.Kind) { case ExprTypeKind.FLOAT: CalcAndSaveFloat(state); return(Reg.ST0); case ExprTypeKind.DOUBLE: CalcAndSaveDouble(state); return(Reg.ST0); default: throw new InvalidProgramException(); } default: throw new InvalidProgramException(); } }