/// <summary> /// Gets whether the type supports collection initializers. /// </summary> static bool IsCollectionType(TypeReference tr) { if (tr == null) return false; TypeDefinition td = tr.Resolve(); while (td != null) { if (td.Interfaces.Any(intf => intf.Name == "IEnumerable" && intf.Namespace == "System.Collections")) return true; td = td.BaseType != null ? td.BaseType.Resolve() : null; } return false; }
Expression MakeDefaultValue(TypeReference type) { TypeDefinition typeDef = type.Resolve(); if (typeDef != null) { if (TypeAnalysis.IsIntegerOrEnum(typeDef)) return AstBuilder.MakePrimitive(0, typeDef); else if (!typeDef.IsValueType) return new NullReferenceExpression(); switch (typeDef.FullName) { case "System.Nullable`1": return new NullReferenceExpression(); case "System.Single": return new PrimitiveExpression(0f); case "System.Double": return new PrimitiveExpression(0.0); case "System.Decimal": return new PrimitiveExpression(0m); } } return new DefaultValueExpression { Type = AstBuilder.ConvertType(type) }; }
static bool OperandFitsInType(TypeReference type, int num) { TypeDefinition typeDef = type.Resolve() as TypeDefinition; if (typeDef != null && typeDef.IsEnum) { type = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType; } switch (type.MetadataType) { case MetadataType.SByte: return sbyte.MinValue <= num && num <= sbyte.MaxValue; case MetadataType.Int16: return short.MinValue <= num && num <= short.MaxValue; case MetadataType.Byte: return byte.MinValue <= num && num <= byte.MaxValue; case MetadataType.Char: return char.MinValue <= num && num <= char.MaxValue; case MetadataType.UInt16: return ushort.MinValue <= num && num <= ushort.MaxValue; default: return true; } }
static bool? IsSigned(TypeReference 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) TypeDefinition typeDef = type.Resolve() as TypeDefinition; if (typeDef != null && typeDef.IsEnum) { TypeReference underlyingType = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType; return IsSigned(underlyingType); } switch (type.MetadataType) { case MetadataType.SByte: case MetadataType.Int16: case MetadataType.Int32: case MetadataType.Int64: case MetadataType.IntPtr: return true; case MetadataType.Byte: case MetadataType.Char: case MetadataType.UInt16: case MetadataType.UInt32: case MetadataType.UInt64: case MetadataType.UIntPtr: return false; default: return null; } }
public static bool IsEnum(TypeReference 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) TypeDefinition typeDef = type.Resolve() as TypeDefinition; return typeDef != null && typeDef.IsEnum; }
public const int NativeInt = 33; // treat native int as between int32 and int64 public static int GetInformationAmount(TypeReference type) { if (type == null) return 0; if (type.IsValueType && !IsArrayPointerOrReference(type)) { // value type might be an enum TypeDefinition typeDef = type.Resolve() as TypeDefinition; if (typeDef != null && typeDef.IsEnum) { TypeReference underlyingType = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType; return GetInformationAmount(underlyingType); } } switch (type.MetadataType) { case MetadataType.Void: return 0; case MetadataType.Boolean: return 1; case MetadataType.SByte: case MetadataType.Byte: return 8; case MetadataType.Char: case MetadataType.Int16: case MetadataType.UInt16: return 16; case MetadataType.Int32: case MetadataType.UInt32: case MetadataType.Single: return 32; case MetadataType.Int64: case MetadataType.UInt64: case MetadataType.Double: return 64; case MetadataType.IntPtr: case MetadataType.UIntPtr: return NativeInt; default: return 100; // we consider structs/objects to have more information than any primitives } }