Example #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.SetGlobal, 1, stack.Count);
            }

            CompileIKVM.GlobalInfo setter;
            try
            {
                setter = context.GlobalSetters[this.Index];
            }
            catch (System.IndexOutOfRangeException x)
            {
                throw new CompilerException($"Global at index {this.Index} does not exist.", x);
            }

            if (setter == null)
            {
                throw new CompilerException($"Global at index {this.Index} is immutable.");
            }

            var type = stack.Pop();

            if (type != setter.Type)
            {
                throw new StackTypeInvalidException(OpCode.SetGlobal, setter.Type, type);
            }

            context.EmitLoadThis();
            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, setter.Builder);
        }
Example #2
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            if (context.GlobalGetters == null)
            {
                throw new CompilerException("Can't use GetGlobal without a global section.");
            }

            CompileIKVM.GlobalInfo getter;
            try
            {
                getter = context.GlobalGetters[this.Index];
            }
            catch (System.IndexOutOfRangeException x)
            {
                throw new CompilerException($"Global at index {this.Index} does not exist.", x);
            }

            if (getter.IsMutable)
            {
                context.EmitLoadThis();
            }

            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, getter.Builder);

            context.Stack.Push(getter.Type);
        }
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            base.CompileIKVM(context, universe);

            context.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4_0);
            context.Emit(IKVM.Reflection.Emit.OpCodes.Ceq);
        }
Example #4
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

            if (stack.Count < 2)
            {
                throw new StackTooSmallException(this.OpCode, 2, stack.Count);
            }

            var type = stack.Pop();

            if (type != this.Type)
            {
                throw new StackTypeInvalidException(this.OpCode, this.Type, type);
            }

            type = stack.Pop();
            if (type != ValueType.Int32)
            {
                throw new StackTypeInvalidException(this.OpCode, ValueType.Int32, type);
            }

            Int32Constant.Emit(context, (int)this.Offset);
            context.EmitLoadThis();
            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, this.IKVMCreateStoreMethod(this.StoreHelper, context, universe));
        }
Example #5
0
        internal override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

            if (stack.Count < 2)
            {
                throw new StackTooSmallException(this.OpCode, 2, stack.Count);
            }

            var typeB = stack.Pop();
            var typeA = stack.Pop();

            if (typeA != this.ValueType)
            {
                throw new StackTypeInvalidException(this.OpCode, this.ValueType, typeA);
            }

            if (typeA != typeB)
            {
                throw new StackParameterMismatchException(this.OpCode, typeA, typeB);
            }

            stack.Push(ValueType.Int32);

            context.Emit(this.IKVMEmittedOpCode);
        }
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

            if (stack.Count == 0)
            {
                throw new StackTooSmallException(this.OpCode, 1, 0);
            }

            var type = stack.Pop();

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

            if (this.Offset != 0)
            {
                Int32Constant.Emit(context, (int)this.Offset);
                context.Emit(IKVM.Reflection.Emit.OpCodes.Add_Ovf_Un);
            }

            this.IKVMEmitRangeCheck(context, universe);

            context.EmitLoadThis();
            context.Emit(IKVM.Reflection.Emit.OpCodes.Ldfld, context.Memory);
            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, Runtime.UnmanagedMemory.IKVMStartGetter(universe));
            context.Emit(IKVM.Reflection.Emit.OpCodes.Add);

            byte alignment;

            switch (this.Flags & Options.Align8)
            {
            default:     //Impossible to hit, but needed to avoid compiler error the about alignment variable.
            case Options.Align1: alignment = 1; break;

            case Options.Align2: alignment = 2; break;

            case Options.Align4: alignment = 4; break;

            case Options.Align8: alignment = 8; break;
            }

            if (alignment != 4)
            {
                context.Emit(IKVM.Reflection.Emit.OpCodes.Unaligned, alignment);
            }

            context.Emit(this.IKVMEmittedOpCode);
            var conversion = this.IKVMConversionOpCode;

            if (conversion != IKVM.Reflection.Emit.OpCodes.Nop)
            {
                context.Emit(conversion);
            }

            stack.Push(this.Type);
        }
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

            if (stack.Count < 2)
            {
                throw new StackTooSmallException(OpCode.Int64RotateLeft, 2, stack.Count);
            }

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

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

            if (typeA != typeB)
            {
                throw new StackParameterMismatchException(OpCode.Int64RotateLeft, typeA, typeB);
            }

            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, context[HelperMethod.Int64RotateLeft, (helper, c) =>
                                                                    {
                                                                        var builder = c.ExportsBuilder.DefineMethod(
                                                                            "☣ Int64RotateLeft",
                                                                            IKVMCompilationContext.HelperMethodAttributes,
                                                                            universe.Import(typeof(ulong)),
                                                                            new[]
                {
                    universe.Import(typeof(ulong)),
                    universe.Import(typeof(long)),
                }
                                                                            );

                                                                        var il = builder.GetILGenerator();
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_1);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Conv_I4);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4_S, 63);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.And);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Shl);

                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4_S, 64);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_1);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Conv_I4);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Sub);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4_S, 63);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.And);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Shr_Un);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Or);

                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ret);
                                                                        return(builder);
                                                                    }
                         ]);
        }
