internal sealed override void Compile(CompilationContext context)
        {
            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(OpCodes.Call, context[this.StoreHelper, this.CreateStoreMethod]);
        }
Example #2
0
        internal sealed override void Compile(CompilationContext context)
        {
            context.PopStack(this.OpCode, this.Type, WebAssemblyValueType.Int32);

            Int32Constant.Emit(context, (int)this.Offset);
            context.EmitLoadThis();
            context.Emit(OpCodes.Call, context[this.StoreHelper, this.CreateStoreMethod]);
        }
        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);
        }
Example #4
0
        internal sealed override void Compile(CompilationContext context)
        {
            var stack = context.Stack;

            context.PopStackNoReturn(this.OpCode, WebAssemblyValueType.Int32);

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

            this.EmitRangeCheck(context);

            context.EmitLoadThis();
            context.Emit(OpCodes.Ldfld, context.CheckedMemory);
            context.Emit(OpCodes.Call, UnmanagedMemory.StartGetter);
            context.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;
            }

            //8-byte alignment is not available in IL.
            //See: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.unaligned?view=net-5.0
            //However, because 8-byte alignment is subset of 4-byte alignment,
            //We don't have to consider it.
            if (alignment != 4 && alignment != 8)
            {
                context.Emit(OpCodes.Unaligned, alignment);
            }

            context.Emit(this.EmittedOpCode);
            var conversion = this.ConversionOpCode;

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

            stack.Push(this.Type);
        }
Example #5
0
        internal sealed override void Compile(CompilationContext context)
        {
            var stack = context.Stack;

            context.PopStack(this.OpCode, WebAssemblyValueType.Int32);

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

            this.EmitRangeCheck(context);

            context.EmitLoadThis();
            context.Emit(OpCodes.Ldfld, context.CheckedMemory);
            context.Emit(OpCodes.Call, UnmanagedMemory.StartGetter);
            context.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(OpCodes.Unaligned, alignment);
            }

            context.Emit(this.EmittedOpCode);
            var conversion = this.ConversionOpCode;

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

            stack.Push(this.Type);
        }
Example #6
0
        internal sealed override void Compile(CompilationContext context)
        {
            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(OpCodes.Call, context[HelperMethod.GetFunctionPointer]);
            context.Emit(OpCodes.Stloc, context.IndirectPointerLocal.LocalIndex);
            context.EmitLoadThis();
            context.Emit(OpCodes.Ldloc, context.IndirectPointerLocal.LocalIndex);
            context.EmitCalli(
                signature.ReturnTypes.Length == 0 ? typeof(void) : signature.ReturnTypes[0],
                signature.ParameterTypes.Concat(new[] { context.ExportsBuilder.AsType() }).ToArray(
                    ));
        }