public override Reg CGenValue(CGenState state) { Reg ret = this.Expr.CGenValue(state); switch (this.Kind) { case TypeCastType.DOUBLE_TO_FLOAT: case TypeCastType.FLOAT_TO_DOUBLE: case TypeCastType.PRESERVE_INT16: case TypeCastType.PRESERVE_INT8: case TypeCastType.NOP: return ret; case TypeCastType.DOUBLE_TO_INT32: case TypeCastType.FLOAT_TO_INT32: state.CGenConvertFloatToLong(); return Reg.EAX; case TypeCastType.INT32_TO_DOUBLE: case TypeCastType.INT32_TO_FLOAT: state.CGenConvertLongToFloat(); return Reg.ST0; case TypeCastType.INT16_TO_INT32: state.MOVSWL(Reg.AX, Reg.EAX); return ret; case TypeCastType.INT8_TO_INT16: case TypeCastType.INT8_TO_INT32: state.MOVSBL(Reg.AL, Reg.EAX); return ret; case TypeCastType.UINT16_TO_UINT32: state.MOVZWL(Reg.AX, Reg.EAX); return ret; case TypeCastType.UINT8_TO_UINT16: case TypeCastType.UINT8_TO_UINT32: state.MOVZBL(Reg.AL, Reg.EAX); return ret; default: throw new InvalidProgramException(); } }
public override Reg CGenValue(CGenState state) { // %eax is the address of the struct/union if (this.Expr.CGenValue(state) != Reg.EAX) { throw new InvalidProgramException(); } if (this.Expr.Type.Kind != ExprTypeKind.STRUCT_OR_UNION) { throw new InvalidProgramException(); } // size of the struct or union Int32 struct_size = this.Expr.Type.SizeOf; // offset inside the pack Int32 attrib_offset = ((StructOrUnionType)this.Expr.Type) .Attribs .First(_ => _.name == this.Name) .offset; // can't be a function designator. switch (this.Type.Kind) { case ExprTypeKind.ARRAY: case ExprTypeKind.STRUCT_OR_UNION: state.ADDL(attrib_offset, Reg.EAX); return Reg.EAX; case ExprTypeKind.CHAR: state.MOVSBL(attrib_offset, Reg.EAX, Reg.EAX); return Reg.EAX; case ExprTypeKind.UCHAR: state.MOVZBL(attrib_offset, Reg.EAX, Reg.EAX); return Reg.EAX; case ExprTypeKind.SHORT: state.MOVSWL(attrib_offset, Reg.EAX, Reg.EAX); return Reg.EAX; case ExprTypeKind.USHORT: state.MOVZWL(attrib_offset, Reg.EAX, Reg.EAX); return Reg.EAX; case ExprTypeKind.LONG: case ExprTypeKind.ULONG: case ExprTypeKind.POINTER: state.MOVL(attrib_offset, Reg.EAX, Reg.EAX); return Reg.EAX; case ExprTypeKind.FLOAT: state.FLDS(attrib_offset, Reg.EAX); return Reg.ST0; case ExprTypeKind.DOUBLE: state.FLDL(attrib_offset, Reg.EAX); return Reg.ST0; default: throw new InvalidProgramException(); } }
public override Reg CGenValue(CGenState state) { Reg ret = this.Expr.CGenValue(state); if (ret != Reg.EAX) { throw new InvalidProgramException(); } if (this.Expr.Type.Kind != ExprTypeKind.POINTER) { throw new InvalidProgramException(); } ExprType type = ((PointerType)this.Expr.Type).RefType; switch (type.Kind) { case ExprTypeKind.ARRAY: case ExprTypeKind.FUNCTION: return Reg.EAX; case ExprTypeKind.CHAR: state.MOVSBL(0, Reg.EAX, Reg.EAX); return Reg.EAX; case ExprTypeKind.UCHAR: state.MOVZBL(0, Reg.EAX, Reg.EAX); return Reg.EAX; case ExprTypeKind.SHORT: state.MOVSWL(0, Reg.EAX, Reg.EAX); return Reg.EAX; case ExprTypeKind.USHORT: state.MOVZWL(0, Reg.EAX, Reg.EAX); return Reg.EAX; case ExprTypeKind.LONG: case ExprTypeKind.ULONG: case ExprTypeKind.POINTER: state.MOVL(0, Reg.EAX, Reg.EAX); return Reg.EAX; case ExprTypeKind.FLOAT: state.FLDS(0, Reg.EAX); return Reg.ST0; case ExprTypeKind.DOUBLE: state.FLDL(0, Reg.EAX); return Reg.ST0; case ExprTypeKind.STRUCT_OR_UNION: //// %esi = src address //state.MOVL(Reg.EAX, Reg.ESI); //// %edi = dst address //state.CGenExpandStackBy(Utils.RoundUp(Type.SizeOf, 4)); //state.LEA(0, Reg.ESP, Reg.EDI); //// %ecx = nbytes //state.MOVL(Type.SizeOf, Reg.ECX); //state.CGenMemCpy(); //return Reg.STACK; return Reg.EAX; case ExprTypeKind.VOID: default: throw new InvalidProgramException(); } }
public override Reg CGenValue(CGenState state) { Env.Entry entry = this.Env.Find(this.Name).Value; Int32 offset = entry.Offset; //if (entry.Kind == Env.EntryKind.STACK) { // offset = -offset; //} switch (entry.Kind) { case Env.EntryKind.ENUM: // 1. If the variable is an enum constant, // return the Value in %eax. state.MOVL(offset, Reg.EAX); return Reg.EAX; case Env.EntryKind.FRAME: case Env.EntryKind.STACK: // 2. If the variable is a function argument or a local variable, // the address would be offset(%ebp). switch (this.Type.Kind) { case ExprTypeKind.LONG: case ExprTypeKind.ULONG: case ExprTypeKind.POINTER: // %eax = offset(%ebp) state.MOVL(offset, Reg.EBP, Reg.EAX); return Reg.EAX; case ExprTypeKind.FLOAT: // %st(0) = offset(%ebp) state.FLDS(offset, Reg.EBP); return Reg.ST0; case ExprTypeKind.DOUBLE: // %st(0) = offset(%ebp) state.FLDL(offset, Reg.EBP); return Reg.ST0; case ExprTypeKind.STRUCT_OR_UNION: // %eax = address state.LEA(offset, Reg.EBP, Reg.EAX); return Reg.EAX; //state.LEA(offset, Reg.EBP, Reg.ESI); // source address //state.CGenExpandStackBy(Utils.RoundUp(Type.SizeOf, 4)); //state.LEA(0, Reg.ESP, Reg.EDI); // destination address //state.MOVL(Type.SizeOf, Reg.ECX); // nbytes //state.CGenMemCpy(); //return Reg.STACK; case ExprTypeKind.VOID: throw new InvalidProgramException("How could a variable be void?"); // %eax = $0 // state.MOVL(0, Reg.EAX); // return Reg.EAX; case ExprTypeKind.FUNCTION: throw new InvalidProgramException("How could a variable be a function designator?"); // %eax = function_name // state.MOVL(name, Reg.EAX); // return Reg.EAX; case ExprTypeKind.CHAR: // %eax = [char -> long](off(%ebp)) state.MOVSBL(offset, Reg.EBP, Reg.EAX); return Reg.EAX; case ExprTypeKind.UCHAR: // %eax = [uchar -> ulong](off(%ebp)) state.MOVZBL(offset, Reg.EBP, Reg.EAX); return Reg.EAX; case ExprTypeKind.SHORT: // %eax = [short -> long](off(%ebp)) state.MOVSWL(offset, Reg.EBP, Reg.EAX); return Reg.EAX; case ExprTypeKind.USHORT: // %eax = [ushort -> ulong](off(%ebp)) state.MOVZWL(offset, Reg.EBP, Reg.EAX); return Reg.EAX; case ExprTypeKind.ARRAY: // %eax = (off(%ebp)) state.LEA(offset, Reg.EBP, Reg.EAX); // source address return Reg.EAX; default: throw new InvalidOperationException($"Cannot get value of {this.Type.Kind}"); } case Env.EntryKind.GLOBAL: switch (this.Type.Kind) { case ExprTypeKind.CHAR: state.MOVSBL(this.Name, Reg.EAX); return Reg.EAX; case ExprTypeKind.UCHAR: state.MOVZBL(this.Name, Reg.EAX); return Reg.EAX; case ExprTypeKind.SHORT: state.MOVSWL(this.Name, Reg.EAX); return Reg.EAX; case ExprTypeKind.USHORT: state.MOVZWL(this.Name, Reg.EAX); return Reg.EAX; case ExprTypeKind.LONG: case ExprTypeKind.ULONG: case ExprTypeKind.POINTER: state.MOVL(this.Name, Reg.EAX); return Reg.EAX; case ExprTypeKind.FUNCTION: state.MOVL("$" + this.Name, Reg.EAX); return Reg.EAX; case ExprTypeKind.FLOAT: state.FLDS(this.Name); return Reg.ST0; case ExprTypeKind.DOUBLE: state.FLDL(this.Name); return Reg.ST0; case ExprTypeKind.STRUCT_OR_UNION: state.MOVL($"${this.Name}", Reg.EAX); return Reg.EAX; //state.LEA(name, Reg.ESI); // source address //state.CGenExpandStackBy(Utils.RoundUp(Type.SizeOf, 4)); //state.LEA(0, Reg.ESP, Reg.EDI); // destination address //state.MOVL(Type.SizeOf, Reg.ECX); // nbytes //state.CGenMemCpy(); //return Reg.STACK; case ExprTypeKind.VOID: throw new InvalidProgramException("How could a variable be void?"); //state.MOVL(0, Reg.EAX); //return Reg.EAX; case ExprTypeKind.ARRAY: state.MOVL($"${this.Name}", Reg.EAX); return Reg.EAX; default: throw new InvalidProgramException("cannot get the Value of a " + this.Type.Kind); } case Env.EntryKind.TYPEDEF: default: throw new InvalidProgramException("cannot get the Value of a " + entry.Kind); } }