Example #8
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var loopStart = context.DefineLabel();

            context.Labels.Add(checked ((uint)context.Depth.Count), loopStart);
            context.Depth.Push(Type);
            context.MarkLabel(loopStart);
            context.LoopLabels.Add(loopStart);
        }
Example #9
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

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

            var type = stack.Pop();

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

            type = stack.Peek(); //Assuming validation passes, the remaining type will be this.
            if (type != ValueType.Float32)
            {
                throw new StackTypeInvalidException(OpCode.Float32CopySign, ValueType.Float32, type);
            }

            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, context[HelperMethod.Float32CopySign, (helper, c) =>
                                                                    {
                                                                        var builder = c.ExportsBuilder.DefineMethod(
                                                                            "☣ Float32CopySign",
                                                                            IKVMCompilationContext.HelperMethodAttributes,
                                                                            universe.Import(typeof(float)),
                                                                            new[]
                {
                    universe.Import(typeof(float)),
                    universe.Import(typeof(float)),
                }
                                                                            );

                                                                        var il = builder.GetILGenerator();
                                                                        var value = il.DeclareLocal(universe.Import(typeof(uint)));

                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarga_S, 0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldind_U4);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4, 0x7fffffff);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.And);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarga_S, 1);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldind_U4);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4, 0x80000000);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.And);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Or);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Stloc_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldloca_S, value);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldind_R4);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ret);

                                                                        return(builder);
                                                                    }
                         ]);
        }
Example #10
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var afterElse = context.DefineLabel();

            context.Emit(IKVM.Reflection.Emit.OpCodes.Br, afterElse);

            var target = checked ((uint)context.Depth.Count) - 1;

            context.MarkLabel(context.Labels[target]);
            context.Labels[target] = afterElse;
        }
Example #11
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            Assert(context != null);

            var returns = context.Signature.RawReturnTypes;
            var stack   = context.Stack;

            Assert(stack != null);

            var returnsLength = returns.Length;

            Assert(returnsLength == 0 || returnsLength == 1); //WebAssembly doesn't currently offer multiple returns, which should be blocked earlier.

            var stackCount = stack.Count;

            if (stackCount < returnsLength)
            {
                throw new StackTooSmallException(OpCode.Return, returnsLength, 0);
            }

            if (stackCount > returnsLength)
            {
                if (returnsLength == 0)
                {
                    for (var i = 0; i < stackCount - returnsLength; i++)
                    {
                        context.Emit(IKVM.Reflection.Emit.OpCodes.Pop);
                    }
                }
                else
                {
                    var value = context.DeclareLocal(universe.Import(returns[0].ToSystemType()));
                    context.Emit(IKVM.Reflection.Emit.OpCodes.Stloc, value.LocalIndex);

                    for (var i = 0; i < stackCount - returnsLength; i++)
                    {
                        context.Emit(IKVM.Reflection.Emit.OpCodes.Pop);
                    }

                    context.Emit(IKVM.Reflection.Emit.OpCodes.Ldloc, value.LocalIndex);
                }
            }
            else if (returnsLength == 1)
            {
                var type = stack.Pop();
                if (type != returns[0])
                {
                    throw new StackTypeInvalidException(OpCode.Return, returns[0], type);
                }
            }

            context.Emit(IKVM.Reflection.Emit.OpCodes.Ret);
        }
