/// <summary> /// Create code to box the given source value into the given type. /// </summary> public static RLRange Box(this IRLBuilder builder, ISourceLocation sequencePoint, RegisterSpec source, XTypeReference type, DexTargetPackage targetPackage, IRegisterAllocator frame) { if (type.IsPrimitive) { if (type.IsByte()) builder.Add(sequencePoint, RCode.Int_to_byte, source.Register, source.Register); else if (type.IsUInt16()) builder.Add(sequencePoint, RCode.Int_to_short, source.Register, source.Register); // Call appropriate valueOf method var boxedType = type.Module.TypeSystem.Object; var r = frame.AllocateTemp(boxedType.GetReference(targetPackage)); var call = builder.Add(sequencePoint, RCode.Invoke_static, type.GetBoxValueOfMethod(), source.Registers); var last = builder.Add(sequencePoint, RCode.Move_result_object, r); return new RLRange(call, last, r); } if (type.IsGenericParameter) { var nop = builder.Add(sequencePoint, RCode.Nop); return new RLRange(nop, source); } XTypeDefinition typeDef ; if (type.TryResolve(out typeDef) && (typeDef.IsEnum)) { // Call appropriate valueOf method /*var boxedType = type.Module.TypeSystem.Object; var r = frame.AllocateTemp(boxedType.GetReference(target, nsConverter)); var call = builder.Add(sequencePoint, RCode.Invoke_static, typeDef.GetEnumUnderlyingType().GetBoxValueOfMethod(), source.Registers); var last = builder.Add(sequencePoint, RCode.Move_result_object, r); return new RLRange(call, last, r);*/ } // Just cast var checkCast = builder.Add(sequencePoint, RCode.Check_cast, type.GetReference(targetPackage), source); return new RLRange(checkCast, source); }
/// <summary> /// Is the given type a struct? /// </summary> public static bool IsStruct(this XTypeReference type, out XTypeDefinition typeDef) { typeDef = null; if (type == null) { return(false); } return(type.TryResolve(out typeDef) && typeDef.IsStruct); }
/// <summary> /// Is the given type an enum? /// </summary> public static bool IsEnum(this XTypeReference type, out XTypeDefinition typeDef) { typeDef = null; if (type == null) { return(false); } type = type.GetWithoutModifiers(); return(type.TryResolve(out typeDef) && typeDef.IsEnum); }
/// <summary> /// Is the given type IEnumerable or a derived interface? /// </summary> public static bool ExtendsIEnumerable(this XTypeReference type) { if (type.FullName == "System.Collections.IEnumerable") { return(true); } XTypeDefinition typeDef; if (!type.TryResolve(out typeDef) || !typeDef.IsInterface) { return(false); } return(typeDef.Interfaces.Any(ExtendsIEnumerable)); }
/// <summary> /// Is the given type System.Collections.ICollection or a derived interface? /// </summary> public static bool ExtendsICollection(this XTypeReference type) { type = type.GetWithoutModifiers(); if (type.FullName == "System.Collections.ICollection") { return(true); } XTypeDefinition typeDef; if (!type.TryResolve(out typeDef) || !typeDef.IsInterface) { return(false); } return(typeDef.Interfaces.Any(ExtendsICollection)); }
/// <summary> /// Is the given type System.Collections.IList, System.Collections.Generic.IList(T) or a derived interface? /// </summary> public static bool ExtendsIList(this XTypeReference type) { var fullName = type.FullName; if ((fullName == "System.Collections.IList") || (fullName == "System.Collections.Generic.IList`1")) { return(true); } XTypeDefinition typeDef; if (!type.TryResolve(out typeDef) || !typeDef.IsInterface) { return(false); } return(typeDef.Interfaces.Any(ExtendsIList)); }
/// <summary> /// Generate an Add opcode. /// </summary> private static RCode OpcodeForType(XTypeReference type, RCode[] opcodes) { if (type.IsInt32() || type.IsUInt32() || type.IsInt16() || type.IsUInt16() || type.IsChar() || type.IsByte() || type.IsSByte() || type.IsBoolean()) return opcodes[0]; if (type.IsInt64() || type.IsUInt64()) return opcodes[1]; if (type.IsFloat()) return opcodes[2]; if (type.IsDouble()) return opcodes[3]; XTypeDefinition typeDef; if (type.TryResolve(out typeDef)) { if (typeDef.IsEnum) { return OpcodeForType(typeDef.GetEnumUnderlyingType(), opcodes); } } throw new ArgumentException("Unsupported type " + type); }
static bool OperandFitsInType(XTypeReference type, int num) { XTypeDefinition typeDef; if (type.TryResolve(out typeDef) && typeDef.IsEnum) { type = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType; } switch (type.Kind) { case XTypeReferenceKind.SByte: return sbyte.MinValue <= num && num <= sbyte.MaxValue; case XTypeReferenceKind.Short: return short.MinValue <= num && num <= short.MaxValue; case XTypeReferenceKind.Byte: return byte.MinValue <= num && num <= byte.MaxValue; case XTypeReferenceKind.Char: return char.MinValue <= num && num <= char.MaxValue; case XTypeReferenceKind.UShort: return ushort.MinValue <= num && num <= ushort.MaxValue; default: return true; } }
static bool? IsSigned(XTypeReference type) { if (type == null || IsArrayPointerOrReference(type)) return null; // unfortunately we cannot rely on type.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec) XTypeDefinition typeDef; if (type.TryResolve(out typeDef) && typeDef.IsEnum) { var underlyingType = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType; return IsSigned(underlyingType); } switch (type.Kind) { case XTypeReferenceKind.SByte: case XTypeReferenceKind.Short: case XTypeReferenceKind.Int: case XTypeReferenceKind.Long: case XTypeReferenceKind.IntPtr: return true; case XTypeReferenceKind.Byte: case XTypeReferenceKind.Char: case XTypeReferenceKind.UShort: case XTypeReferenceKind.UInt: case XTypeReferenceKind.ULong: case XTypeReferenceKind.UIntPtr: return false; default: return null; } }
public static bool IsEnum(XTypeReference type) { // Arrays/Pointers/ByReference resolve to their element type, but we don't want to consider those to be enums // However, GenericInstanceTypes, ModOpts etc. should be considered enums. if (type == null || IsArrayPointerOrReference(type)) return false; // unfortunately we cannot rely on type.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec) XTypeDefinition typeDef; return type.TryResolve(out typeDef) && typeDef.IsEnum; }
private const int NativeInt = 33; // treat native int as between int32 and int64 private static int GetInformationAmount(XTypeReference type) { if (type == null) return 0; if (type.IsValueType && !IsArrayPointerOrReference(type)) { // value type might be an enum XTypeDefinition typeDef; if (type.TryResolve(out typeDef) && typeDef.IsEnum) { var underlyingType = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType; return GetInformationAmount(underlyingType); } } switch (type.Kind) { case XTypeReferenceKind.Void: return 0; case XTypeReferenceKind.Bool: return 1; case XTypeReferenceKind.SByte: case XTypeReferenceKind.Byte: return 8; case XTypeReferenceKind.Char: case XTypeReferenceKind.Short: case XTypeReferenceKind.UShort: return 16; case XTypeReferenceKind.Int: case XTypeReferenceKind.UInt: case XTypeReferenceKind.Float: return 32; case XTypeReferenceKind.Long: case XTypeReferenceKind.ULong: case XTypeReferenceKind.Double: return 64; case XTypeReferenceKind.IntPtr: case XTypeReferenceKind.UIntPtr: return NativeInt; default: return 100; // we consider structs/objects to have more information than any primitives } }