protected FunctionType(ExprType ret_t, List <Utils.StoreEntry> args, Boolean is_varargs) : base(true, false) { this.Args = args; this.ReturnType = ret_t; this.HasVarArgs = is_varargs; }
public void DefineStruct(IReadOnlyList <Tuple <String, ExprType> > attribs) { if (this.IsComplete) { throw new InvalidOperationException("Cannot redefine a struct."); } this._attribs = new List <Utils.StoreEntry>(); Int32 offset = 0; Int32 struct_alignment = 0; foreach (Tuple <String, ExprType> attrib in attribs) { String name = attrib.Item1; ExprType type = attrib.Item2; Int32 attrib_alignment = type.Alignment; // All attributes must be aligned. // This means that the alignment of the struct is the largest attribute alignment. struct_alignment = Math.Max(struct_alignment, attrib_alignment); // Make sure all attributes are put into aligned places. offset = Utils.RoundUp(offset, attrib_alignment); this._attribs.Add(new Utils.StoreEntry(name, type, offset)); offset += type.SizeOf; } this._size_of = Utils.RoundUp(offset, struct_alignment); }
public Decln(String name, StorageClass scs, ExprType type, Option <Initr> initr) { this.name = name; this.scs = scs; this.type = type; this.initr = initr; }
public override void CGenStmt(Env env, CGenState state) { ExprType ret_type = env.GetCurrentFunction().ReturnType; Int32 stack_size = state.StackSize; if (this.ExprOpt.IsSome) { // Evaluate the Value. this.ExprOpt.Value.CGenValue(state); // If the function returns a struct, copy it to the address given by 8(%ebp). if (this.ExprOpt.Value.Type is StructOrUnionType) { state.MOVL(Reg.EAX, Reg.ESI); state.MOVL(2 * ExprType.SIZEOF_POINTER, Reg.EBP, Reg.EDI); state.MOVL(this.ExprOpt.Value.Type.SizeOf, Reg.ECX); state.CGenMemCpy(); state.MOVL(2 * ExprType.SIZEOF_POINTER, Reg.EBP, Reg.EAX); } // Restore stack size. state.CGenForceStackSizeTo(stack_size); } // Jump to end of the function. state.JMP(state.ReturnLabel); }
/// <summary> /// <para>Perform the usual arithmetic conversion on two expressions.</para> /// <para>If either expression is <see cref="DoubleType"/>, then both are converted to <see cref="DoubleType"/>.</para> /// <para>Else, if either expression is <see cref="FloatType"/>, then both are converted to <see cref="FloatType"/>.</para> /// <para>Else, if either expression is <see cref="ULongType"/>, then both are converted to <see cref="ULongType"/>.</para> /// <para>Else, both are converted to <see cref="LongType"/>.</para> /// </summary> /// <param name="e1">The first expression to be casted. Must have <see cref="ArithmeticType"/>.</param> /// <param name="e2">The second expression to be casted. Must have <see cref="ArithmeticType"/>.</param> /// <returns> /// The two casted expressions, and an <see cref="ExprTypeKind"/>. /// </returns> public static Tuple <Expr, Expr, ExprTypeKind> UsualArithmeticConversion(Expr e1, Expr e2) { ExprType t1 = e1.Type; ExprType t2 = e2.Type; Boolean c1 = t1.IsConst; Boolean v1 = t1.IsVolatile; Boolean c2 = t2.IsConst; Boolean v2 = t2.IsVolatile; // 1. if either Expr is double: both are converted to double if (t1.Kind == ExprTypeKind.DOUBLE || t2.Kind == ExprTypeKind.DOUBLE) { return(new Tuple <Expr, Expr, ExprTypeKind>(MakeCast(e1, new DoubleType(c1, v1)), MakeCast(e2, new DoubleType(c2, v2)), ExprTypeKind.DOUBLE)); } // 2. if either Expr is float: both are converted to float if (t1.Kind == ExprTypeKind.FLOAT || t2.Kind == ExprTypeKind.FLOAT) { return(new Tuple <Expr, Expr, ExprTypeKind>(MakeCast(e1, new FloatType(c1, v1)), MakeCast(e2, new FloatType(c2, v2)), ExprTypeKind.FLOAT)); } // 3. if either Expr is unsigned long: both are converted to unsigned long if (t1.Kind == ExprTypeKind.ULONG || t2.Kind == ExprTypeKind.ULONG) { return(new Tuple <Expr, Expr, ExprTypeKind>(MakeCast(e1, new ULongType(c1, v1)), MakeCast(e2, new ULongType(c2, v2)), ExprTypeKind.ULONG)); } // 4. both are converted to long return(new Tuple <Expr, Expr, ExprTypeKind>(MakeCast(e1, new LongType(c1, v1)), MakeCast(e2, new LongType(c2, v2)), ExprTypeKind.LONG)); }
public ConditionalExpr(Expr cond, Expr trueExpr, Expr falseExpr, ExprType type) { this.Cond = cond; this.TrueExpr = trueExpr; this.FalseExpr = falseExpr; this.Type = type; }
private TypeCast(TypeCastType kind, Expr expr, ExprType type, Env env) { this.Expr = expr; this.Kind = kind; this.Type = type; this.Env = env; }
// PushEnum // ======== // input: name, Type // output: Environment // return a new environment which adds a enum Value // public Scope PushEnum(String name, ExprType type, Int32 value) { Scope scope = new Scope(this); scope.enums.Add(new Utils.StoreEntry(name, type, value)); return(scope); }
public static Int32 GetOffset(ExprType base_type, IReadOnlyList <Int32> indices) { Int32 offset = 0; ExprType from_type = base_type; foreach (Int32 to_index in indices) { offset += GetOffset(from_type, to_index); from_type = GetType(from_type, to_index); } return(offset); }
public List <ExprType> GetTypes(ExprType base_type, IReadOnlyList <Int32> indices) { List <ExprType> types = new List <ExprType> { base_type }; ExprType from_type = base_type; foreach (Int32 to_index in indices) { from_type = GetType(from_type, to_index); types.Add(from_type); } return(types); }
/// <summary> /// Read an expression in the initializer list, locate the corresponding position. /// </summary> public void Locate(ExprType type) { switch (type.Kind) { case ExprTypeKind.STRUCT_OR_UNION: LocateStruct((StructOrUnionType)type); return; default: // Even if the expression is of array Type, treat it as a scalar (pointer). LocateScalar(); return; } }
public override Boolean EqualType(ExprType other) { return((other is FunctionType) && (other as FunctionType).HasVarArgs == this.HasVarArgs // same return Type && (other as FunctionType).ReturnType.EqualType(this.ReturnType) // same number of arguments && (other as FunctionType).Args.Count == this.Args.Count // same argument types && (other as FunctionType).Args.Zip(this.Args, (entry1, entry2) => entry1.type.EqualType(entry2.type)).All(_ => _)); }
// MakeCast // ======== // input: Expr, Type // output: TypeCast // converts Expr to Type // public static Expr MakeCast(Expr expr, ExprType type, Env env) { // if two types are equal, return Expr if (EqualType(expr.Type, type)) { return(expr); } // from pointer if (expr.Type.Kind == ExprTypeKind.POINTER) { return(FromPointer(expr, type, env)); } // to pointer if (type.Kind == ExprTypeKind.POINTER) { return(ToPointer(expr, type, env)); } switch (expr.Type.Kind) { // from signed integral case ExprTypeKind.CHAR: case ExprTypeKind.SHORT: case ExprTypeKind.LONG: return(SignedIntegralToArith(expr, type)); // from unsigned integral case ExprTypeKind.UCHAR: case ExprTypeKind.USHORT: case ExprTypeKind.ULONG: return(UnsignedIntegralToArith(expr, type)); // from float case ExprTypeKind.FLOAT: case ExprTypeKind.DOUBLE: return(FloatToArith(expr, type)); case ExprTypeKind.VOID: case ExprTypeKind.POINTER: case ExprTypeKind.FUNCTION: case ExprTypeKind.ARRAY: case ExprTypeKind.INCOMPLETE_ARRAY: case ExprTypeKind.STRUCT_OR_UNION: default: throw new InvalidOperationException("Error: expression Type not supported for casting from."); } }
public static Int32 GetOffset(ExprType from_type, Int32 to_index) { switch (from_type.Kind) { case ExprTypeKind.ARRAY: return(to_index * ((ArrayType)from_type).ElemType.SizeOf); case ExprTypeKind.INCOMPLETE_ARRAY: return(to_index * ((IncompleteArrayType)from_type).ElemType.SizeOf); case ExprTypeKind.STRUCT_OR_UNION: return(((StructOrUnionType)from_type).Attribs[to_index].offset); default: throw new InvalidProgramException("Not an aggregate Type."); } }
public void Next() { // From base_type to CurType. List <ExprType> types = GetTypes(this.base_type, this.indices); // We try to jump as many levels out as we can. do { Int32 index = this.indices.Last(); this.indices.RemoveAt(this.indices.Count - 1); types.RemoveAt(types.Count - 1); ExprType type = types.Last(); switch (type.Kind) { case ExprTypeKind.ARRAY: if (index < ((ArrayType)type).NumElems - 1) { // There are more elements in the array. this.indices.Add(index + 1); return; } break; case ExprTypeKind.INCOMPLETE_ARRAY: this.indices.Add(index + 1); return; case ExprTypeKind.STRUCT_OR_UNION: if (((StructOrUnionType)type).IsStruct && index < ((StructOrUnionType)type).Attribs.Count - 1) { // There are more members in the struct. // (not union, since we can only initialize the first member of a union) this.indices.Add(index + 1); return; } break; default: break; } } while (this.indices.Any()); }
public static FunctionType Create(ExprType ret_type, List <Tuple <String, ExprType> > args, Boolean is_varargs) { Tuple <Int32, IReadOnlyList <Int32> > r_pack = Utils.PackArguments(args.ConvertAll(_ => _.Item2)); IReadOnlyList <Int32> offsets = r_pack.Item2; if (ret_type is StructOrUnionType) { offsets = offsets.Select(_ => _ + 3 * SIZEOF_POINTER).ToList(); } else { offsets = offsets.Select(_ => _ + 2 * SIZEOF_POINTER).ToList(); } return(new FunctionType( ret_type, args.Zip(offsets, (name_type, offset) => new Utils.StoreEntry(name_type.Item1, name_type.Item2, offset) ).ToList(), is_varargs )); }
/// <summary> /// From: /// pointer /// To: /// pointer, integral /// </summary> public static Expr FromPointer(Expr expr, ExprType type, Env env) { ExprTypeKind from = expr.Type.Kind; ExprTypeKind to = type.Kind; if (from != ExprTypeKind.POINTER) { throw new InvalidOperationException("Expected a pointer."); } // if we are casting to another pointer, do a nop if (to == ExprTypeKind.POINTER) { if (expr.IsConstExpr) { return(new ConstPtr(((ConstPtr)expr).Value, type, env)); } return(new TypeCast(TypeCastType.NOP, expr, type, env)); } // if we are casting to an integral if (type.IsIntegral) { // pointer -> ulong -> whatever integral if (expr.IsConstExpr) { expr = new ConstULong(((ConstPtr)expr).Value, env); } else { expr = new TypeCast(TypeCastType.NOP, expr, new ULongType(type.IsConst, type.IsVolatile), env); } return(MakeCast(expr, type, env)); } throw new InvalidOperationException("Casting from a pointer to an unsupported Type."); }
// PushEntry // ========= // input: loc, name, Type // output: Scope // returns a new scope with everything the same as this, excpet for a new entry // public Scope PushEntry(EntryKind loc, String name, ExprType type) { Scope scope = new Scope(this); switch (loc) { case EntryKind.STACK: scope.esp_pos -= Utils.RoundUp(type.SizeOf, 4); scope.locals.Add(new Utils.StoreEntry(name, type, scope.esp_pos)); break; case EntryKind.GLOBAL: scope.globals.Add(new Utils.StoreEntry(name, type, 0)); break; case EntryKind.TYPEDEF: scope.typedefs.Add(new Utils.StoreEntry(name, type, 0)); break; default: return(null); } return(scope); }
public Decln(String name, StorageClass scs, ExprType type, Option<Initr> initr) { this.name = name; this.scs = scs; this.type = type; this.initr = initr; }
// PushEnum // ======== // input: name, Type // output: Environment // return a new environment which adds a enum Value // public Scope PushEnum(String name, ExprType type, Int32 value) { Scope scope = new Scope(this); scope.enums.Add(new Utils.StoreEntry(name, type, value)); return scope; }
// PushEnum // ======== // input: name, Type // output: Environment // return a new environment which adds a enum Value // public Env PushEnum(String name, ExprType type, Int32 value) { Scope top = this._scopes.Peek(); return new Env(this._scopes.Pop().Push(top.PushEnum(name, type, value))); }
/// <summary> /// From: /// uchar, ushort, ulong /// To: /// char, uchar, short, ushort, long, ulong, float, double /// </summary> /// <remarks> /// Aaccording to MSDN "Conversions from Unsigned Integral Types", /// unsigned long converts directly to double. /// However, I just treat unsigned long as long. /// </remarks> public static Expr UnsignedIntegralToArith(Expr expr, ExprType type) { ExprTypeKind from = expr.Type.Kind; ExprTypeKind to = type.Kind; Env env = expr.Env; switch (from) { case ExprTypeKind.UCHAR: switch (to) { case ExprTypeKind.CHAR: return new TypeCast(TypeCastType.NOP, expr, type); case ExprTypeKind.SHORT: case ExprTypeKind.USHORT: return new TypeCast(TypeCastType.UINT8_TO_UINT16, expr, type); case ExprTypeKind.LONG: case ExprTypeKind.ULONG: return new TypeCast(TypeCastType.UINT8_TO_UINT32, expr, type); case ExprTypeKind.FLOAT: // uchar -> ulong -> long -> float return new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.UINT8_TO_UINT32, expr, new LongType(type.IsConst, type.IsVolatile)), type); case ExprTypeKind.DOUBLE: // uchar -> ulong -> long -> double return new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.UINT8_TO_UINT32, expr, new LongType(type.IsConst, type.IsVolatile)), type); default: Debug.Assert(false); return null; } case ExprTypeKind.USHORT: switch (to) { case ExprTypeKind.CHAR: case ExprTypeKind.UCHAR: return new TypeCast(TypeCastType.PRESERVE_INT8, expr, type); case ExprTypeKind.USHORT: return new TypeCast(TypeCastType.NOP, expr, type); case ExprTypeKind.LONG: case ExprTypeKind.ULONG: return new TypeCast(TypeCastType.UINT16_TO_UINT32, expr, type); case ExprTypeKind.FLOAT: // ushort -> ulong -> long -> float return new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.UINT16_TO_UINT32, expr, new LongType(type.IsConst, type.IsVolatile)), type); case ExprTypeKind.DOUBLE: // ushort -> ulong -> long -> double return new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.UINT16_TO_UINT32, expr, new LongType(type.IsConst, type.IsVolatile)), type); default: Debug.Assert(false); return null; } case ExprTypeKind.ULONG: switch (to) { case ExprTypeKind.CHAR: if (expr.IsConstExpr) { return new ConstLong((SByte)((ConstULong)expr).Value, env); } return new TypeCast(TypeCastType.PRESERVE_INT8, expr, type); case ExprTypeKind.UCHAR: if (expr.IsConstExpr) { return new ConstULong((Byte)((ConstULong)expr).Value, env); } return new TypeCast(TypeCastType.PRESERVE_INT8, expr, type); case ExprTypeKind.SHORT: if (expr.IsConstExpr) { return new ConstLong((Int16)((ConstULong)expr).Value, env); } return new TypeCast(TypeCastType.PRESERVE_INT16, expr, type); case ExprTypeKind.USHORT: if (expr.IsConstExpr) { return new ConstULong((UInt16)((ConstULong)expr).Value, env); } return new TypeCast(TypeCastType.PRESERVE_INT16, expr, type); case ExprTypeKind.LONG: if (expr.IsConstExpr) { return new ConstLong((Int32)((ConstULong)expr).Value, env); } return new TypeCast(TypeCastType.NOP, expr, type); case ExprTypeKind.FLOAT: if (expr.IsConstExpr) { return new ConstFloat(((ConstULong)expr).Value, env); } return new TypeCast(TypeCastType.INT32_TO_FLOAT, expr, type); case ExprTypeKind.DOUBLE: if (expr.IsConstExpr) { return new ConstDouble(((ConstULong)expr).Value, env); } return new TypeCast(TypeCastType.INT32_TO_DOUBLE, expr, type); default: Debug.Assert(false); return null; } default: Debug.Assert(false); return null; } }
public StoreEntry(String name, ExprType type, Int32 offset) { this.name = name; this.type = type; this.offset = offset; }
public static Int32 GetOffset(ExprType from_type, Int32 to_index) { switch (from_type.Kind) { case ExprTypeKind.ARRAY: return to_index * ((ArrayType)from_type).ElemType.SizeOf; case ExprTypeKind.INCOMPLETE_ARRAY: return to_index * ((IncompleteArrayType)from_type).ElemType.SizeOf; case ExprTypeKind.STRUCT_OR_UNION: return ((StructOrUnionType)from_type).Attribs[to_index].offset; default: throw new InvalidProgramException("Not an aggregate Type."); } }
public void Locate(ExprType type) => this.trace.Last().Locate(type);
/// <summary> /// From: /// char, short, long /// To: /// char, uchar, short, ushort, long, ulong, float double /// </summary> public static Expr SignedIntegralToArith(Expr expr, ExprType type) { ExprTypeKind from = expr.Type.Kind; ExprTypeKind to = type.Kind; Env env = expr.Env; switch (from) { case ExprTypeKind.CHAR: switch (to) { case ExprTypeKind.SHORT: case ExprTypeKind.USHORT: return(new TypeCast(TypeCastType.INT8_TO_INT16, expr, type)); case ExprTypeKind.LONG: case ExprTypeKind.ULONG: return(new TypeCast(TypeCastType.INT8_TO_INT32, expr, type)); case ExprTypeKind.UCHAR: return(new TypeCast(TypeCastType.NOP, expr, type)); case ExprTypeKind.FLOAT: // char -> long -> float return(new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.INT8_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type)); case ExprTypeKind.DOUBLE: // char -> long -> double return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.INT8_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type)); case ExprTypeKind.VOID: case ExprTypeKind.POINTER: case ExprTypeKind.FUNCTION: case ExprTypeKind.ARRAY: case ExprTypeKind.INCOMPLETE_ARRAY: case ExprTypeKind.STRUCT_OR_UNION: case ExprTypeKind.CHAR: default: throw new InvalidProgramException($"Cannot cast from {from} to {to}"); } case ExprTypeKind.SHORT: switch (to) { case ExprTypeKind.CHAR: case ExprTypeKind.UCHAR: return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type)); case ExprTypeKind.USHORT: return(new TypeCast(TypeCastType.NOP, expr, type)); case ExprTypeKind.LONG: case ExprTypeKind.ULONG: return(new TypeCast(TypeCastType.INT16_TO_INT32, expr, type)); case ExprTypeKind.FLOAT: // short -> long -> float return(new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.INT16_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type)); case ExprTypeKind.DOUBLE: // short -> long -> double return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.INT16_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type)); case ExprTypeKind.VOID: case ExprTypeKind.SHORT: case ExprTypeKind.POINTER: case ExprTypeKind.FUNCTION: case ExprTypeKind.ARRAY: case ExprTypeKind.INCOMPLETE_ARRAY: case ExprTypeKind.STRUCT_OR_UNION: default: throw new InvalidProgramException($"Cannot cast from {from} to {to}"); } case ExprTypeKind.LONG: switch (to) { case ExprTypeKind.CHAR: if (expr.IsConstExpr) { return(new ConstChar((SByte)((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type)); case ExprTypeKind.UCHAR: if (expr.IsConstExpr) { return(new ConstUChar((Byte)((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type)); case ExprTypeKind.SHORT: if (expr.IsConstExpr) { return(new ConstShort((Int16)((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.PRESERVE_INT16, expr, type)); case ExprTypeKind.USHORT: if (expr.IsConstExpr) { return(new ConstUShort((UInt16)((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.PRESERVE_INT16, expr, type)); case ExprTypeKind.ULONG: if (expr.IsConstExpr) { return(new ConstULong((UInt32)((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.NOP, expr, type)); case ExprTypeKind.FLOAT: if (expr.IsConstExpr) { return(new ConstFloat(((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.INT32_TO_FLOAT, expr, type)); case ExprTypeKind.DOUBLE: if (expr.IsConstExpr) { return(new ConstDouble(((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, expr, type)); case ExprTypeKind.VOID: case ExprTypeKind.LONG: case ExprTypeKind.POINTER: case ExprTypeKind.FUNCTION: case ExprTypeKind.ARRAY: case ExprTypeKind.INCOMPLETE_ARRAY: case ExprTypeKind.STRUCT_OR_UNION: default: throw new InvalidProgramException($"Cannot cast from {from} to {to}"); } default: throw new InvalidProgramException(); } }
public Attribute(Expr expr, String name, ExprType type) { this.Expr = expr; this.Name = name; this.Type = type; }
public static Expr MakeCast(Expr expr, ExprType type) => MakeCast(expr, type, expr.Env);
public static Boolean EqualType(ExprType t1, ExprType t2) { return t1.EqualType(t2); }
public static Boolean EqualType(ExprType t1, ExprType t2) { return(t1.EqualType(t2)); }
/// <summary> /// From: /// pointer, integral /// To: /// pointer /// </summary> public static Expr ToPointer(Expr expr, ExprType type, Env env) { ExprTypeKind from = expr.Type.Kind; ExprTypeKind to = type.Kind; if (to != ExprTypeKind.POINTER) { throw new InvalidOperationException("Error: expected casting to pointer."); } if (from == ExprTypeKind.POINTER) { if (expr.IsConstExpr) { return(new ConstPtr(((ConstPtr)expr).Value, type, env)); } return(new TypeCast(TypeCastType.NOP, expr, type, env)); } if (expr.Type.IsIntegral) { // if we are casting from an integral // whatever integral -> ulong switch (expr.Type.Kind) { case ExprTypeKind.CHAR: case ExprTypeKind.SHORT: case ExprTypeKind.LONG: expr = SignedIntegralToArith(expr, new ULongType(type.IsConst, type.IsVolatile)); break; case ExprTypeKind.UCHAR: case ExprTypeKind.USHORT: case ExprTypeKind.ULONG: expr = UnsignedIntegralToArith(expr, new ULongType(type.IsConst, type.IsVolatile)); break; default: break; } // ulong -> pointer if (expr.IsConstExpr) { return(new ConstPtr(((ConstULong)expr).Value, type, env)); } return(new TypeCast(TypeCastType.NOP, expr, type, env)); } if (expr.Type is FunctionType) { if (!expr.Type.EqualType(((PointerType)type).RefType)) { throw new InvalidOperationException("Casting from an incompatible function."); } // TODO: only allow compatible Type? return(new TypeCast(TypeCastType.NOP, expr, type, env)); } if (expr.Type is ArrayType) { // TODO: allow any pointer Type to cast to? return(new TypeCast(TypeCastType.NOP, expr, type, env)); } throw new InvalidOperationException("Error: casting from an unsupported Type to pointer."); }
public void Iterate(ExprType type, Action<Int32, Expr> action) => Iterate(new MemberIterator(type), action);
public Dereference(Expr expr, ExprType type) { this.Expr = expr; this.Type = type; }
public Status(ExprType base_type) { this.base_type = base_type; this.indices = new List<Int32>(); }
public Variable(ExprType type, String name, Env env) { this.Name = name; this.Env = env; this.Type = type; }
public List<ExprType> GetTypes(ExprType base_type, IReadOnlyList<Int32> indices) { List<ExprType> types = new List<ExprType> { base_type }; ExprType from_type = base_type; foreach (Int32 to_index in indices) { from_type = GetType(from_type, to_index); types.Add(from_type); } return types; }
/// <summary> /// From: /// char, short, long /// To: /// char, uchar, short, ushort, long, ulong, float double /// </summary> public static Expr SignedIntegralToArith(Expr expr, ExprType type) { ExprTypeKind from = expr.Type.Kind; ExprTypeKind to = type.Kind; Env env = expr.Env; switch (from) { case ExprTypeKind.CHAR: switch (to) { case ExprTypeKind.SHORT: case ExprTypeKind.USHORT: return new TypeCast(TypeCastType.INT8_TO_INT16, expr, type); case ExprTypeKind.LONG: case ExprTypeKind.ULONG: return new TypeCast(TypeCastType.INT8_TO_INT32, expr, type); case ExprTypeKind.UCHAR: return new TypeCast(TypeCastType.NOP, expr, type); case ExprTypeKind.FLOAT: // char -> long -> float return new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.INT8_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type); case ExprTypeKind.DOUBLE: // char -> long -> double return new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.INT8_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type); case ExprTypeKind.VOID: case ExprTypeKind.POINTER: case ExprTypeKind.FUNCTION: case ExprTypeKind.ARRAY: case ExprTypeKind.INCOMPLETE_ARRAY: case ExprTypeKind.STRUCT_OR_UNION: case ExprTypeKind.CHAR: default: throw new InvalidProgramException($"Cannot cast from {from} to {to}"); } case ExprTypeKind.SHORT: switch (to) { case ExprTypeKind.CHAR: case ExprTypeKind.UCHAR: return new TypeCast(TypeCastType.PRESERVE_INT8, expr, type); case ExprTypeKind.USHORT: return new TypeCast(TypeCastType.NOP, expr, type); case ExprTypeKind.LONG: case ExprTypeKind.ULONG: return new TypeCast(TypeCastType.INT16_TO_INT32, expr, type); case ExprTypeKind.FLOAT: // short -> long -> float return new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.INT16_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type); case ExprTypeKind.DOUBLE: // short -> long -> double return new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.INT16_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type); case ExprTypeKind.VOID: case ExprTypeKind.SHORT: case ExprTypeKind.POINTER: case ExprTypeKind.FUNCTION: case ExprTypeKind.ARRAY: case ExprTypeKind.INCOMPLETE_ARRAY: case ExprTypeKind.STRUCT_OR_UNION: default: throw new InvalidProgramException($"Cannot cast from {from} to {to}"); } case ExprTypeKind.LONG: switch (to) { case ExprTypeKind.CHAR: if (expr.IsConstExpr) { return new ConstChar((SByte)((ConstLong)expr).Value, env); } return new TypeCast(TypeCastType.PRESERVE_INT8, expr, type); case ExprTypeKind.UCHAR: if (expr.IsConstExpr) { return new ConstUChar((Byte)((ConstLong)expr).Value, env); } return new TypeCast(TypeCastType.PRESERVE_INT8, expr, type); case ExprTypeKind.SHORT: if (expr.IsConstExpr) { return new ConstShort((Int16)((ConstLong)expr).Value, env); } return new TypeCast(TypeCastType.PRESERVE_INT16, expr, type); case ExprTypeKind.USHORT: if (expr.IsConstExpr) { return new ConstUShort((UInt16)((ConstLong)expr).Value, env); } return new TypeCast(TypeCastType.PRESERVE_INT16, expr, type); case ExprTypeKind.ULONG: if (expr.IsConstExpr) { return new ConstULong((UInt32)((ConstLong)expr).Value, env); } return new TypeCast(TypeCastType.NOP, expr, type); case ExprTypeKind.FLOAT: if (expr.IsConstExpr) { return new ConstFloat(((ConstLong)expr).Value, env); } return new TypeCast(TypeCastType.INT32_TO_FLOAT, expr, type); case ExprTypeKind.DOUBLE: if (expr.IsConstExpr) { return new ConstDouble(((ConstLong)expr).Value, env); } return new TypeCast(TypeCastType.INT32_TO_DOUBLE, expr, type); case ExprTypeKind.VOID: case ExprTypeKind.LONG: case ExprTypeKind.POINTER: case ExprTypeKind.FUNCTION: case ExprTypeKind.ARRAY: case ExprTypeKind.INCOMPLETE_ARRAY: case ExprTypeKind.STRUCT_OR_UNION: default: throw new InvalidProgramException($"Cannot cast from {from} to {to}"); } default: throw new InvalidProgramException(); } }
// MakeCast // ======== // input: Expr, Type // output: TypeCast // converts Expr to Type // public static Expr MakeCast(Expr expr, ExprType type, Env env) { // if two types are equal, return Expr if (EqualType(expr.Type, type)) { return expr; } // from pointer if (expr.Type.Kind == ExprTypeKind.POINTER) { return FromPointer(expr, type, env); } // to pointer if (type.Kind == ExprTypeKind.POINTER) { return ToPointer(expr, type, env); } switch (expr.Type.Kind) { // from signed integral case ExprTypeKind.CHAR: case ExprTypeKind.SHORT: case ExprTypeKind.LONG: return SignedIntegralToArith(expr, type); // from unsigned integral case ExprTypeKind.UCHAR: case ExprTypeKind.USHORT: case ExprTypeKind.ULONG: return UnsignedIntegralToArith(expr, type); // from float case ExprTypeKind.FLOAT: case ExprTypeKind.DOUBLE: return FloatToArith(expr, type); case ExprTypeKind.VOID: case ExprTypeKind.POINTER: case ExprTypeKind.FUNCTION: case ExprTypeKind.ARRAY: case ExprTypeKind.INCOMPLETE_ARRAY: case ExprTypeKind.STRUCT_OR_UNION: default: throw new InvalidOperationException("Error: expression Type not supported for casting from."); } }
public Initr ConformType(ExprType type) => ConformType(new MemberIterator(type));
// PushEntry // ========= // input: loc, name, Type // output: Scope // returns a new scope with everything the same as this, excpet for a new entry // public Scope PushEntry(EntryKind loc, String name, ExprType type) { Scope scope = new Scope(this); switch (loc) { case EntryKind.STACK: scope.esp_pos -= Utils.RoundUp(type.SizeOf, 4); scope.locals.Add(new Utils.StoreEntry(name, type, scope.esp_pos)); break; case EntryKind.GLOBAL: scope.globals.Add(new Utils.StoreEntry(name, type, 0)); break; case EntryKind.TYPEDEF: scope.typedefs.Add(new Utils.StoreEntry(name, type, 0)); break; default: return null; } return scope; }
/// <summary> /// From: /// pointer, integral /// To: /// pointer /// </summary> public static Expr ToPointer(Expr expr, ExprType type, Env env) { ExprTypeKind from = expr.Type.Kind; ExprTypeKind to = type.Kind; if (to != ExprTypeKind.POINTER) { throw new InvalidOperationException("Error: expected casting to pointer."); } if (from == ExprTypeKind.POINTER) { if (expr.IsConstExpr) { return new ConstPtr(((ConstPtr)expr).Value, type, env); } return new TypeCast(TypeCastType.NOP, expr, type, env); } if (expr.Type.IsIntegral) { // if we are casting from an integral // whatever integral -> ulong switch (expr.Type.Kind) { case ExprTypeKind.CHAR: case ExprTypeKind.SHORT: case ExprTypeKind.LONG: expr = SignedIntegralToArith(expr, new ULongType(type.IsConst, type.IsVolatile)); break; case ExprTypeKind.UCHAR: case ExprTypeKind.USHORT: case ExprTypeKind.ULONG: expr = UnsignedIntegralToArith(expr, new ULongType(type.IsConst, type.IsVolatile)); break; default: break; } // ulong -> pointer if (expr.IsConstExpr) { return new ConstPtr(((ConstULong)expr).Value, type, env); } return new TypeCast(TypeCastType.NOP, expr, type, env); } if (expr.Type is FunctionType) { if (!expr.Type.EqualType(((PointerType)type).RefType)) { throw new InvalidOperationException("Casting from an incompatible function."); } // TODO: only allow compatible Type? return new TypeCast(TypeCastType.NOP, expr, type, env); } if (expr.Type is ArrayType) { // TODO: allow any pointer Type to cast to? return new TypeCast(TypeCastType.NOP, expr, type, env); } throw new InvalidOperationException("Error: casting from an unsupported Type to pointer."); }
// PushEntry // ========= // input: loc, name, Type // ouput: Environment // return a new environment which adds a symbol entry // public Env PushEntry(EntryKind loc, String name, ExprType type) { Scope top = this._scopes.Peek(); return new Env(this._scopes.Pop().Push(top.PushEntry(loc, name, type))); }
public MemberIterator(ExprType type) { this.trace = new List <Status> { new Status(type) }; }
public Entry(EntryKind kind, ExprType type, Int32 offset) { this.Kind = kind; this.Type = type; this.Offset = offset; }
public Status(ExprType base_type) { this.base_type = base_type; this.indices = new List <Int32>(); }
public static ExprType GetType(ExprType base_type, IReadOnlyList <Int32> indices) => indices.Aggregate(base_type, GetType);
public MemberIterator(ExprType type) { this.trace = new List<Status> { new Status(type) }; }
/// <summary> /// From: /// pointer /// To: /// pointer, integral /// </summary> public static Expr FromPointer(Expr expr, ExprType type, Env env) { ExprTypeKind from = expr.Type.Kind; ExprTypeKind to = type.Kind; if (from != ExprTypeKind.POINTER) { throw new InvalidOperationException("Expected a pointer."); } // if we are casting to another pointer, do a nop if (to == ExprTypeKind.POINTER) { if (expr.IsConstExpr) { return new ConstPtr(((ConstPtr)expr).Value, type, env); } return new TypeCast(TypeCastType.NOP, expr, type, env); } // if we are casting to an integral if (type.IsIntegral) { // pointer -> ulong -> whatever integral if (expr.IsConstExpr) { expr = new ConstULong(((ConstPtr)expr).Value, env); } else { expr = new TypeCast(TypeCastType.NOP, expr, new ULongType(type.IsConst, type.IsVolatile), env); } return MakeCast(expr, type, env); } throw new InvalidOperationException("Casting from a pointer to an unsupported Type."); }
public static ExprType GetType(ExprType base_type, IReadOnlyList<Int32> indices) => indices.Aggregate(base_type, GetType);
public TypeCast(TypeCastType kind, Expr expr, ExprType type) : this(kind, expr, type, expr.Env) { }
public static Int32 GetOffset(ExprType base_type, IReadOnlyList<Int32> indices) { Int32 offset = 0; ExprType from_type = base_type; foreach (Int32 to_index in indices) { offset += GetOffset(from_type, to_index); from_type = GetType(from_type, to_index); } return offset; }
/// <summary> /// From: /// float, double /// To: /// char, uchar, short, ushort, long, ulong, float, double /// </summary> /// <remarks> /// According to MSDN "Conversions from Floating-Point Types", /// float cannot convert to unsigned char. /// I don't know why, but I follow it. /// </remarks> public static Expr FloatToArith(Expr expr, ExprType type) { ExprTypeKind from = expr.Type.Kind; ExprTypeKind to = type.Kind; Env env = expr.Env; switch (from) { case ExprTypeKind.FLOAT: switch (to) { case ExprTypeKind.CHAR: if (expr.IsConstExpr) { return new ConstLong((SByte)((ConstFloat)expr).Value, env); } return new TypeCast(TypeCastType.PRESERVE_INT8, new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type); case ExprTypeKind.SHORT: if (expr.IsConstExpr) { return new ConstLong((Int16)((ConstFloat)expr).Value, env); } return new TypeCast(TypeCastType.PRESERVE_INT16, new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type); case ExprTypeKind.USHORT: if (expr.IsConstExpr) { return new ConstULong((UInt16)((ConstFloat)expr).Value, env); } return new TypeCast(TypeCastType.PRESERVE_INT16, new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type); case ExprTypeKind.LONG: if (expr.IsConstExpr) { return new ConstLong((Int32)((ConstFloat)expr).Value, env); } return new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, type); case ExprTypeKind.ULONG: if (expr.IsConstExpr) { return new ConstULong((UInt32)((ConstFloat)expr).Value, env); } return new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, type); case ExprTypeKind.DOUBLE: if (expr.IsConstExpr) { return new ConstDouble(((ConstFloat)expr).Value, env); } return new TypeCast(TypeCastType.FLOAT_TO_DOUBLE, expr, type); default: throw new InvalidProgramException(); } case ExprTypeKind.DOUBLE: switch (to) { case ExprTypeKind.CHAR: // double -> float -> char if (expr.IsConstExpr) { return new ConstLong((SByte)((ConstDouble)expr).Value, env); } return FloatToArith(FloatToArith(expr, new FloatType(type.IsConst, type.IsVolatile)), new CharType(type.IsConst, type.IsVolatile)); case ExprTypeKind.SHORT: // double -> float -> short if (expr.IsConstExpr) { return new ConstLong((Int16)((ConstDouble)expr).Value, env); } return FloatToArith(FloatToArith(expr, new FloatType(type.IsConst, type.IsVolatile)), new ShortType(type.IsConst, type.IsVolatile)); case ExprTypeKind.LONG: // double -> float -> short if (expr.IsConstExpr) { return new ConstLong((Int32)((ConstDouble)expr).Value, env); } return new TypeCast(TypeCastType.DOUBLE_TO_INT32, expr, type); case ExprTypeKind.ULONG: if (expr.IsConstExpr) { return new ConstULong((UInt32)((ConstDouble)expr).Value, env); } return new TypeCast(TypeCastType.DOUBLE_TO_INT32, expr, type); case ExprTypeKind.USHORT: // double -> long -> ushort if (expr.IsConstExpr) { return new ConstULong((UInt16)((ConstDouble)expr).Value, env); } return new TypeCast(TypeCastType.PRESERVE_INT16, new TypeCast(TypeCastType.DOUBLE_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type); case ExprTypeKind.FLOAT: if (expr.IsConstExpr) { return new ConstFloat((Single)((ConstDouble)expr).Value, env); } return new TypeCast(TypeCastType.DOUBLE_TO_FLOAT, expr, type); default: throw new InvalidProgramException(); } default: throw new InvalidProgramException(); } }
public void Iterate(ExprType type, Action <Int32, Expr> action) => Iterate(new MemberIterator(type), action);