Example #12
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

            if (stack.Count == 0)
            {
                throw new StackTooSmallException(OpCode.Drop, 1, 0);
            }

            stack.Pop();

            context.Emit(IKVM.Reflection.Emit.OpCodes.Pop);
        }
Example #13
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            Assert(context != null);

            var stack = context.Stack;

            Assert(stack != null);
            if (stack.Count < 3)
            {
                throw new StackTooSmallException(OpCode.Select, 3, stack.Count);
            }

            var type = stack.Pop();

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

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

            if (typeA != typeB)
            {
                throw new StackParameterMismatchException(OpCode.Select, typeA, typeB);
            }

            HelperMethod helper;

            switch (typeA)
            {
            default:     //This shouldn't be possible due to previous validations.
                Fail("Unknown ValueType.");
                return;

            case ValueType.Int32: helper = HelperMethod.SelectInt32; break;

            case ValueType.Int64: helper = HelperMethod.SelectInt64; break;

            case ValueType.Float32: helper = HelperMethod.SelectFloat32; break;

            case ValueType.Float64: helper = HelperMethod.SelectFloat64; break;
            }
            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, IKVMCreateSelectHelper(helper, context, universe));
        }
Example #14
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

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

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

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

            context.Emit(this.IKVMEmittedOpCode);
        }
Example #15
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

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

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

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

            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, IKVMCreateHelper(HelperMethod.Int32CountOneBits, context, universe));
        }
Example #16
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var signature   = context.Types[this.Type];
            var paramTypes  = signature.RawParameterTypes;
            var returnTypes = signature.RawReturnTypes;

            var stack = context.Stack;

            if (stack.Count < paramTypes.Length)
            {
                throw new StackTooSmallException(OpCode.CallIndirect, paramTypes.Length, stack.Count);
            }

            var type = stack.Pop();

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

            for (var i = paramTypes.Length - 1; i >= 0; i--)
            {
                type = stack.Pop();
                if (type != paramTypes[i])
                {
                    throw new StackTypeInvalidException(OpCode.CallIndirect, paramTypes[i], type);
                }
            }

            for (var i = 0; i < returnTypes.Length; i++)
            {
                stack.Push(returnTypes[i]);
            }

            Int32Constant.Emit(context, checked ((int)this.Type));
            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, context[HelperMethod.GetFunctionPointer]);
            context.Emit(IKVM.Reflection.Emit.OpCodes.Stloc, context.IndirectPointerLocal.LocalIndex);
            context.EmitLoadThis();
            context.Emit(IKVM.Reflection.Emit.OpCodes.Ldloc, context.IndirectPointerLocal.LocalIndex);
            context.EmitCalli(
                signature.IKVMReturnTypes.Length == 0 ? universe.Import(typeof(void)) : signature.IKVMReturnTypes[0],
                signature.IKVMParameterTypes.Concat(new[] { context.ExportsBuilder.AsType() }).ToArray(
                    ));
        }
Example #17
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);
                                                                    }
                         ]);
        }
Example #18
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

            if (stack.Count == 0)
            {
                throw new StackTooSmallException(this.OpCode, 1, 0);
            }

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

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

            context.Emit(IKVM.Reflection.Emit.OpCodes.Conv_R8);
            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, this.IKVMMethodInfo);
            context.Emit(IKVM.Reflection.Emit.OpCodes.Conv_R4);
        }
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

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

            var type = stack.Pop();

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

            context.Emit(IKVM.Reflection.Emit.OpCodes.Conv_U8);

            stack.Push(ValueType.Int64);
        }
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

            if (stack.Count == 0)
            {
                throw new StackTooSmallException(OpCode.Float32DemoteFloat64, 1, 0);
            }

            var type = stack.Pop();

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

            context.Emit(IKVM.Reflection.Emit.OpCodes.Conv_R4);

            stack.Push(ValueType.Float32);
        }
