public virtual void CGenPush(Env env, CGenState state) { Reg ret = CGenValue(env, state); switch (type.kind) { case ExprType.Kind.CHAR: case ExprType.Kind.UCHAR: case ExprType.Kind.SHORT: case ExprType.Kind.USHORT: case ExprType.Kind.LONG: case ExprType.Kind.ULONG: // Integral if (ret != Reg.EAX) { throw new InvalidProgramException("Integral values should be returned to %eax"); } state.CGenPushLong(Reg.EAX); break; case ExprType.Kind.FLOAT: // Float if (ret != Reg.ST0) { throw new InvalidProgramException("Floats should be returned to %st(0)"); } state.CGenExpandStackBy4Bytes(); state.FSTS(0, Reg.ESP); break; case ExprType.Kind.DOUBLE: // Double if (ret != Reg.ST0) { throw new InvalidProgramException("Doubles should be returned to %st(0)"); } state.CGenExpandStackBy8Bytes(); state.FSTL(0, Reg.ESP); break; case ExprType.Kind.ARRAY: case ExprType.Kind.FUNCTION: case ExprType.Kind.POINTER: // Pointer if (ret != Reg.EAX) { throw new InvalidProgramException("Pointer values should be returned to %eax"); } state.CGenPushLong(Reg.EAX); break; case ExprType.Kind.INCOMPLETE_ARRAY: case ExprType.Kind.VOID: throw new InvalidProgramException(type.kind.ToString() + " can't be pushed onto the stack"); case ExprType.Kind.STRUCT_OR_UNION: throw new NotImplementedException(); } }
public override Reg CGenValue(Env env, CGenState state) { // 1. %eax = &lhs lvalue.CGenAddress(env, state); // 2. push %eax Int32 pos = state.CGenPushLong(Reg.EAX); Reg ret = rvalue.CGenValue(env, state); switch (lvalue.type.kind) { case ExprType.Kind.CHAR: case ExprType.Kind.UCHAR: // pop %ebx // now %ebx = %lhs state.CGenPopLong(pos, Reg.EBX); // *%ebx = %al state.MOVB(Reg.AL, 0, Reg.EBX); return Reg.EAX; case ExprType.Kind.SHORT: case ExprType.Kind.USHORT: // pop %ebx // now %ebx = %lhs state.CGenPopLong(pos, Reg.EBX); // *%ebx = %al state.MOVW(Reg.AX, 0, Reg.EBX); return Reg.EAX; case ExprType.Kind.LONG: case ExprType.Kind.ULONG: case ExprType.Kind.POINTER: // pop %ebx // now %ebx = &lhs state.CGenPopLong(pos, Reg.EBX); // *%ebx = %al state.MOVL(Reg.EAX, 0, Reg.EBX); return Reg.EAX; case ExprType.Kind.FLOAT: // pop %ebx // now %ebx = &lhs state.CGenPopLong(pos, Reg.EBX); // *%ebx = %st(0) state.FSTS(0, Reg.EBX); return Reg.ST0; case ExprType.Kind.DOUBLE: // pop %ebx // now %ebx = &lhs state.CGenPopLong(pos, Reg.EBX); // *%ebx = %st(0) state.FSTL(0, Reg.EBX); return Reg.ST0; case ExprType.Kind.STRUCT_OR_UNION: // pop %edi // now %edi = &lhs state.CGenPopLong(pos, Reg.EDI); // %esi = &rhs state.MOVL(Reg.EAX, Reg.ESI); // %ecx = nbytes state.MOVL(lvalue.type.SizeOf, Reg.ECX); state.CGenMemCpy(); // %eax = &lhs state.MOVL(Reg.EDI, Reg.EAX); return Reg.EAX; case ExprType.Kind.FUNCTION: case ExprType.Kind.VOID: case ExprType.Kind.ARRAY: case ExprType.Kind.INCOMPLETE_ARRAY: default: throw new InvalidProgramException("cannot assign to a " + type.kind.ToString()); } }
public override Reg CGenValue(CGenState state) { // 1. %eax = &left this.Left.CGenAddress(state); // 2. push %eax Int32 pos = state.CGenPushLong(Reg.EAX); Reg ret = this.Right.CGenValue(state); switch (this.Left.Type.Kind) { case ExprTypeKind.CHAR: case ExprTypeKind.UCHAR: // pop %ebx // now %ebx = %Left state.CGenPopLong(pos, Reg.EBX); // *%ebx = %al state.MOVB(Reg.AL, 0, Reg.EBX); return(Reg.EAX); case ExprTypeKind.SHORT: case ExprTypeKind.USHORT: // pop %ebx // now %ebx = %Left state.CGenPopLong(pos, Reg.EBX); // *%ebx = %al state.MOVW(Reg.AX, 0, Reg.EBX); return(Reg.EAX); case ExprTypeKind.LONG: case ExprTypeKind.ULONG: case ExprTypeKind.POINTER: // pop %ebx // now %ebx = &Left state.CGenPopLong(pos, Reg.EBX); // *%ebx = %al state.MOVL(Reg.EAX, 0, Reg.EBX); return(Reg.EAX); case ExprTypeKind.FLOAT: // pop %ebx // now %ebx = &Left state.CGenPopLong(pos, Reg.EBX); // *%ebx = %st(0) state.FSTS(0, Reg.EBX); return(Reg.ST0); case ExprTypeKind.DOUBLE: // pop %ebx // now %ebx = &Left state.CGenPopLong(pos, Reg.EBX); // *%ebx = %st(0) state.FSTL(0, Reg.EBX); return(Reg.ST0); case ExprTypeKind.STRUCT_OR_UNION: // pop %edi // now %edi = &Left state.CGenPopLong(pos, Reg.EDI); // %esi = &Right state.MOVL(Reg.EAX, Reg.ESI); // %ecx = nbytes state.MOVL(this.Left.Type.SizeOf, Reg.ECX); state.CGenMemCpy(); // %eax = &Left state.MOVL(Reg.EDI, Reg.EAX); return(Reg.EAX); case ExprTypeKind.FUNCTION: case ExprTypeKind.VOID: case ExprTypeKind.ARRAY: case ExprTypeKind.INCOMPLETE_ARRAY: default: throw new InvalidProgramException("cannot assign to a " + this.Type.Kind); } }
// Before the actual calculation, the state is set to this. // // regs: // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // // float stack: // +-------+ // | expr | <- %st(1) // +-------+ // | 1.0 | <- %st(0) // +-------+ // // 1. Compute %st(1) + %st(0) and stores in %st(0). // // regs: // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // // float stack: // +------------+ // | expr | <- %st(1) // +------------+ // | expr + 1.0 | <- %st(0) // +------------+ // // 2. Store %st(0) in memory. // // regs: // %ecx = &expr // // stack: // +-------+ // | ..... | <- %esp // +-------+ // // float stack: // +------------+ // | expr + 1.0 | <- %st(0) // +------------+ // public override void CalcAndSaveFloat(CGenState state) { state.FADD(1, 0); state.FSTS(0, Reg.ECX); }
public override void CalcAndSaveFloat(CGenState state) { state.FSUB(1, 0); state.FSTS(0, Reg.ECX); }