private static void EmitConvert(FleeILGenerator ilg, OpCode convertOpcode) { if ((ilg != null)) { ilg.Emit(convertOpcode); } }
private static bool ImplicitConvertToInt64(TypeCode sourceTypeCode, FleeILGenerator ilg) { switch (sourceTypeCode) { case TypeCode.SByte: case TypeCode.Int16: case TypeCode.Int32: EmitConvert(ilg, OpCodes.Conv_I8); break; case TypeCode.Char: case TypeCode.Byte: case TypeCode.UInt16: case TypeCode.UInt32: EmitConvert(ilg, OpCodes.Conv_U8); break; case TypeCode.Int64: break; default: return(false); } return(true); }
/// <summary> /// Add a branch from a location to a target label /// </summary> /// <param name="ilg"></param> /// <param name="target"></param> /// <remarks></remarks> public void AddBranch(FleeILGenerator ilg, Label target) { ILLocation startLoc = new ILLocation(ilg.Length); BranchInfo bi = new BranchInfo(startLoc, target); MyBranchInfos.Add(bi); }
/// <summary> /// Set the position for a label /// </summary> /// <param name="ilg"></param> /// <param name="target"></param> /// <remarks></remarks> public void MarkLabel(FleeILGenerator ilg, Label target) { int pos = ilg.Length; foreach (BranchInfo bi in MyBranchInfos) { bi.Mark(target, pos); } }
public static void EmitArrayLoad(FleeILGenerator ilg, Type elementType) { TypeCode tc = Type.GetTypeCode(elementType); switch (tc) { case TypeCode.Byte: ilg.Emit(OpCodes.Ldelem_U1); break; case TypeCode.SByte: case TypeCode.Boolean: ilg.Emit(OpCodes.Ldelem_I1); break; case TypeCode.Int16: ilg.Emit(OpCodes.Ldelem_I2); break; case TypeCode.UInt16: ilg.Emit(OpCodes.Ldelem_U2); break; case TypeCode.Int32: ilg.Emit(OpCodes.Ldelem_I4); break; case TypeCode.UInt32: ilg.Emit(OpCodes.Ldelem_U4); break; case TypeCode.Int64: case TypeCode.UInt64: ilg.Emit(OpCodes.Ldelem_I8); break; case TypeCode.Single: ilg.Emit(OpCodes.Ldelem_R4); break; case TypeCode.Double: ilg.Emit(OpCodes.Ldelem_R8); break; case TypeCode.Object: case TypeCode.String: ilg.Emit(OpCodes.Ldelem_Ref); break; default: // Must be a non-primitive value type ilg.Emit(OpCodes.Ldelema, elementType); ilg.Emit(OpCodes.Ldobj, elementType); return; } }
/// <summary> /// Get a label by a key. Create the label if it is not present. /// </summary> /// <param name="key"></param> /// <param name="ilg"></param> /// <returns></returns> /// <remarks></remarks> public Label GetLabel(object key, FleeILGenerator ilg) { Label lbl; if (MyKeyLabelMap.TryGetValue(key, out lbl) == false) { lbl = ilg.DefineLabel(); MyKeyLabelMap.Add(key, lbl); } return(lbl); }
/// <summary> /// Determine if a branch from a point to a label will be long /// </summary> /// <param name="ilg"></param> /// <param name="target"></param> /// <returns></returns> /// <remarks></remarks> public bool IsLongBranch(FleeILGenerator ilg, Label target) { ILLocation startLoc = new ILLocation(ilg.Length); BranchInfo bi = new BranchInfo(startLoc, target); int index = MyBranchInfos.IndexOf(bi); bi = MyBranchInfos[index]; return(bi.IsLongBranch); }
public static void EmitLoadLocalAddress(FleeILGenerator ilg, int index) { Debug.Assert(index >= 0, "Invalid index"); if (index <= byte.MaxValue) { ilg.Emit(OpCodes.Ldloca_S, Convert.ToByte(index)); } else { ilg.Emit(OpCodes.Ldloca, index); } }
private static bool ImplicitConvertToUInt16(TypeCode sourceTypeCode, FleeILGenerator ilg) { switch (sourceTypeCode) { case TypeCode.Char: case TypeCode.Byte: case TypeCode.UInt16: return(true); default: return(false); } }
public static bool EmitImplicitConvert(Type sourceType, Type destType, FleeILGenerator ilg) { if (object.ReferenceEquals(sourceType, destType)) { return(true); } else if (EmitOverloadedImplicitConvert(sourceType, destType, ilg) == true) { return(true); } else if (ImplicitConvertToReferenceType(sourceType, destType, ilg) == true) { return(true); } else { return(ImplicitConvertToValueType(sourceType, destType, ilg)); } }
private static void EmitToAssembly(ExpressionElement rootElement, IServiceContainer services) { AssemblyName assemblyName = new AssemblyName(EmitAssemblyName); string assemblyFileName = string.Format("{0}.dll", EmitAssemblyName); AssemblyBuilder assemblyBuilder = System.AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyFileName, assemblyFileName); MethodBuilder mb = moduleBuilder.DefineGlobalMethod("Evaluate", MethodAttributes.Public | MethodAttributes.Static, typeof(T), new Type[] { typeof(object), typeof(ExpressionContext), typeof(VariableCollection) }); FleeILGenerator ilg = new FleeILGenerator(mb.GetILGenerator()); rootElement.Emit(ilg, services); moduleBuilder.CreateGlobalFunctions(); assemblyBuilder.Save(assemblyFileName); }
private void Compile(string expression, ExpressionOptions options) { // Add the services that will be used by elements during the compile IServiceContainer services = new ServiceContainer(); this.AddServices(services); // Parse and get the root element of the parse tree ExpressionElement topElement = _myContext.Parse(expression, services); if (options.ResultType == null) { options.ResultType = topElement.ResultType; } RootExpressionElement rootElement = new RootExpressionElement(topElement, options.ResultType); DynamicMethod dm = this.CreateDynamicMethod(); FleeILGenerator ilg = new FleeILGenerator(dm.GetILGenerator()); // Emit the IL rootElement.Emit(ilg, services); ilg.ValidateLength(); // Emit to an assembly if required if (options.EmitToAssembly == true) { EmitToAssembly(rootElement, services); } Type delegateType = typeof(ExpressionEvaluator <>).MakeGenericType(typeof(T)); _myEvaluator = (ExpressionEvaluator <T>)dm.CreateDelegate(delegateType); }
private static bool ImplicitConvertToReferenceType(Type sourceType, Type destType, FleeILGenerator ilg) { if (destType.IsValueType == true) { return(false); } if (object.ReferenceEquals(sourceType, typeof(Null))) { // Null is always convertible to a reference type return(true); } if (destType.IsAssignableFrom(sourceType) == false) { return(false); } if (sourceType.IsValueType == true) { if ((ilg != null)) { ilg.Emit(OpCodes.Box, sourceType); } } return(true); }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { Utility.EmitLoadLocal(ilg, _myIndex); }
/// <summary> ///Emit an implicit conversion (if the ilg is not null) and returns a value that determines whether the implicit conversion /// succeeded /// </summary> /// <param name="sourceType"></param> /// <param name="destType"></param> /// <param name="ilg"></param> /// <returns></returns> public static bool EmitImplicitNumericConvert(Type sourceType, Type destType, FleeILGenerator ilg) { TypeCode sourceTypeCode = Type.GetTypeCode(sourceType); TypeCode destTypeCode = Type.GetTypeCode(destType); switch (destTypeCode) { case TypeCode.Int16: return(ImplicitConvertToInt16(sourceTypeCode, ilg)); case TypeCode.UInt16: return(ImplicitConvertToUInt16(sourceTypeCode, ilg)); case TypeCode.Int32: return(ImplicitConvertToInt32(sourceTypeCode, ilg)); case TypeCode.UInt32: return(ImplicitConvertToUInt32(sourceTypeCode, ilg)); case TypeCode.Double: return(ImplicitConvertToDouble(sourceTypeCode, ilg)); case TypeCode.Single: return(ImplicitConvertToSingle(sourceTypeCode, ilg)); case TypeCode.Int64: return(ImplicitConvertToInt64(sourceTypeCode, ilg)); case TypeCode.UInt64: return(ImplicitConvertToUInt64(sourceTypeCode, ilg)); default: return(false); } }
private static bool ImplicitConvertToValueType(Type sourceType, Type destType, FleeILGenerator ilg) { // We only handle value types if (sourceType.IsValueType == false & destType.IsValueType == false) { return(false); } // No implicit conversion to enum. Have to do this check here since calling GetTypeCode on an enum will return the typecode // of the underlying type which screws us up. if (sourceType.IsEnum == true | destType.IsEnum == true) { return(false); } return(EmitImplicitNumericConvert(sourceType, destType, ilg)); }
private static bool EmitOverloadedImplicitConvert(Type sourceType, Type destType, FleeILGenerator ilg) { // Look for an implicit operator on the destination type MethodInfo mi = Utility.GetSimpleOverloadedOperator("Implicit", sourceType, destType); if (mi == null) { // No match return(false); } if ((ilg != null)) { ilg.Emit(OpCodes.Call, mi); } return(true); }