private static MethodBuilder BuildRunMethod <T, R>(Expression <Kernel <T, R> > kernel, TypeBuilder tb, FieldInfo xmin, FieldInfo xmax, FieldInfo ymin, FieldInfo ymax, FieldInfo source, FieldInfo target) where T : unmanaged where R : unmanaged { var km = KernelMeasure.Measure(kernel.Compile()); //TODO: perform an expression-only measure var staticRun = tb.DefineMethod("RunStatic", MethodAttributes.HideBySig | MethodAttributes.Private | MethodAttributes.Static, null, new[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(UnsafeArray2dPtr <T>), UnsafeArray2d.GetRefType <R>() }); var xmin_arg = Parameter(typeof(int), "xmin"); var xmax_arg = Parameter(typeof(int), "xmax"); var ymin_arg = Parameter(typeof(int), "ymin"); var ymax_arg = Parameter(typeof(int), "ymax"); var height_arg = Parameter(typeof(int), "height"); var sourcePtr_arg = Parameter(typeof(UnsafeArray2dPtr <T>), "sourcePtr"); var targetPtr_arg = Parameter(UnsafeArray2d.GetRefType <R>(), "targetPtr"); var i_var = Variable(typeof(int), "i"); var j_var = Variable(typeof(int), "j"); var w_var = Variable(typeof(int), "w"); var inlinedKernel = new CellAccessUnsafeInliner(kernel.Parameters[0], sourcePtr_arg, i_var, j_var, height_arg, w_var).Visit(kernel.Body); BlockExpression fe = null; if (typeof(T) == typeof(R)) // slight optimization { var l = Label(); var d_var = Variable(typeof(int), "d"); var lineEnd_var = Variable(typeof(UnsafeArray2dPtr <T>), "lineEnd"); fe = Block( new[] { w_var, d_var, lineEnd_var }, Assign(w_var, Property(sourcePtr_arg, typeof(UnsafeArray2dPtr <T>).GetProperty(nameof(UnsafeArray2dPtr <T> .Stride)))), Assign(d_var, Subtract(targetPtr_arg, sourcePtr_arg)), For(i_var, xmin_arg, LessThan(i_var, xmax_arg), Constant(1), Block( Assign(lineEnd_var, Subtract(Add(sourcePtr_arg, ymax_arg), ymin_arg)), Loop( IfThenElse( LessThan(sourcePtr_arg, lineEnd_var), Block( Assign( MakeIndex( sourcePtr_arg, typeof(UnsafeArray2dPtr <T>).GetProperty("Item", new[] { typeof(int) }), new[] { d_var } ), inlinedKernel ), AddAssign(sourcePtr_arg, Constant(1)) // skip to the next element ), Break(l) ), l ), AddAssign(sourcePtr_arg, Constant(km.ymax - km.ymin)) // skip to the next row ) ) ); } else { fe = Block( new[] { w_var }, Assign(w_var, Property(sourcePtr_arg, typeof(UnsafeArray2dPtr <T>).GetProperty(nameof(UnsafeArray2dPtr <T> .Stride)))), For(i_var, xmin_arg, LessThan(i_var, xmax_arg), Constant(1), Block( For( j_var, ymin_arg, LessThan(j_var, ymax_arg), Constant(1), Block( Assign( MakeIndex( targetPtr_arg, UnsafeArray2d.GetRefType <R>().GetProperty("Item", new[] { typeof(int) }), new[] { Constant(0) } ), inlinedKernel ), AddAssign(sourcePtr_arg, Constant(1)), // skip to the next element AddAssign(targetPtr_arg, Constant(1)) ) ), AddAssign(sourcePtr_arg, Constant(km.ymax - km.ymin)), // skip to the next row AddAssign(targetPtr_arg, Constant(km.ymax - km.ymin)) ) ) ); } LambdaExpression staticRunLambda = Lambda(fe, xmin_arg, xmax_arg, ymin_arg, ymax_arg, height_arg, sourcePtr_arg, targetPtr_arg); staticRunLambda.CompileToMethod(staticRun); return(BuildInstanceRun <T, R>(tb, xmin, xmax, ymin, ymax, source, target, staticRun)); }
private static MethodBuilder BuildRunMethod <R>(LambdaExpression kernel, TypeBuilder tb, FieldInfo xmin, FieldInfo xmax, FieldInfo ymin, FieldInfo ymax, IEnumerable <FieldInfo> sources, FieldInfo target, bool recurrent) { var km = KernelMeasure.Measure(kernel); //TODO: perform an expression-only measure var sourceTypes = (from s in sources let elemType = s.FieldType.GetGenericArguments()[0] select typeof(UnsafeArray2dPtr <>).MakeGenericType(elemType)).ToArray(); var paramTypes = Enumerable.Repeat(typeof(int), 5) .Concat(sourceTypes) .Append(UnsafeArray2d.GetRefType <R>()).ToArray(); var staticRun = tb.DefineMethod("RunStatic", MethodAttributes.HideBySig | MethodAttributes.Private | MethodAttributes.Static, null, paramTypes); var xmin_arg = Parameter(typeof(int), "xmin"); var xmax_arg = Parameter(typeof(int), "xmax"); var ymin_arg = Parameter(typeof(int), "ymin"); var ymax_arg = Parameter(typeof(int), "ymax"); var height_arg = Parameter(typeof(int), "height"); var sourceArgs = new List <ParameterExpression>(); var i = 0; foreach (var s in sources) { sourceArgs.Add(Parameter(sourceTypes[i++], s.Name.Substring(1) + "Ptr")); } var targetPtr_arg = Parameter(UnsafeArray2d.GetRefType <R>(), "targetPtr"); var paramMap = new Dictionary <ParameterExpression, ParameterExpression>(); for (i = 0; i < sourceArgs.Count; i++) { //if(kernel.Parameters[i].Type.IsConstructedGenericType && kernel.Parameters[i].Type.GetGenericTypeDefinition() == typeof(ICell<>)) paramMap.Add(kernel.Parameters[i], sourceArgs[i]); } if (recurrent) { paramMap.Add(kernel.Parameters[i], targetPtr_arg); } var i_var = Variable(typeof(int), "i"); var j_var = Variable(typeof(int), "j"); var w_var = Variable(typeof(int), "w"); var inlinedKernelBody = new CellAccessUnsafeInliner(paramMap, i_var, j_var, height_arg, w_var).Visit(kernel.Body); BlockExpression fe = null; { fe = Block( new[] { w_var }, Assign(w_var, Property(targetPtr_arg, UnsafeArray2d.GetRefType <R>().GetProperty("Stride"))), For(i_var, xmin_arg, LessThan(i_var, xmax_arg), Constant(1), Block( For( j_var, ymin_arg, LessThan(j_var, ymax_arg), Constant(1), Block( Assign( MakeIndex( targetPtr_arg, UnsafeArray2d.GetRefType <R>().GetProperty("Item", new[] { typeof(int) }), new[] { Constant(0) } ), inlinedKernelBody ), Block(from s in sourceArgs select AddAssign(s, Constant(1))), // skip to the next element AddAssign(targetPtr_arg, Constant(1)) ) ), Block(from s in sourceArgs select AddAssign(s, Constant(km.ymax - km.ymin))), // skip to the next row AddAssign(targetPtr_arg, Constant(km.ymax - km.ymin)) ) ) ); } LambdaExpression staticRunLambda = Lambda(fe, (new[] { xmin_arg, xmax_arg, ymin_arg, ymax_arg, height_arg }).Concat(sourceArgs).Append(targetPtr_arg)); staticRunLambda.CompileToMethod(staticRun); return(BuildInstanceRun <R>(tb, xmin, xmax, ymin, ymax, sources, target, staticRun)); }