/// <summary>
        /// Allows quick internal call replacements
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        /// <param name="internalMethod">The internal method to replace with.</param>
        /// <param name="internalClass">The internal class that has the internal method.</param>
        protected void Internal(Context context, BaseMethodCompiler methodCompiler, string internalMethod, string internalClass = "Internal")
        {
            if (context == null || methodCompiler == null || internalMethod == null || internalClass == null)
                throw new ArgumentNullException();

            var type = methodCompiler.TypeSystem.GetTypeByName("Mosa.Runtime", internalClass);
            Debug.Assert(type != null, "Cannot find Mosa.Runtime." + internalClass);

            var method = type.FindMethodByName(internalMethod);
            Debug.Assert(method != null, "Cannot find " + internalMethod + " in " + type.Name);

            Operand callTargetOperand = Operand.CreateSymbolFromMethod(methodCompiler.TypeSystem, method);

            var operands = new Operand[context.OperandCount];

            for (int i = 0; i < context.OperandCount; i++)
                operands[i] = context.GetOperand(i);

            Operand result = context.Result;

            context.SetInstruction(IRInstruction.Call, result, callTargetOperand);

            for (int i = 0; i < operands.Length; i++)
            {
                context.SetOperand(1 + i, operands[i]);
            }

            context.OperandCount = (byte)(1 + operands.Length);
            context.InvokeMethod = method;
        }
        /// <summary>
        /// Validates the specified instruction.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Resolve(Context ctx, BaseMethodCompiler compiler)
        {
            base.Resolve(ctx, compiler);

            ctx.Result = ctx.Operand1;
            ctx.ResultCount = 2;
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Validate(Context ctx, BaseMethodCompiler compiler)
        {
            base.Validate(ctx, compiler);

            var stackTypeForOperand1 = ctx.Operand1.StackType;
            var stackTypeForOperand2 = ctx.Operand2.StackType;

            if (ctx.Operand1.Type is ValueTypeSigType)
            {
                var op1Type = compiler.Method.Module.GetType((ctx.Operand1.Type as ValueTypeSigType).Token);
                if (op1Type.BaseType.FullName == "System.Enum")
                    stackTypeForOperand1 = this.FromSigType(op1Type.Fields[0].SignatureType.Type);
            }

            if (ctx.Operand2.Type is ValueTypeSigType)
            {
                var op2Type = compiler.Method.Module.GetType((ctx.Operand2.Type as ValueTypeSigType).Token);
                if (op2Type.BaseType.FullName == "System.Enum")
                    stackTypeForOperand2 = this.FromSigType(op2Type.Fields[0].SignatureType.Type);
            }

            var result = _opTable[(int)stackTypeForOperand1][(int)stackTypeForOperand2];

            if (result == StackTypeCode.Unknown)
                throw new InvalidOperationException(@"Invalid stack result of instruction: " + result.ToString() + " (" + ctx.Operand1.ToString() + ")");

            ctx.Result = compiler.CreateVirtualRegister(Operand.SigTypeFromStackType(result));
        }
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            var result = context.Result;
            var operand1 = context.Operand1;
            if (operand1.IsValueType)
            {
                InstructionNode def = operand1.Definitions[0];
                var replacements = new List<Tuple<InstructionNode, int>>();
                foreach (var use in operand1.Uses)
                    for (int i = 0; i < use.OperandCount; i++)
                        if (use.GetOperand(i) == operand1)
                            replacements.Add(new Tuple<InstructionNode, int>(use, i));

                foreach (var replace in replacements)
                    replace.Item1.SetOperand(replace.Item2, def.Operand1);

                operand1 = def.Operand1;
                def.Empty();

                if (operand1.IsMemoryAddress)
                {
                    context.SetInstruction(IRInstruction.AddressOf, result, operand1);
                    return;
                }
            }
            context.SetInstruction(IRInstruction.Move, result, operand1);
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="compiler">The compiler.</param>
        public override void Resolve(Context ctx, BaseMethodCompiler compiler)
        {
            base.Resolve(ctx, compiler);

            // Validate the typecode & determine the resulting stack type
            MosaType resultType;

            switch (opcode)
            {
                case OpCode.Conv_u: goto case OpCode.Conv_i;
                case OpCode.Conv_i: resultType = compiler.TypeSystem.BuiltIn.I; break;
                case OpCode.Conv_i1: resultType = compiler.TypeSystem.BuiltIn.I1; break;
                case OpCode.Conv_i2: resultType = compiler.TypeSystem.BuiltIn.I2; break;
                case OpCode.Conv_i4: resultType = compiler.TypeSystem.BuiltIn.I4; break;
                case OpCode.Conv_i8: resultType = compiler.TypeSystem.BuiltIn.I8; break;
                case OpCode.Conv_r4: resultType = compiler.TypeSystem.BuiltIn.R4; break;
                case OpCode.Conv_r8: resultType = compiler.TypeSystem.BuiltIn.R8; break;
                case OpCode.Conv_u1: resultType = compiler.TypeSystem.BuiltIn.U1; break;
                case OpCode.Conv_u2: resultType = compiler.TypeSystem.BuiltIn.U2; break;
                case OpCode.Conv_u4: resultType = compiler.TypeSystem.BuiltIn.U4; break;
                case OpCode.Conv_u8: resultType = compiler.TypeSystem.BuiltIn.U8; break;
                case OpCode.Conv_ovf_i: goto case OpCode.Conv_i;
                case OpCode.Conv_ovf_u: goto case OpCode.Conv_i;
                case OpCode.Conv_ovf_i_un: goto case OpCode.Conv_i;
                case OpCode.Conv_ovf_u_un: goto case OpCode.Conv_i;
                case OpCode.Conv_r_un: resultType = compiler.TypeSystem.BuiltIn.R8; break;
                default: throw new NotSupportedException(@"Overflow checking conversions not supported.");
            }

            ctx.Result = compiler.CreateVirtualRegister(resultType.GetStackType());
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Resolve(Context ctx, BaseMethodCompiler compiler)
        {
            base.Resolve(ctx, compiler);

            // Simple result is the same type as the unary argument
            ctx.Result = compiler.CreateVirtualRegister(ctx.Operand1.Type);
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Validate(Context ctx, BaseMethodCompiler compiler)
        {
            base.Validate(ctx, compiler);

            StackTypeCode result = StackTypeCode.Unknown;
            switch (opcode)
            {
                case OpCode.Add_ovf_un:
                    result = _addovfunTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType];
                    break;

                case OpCode.Sub_ovf_un:
                    result = _subovfunTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType];
                    break;

                default:
                    result = _operandTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType];
                    break;
            }

            if (StackTypeCode.Unknown == result)
                throw new InvalidOperationException(@"Invalid operand types passed to " + opcode);

            ctx.Result = compiler.CreateVirtualRegister(Operand.SigTypeFromStackType(result));
        }
 private Operand GetRuntimeTypeHandle(Context context, BaseMethodCompiler methodCompiler)
 {
     var typeDef = Operand.CreateUnmanagedSymbolPointer(methodCompiler.TypeSystem, StringClassTypeDefinitionSymbolName);
     var runtimeTypeHandle = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.GetTypeByName("System", "RuntimeTypeHandle"));
     var before = context.InsertBefore();
     before.SetInstruction(IRInstruction.Move, runtimeTypeHandle, typeDef);
     return runtimeTypeHandle;
 }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Validate(Context ctx, BaseMethodCompiler compiler)
        {
            base.Validate(ctx, compiler);

            SZArraySigType arrayType = ctx.Operand1.Type as SZArraySigType;
            if (arrayType == null)
                throw new InvalidProgramException(@"Operand to ldlen is not a vector.");

            ctx.Result = compiler.CreateVirtualRegister(BuiltInSigType.IntPtr);
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="compiler">The compiler.</param>
        public override void Validate(Context ctx, BaseMethodCompiler compiler)
        {
            base.Validate(ctx, compiler);

            // Validate the operand
            StackTypeCode result = _typeCodes[(int)ctx.Operand1.StackType];
            if (StackTypeCode.Unknown == result)
                throw new InvalidOperationException(@"Invalid operand to Neg instruction [" + result + "]");

            ctx.Result = compiler.CreateVirtualRegister(ctx.Operand1.Type);
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Resolve(Context ctx, BaseMethodCompiler compiler)
        {
            base.Resolve(ctx, compiler);

            //FIXME: Intent?
            //SigType destType = ctx.Operand1.Type;

            //Debug.Assert(destType is PtrSigType || destType is RefSigType, @"Destination operand not a pointer or reference.");
            //if (!(destType is PtrSigType || destType is RefSigType))
            //    throw new InvalidOperationException(@"Invalid operand.");
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Resolve(Context ctx, BaseMethodCompiler compiler)
        {
            base.Resolve(ctx, compiler);

            var result = operandTable[(int)ctx.Operand1.Type.GetStackTypeCode()][(int)ctx.Operand2.Type.GetStackTypeCode()];
            Debug.Assert(StackTypeCode.Unknown != result, @"Can't shift with the given virtualLocal operands.");
            if (StackTypeCode.Unknown == result)
                throw new InvalidOperationException(@"Invalid virtualLocal state for pairing (" + ctx.Operand1.Type.GetStackType() + ", " + ctx.Operand2.Type.GetStackType() + ")");

            ctx.Result = compiler.CreateVirtualRegister(compiler.TypeSystem.GetStackTypeFromCode(result));
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Validate(Context ctx, BaseMethodCompiler compiler)
        {
            base.Validate(ctx, compiler);

            StackTypeCode result = _operandTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType];
            Debug.Assert(StackTypeCode.Unknown != result, @"Can't shift with the given stack operands.");
            if (StackTypeCode.Unknown == result)
                throw new InvalidOperationException(@"Invalid stack state for pairing (" + ctx.Operand1.StackType + ", " + ctx.Operand2.StackType + ")");

            ctx.Result = compiler.CreateVirtualRegister(Operand.SigTypeFromStackType(result));
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="compiler">The compiler.</param>
        public override void Resolve(Context ctx, BaseMethodCompiler compiler)
        {
            base.Resolve(ctx, compiler);

            // Validate the operand
            var result = opTable[(int)ctx.Operand1.Type.GetStackTypeCode()];
            if (StackTypeCode.Unknown == result)
                throw new InvalidOperationException(@"Invalid operand to Not instruction.");

            ctx.Result = compiler.CreateVirtualRegister(ctx.Operand1.Type);
        }
 /// <summary>
 /// Replaces the intrinsic call site
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="methodCompiler">The method compiler.</param>
 void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
 {
     var result = context.Result;
     var operand1 = context.Operand1;
     if (operand1.IsValueType)
     {
         operand1 = context.Previous.Operand1;
         context.Previous.Empty();
         context.SetInstruction(IRInstruction.AddressOf, result, operand1);
         return;
     }
     context.SetInstruction(IRInstruction.Move, result, operand1);
 }
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            var method = methodCompiler.Compiler.PlatformInternalRuntimeType.FindMethodByName("AllocateString");

            Operand callTargetOperand = Operand.CreateSymbolFromMethod(methodCompiler.TypeSystem, method);

            Operand typeDefinitionOperand = GetRuntimeTypeHandle(context, methodCompiler);
            Operand lengthOperand = context.Operand1;
            Operand result = context.Result;

            context.SetInstruction(IRInstruction.Call, result, callTargetOperand, typeDefinitionOperand, lengthOperand);
            context.InvokeMethod = method;
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Resolve(Context ctx, BaseMethodCompiler compiler)
        {
            base.Resolve(ctx, compiler);

            // If we're ldind.i8, fix an IL deficiency that the result may be U8
            if (opcode == OpCode.Ldind_i8 && elementType.Value == MosaTypeCode.I8)
            {
                if (ctx.Operand1.Type.ElementType != null && ctx.Operand1.Type.ElementType.IsU8)
                {
                    ctx.Result = compiler.CreateVirtualRegister(compiler.TypeSystem.BuiltIn.U8);
                }
            }
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Resolve(Context ctx, BaseMethodCompiler compiler)
        {
            base.Resolve(ctx, compiler);

            var stackTypeForOperand1 = ctx.Operand1.Type.GetStackTypeCode();
            var stackTypeForOperand2 = ctx.Operand2.Type.GetStackTypeCode();

            var result = opTable[(int)stackTypeForOperand1][(int)stackTypeForOperand2];

            if (result == StackTypeCode.Unknown)
            {
                throw new InvalidOperationException(@"Invalid virtualLocal result of instruction: " + result.ToString() + " (" + ctx.Operand1.ToString() + ")");
            }

            ctx.Result = compiler.CreateVirtualRegister(compiler.TypeSystem.GetStackTypeFromCode(result));
        }
        /// <summary>
        /// Expands method call instruction represented by the context to perform the method call.
        /// </summary>
        /// <param name="typeLayout">The type layouts.</param>
        /// <param name="context">The context.</param>
        public override void MakeCall(BaseMethodCompiler compiler, MosaTypeLayout typeLayout, Context context)
        {
            /*
             * Calling convention is right-to-left, pushed on the stack. Return value in EAX for integral
             * types 4 bytes or less, XMM0 for floating point and EAX:EDX for 64-bit. If this is a method
             * of a type, the this argument is moved to ECX right before the call.
             * If return value is value type, a stack local is allocated as a hidden parameter in caller
             * stack, the callee will then store the return value in the allocated space
             * The return value is the first parameter (even before this)
             * The callee will place the address of the return value into EAX and the caller will then
             * either retrieve the return value using compound move or will let one of the callers higher
             * in the caller chain handle the retrieval of the return value using compound move.
             */

            Operand target = context.Operand1;
            Operand result = context.Result;
            MosaMethod method = context.InvokeMethod;

            Debug.Assert(method != null, context.ToString());

            Operand scratch = Operand.CreateCPURegister(typeLayout.TypeSystem.BuiltIn.Pointer, scratchRegister);

            List<Operand> operands = BuildOperands(context);

            int stackSize = CalculateStackSizeForParameters(typeLayout, architecture, operands, method);

            context.Empty();

            int returnSize = 0;
            if (typeLayout.IsCompoundType(method.Signature.ReturnType))
            {
                returnSize = typeLayout.GetTypeSize(method.Signature.ReturnType);
            }

            if (stackSize != 0 || returnSize != 0)
            {
                ReserveStackSizeForCall(typeLayout.TypeSystem, context, returnSize + stackSize, scratch);
                PushOperands(compiler, typeLayout, context, method, operands, returnSize + stackSize, scratch);
            }

            // the mov/call two-instructions combo is to help facilitate the register allocator
            architecture.InsertMoveInstruction(context, scratch, target);
            architecture.InsertCallInstruction(context, scratch);

            CleanupReturnValue(compiler, typeLayout, context, result);
            FreeStackAfterCall(typeLayout.TypeSystem, context, returnSize + stackSize);
        }
Exemple #20
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            var size = InstructionSize.Size32;

            if (context.OperandCount == 1)
            {
                context.SetInstruction(IRInstruction.LoadInteger, size, context.Result, context.Operand1, Operand.CreateConstant(methodCompiler.TypeSystem, 0));
            }
            else if (context.OperandCount == 2)
            {
                context.SetInstruction(IRInstruction.LoadInteger, size, context.Result, context.Operand1, context.Operand2);
            }
            else
            {
                throw new InvalidCompilerException();
            }
        }
Exemple #21
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            var size = methodCompiler.Architecture.NativePointerSize == 4 ? InstructionSize.Size32 : InstructionSize.Size64;

            if (context.OperandCount == 1)
            {
                context.SetInstruction(IRInstruction.Load, size, context.Result, context.Operand1, Operand.CreateConstantSignedInt(methodCompiler.TypeSystem, 0));
            }
            else if (context.OperandCount == 2)
            {
                context.SetInstruction(IRInstruction.Load, size, context.Result, context.Operand1, context.Operand2);
            }
            else
            {
                throw new InvalidCompilerException();
            }
        }
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            string arch = "Mosa.Platform.Internal." + methodCompiler.Architecture.PlatformName;

            var type = methodCompiler.TypeSystem.GetTypeByName(arch, "Runtime");
            Debug.Assert(type != null, "Cannot find " + arch + ".Runtime");

            var method = type.FindMethodByName("InitializeArray");

            Operand callTargetOperand = Operand.CreateSymbolFromMethod(methodCompiler.TypeSystem, method);

            Operand arrayOperand = context.Operand1;
            Operand fieldOperand = context.Operand2;

            context.SetInstruction(IRInstruction.Call, null, callTargetOperand, arrayOperand, fieldOperand);
            context.MosaMethod = method;
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Validate(Context ctx, BaseMethodCompiler compiler)
        {
            base.Validate(ctx, compiler);

            // Make sure the base is a typed reference
            throw new NotImplementedException();
            /*
                if (!Object.ReferenceEquals(_operands[0].Type, MetadataTypeReference.FromName(compiler.Assembly.Metadata, @"System", @"TypedReference")))
                {
                    Debug.Assert(false);
                    throw new InvalidProgramException(@"Invalid stack object.");
                }

                // Push the loaded value
                _results[0] = CreateResultOperand(_typeRef);
             */
        }
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            string arch = "Mosa.Platform.Internal." + methodCompiler.Architecture.PlatformName;

            var type = methodCompiler.TypeSystem.GetTypeByName(arch, "Runtime");
            Debug.Assert(type != null, "Cannot find " + arch + ".Runtime");

            var method = type.FindMethodByName("AllocateString");

            Operand callTargetOperand = Operand.CreateSymbolFromMethod(methodCompiler.TypeSystem, method);

            Operand methodTableOperand = Operand.CreateUnmanagedSymbolPointer(methodCompiler.TypeSystem, StringClassMethodTableSymbolName);
            Operand lengthOperand = context.Operand1;
            Operand result = context.Result;

            context.SetInstruction(IRInstruction.Call, result, callTargetOperand, methodTableOperand, lengthOperand);
            context.MosaMethod = method;
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Resolve(Context ctx, BaseMethodCompiler compiler)
        {
            base.Resolve(ctx, compiler);

            StackTypeCode result = StackTypeCode.Unknown;
            switch (opcode)
            {
                case OpCode.Add: result = addTable[(int)ctx.Operand1.Type.GetStackTypeCode()][(int)ctx.Operand2.Type.GetStackTypeCode()]; break;
                case OpCode.Sub: result = subTable[(int)ctx.Operand1.Type.GetStackTypeCode()][(int)ctx.Operand2.Type.GetStackTypeCode()]; break;
                default: result = operandTable[(int)ctx.Operand1.Type.GetStackTypeCode()][(int)ctx.Operand2.Type.GetStackTypeCode()]; break;
            }

            if (result == StackTypeCode.Unknown)
            {
                throw new InvalidOperationException(@"Invalid operand types passed to " + opcode);
            }

            MosaType resultType = null;

            if (StackTypeCode.UnmanagedPointer != result)
            {
                resultType = compiler.TypeSystem.GetStackTypeFromCode(result);

                if (result == StackTypeCode.F && ctx.Operand1.Type.IsR4 && ctx.Operand2.Type.IsR4)
                    resultType = compiler.TypeSystem.BuiltIn.R4;
            }
            else
            {
                if (ctx.Operand1.Type.IsPointer)
                {
                    resultType = ctx.Operand1.Type;
                }
                else if (ctx.Operand2.Type.IsPointer)
                {
                    resultType = ctx.Operand2.Type;
                }
                else
                    throw new InvalidOperationException(@"Invalid operand types passed to " + opcode);
            }

            //Debug.Assert(resultType != null, ctx.ToString());

            ctx.Result = compiler.CreateVirtualRegister(resultType);
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Resolve(Context ctx, BaseMethodCompiler compiler)
        {
            base.Resolve(ctx, compiler);

            StackTypeCode result = StackTypeCode.Unknown;

            switch (opcode)
            {
                case OpCode.Add_ovf_un: result = addovfunTable[(int)ctx.Operand1.Type.GetStackTypeCode()][(int)ctx.Operand2.Type.GetStackTypeCode()]; break;
                case OpCode.Sub_ovf_un: result = subovfunTable[(int)ctx.Operand1.Type.GetStackTypeCode()][(int)ctx.Operand2.Type.GetStackTypeCode()]; break;
                default: result = operandTable[(int)ctx.Operand1.Type.GetStackTypeCode()][(int)ctx.Operand2.Type.GetStackTypeCode()]; break;
            }

            if (StackTypeCode.Unknown == result)
            {
                throw new InvalidOperationException(@"Invalid operand types passed to " + opcode);
            }

            ctx.Result = compiler.CreateVirtualRegister(compiler.TypeSystem.GetStackTypeFromCode(result));
        }
 /// <summary>
 /// Replaces the intrinsic call site
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="methodCompiler">The method compiler.</param>
 void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
 {
     Internal(context, methodCompiler, context.InvokeMethod.Name, "InternalsForObject");
 }
 /// <summary>
 /// Replaces the intrinsic call site
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="methodCompiler">The method compiler.</param>
 void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
 {
     context.SetInstruction(IRInstruction.AddressOf, context.Result, context.Operand1);
 }
        /// <summary>
        /// Lays out all parameters of the method.
        /// </summary>
        /// <param name="compiler">The method compiler providing the parameters.</param>
        private void LayoutParameters(BaseMethodCompiler compiler)
        {
            List<Operand> paramOps = new List<Operand>();

            int offset = 0;

            if (compiler.Method.Signature.HasThis || compiler.Method.Signature.HasExplicitThis)
                ++offset;

            for (int i = 0; i < compiler.Method.Parameters.Count + offset; ++i)
                paramOps.Add(compiler.GetParameterOperand(i));

            LayoutVariables(paramOps, callingConvention, callingConvention.OffsetOfFirstParameter, -1);
        }
 /// <summary>
 /// Replaces the intrinsic call site
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="methodCompiler">The method compiler.</param>
 void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
 {
     var result = context.Result;
     var operand1 = context.Operand1;
     context.SetInstruction(IRInstruction.MoveInteger, result, operand1);
 }
        /// <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;
                context.Result = compiler.CreateVirtualRegister(method.Signature.ReturnType.GetStackType());
            }
            else
            {
                context.ResultCount = 0;
            }

            context.OperandCount = (byte)paramCount;
        }