public static void GenerateLoop(GenerationContextBase context, LocalBuilder countLocal, LocalBuilder loopControlLocal, Action loopAction, bool reversed = false) { var loopLabel = context.Generator.DefineLabel(); var loopFinishLabel = context.Generator.DefineLabel(); if (reversed) { context.Generator.PushLocalValueOntoStack(countLocal); context.Generator.PushIntegerOntoStack(1); context.Generator.Emit(OpCodes.Sub); // put <<countLocal>> - 1 on stack } else { context.Generator.PushIntegerOntoStack(0); // put <<0> on stack } context.Generator.StoreLocalValueFromStack(loopControlLocal); // initialize <<loopControl>> variable using value from stack context.Generator.MarkLabel(loopLabel); context.Generator.PushLocalValueOntoStack(loopControlLocal); if (reversed) { context.Generator.PushIntegerOntoStack(-1); } else { context.Generator.PushLocalValueOntoStack(countLocal); } context.Generator.Emit(OpCodes.Beq, loopFinishLabel); loopAction(); context.Generator.PushLocalValueOntoStack(loopControlLocal); context.Generator.PushIntegerOntoStack(reversed ? -1 : 1); context.Generator.Emit(OpCodes.Add); context.Generator.StoreLocalValueFromStack(loopControlLocal); // change <<loopControl>> variable by one context.Generator.Emit(OpCodes.Br, loopLabel); // jump to the next loop iteration context.Generator.MarkLabel(loopFinishLabel); }
public static void DumpToLibrary <T>(GenerationContextBase context, Action <GenerationContextBase> generateCodeAction, string postfix = null) { var invokeMethod = typeof(T).GetMethod("Invoke"); var returnType = invokeMethod.ReturnType; var argumentTypes = invokeMethod.GetParameters().Select(x => x.ParameterType).ToArray(); if (postfix != null) { foreach (var c in new[] { '`', '<', '>', ',', '[', ']' }) { postfix = postfix.Replace(c, '_'); } } var name = string.Format("{0}_{1}", counter++, postfix); var aname = new AssemblyName(name); var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(aname, AssemblyBuilderAccess.Save); var customAttribute = new CustomAttributeBuilder( typeof(DebuggableAttribute).GetConstructor(new[] { typeof(DebuggableAttribute.DebuggingModes) }), new object[] { DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.Default } ); assembly.SetCustomAttribute(customAttribute); var module = assembly.DefineDynamicModule(aname.Name, aname.Name + ".dll", true); var type = module.DefineType("T"); var method = type.DefineMethod("M", MethodAttributes.Public, returnType, argumentTypes); var generator = method.GetILGenerator(); generateCodeAction(context.WithGenerator(generator)); generator.Emit(OpCodes.Ret); type.CreateType(); assembly.Save(aname.Name + ".dll"); }
public static void GenerateLoop(GenerationContextBase context, LocalBuilder countLocal, Action <LocalBuilder> loopAction, bool reversed = false) { var loopControlLocal = context.Generator.DeclareLocal(typeof(int)); GenerateLoop(context, countLocal, loopControlLocal, () => loopAction(loopControlLocal), reversed); }