Beispiel #1
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

            if (stack.Count < 1)
            {
                throw new StackTooSmallException(OpCode.Int64CountTrailingZeroes, 1, stack.Count);
            }

            var type = stack.Peek(); //Assuming validation passes, the remaining type will be this.

            if (type != ValueType.Int64)
            {
                throw new StackTypeInvalidException(OpCode.Int64CountTrailingZeroes, ValueType.Int64, type);
            }

            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, context[HelperMethod.Int64CountTrailingZeroes, (helper, c) =>
                                                                    {
                                                                        Assert(c != null);

                                                                        var result = context.ExportsBuilder.DefineMethod(
                                                                            "☣ Int64CountTrailingZeroes",
                                                                            IKVMCompilationContext.HelperMethodAttributes,
                                                                            universe.Import(typeof(long)),
                                                                            new[] { universe.Import(typeof(ulong)) });

                                                                        //All modern CPUs have a fast instruction specifically for this process, but there's no way to use it from .NET.
                                                                        //Based on the algorithm found here: http://aggregate.org/MAGIC/#Trailing%20Zero%20Count
                                                                        var il = result.GetILGenerator();
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Neg);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.And);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4_1);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Conv_I8);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Sub);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Call, Int64CountOneBits.IKVMCreateHelper(HelperMethod.Int64CountOneBits, context, universe));
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ret);

                                                                        return(result);
                                                                    }
                         ]);
        }
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

            if (stack.Count < 1)
            {
                throw new StackTooSmallException(OpCode.Int64CountLeadingZeroes, 1, stack.Count);
            }

            var type = stack.Peek(); //Assuming validation passes, the remaining type will be this.

            if (type != ValueType.Int64)
            {
                throw new StackTypeInvalidException(OpCode.Int64CountLeadingZeroes, ValueType.Int64, type);
            }

            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, context[HelperMethod.Int64CountLeadingZeroes, (helper, c) =>
                                                                    {
                                                                        Assert(c != null);

                                                                        var result = context.ExportsBuilder.DefineMethod(
                                                                            "☣ Int64CountLeadingZeroes",
                                                                            IKVMCompilationContext.HelperMethodAttributes,
                                                                            universe.Import(typeof(ulong)),
                                                                            new[] { universe.Import(typeof(ulong)) });

                                                                        //All modern CPUs have a fast instruction specifically for this process, but there's no way to use it from .NET.
                                                                        //This algorithm is extended from https://stackoverflow.com/questions/10439242/count-leading-zeroes-in-an-int32
                                                                        var il = result.GetILGenerator();
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4_1);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Shr_Un);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Or);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Starg_S, 0);

                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4_2);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Shr_Un);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Or);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Starg_S, 0);

                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4_4);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Shr_Un);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Or);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Starg_S, 0);

                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4_8);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Shr_Un);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Or);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Starg_S, 0);

                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4_S, 16);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Shr_Un);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Or);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Starg_S, 0);

                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4_S, 32);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Shr_Un);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Or);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Starg_S, 0);

                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4_S, 64);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Call, Int64CountOneBits.IKVMCreateHelper(HelperMethod.Int64CountOneBits, context, universe));
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Sub);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ret);

                                                                        return(result);
                                                                    }
                         ]);
        }