public void EmitCall(OpCode op, MethodInfo method, IEnumerable <Type> parameterTypes, Type[] arglist) { InstructionSizes.Add(() => InstructionSize.Get(op)); LengthCache.Clear(); Buffer.Add( (il, logOnly, log) => { if (!logOnly) { il.EmitCall(op, method, arglist); } var mtdString = method is MethodBuilder ? method.Name : method.ToString(); log.AppendLine(op + " " + mtdString + " __arglist(" + Join(", ", arglist) + ")"); } ); var parameters = new LinqList <Type>(parameterTypes); if (!method.IsStatic) { var declaring = method.DeclaringType; if (TypeHelpers.IsValueType(declaring)) { declaring = declaring.MakePointerType(); } parameters.Insert(0, declaring); } parameters.AddRange(arglist); var paras = new List <object> { method }; paras.AddRange(arglist); TraversableBuffer.Add(new BufferedILInstruction { IsInstruction = op, MethodReturnType = method.ReturnType, MethodParameterTypes = parameters }); Operations.Add(new Operation <DelegateType> { OpCode = op, Parameters = paras.ToArray() }); }
private static Type Alias(Type t) { if (TypeHelpers.IsValueType(t) && TypeHelpers.IsEnum(t)) { return(Alias(Enum.GetUnderlyingType(t))); } Type ret; if (!_AliasCache.TryGetValue(t, out ret)) { ret = t; } return(ret); }
private static LinqList <Type> GetBases(Type t) { if (TypeHelpers.IsValueType(t)) { return(new LinqList <Type>()); } var ret = new LinqList <Type>(); t = TypeHelpers.GetBaseType(t); while (t != null) { ret.Add(t); t = TypeHelpers.GetBaseType(t); } return(ret); }
public void Emit(OpCode op, ConstructorInfo cons, IEnumerable <Type> parameterTypes) { InstructionSizes.Add(() => InstructionSize.Get(op)); LengthCache.Clear(); Buffer.Add( (il, logOnly, log) => { if (!logOnly) { il.Emit(op, cons); } var mtdString = cons is ConstructorBuilder ? cons.Name : cons.ToString(); log.AppendLine(op + " " + mtdString); } ); var parameters = new LinqList <Type>(parameterTypes); var declaring = cons.DeclaringType; if (TypeHelpers.IsValueType(declaring)) { declaring = declaring.MakePointerType(); } parameters.Insert(0, declaring); TraversableBuffer.Add(new BufferedILInstruction { IsInstruction = op, MethodReturnType = typeof(void), MethodParameterTypes = parameters }); Operations.Add(new Operation <DelegateType> { OpCode = op, Parameters = new object[] { cons } }); }
public static bool IsAssignableFrom(TypeOnStack type1, TypeOnStack type2) { // voids aren't assignable if (type1.IsVoid || type2.IsVoid) { return(false); } // wildcards match *everything* if (type1 == TypeOnStack.Get <WildcardType>() || type2 == TypeOnStack.Get <WildcardType>()) { return(true); } if (type1.IsArray && type2.IsArray) { if (type1.Type.GetArrayRank() == type2.Type.GetArrayRank()) { var t1Elem = type1.Type.GetElementType(); var t2Elem = type2.Type.GetElementType(); while (t1Elem.HasElementType) { t1Elem = t1Elem.GetElementType(); } while (t2Elem.HasElementType) { t2Elem = t2Elem.GetElementType(); } if (t1Elem == typeof(WildcardType) || t2Elem == typeof(WildcardType)) { return(true); } } } if (type1.IsPointer && type2.IsPointer) { if (type1.Type.GetElementType() == typeof(WildcardType) || type2.Type.GetElementType() == typeof(WildcardType)) { return(true); } } if (type1.IsReference && type2.IsReference) { if (type1.Type.GetElementType() == typeof(WildcardType) || type2.Type.GetElementType() == typeof(WildcardType)) { return(true); } } // any pointer type matches, well, any pointer if (type1.Type == typeof(AnyPointerType) && type2.IsPointer) { return(true); } if (type2.Type == typeof(AnyPointerType) && type1.IsPointer) { return(true); } // likewise for any by ref if (type1.Type == typeof(AnyByRefType) && type2.IsReference) { return(true); } if (type2.Type == typeof(AnyByRefType) && type1.IsReference) { return(true); } // Native int can be convereted to any pointer type if (type1.IsPointer && type2 == TypeOnStack.Get <NativeIntType>()) { return(true); } if (type2.IsPointer && type1 == TypeOnStack.Get <NativeIntType>()) { return(true); } // it's possible to assign a struct* to an interface or object if (!(type2.IsPointerToValueType && (type1.IsInterface || type1.Type.Equals(typeof(object))))) { if ((type1.IsPointer || type1.IsReference) && !(type2.IsPointer || type2.IsReference)) { return(false); } if ((type2.IsPointer || type2.IsReference) && !(type1.IsPointer || type1.IsReference)) { return(false); } } if (type1.IsPointer || type1.IsReference) { return(type1.Type.GetElementType() == type2.Type.GetElementType()); } var t1 = type1.Type; var t2 = type2.Type; // The null type can be assigned to any reference type if (t1 == typeof(NullType) && !TypeHelpers.IsValueType(t2)) { return(true); } if (t2 == typeof(NullType) && !TypeHelpers.IsValueType(t1)) { return(true); } t1 = Alias(t1); t2 = Alias(t2); return(ReallyIsAssignableFrom(t1, t2)); }
private static bool ReallyIsAssignableFrom(Type t1, Type t2) { if (t1 == t2) { return(true); } if (t1 == typeof(OnlyObjectType)) { if (t2 == typeof(object)) { return(true); } return(false); } // quick and dirty base case if (t1 == typeof(object) && !TypeHelpers.IsValueType(t2)) { return(true); } // you have to box in this case if ((t1 == typeof(object) || TypeHelpers.IsInterface(t1)) && TypeHelpers.IsValueType(t2)) { return(false); } var t1Bases = GetBases(t1); var t2Bases = GetBases(t2); if (t2Bases.Any(t2b => TypeOnStack.Get(t1).IsAssignableFrom(TypeOnStack.Get(t2b)))) { return(true); } if (TypeHelpers.IsInterface(t1)) { var t2Interfaces = t2.IsPointer ? (LinqArray <Type>)t2.GetElementType().GetInterfaces() : (LinqArray <Type>)t2.GetInterfaces(); return(t2Interfaces.Any(t2i => TypeOnStack.Get(t1).IsAssignableFrom(TypeOnStack.Get(t2i)))); } if (TypeHelpers.IsGenericType(t1) && TypeHelpers.IsGenericType(t2)) { var t1Def = t1.GetGenericTypeDefinition(); var t2Def = t2.GetGenericTypeDefinition(); if (t1Def != t2Def) { return(false); } var t1Args = t1.GetGenericArguments(); var t2Args = t2.GetGenericArguments(); for (var i = 0; i < t1Args.Length; i++) { if (!TypeOnStack.Get(t1Args[i]).IsAssignableFrom(TypeOnStack.Get(t2Args[i]))) { return(false); } } return(true); } try { return(t1.IsAssignableFrom(t2)); } catch (NotSupportedException) { // Builders, some generic types, and so on don't implement this; just assume it's *no good* for now return(false); } }