Пример #1
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);
        }