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;
}
}