Example #21
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            if (this.Index >= context.Methods.Length)
            {
                throw new CompilerException($"Function for index {this.Index} requseted, the assembly contains only {context.Methods.Length}.");
            }

            var signature   = context.FunctionSignatures[this.Index];
            var paramTypes  = signature.RawParameterTypes;
            var returnTypes = signature.RawReturnTypes;

            var stack = context.Stack;

            if (stack.Count < paramTypes.Length)
            {
                throw new StackTooSmallException(this.OpCode, paramTypes.Length, stack.Count);
            }

            for (var i = paramTypes.Length - 1; i >= 0; i--)
            {
                var type = stack.Pop();
                if (type != paramTypes[i])
                {
                    throw new StackTypeInvalidException(this.OpCode, paramTypes[i], type);
                }
            }

            for (var i = 0; i < returnTypes.Length; i++)
            {
                stack.Push(returnTypes[i]);
            }

            var target = context.Methods[this.Index];

            if (target is IKVM.Reflection.Emit.MethodBuilder) //Indicates a dynamically generated method.
            {
                context.EmitLoadThis();
            }
            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, target);
        }
Example #22
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

            if (stack.Count == 0)
            {
                throw new StackTooSmallException(OpCode.If, 1, 0);
            }

            var type = stack.Pop();

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

            var label = context.DefineLabel();

            context.Labels.Add(checked ((uint)context.Depth.Count), label);
            context.Depth.Push(Type);
            context.Emit(IKVM.Reflection.Emit.OpCodes.Brfalse, label);
        }
Example #23
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

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

            var type = stack.Pop();

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

            stack.Push(ValueType.Float32);

            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, context[HelperMethod.Float32ReinterpretInt32, (helper, c) =>
                                                                    {
                                                                        var builder = c.ExportsBuilder.DefineMethod(
                                                                            "☣ Float32ReinterpretInt32",
                                                                            IKVMCompilationContext.HelperMethodAttributes,
                                                                            universe.Import(typeof(float)),
                                                                            new[]
                {
                    universe.Import(typeof(int)),
                }
                                                                            );

                                                                        var il = builder.GetILGenerator();
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarga_S, 0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldind_R4);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ret);
                                                                        return(builder);
                                                                    }
                         ]);
        }
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

            if (stack.Count < 2)
            {
                throw new StackTooSmallException(this.OpCode, 2, stack.Count);
            }

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

            if (typeA != this.ValueType)
            {
                throw new StackTypeInvalidException(this.OpCode, this.ValueType, typeA);
            }

            if (typeA != typeB)
            {
                throw new StackParameterMismatchException(this.OpCode, typeA, typeB);
            }

            context.Emit(IKVM.Reflection.Emit.OpCodes.Call, this.IKVMMethodInfo);
        }
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

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

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

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

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

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

                                                                        //All modern CPUs have a fast instruction specifically for this process, but there's no way to use it from .NET.
                                                                        //This algorithm is 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.Ldc_I4_S, 32);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Call, Int32CountOneBits.IKVMCreateHelper(HelperMethod.Int32CountOneBits, context, universe));
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Sub);
                                                                        il.Emit(IKVM.Reflection.Emit.OpCodes.Ret);

                                                                        return(result);
                                                                    }
                         ]);
        }
Example #26
0
 internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
 {
     context.Labels.Add(checked ((uint)context.Depth.Count), context.DefineLabel());
     context.Depth.Push(Type);
 }
Example #27
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            var stack = context.Stack;

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

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

            if (setType != context.Locals[this.Index])
            {
                throw new StackTypeInvalidException(OpCode.TeeLocal, context.Locals[this.Index], setType);
            }

            context.Emit(IKVM.Reflection.Emit.OpCodes.Dup);

            var localIndex = this.Index - context.Signature.ParameterTypes.Length;

            if (localIndex < 0)
            {
                //Referring to a parameter.
                if (this.Index <= byte.MaxValue)
                {
                    context.Emit(IKVM.Reflection.Emit.OpCodes.Starg_S, checked ((byte)this.Index));
                }
                else
                {
                    context.Emit(IKVM.Reflection.Emit.OpCodes.Starg, checked ((ushort)this.Index));
                }
            }
            else
            {
                //Referring to a local.
                switch (localIndex)
                {
                default:
                    if (localIndex > 65534)     // https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stloc
                    {
                        throw new CompilerException($"Implementation limit exceeded: maximum accessible local index is 65534, tried to access {localIndex}.");
                    }

                    if (localIndex <= byte.MaxValue)
                    {
                        context.Emit(IKVM.Reflection.Emit.OpCodes.Stloc_S, (byte)localIndex);
                    }
                    else
                    {
                        context.Emit(IKVM.Reflection.Emit.OpCodes.Stloc, checked ((ushort)localIndex));
                    }
                    break;

                case 0: context.Emit(IKVM.Reflection.Emit.OpCodes.Stloc_0); break;

                case 1: context.Emit(IKVM.Reflection.Emit.OpCodes.Stloc_1); break;

                case 2: context.Emit(IKVM.Reflection.Emit.OpCodes.Stloc_2); break;

                case 3: context.Emit(IKVM.Reflection.Emit.OpCodes.Stloc_3); break;
                }
            }
        }
