Esempio n. 1
0
        /// <summary>
        /// Sets the invoke target.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="compiler">The compiler.</param>
        /// <param name="method">The method.</param>
        private static void SetInvokeTarget(InstructionNode context, BaseMethodCompiler compiler, MosaMethod method)
        {
            context.InvokeMethod = method;

            // Fix the parameter list
            int paramCount = method.Signature.Parameters.Count;

            if (method.HasThis && !method.HasExplicitThis)
            {
                paramCount++;
            }

            // Setup operands for parameters and the return value
            if (!method.Signature.ReturnType.IsVoid)
            {
                context.ResultCount = 1;

                if (compiler.StoreOnStack(method.Signature.ReturnType))
                {
                    context.Result = AllocateVirtualRegisterOrStackSlot(compiler, method.Signature.ReturnType);
                }
                else
                {
                    context.Result = compiler.CreateVirtualRegister(method.Signature.ReturnType.GetStackType());
                }
            }
            else
            {
                context.ResultCount = 0;
            }

            context.OperandCount = (byte)paramCount;
        }
Esempio n. 2
0
        /// <summary>
        /// Requests the calling convention to create an appropriate move instruction to populate the return
        /// value of a method.
        /// </summary>
        /// <param name="compiler">The compiler.</param>
        /// <param name="context">The context.</param>
        /// <param name="operand">The operand, that's holding the return value.</param>
        public override void SetReturnValue(BaseMethodCompiler compiler, Context context, Operand operand)
        {
            int size, alignment;

            architecture.GetTypeRequirements(compiler.TypeLayout, operand.Type, out size, out alignment);
            size = Alignment.AlignUp(size, alignment);

            if (operand.IsR4)
            {
                architecture.InsertMoveInstruction(context, Operand.CreateCPURegister(operand.Type, returnFloatingPointRegister), operand);
            }
            else if (operand.IsR8)
            {
                architecture.InsertMoveInstruction(context, Operand.CreateCPURegister(operand.Type, returnFloatingPointRegister), operand);
            }
            else if (operand.IsLong)
            {
                MosaType highType = (operand.IsI8) ? compiler.TypeSystem.BuiltIn.I4 : compiler.TypeSystem.BuiltIn.U4;

                architecture.InsertMoveInstruction(context, Operand.CreateCPURegister(compiler.TypeSystem.BuiltIn.U4, return32BitRegister), operand.Low);
                architecture.InsertMoveInstruction(context, Operand.CreateCPURegister(highType, return64BitRegister), operand.High);
            }
            else if (compiler.StoreOnStack(operand.Type))
            {
                int size2 = compiler.TypeLayout.GetTypeSize(operand.Type);
                var OffsetOfFirstParameterOperand = Operand.CreateConstant(compiler.TypeSystem, OffsetOfFirstParameter);
                architecture.InsertCompoundCopy(compiler, context, compiler.StackFrame, OffsetOfFirstParameterOperand, compiler.StackFrame, operand, size2);
            }
            else
            {
                architecture.InsertMoveInstruction(context, Operand.CreateCPURegister(operand.Type, return32BitRegister), operand);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Pushes the specified instructions.
        /// </summary>
        /// <param name="compiler">The compiler.</param>
        /// <param name="context">The context.</param>
        /// <param name="operand">The op.</param>
        /// <param name="offset">Size of the stack.</param>
        /// <param name="size">Size of the parameter.</param>
        /// <param name="scratch">The scratch.</param>
        private void Push(BaseMethodCompiler compiler, Context context, Operand operand, int offset, int size, Operand scratch)
        {
            var offsetOperand = Operand.CreateConstant(compiler.TypeSystem, offset);

            if (operand.Is64BitInteger)
            {
                var offset4Operand = Operand.CreateConstant(compiler.TypeSystem, offset + 4);

                architecture.InsertStoreInstruction(context, scratch, offsetOperand, operand.Low);
                architecture.InsertStoreInstruction(context, scratch, offset4Operand, operand.High);
            }
            else if (operand.IsR)
            {
                if (operand.IsR8 && size == 4)
                {
                    Operand op2 = Operand.CreateCPURegister(compiler.TypeSystem.BuiltIn.R4, returnFloatingPointRegister);
                    architecture.InsertMoveInstruction(context, op2, operand);
                    architecture.InsertStoreInstruction(context, scratch, offsetOperand, op2);
                }
                else
                {
                    architecture.InsertStoreInstruction(context, scratch, offsetOperand, operand);
                }
            }
            else if (compiler.StoreOnStack(operand.Type))
            {
                var offset2 = Operand.CreateConstant(compiler.TypeSystem, offset);
                architecture.InsertCompoundCopy(compiler, context, scratch, offset2, compiler.StackFrame, operand, compiler.TypeLayout.GetTypeSize(operand.Type));
            }
            else
            {
                architecture.InsertStoreInstruction(context, scratch, offsetOperand, operand);
            }
        }
Esempio n. 4
0
        private static int CalculateReturnSize(BaseMethodCompiler compiler, MosaMethod method)
        {
            if (compiler.StoreOnStack(method.Signature.ReturnType))
            {
                return(compiler.TypeLayout.GetTypeSize(method.Signature.ReturnType));
            }

            return(0);
        }
Esempio n. 5
0
        private static int CalculateReturnSize(BaseMethodCompiler compiler, Operand result)
        {
            if (result == null)
            {
                return(0);
            }

            if (compiler.StoreOnStack(result.Type))
            {
                return(compiler.TypeLayout.GetTypeSize(result.Type));
            }

            return(0);
        }
Esempio n. 6
0
        /// <summary>
        /// Cleanups the return value.
        /// </summary>
        /// <param name="compiler">The compiler.</param>
        /// <param name="context">The context.</param>
        /// <param name="result">The result.</param>
        private void CleanupReturnValue(BaseMethodCompiler compiler, Context context, Operand result)
        {
            if (result == null)
            {
                return;
            }

            if (result.IsR)
            {
                Operand returnFP = Operand.CreateCPURegister(result.Type, returnFloatingPointRegister);
                context.AppendInstruction(IRInstruction.Gen, returnFP);
                architecture.InsertMoveInstruction(context, result, returnFP);
            }
            else if (result.Is64BitInteger)
            {
                Operand returnLow  = Operand.CreateCPURegister(result.Type, return32BitRegister);
                Operand returnHigh = Operand.CreateCPURegister(compiler.TypeSystem.BuiltIn.U4, return64BitRegister);
                context.AppendInstruction(IRInstruction.Gen, returnLow);
                context.AppendInstruction(IRInstruction.Gen, returnHigh);
                architecture.InsertMoveInstruction(context, result.Low, returnLow);
                architecture.InsertMoveInstruction(context, result.High, returnHigh);
            }
            else if (compiler.StoreOnStack(result.Type))
            {
                Debug.Assert(result.IsStackLocal);
                int size = compiler.TypeLayout.GetTypeSize(result.Type);
                var stackPointerRegister = Operand.CreateCPURegister(compiler.TypeSystem.BuiltIn.Pointer, architecture.StackPointerRegister);
                architecture.InsertCompoundCopy(compiler, context, compiler.StackFrame, result, stackPointerRegister, compiler.ConstantZero, size);
            }
            else
            {
                Operand returnLow = Operand.CreateCPURegister(result.Type, return32BitRegister);
                context.AppendInstruction(IRInstruction.Gen, returnLow);
                architecture.InsertMoveInstruction(context, result, returnLow);
            }
        }
        /// <summary>
        /// Pushes the specified instructions.
        /// </summary>
        /// <param name="compiler">The compiler.</param>
        /// <param name="typeLayout">The type layout.</param>
        /// <param name="context">The context.</param>
        /// <param name="operand">The op.</param>
        /// <param name="offset">Size of the stack.</param>
        /// <param name="size">Size of the parameter.</param>
        /// <param name="scratch">The scratch.</param>
        private void Push(BaseMethodCompiler compiler, Context context, Operand operand, int offset, int size, Operand scratch)
        {
            var offsetOperand = Operand.CreateConstant(compiler.TypeSystem, offset);

            if (operand.Is64BitInteger)
            {
                var offset4Operand = Operand.CreateConstant(compiler.TypeSystem, offset + 4);

                architecture.InsertStoreInstruction(context, scratch, offsetOperand, operand.Low);
                architecture.InsertStoreInstruction(context, scratch, offset4Operand, operand.High);
            }
            else if (operand.IsR)
            {
                if (operand.IsR8 && size == 4)
                {
                    Operand op2 = Operand.CreateCPURegister(compiler.TypeSystem.BuiltIn.R4, returnFloatingPointRegister);
                    architecture.InsertMoveInstruction(context, op2, operand);
                    architecture.InsertStoreInstruction(context, scratch, offsetOperand, op2);
                }
                else
                {
                    architecture.InsertStoreInstruction(context, scratch, offsetOperand, operand);
                }
            }
            else if (compiler.StoreOnStack(operand.Type))
            {
                var offset2 = Operand.CreateConstant(compiler.TypeSystem, offset);
                architecture.InsertCompoundMoveInstruction(compiler, context, scratch, offset2, compiler.StackFrame, operand, compiler.TypeLayout.GetTypeSize(operand.Type));
            }
            else
            {
                architecture.InsertStoreInstruction(context, scratch, offsetOperand, operand);
            }
        }
        /// <summary>
        /// Cleanups the return value.
        /// </summary>
        /// <param name="compiler">The compiler.</param>
        /// <param name="typeLayout">The type layouts.</param>
        /// <param name="context">The context.</param>
        /// <param name="result">The result.</param>
        private void CleanupReturnValue(BaseMethodCompiler compiler, Context context, Operand result)
        {
            if (result == null)
                return;

            if (result.IsR)
            {
                Operand returnFP = Operand.CreateCPURegister(result.Type, returnFloatingPointRegister);
                context.AppendInstruction(IRInstruction.Gen, returnFP);
                architecture.InsertMoveInstruction(context, result, returnFP);
            }
            else if (result.Is64BitInteger)
            {
                Operand returnLow = Operand.CreateCPURegister(result.Type, return32BitRegister);
                Operand returnHigh = Operand.CreateCPURegister(compiler.TypeSystem.BuiltIn.U4, return64BitRegister);
                context.AppendInstruction(IRInstruction.Gen, returnLow);
                context.AppendInstruction(IRInstruction.Gen, returnHigh);
                architecture.InsertMoveInstruction(context, result.Low, returnLow);
                architecture.InsertMoveInstruction(context, result.High, returnHigh);
            }
            else if (compiler.StoreOnStack(result.Type))
            {
                Debug.Assert(result.IsStackLocal);
                int size = compiler.TypeLayout.GetTypeSize(result.Type);
                var stackPointerRegister = Operand.CreateCPURegister(compiler.TypeSystem.BuiltIn.Pointer, architecture.StackPointerRegister);
                architecture.InsertCompoundMoveInstruction(compiler, context, result, result, stackPointerRegister, compiler.ConstantZero, size);
            }
            else
            {
                Operand returnLow = Operand.CreateCPURegister(result.Type, return32BitRegister);
                context.AppendInstruction(IRInstruction.Gen, returnLow);
                architecture.InsertMoveInstruction(context, result, returnLow);
            }
        }
        private static int CalculateReturnSize(BaseMethodCompiler compiler, Operand result)
        {
            if (result == null)
                return 0;

            if (compiler.StoreOnStack(result.Type))
            {
                return compiler.TypeLayout.GetTypeSize(result.Type);
            }

            return 0;
        }
        private static int CalculateReturnSize(BaseMethodCompiler compiler, MosaMethod method)
        {
            if (compiler.StoreOnStack(method.Signature.ReturnType))
            {
                return compiler.TypeLayout.GetTypeSize(method.Signature.ReturnType);
            }

            return 0;
        }
        /// <summary>
        /// Requests the calling convention to create an appropriate move instruction to populate the return
        /// value of a method.
        /// </summary>
        /// <param name="compiler">The compiler.</param>
        /// <param name="typeLayout">The type layouts.</param>
        /// <param name="context">The context.</param>
        /// <param name="operand">The operand, that's holding the return value.</param>
        public override void SetReturnValue(BaseMethodCompiler compiler, Context context, Operand operand)
        {
            int size, alignment;
            architecture.GetTypeRequirements(compiler.TypeLayout, operand.Type, out size, out alignment);
            size = Alignment.AlignUp(size, alignment);

            if (operand.IsR4)
            {
                architecture.InsertMoveInstruction(context, Operand.CreateCPURegister(operand.Type, returnFloatingPointRegister), operand);
            }
            else if (operand.IsR8)
            {
                architecture.InsertMoveInstruction(context, Operand.CreateCPURegister(operand.Type, returnFloatingPointRegister), operand);
            }
            else if (operand.IsLong)
            {
                MosaType highType = (operand.IsI8) ? compiler.TypeSystem.BuiltIn.I4 : compiler.TypeSystem.BuiltIn.U4;

                architecture.InsertMoveInstruction(context, Operand.CreateCPURegister(compiler.TypeSystem.BuiltIn.U4, return32BitRegister), operand.Low);
                architecture.InsertMoveInstruction(context, Operand.CreateCPURegister(highType, return64BitRegister), operand.High);
            }
            else if (size == 4 || size == 2 || size == 1)
            {
                architecture.InsertMoveInstruction(context, Operand.CreateCPURegister(operand.Type, return32BitRegister), operand);
            }
            else if (compiler.StoreOnStack(operand.Type))
            {
                int size2 = compiler.TypeLayout.GetTypeSize(operand.Type);
                var OffsetOfFirstParameterOperand = Operand.CreateConstant(compiler.TypeSystem, OffsetOfFirstParameter);
                architecture.InsertCompoundMoveInstruction(compiler, context, compiler.StackFrame, OffsetOfFirstParameterOperand, compiler.StackFrame, operand, size2);
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Sets the invoke target.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="compiler">The compiler.</param>
        /// <param name="method">The method.</param>
        private static void SetInvokeTarget(InstructionNode context, BaseMethodCompiler compiler, MosaMethod method)
        {
            context.InvokeMethod = method;

            // Fix the parameter list
            int paramCount = method.Signature.Parameters.Count;

            if (method.HasThis && !method.HasExplicitThis)
                paramCount++;

            // Setup operands for parameters and the return value
            if (!method.Signature.ReturnType.IsVoid)
            {
                context.ResultCount = 1;

                if (compiler.StoreOnStack(method.Signature.ReturnType))
                {
                    context.Result = AllocateVirtualRegisterOrStackSlot(compiler, method.Signature.ReturnType);
                }
                else
                {
                    context.Result = compiler.CreateVirtualRegister(method.Signature.ReturnType.GetStackType());
                }
            }
            else
            {
                context.ResultCount = 0;
            }

            context.OperandCount = (byte)paramCount;
        }