Example #28
0
 internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
 {
     context.Emit(IKVM.Reflection.Emit.OpCodes.Nop);
 }
Example #29
0
        internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            Assert(context != null);
            Assert(context.Depth != null);

            var stack = context.Stack;

            Assert(stack != null);

            var blockType = context.Depth.Count == 0 ? BlockType.Empty : context.Depth.Pop();

            if (context.Depth.Count == 0)
            {
                if (context.Previous == OpCode.Return)
                {
                    return; //WebAssembly requires functions to end on "end", but an immediately previous return is allowed.
                }
                var returns       = context.Signature.RawReturnTypes;
                var returnsLength = returns.Length;
                if (returnsLength != stack.Count)
                {
                    throw new StackSizeIncorrectException(OpCode.End, returnsLength, stack.Count);
                }

                Assert(returnsLength == 0 || returnsLength == 1); //WebAssembly doesn't currently offer multiple returns, which should be blocked earlier.

                if (returnsLength == 1)
                {
                    var type = stack.Pop();
                    if (type != returns[0])
                    {
                        throw new StackTypeInvalidException(OpCode.End, returns[0], type);
                    }
                }

                context.Emit(IKVM.Reflection.Emit.OpCodes.Ret);
            }
            else
            {
                if (blockType.TryToValueType(out var expectedType))
                {
                    var type = stack.Peek();
                    if (type != expectedType)
                    {
                        throw new StackTypeInvalidException(OpCode.End, expectedType, type);
                    }
                }

                var depth = checked ((uint)context.Depth.Count);
                var label = context.Labels[depth];

                if (!context.LoopLabels.Contains(label)) //Loop labels are marked where defined.
                {
                    context.MarkLabel(label);
                }
                else
                {
                    context.LoopLabels.Remove(label);
                }

                context.Labels.Remove(depth);
            }
        }
Example #30
0
        internal static IKVM.Reflection.Emit.MethodBuilder IKVMCreateHelper(HelperMethod helper, IKVMCompilationContext context, IKVM.Reflection.Universe universe)
        {
            Assert(context != null);

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

            //All modern CPUs have a fast instruction specifically for this process, but there's no way to use it from .NET.
            //This algorithm is from https://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer
            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.Ldc_I4, 0x55555555);
            il.Emit(IKVM.Reflection.Emit.OpCodes.And);
            il.Emit(IKVM.Reflection.Emit.OpCodes.Sub);
            il.Emit(IKVM.Reflection.Emit.OpCodes.Starg_S, 0);
            il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0);
            il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4, 0x33333333);
            il.Emit(IKVM.Reflection.Emit.OpCodes.And);
            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.Ldc_I4, 0x33333333);
            il.Emit(IKVM.Reflection.Emit.OpCodes.And);
            il.Emit(IKVM.Reflection.Emit.OpCodes.Add);
            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.Add);
            il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4, 0x0f0f0f0f);
            il.Emit(IKVM.Reflection.Emit.OpCodes.And);
            il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4, 0x01010101);
            il.Emit(IKVM.Reflection.Emit.OpCodes.Mul);
            il.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4_S, 24);
            il.Emit(IKVM.Reflection.Emit.OpCodes.Shr_Un);
            il.Emit(IKVM.Reflection.Emit.OpCodes.Ret);

            return(result);
        }