예제 #1
0
파일: NewArr.cs 프로젝트: zrbruce/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Load the metadata token used to get the type info
            int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            //Get the type info for the element type
            Type elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);

            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);
            conversionState.AddExternalLabel(conversionState.GetNewArrMethodInfo().ID);

            //New array must:
            // - Allocate memory on the heap for the object
            //          - If no memory is left, throw a panic attack because we're out of memory...
            // - Call the specified constructor

            int currOpPosition = conversionState.PositionOf(theOp);

            //Attempt to allocate memory on the heap for the new array
            //This involves:
            // - (Number of elements is already on the stack)
            // - Pushing the element type reference onto the stack
            // - Calling GC NewArr method
            // - Check the pointer == 0, if so, out of memory

            //Push type reference
            string typeIdStr = conversionState.TheILLibrary.GetTypeInfo(elementType).ID;

            conversionState.AddExternalLabel(typeIdStr);
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Dword, Src = typeIdStr
            });
            //Push a dword for return value (i.e. new array pointer)
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Dword, Src = "0"
            });
            //Get the GC.NewArr method ID (i.e. ASM label)
            string methodLabel = conversionState.GetNewArrMethodInfo().ID;

            //Call GC.NewArr
            conversionState.Append(new ASMOps.Call()
            {
                Target = methodLabel
            });
            //Pop the return value (i.e. new array pointer)
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Dword, Dest = "EAX"
            });
            //Remove args from stack
            conversionState.Append(new ASMOps.Add()
            {
                Src = "8", Dest = "ESP"
            });
            //Check if pointer == 0?
            conversionState.Append(new ASMOps.Cmp()
            {
                Arg1 = "EAX", Arg2 = "0"
            });
            //If it isn't 0, not out of memory so continue execution
            conversionState.Append(new ASMOps.Jmp()
            {
                JumpType = ASMOps.JmpOp.JumpNotZero, DestILPosition = currOpPosition, Extension = "NotNullMem"
            });
            //If we are out of memory, we have a massive problem
            //Because it means we don't have space to create a new exception object
            //So ultimately we just have to throw a kernel panic
            //Throw a panic attack... ( :/ ) by calling kernel Halt(uint lastAddress)

            //result.AppendLine("call GetEIP");
            //result.AppendLine("push dword esp");
            //result.AppendLine("push dword ebp");
            //result.AppendLine("pushad");
            //result.AppendLine("mov dword eax, 0xDEADBEEF");
            //result.AppendLine("mov dword ebx, 0x2");
            //result.AppendLine("mov dword ecx, 1");
            //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_GC_Enabled], 1");
            //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_Heap_PreventAllocation], 0");
            //result.AppendLine("jmp method_System_Void_RETEND_Kernel_PreReqs_DECLEND_PageFaultDetection_NAMEEND___Fail");

            conversionState.Append(new ASMOps.Call()
            {
                Target = "GetEIP"
            });
            conversionState.AddExternalLabel("GetEIP");
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
            });
            //Insert the not null label
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "NotNullMem"
            });

            //Push new array pointer
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Dword, Src = "EAX"
            });

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = false,
                sizeOnStackInBytes = 4,
                isNewGCObject      = true,
                isGCManaged        = true,
                isValue            = false
            });
        }
예제 #2
0
파일: Shl.cs 프로젝트: sramos30/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if either or both values to shift left are floating point values or
        /// if the values are 8 bytes in size.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown if either or both values to multiply are not 4 or 8 bytes
        /// in size or if the values are of different size.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Pop in reverse order to push
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            int currOpPosition = conversionState.PositionOf(theOp);

            if (itemB.sizeOnStackInBytes < 4 ||
                itemA.sizeOnStackInBytes < 4)
            {
                throw new InvalidOperationException("Invalid stack operand sizes!");
            }
            else if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Shift left on floats is unsupported!");
            }
            else
            {
                if (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 4)
                {
                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "ECX"
                    });
                    //Pop item A
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "CL", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged        = false
                    });
                }
                else if ((itemA.sizeOnStackInBytes == 4 &&
                          itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! 4,8 not supported.");
                }
                else if ((itemA.sizeOnStackInBytes == 8 &&
                          itemB.sizeOnStackInBytes == 4))
                {
                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "ECX"
                    });
                    //Pop item A (8 bytes)
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EDX"
                    });

                    //Check shift size
                    conversionState.Append(new ASMOps.Cmp()
                    {
                        Arg1 = "ECX", Arg2 = "32"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.JumpGreaterThanEqual, DestILPosition = currOpPosition, Extension = "ShiftMoreThan32", UnsignedTest = true
                    });

                    //Shld (< 32)
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "EAX", Dest = "EDX", Count = "CL"
                    });
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "CL", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.Jump, DestILPosition = currOpPosition, Extension = "End"
                    });

                    //Shld (>= 32)
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "ShiftMoreThan32"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX", Dest = "EDX"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "0", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Sub()
                    {
                        Src = "32", Dest = "ECX"
                    });
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "CL", Dest = "EDX"
                    });

                    //Push result
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "End"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EDX"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged        = false
                    });
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                         itemB.sizeOnStackInBytes == 8)
                {
                    //Note: Shifting by more than 64 bits is pointless since the value will be annihilated entirely.
                    //          "64" fits well within the low 32-bits
                    //      So for this op, we do the same as the 8-4 byte version but discard the top four bytes
                    //          of the second operand
                    //      Except we must check the high bytes for non-zero value. If they are non-zero, we simply
                    //          push a result of zero.

                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "ECX"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EBX"
                    });
                    //Pop item A (8 bytes)
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EDX"
                    });
                    //Check high 4 bytes of second param
                    conversionState.Append(new ASMOps.Cmp()
                    {
                        Arg1 = "EBX", Arg2 = "0"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.JumpZero, DestILPosition = currOpPosition, Extension = "Zero"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "0"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "0"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.Jump, DestILPosition = currOpPosition, Extension = "End2"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "Zero"
                    });

                    conversionState.Append(new ASMOps.Cmp()
                    {
                        Arg1 = "ECX", Arg2 = "32"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.JumpGreaterThanEqual, DestILPosition = currOpPosition, Extension = "ShiftMoreThan32", UnsignedTest = true
                    });

                    //Shld (< 32)
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "EAX", Dest = "EDX", Count = "CL"
                    });
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "CL", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.Jump, DestILPosition = currOpPosition, Extension = "End1"
                    });

                    //Shl (>= 32)
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "ShiftMoreThan32"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX", Dest = "EDX"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "0", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Sub()
                    {
                        Src = "32", Dest = "ECX"
                    });
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "CL", Dest = "EDX"
                    });

                    //Push result
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "End1"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EDX"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "End2"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged        = false
                    });
                }
            }
        }
예제 #3
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            MethodBase constructorMethod = theOp.MethodToCall;
            Type       objectType        = constructorMethod.DeclaringType;

            //New obj must:
            // - Ignore for creation of Delegates
            // - Allocate memory on the heap for the object
            //          - If no memory is left, throw a panic attack because we're out of memory...
            // - Call the specified constructor

            if (typeof(Delegate).IsAssignableFrom(objectType))
            {
                conversionState.Append(new ASMOps.Comment("Ignore newobj calls for Delegates"));
                //Still need to:
                // - Remove the "object" param but preserve the "function pointer"
                StackItem funcPtrItem = conversionState.CurrentStackFrame.Stack.Pop();;
                conversionState.CurrentStackFrame.Stack.Pop();
                conversionState.CurrentStackFrame.Stack.Push(funcPtrItem);

                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "0($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "4($sp)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                });
                conversionState.Append(new ASMOps.Add()
                {
                    Src1 = "$sp", Src2 = "4", Dest = "$sp"
                });
                return;
            }

            Types.MethodInfo constructorMethodInfo = conversionState.TheILLibrary.GetMethodInfo(constructorMethod);

            conversionState.AddExternalLabel(conversionState.GetNewObjMethodInfo().ID);
            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);
            conversionState.AddExternalLabel(constructorMethodInfo.ID);

            int currOpPosition = conversionState.PositionOf(theOp);

            //Attempt to allocate memory on the heap for the new object
            //This involves:
            // - Pushing the type reference onto the stack
            // - Calling GC NewObj method
            // - Check the pointer == 0, if so, out of memory

            //Push type reference
            string typeIdStr = conversionState.TheILLibrary.GetTypeInfo(objectType).ID;

            conversionState.AddExternalLabel(typeIdStr);
            conversionState.Append(new ASMOps.La()
            {
                Dest = "$t4", Label = typeIdStr
            });
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Word, Src = "$t4"
            });
            //Push a word for return value (i.e. new object pointer)
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Word, Src = "$zero"
            });
            //Get the GC.NewObj method ID (i.e. ASM label)
            string methodLabel = conversionState.GetNewObjMethodInfo().ID;

            //Call GC.NewObj
            conversionState.Append(new ASMOps.Call()
            {
                Target = methodLabel
            });
            //Pop the return value (i.e. new object pointer)
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t0"
            });
            //Remove arg 0 from stack
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$sp", Src2 = "4", Dest = "$sp"
            });
            //Check if pointer == 0?
            //If it isn't 0, not out of memory so continue execution
            conversionState.Append(new ASMOps.Branch()
            {
                BranchType = ASMOps.BranchOp.BranchNotZero, Src1 = "$t0", DestILPosition = currOpPosition, Extension = "NotNullMem"
            });
            //If we are out of memory, we have a massive problem
            //Because it means we don't have space to create a new exception object
            //So ultimately we just have to throw a kernel panic
            //Throw a panic attack... ( :/ ) by calling kernel Halt(uint lastAddress)

            //result.AppendLine("call GetEIP");
            //result.AppendLine("push dword esp");
            //result.AppendLine("push dword ebp");
            //result.AppendLine("pushad");
            //result.AppendLine("mov dword eax, 0xDEADBEEF");
            //result.AppendLine("mov dword ebx, 0x1");
            //result.AppendLine("mov dword ecx, 1");
            //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_GC_Enabled], 1");
            //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_Heap_PreventAllocation], 0");
            //result.AppendLine("jmp method_System_Void_RETEND_Kernel_PreReqs_DECLEND_PageFaultDetection_NAMEEND___Fail");

            conversionState.Append(new ASMOps.Call()
            {
                Target = "GetEIP"
            });
            conversionState.AddExternalLabel("GetEIP");
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
            });
            //Insert the not null label
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "NotNullMem"
            });

            //Call the specified constructor
            //This involves:
            // - Push empty dword onto stack
            // - Move all args down by one dword
            // - Move object reference into dword as first arg
            // - Call constructor
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Word, Src = "$zero"
            });
            int sizeOfArgs = 0;

            ParameterInfo[] allParams = constructorMethod.GetParameters();
            foreach (ParameterInfo aParam in allParams)
            {
                sizeOfArgs += conversionState.TheILLibrary.GetTypeInfo(aParam.ParameterType).SizeOnStackInBytes;
                conversionState.CurrentStackFrame.Stack.Pop();
            }
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "$sp", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.RegToReg
            });
            if (sizeOfArgs > 0)
            {
                if (sizeOfArgs % 4 != 0)
                {
                    throw new InvalidOperationException("sizeOfArgs not exact multiple of 4!");
                }

                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = (sizeOfArgs / 4).ToString(), Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                });
                conversionState.Append(new ASMOps.Label()
                {
                    ILPosition = currOpPosition, Extension = "ShiftArgsLoop"
                });
                //Decrement counter ($t2)
                conversionState.Append(new ASMOps.Sub()
                {
                    Src1 = "$t2", Src2 = "1", Dest = "$t2"
                });
                //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "4($t1)", Dest = "$t3" });
                GlobalMethods.LoadData(conversionState, theOp, "$t1", "$t3", 4, 4);
                //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t3", Dest = "0($t1)" });
                GlobalMethods.StoreData(conversionState, theOp, "$t1", "$t3", 0, 4);
                conversionState.Append(new ASMOps.Add()
                {
                    Src1 = "$t1", Src2 = "4", Dest = "$t1"
                });
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.BranchNotZero, Src1 = "$t2", DestILPosition = currOpPosition, Extension = "ShiftArgsLoop"
                });
            }
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "0($t1)" });
            GlobalMethods.StoreData(conversionState, theOp, "$t1", "$t0", 0, 4);
            conversionState.Append(new ASMOps.Call()
            {
                Target = constructorMethodInfo.ID
            });
            //Only remove args from stack - we want the object pointer to remain on the stack
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$sp", Src2 = sizeOfArgs.ToString(), Dest = "$sp"
            });

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = false,
                sizeOnStackInBytes = 4,
                isNewGCObject      = true,
                isGCManaged        = true
            });
        }
예제 #4
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            string xCurrentMethodLabel = GetLabel(aMethod, aOpCode);
            OpType xType   = ( OpType )aOpCode;
            string xTypeID = GetTypeIDLabel(xType.Value);

            //mTypeId = GetService<IMetaDataInfoService>().GetTypeIdLabel( mCastAsType );
            // todo: throw an exception when the class does not support the cast!
            string mReturnNullLabel = xCurrentMethodLabel + "_ReturnNull";

            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true
            };
            new CPUx86.Compare {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 0
            };
            new CPUx86.ConditionalJump {
                Condition = CPUx86.ConditionalTestEnum.Zero, DestinationLabel = mReturnNullLabel
            };
            new CPUx86.Push {
                DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true
            };
            new CPUx86.Push {
                DestinationRef = Cosmos.Assembler.ElementReference.New(xTypeID), DestinationIsIndirect = true
            };
            SysReflection.MethodBase xMethodIsInstance = ReflectionUtilities.GetMethodBase(typeof(VTablesImpl), "IsInstance", "System.Int32", "System.Int32");
            // new OpMethod( ILOpCode.Code.Call, 0, 0, xMethodIsInstance, aOpCode.CurrentExceptionHandler ) );
            IL.Call.DoExecute(Assembler, aMethod, xMethodIsInstance, aOpCode, xCurrentMethodLabel, xCurrentMethodLabel + "_After_IsInstance_Call", DebugEnabled);
            new Label(xCurrentMethodLabel + "_After_IsInstance_Call");
            new CPUx86.Pop {
                DestinationReg = CPUx86.Registers.EAX
            };
            new CPUx86.Compare {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 0
            };
            new CPUx86.ConditionalJump {
                Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = mReturnNullLabel
            };
            new CPUx86.Jump {
                DestinationLabel = ILOp.GetLabel(aMethod, aOpCode.NextPosition)
            };

            new Label(mReturnNullLabel);
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ESP, SourceValue = 4
            };
            string xAllocInfoLabelName = LabelName.Get(GCImplementationRefs.AllocNewObjectRef);

#warning TODO: Emit new exceptions
            //new Newobj( Assembler ).Execute( aMethod, aOpCode );

            //Newobj.Assemble( Assembler,
            //                typeof( InvalidCastException ).GetConstructor( new Type[ 0 ] ),
            //                GetService<IMetaDataInfoService>().GetTypeIdLabel( typeof( InvalidCastException ) ),
            //                mThisLabel,
            //                mMethodInfo,
            //                mCurrentILOffset,
            //                mThisLabel + "_After_NewException",
            //                GetService<IMetaDataInfoService>().GetTypeInfo( typeof( InvalidCastException ) ),
            //                GetService<IMetaDataInfoService>().GetMethodInfo( typeof( InvalidCastException ).GetConstructor( new Type[ 0 ] ), false ),
            //                GetServiceProvider(),
            //                xAllocInfo.LabelName );
            new Label(xCurrentMethodLabel + "_After_NewException");
            //Call.EmitExceptionLogic( Assembler, ( uint )mCurrentILOffset, mMethodInfo, mNextOpLabel, false, null );
        }
예제 #5
0
        public void SizeOfType_ForColorStruct_Returns24()
        {
            var size = ILOp.SizeOfType(typeof(Color));

            Assert.That(size, Is.EqualTo(24));
        }
예제 #6
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            Type retType = (conversionState.Input.TheMethodInfo.IsConstructor ?
                            typeof(void) : ((MethodInfo)conversionState.Input.TheMethodInfo.UnderlyingInfo).ReturnType);

            Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
            if (retTypeInfo.SizeOnStackInBytes != 0)
            {
                conversionState.CurrentStackFrame.Stack.Pop();
            }
        }
예제 #7
0
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     rotateStackItems(conversionState, theOp.StackSwitch_Items, 1);
 }
예제 #8
0
파일: Mul.cs 프로젝트: zrbruce/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if either or both values to multiply are floating point values or
        /// if the values are 8 bytes in size.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown if either or both values to multiply are not 4 or 8 bytes
        /// in size or if the values are of different size.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Pop in reverse order to push
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();


            if (itemB.sizeOnStackInBytes < 4 ||
                itemA.sizeOnStackInBytes < 4)
            {
                throw new InvalidOperationException("Invalid stack operand sizes!");
            }
            else if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Divide floats is unsupported!");
            }
            else
            {
                if (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 4)
                {
                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t1"
                    });
                    //Pop item A
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    //Do the multiplication
                    conversionState.Append(new ASMOps.Mul()
                    {
                        Src1 = "$t0", Src2 = "$t1", Signed = true
                    });
                    //Load the result
                    conversionState.Append(new ASMOps.Mflo()
                    {
                        Dest = "$t0"
                    });
                    //Result stored in $t0
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
                else if ((itemA.sizeOnStackInBytes == 8 &&
                          itemB.sizeOnStackInBytes == 4) ||
                         (itemA.sizeOnStackInBytes == 4 &&
                          itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! They should be 32-32 or 64-64.");
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                         itemB.sizeOnStackInBytes == 8)
                {
                    Logger.LogWarning(Errors.ILCompiler_ScanILOpCustomWarning_ErrorCode, "", 0,
                                      string.Format(Errors.ErrorMessages[Errors.ILCompiler_ScanILOpCustomWarning_ErrorCode],
                                                    "All 64-bit multiplication is treated as unsigned. Ensure you didn't intend signed 64-bit multiplication. Signed 64-bit multiplication is not supported yet."));

                    //A = item A, B = item B
                    //L = low bits, H = high bits
                    // => A = AL + AH, B = BL + BH

                    // A * B = (AL + AH) * (BL + BH)
                    //       = (AL * BL) + (AL * BH) + (AH * BL) (Ignore: + (AH * BH))

                    // AH = 12($sp)
                    // AL = 8($sp)
                    // BH = 4($sp)
                    // BL = 0($sp)

                    // mov $t0, 0        - Zero out registers
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    // mov $t1, 0
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    // mov $t2, 0
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    // mov $t3, 0
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t3", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });

                    // mov $t0, 0($sp) - Load BL
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    // mov $t1, 8($sp) - Load AL
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "8($sp)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    // mul $t1           - BL * AL, result in $lo:$hi
                    conversionState.Append(new ASMOps.Mul()
                    {
                        Src1 = "$t0", Src2 = "$t1", Signed = false
                    });
                    conversionState.Append(new ASMOps.Mfhi()
                    {
                        Dest = "$t3"
                    });
                    conversionState.Append(new ASMOps.Mflo()
                    {
                        Dest = "$t0"
                    });
                    // push $t3          - Push result keeping high bits
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t3"
                    });
                    // push $t0
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });

                    //                   - Add 8 to offsets for result(s)

                    // mov $t0, 0        - Zero out registers
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    // mov $t3, 0
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t3", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    // mov $t0 4+8($sp) - Load BH
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "12($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    // mul $t1           - BH * AL, result in $lo:$hi
                    conversionState.Append(new ASMOps.Mul()
                    {
                        Src1 = "$t0", Src2 = "$t1"
                    });
                    conversionState.Append(new ASMOps.Mflo()
                    {
                        Dest = "$t0"
                    });
                    // push $t0          - Push result truncating high bits
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });

                    //                   - Add 12 to offsets for result(s)

                    // mov $t0, 0        - Zero out registers
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    // mov $t3, 0
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t3", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    // mov $t0, 0+12($sp) - Load BL
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "12($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    // mov $t1, 12+12($sp) - Load AH
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "24($sp)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    // mul $t1             - BL * AH, result in $lo:$hi
                    conversionState.Append(new ASMOps.Mul()
                    {
                        Src1 = "$t0", Src2 = "$t1"
                    });
                    conversionState.Append(new ASMOps.Mflo()
                    {
                        Dest = "$t0"
                    });
                    // push $t0            - Push result truncating high bits
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });

                    //                     - Add 16 to offsets for result(s)

                    // AL * BL = 8($sp) , 64 bits
                    // AL * BH = 4($sp) , 32 bits - high bits
                    // AH * BL = 0($sp) , 32 bits - high bits

                    // mov $t0, 8($sp)  - Load AL * BL
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "8($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    // mov $t3, 12($sp)
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "12($sp)", Dest = "$t3", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    // mov $t1, 0
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    // mov $t2, 4($sp)   - Load AL * BH
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "4($sp)", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    // add $t3, $t2       - Add (AL * BL) + (AL * BH), result in $lo:$hi
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src1 = "$t2", Src2 = "$t3", Dest = "$t3"
                    });
                    // mov $t2, 0($sp)   - Load AH * BL
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0($sp)", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    // add $t3, $t2       - Add ((AL * BL) + (AL * BH)) + (AH * BL), result in $lo:$hi
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src1 = "$t2", Src2 = "$t3", Dest = "$t3"
                    });

                    // add $sp, 16+16     - Remove temp results and input values from stack
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src1 = "$sp", Src2 = "32", Dest = "$sp"
                    });

                    // push $t3           - Push final result
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t3"
                    });
                    // push $t0
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        isNewGCObject      = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
            }
        }
예제 #9
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if any argument or the return value is a floating point number.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            MethodBase methodToCall = theOp.MethodToCall;

            Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall);

            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);
            conversionState.AddExternalLabel(conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID);

            //The method to call is a method base
            //A method base can be either a method info i.e. a normal method
            //or a constructor method. The two types are treated separately.
            if (methodToCall is MethodInfo)
            {
                //Need to do callvirt related stuff to load address of method to call
                // - Check for invoke of a delegate - if so, treat rather differently from normal callvirt

                if (typeof(Delegate).IsAssignableFrom(((MethodInfo)methodToCall).DeclaringType))
                {
                    //Callvirt to delegate method
                    // - We only support calls to Invoke at the moment
                    if (methodToCall.Name != "Invoke")
                    {
                        throw new NotSupportedException("Callvirt to Delegate method not supported! Method name: " + methodToCall.Name);
                    }
                    int bytesForAllParams = ((MethodInfo)methodToCall).GetParameters().Select(x => conversionState.TheILLibrary.GetTypeInfo(x.ParameterType).SizeOnStackInBytes).Sum();

                    // - Move into $t0 address of function to call from stack - delegate reference is function pointer

                    //All the parameters for the method that was called
                    List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();

                    int bytesForParams = allParams.Select(x => conversionState.TheILLibrary.GetTypeInfo(x).SizeOnStackInBytes).Sum();
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = bytesForParams + "($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });


                    //Allocate space on the stack for the return value as necessary
                    Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                    Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                    StackItem      returnItem  = new StackItem()
                    {
                        isFloat            = Utilities.IsFloat(retType),
                        sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                        isGCManaged        = retTypeInfo.IsGCManaged,
                        isValue            = retTypeInfo.IsValueType
                    };
                    //We do not push the return value onto the stack unless it has size > 0
                    //We do not push the return value onto our stack at this point - it is pushed after the call is done

                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        if (returnItem.isFloat)
                        {
                            //SUPPORT - floats
                            throw new NotSupportedException("Cannot handle float return values!");
                        }
                        else if (returnItem.sizeOnStackInBytes == 4)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$zero"
                            });
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$zero"
                            });
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$zero"
                            });
                        }
                        else
                        {
                            throw new NotSupportedException("Invalid return stack operand size!");
                        }
                    }



                    //Append the actual call
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = "$t0"
                    });


                    //After a call, we need to remove the return value and parameters from the stack
                    //This is most easily done by just adding the total number of bytes for params and
                    //return value to the stack pointer ($sp register).

                    //Stores the number of bytes to add
                    // - Initially at least 4 for the delegate (method) ref/pointer
                    int bytesToAdd = 4;
                    //Go through all params that must be removed
                    foreach (Type aParam in allParams)
                    {
                        //Pop the paramter off our stack
                        //(Note: Return value was never pushed onto our stack. See above)
                        conversionState.CurrentStackFrame.Stack.Pop();
                        //Add the size of the paramter to the total number of bytes to pop
                        bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                    }

                    //If there is a return value on the stack
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //We need to store the return value then pop all the params

                        //We now push the return value onto our stack as,
                        //after all is said and done below, it will be the
                        //top item on the stack
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);

                        //SUPPORT - floats (with above)

                        //Pop the return value into the $t0 register
                        //We will push it back on after params are skipped over.
                        if (returnItem.sizeOnStackInBytes == 4)
                        {
                            conversionState.Append(new ASMOps.Pop()
                            {
                                Size = ASMOps.OperandSize.Word, Dest = "$t0"
                            });
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            conversionState.Append(new ASMOps.Pop()
                            {
                                Size = ASMOps.OperandSize.Word, Dest = "$t0"
                            });
                            conversionState.Append(new ASMOps.Pop()
                            {
                                Size = ASMOps.OperandSize.Word, Dest = "$t3"
                            });
                        }
                    }
                    //Skip over the params
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src1 = "$sp", Src2 = bytesToAdd.ToString(), Dest = "$sp"
                    });
                    //If necessary, push the return value onto the stack.
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //SUPPORT - floats (with above)

                        //The return value was stored in $t0
                        //So push it back onto the stack
                        if (returnItem.sizeOnStackInBytes == 4)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$t0"
                            });
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$t3"
                            });
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$t0"
                            });
                        }
                    }
                }
                else
                {
                    //Normal callvirt
                    // - Get object ref from loaded args
                    // - Check object ref not null
                    // - Get type table entry from object ref
                    // - Get method table from type table entry
                    // - Scan method table for the method we want
                    //      - If found, load method address
                    // - Else, check for parent type method table
                    //      - If no parent type method table, throw exception
                    // - Else, scan parent type method table

                    string methodIDValueWanted = methodToCallInfo.IDValue.ToString();
                    int    currOpPosition      = conversionState.PositionOf(theOp);

                    Types.TypeInfo declaringTypeInfo = conversionState.TheILLibrary.GetTypeInfo(methodToCall.DeclaringType);
                    //DB_Type declaringDBType = DebugDatabase.GetType(conversionState.GetTypeID(methodToCall.DeclaringType));

                    //Get object ref
                    int bytesForAllParams = ((MethodInfo)methodToCall).GetParameters().Select(x => conversionState.TheILLibrary.GetTypeInfo(x.ParameterType).SizeOnStackInBytes).Sum();
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = bytesForAllParams + "($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });

                    //Check object ref
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.BranchNotZero, Src1 = "$t0", Src2 = "$zero", DestILPosition = currOpPosition, Extension = "NotNull"
                    });

                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = "GetEIP"
                    });
                    conversionState.AddExternalLabel("GetEIP");
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "NotNull"
                    });

                    //Get type ref
                    int typeOffset = conversionState.TheILLibrary.GetFieldInfo(declaringTypeInfo, "_Type").OffsetInBytes;
                    //conversionState.Append(new ASMOps.La() { Dest = "$t1", Label = "type_Testing1_String" });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = typeOffset.ToString() + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", typeOffset, 4);

                    //Get method table ref
                    int methodTablePtrOffset = conversionState.GetTypeFieldOffset("MethodTablePtr");
                    //conversionState.Append(new ASMOps.La() { Dest = "$t0", Label = "type_Testing1_String_MethodTable" });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = methodTablePtrOffset.ToString() + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", methodTablePtrOffset, 4);

                    //Loop through entries
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "LoopMethodTable"
                    });
                    //Load ID Val for current entry
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 4);
                    //Compare to wanted ID value
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Src = methodIDValueWanted, Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    //If equal, load method address into $t0
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.BranchNotEqual, Src1 = "$t1", Src2 = "$t4", DestILPosition = currOpPosition, Extension = "NotEqual"
                    });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "4($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", 4, 4);
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "Call"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "NotEqual"
                    });
                    //Else, compare to 0 to check for end of table
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.BranchZero, Src1 = "$t1", DestILPosition = currOpPosition, Extension = "EndOfTable"
                    });
                    //Not 0? Move to next entry then loop again
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src1 = "$t0", Src2 = "8", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "LoopMethodTable"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "EndOfTable"
                    });
                    //Compare address value to 0
                    //If not zero, there is a parent method table to check
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "4($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 4, 4);
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.BranchZero, Src1 = "$t1", DestILPosition = currOpPosition, Extension = "NotFound"
                    });
                    //Load parent method table and loop
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t1", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.RegToReg
                    });
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "LoopMethodTable"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "NotFound"
                    });
                    //Throw exception!
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = "GetEIP"
                    });
                    conversionState.AddExternalLabel("GetEIP");
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
                    });

                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "Call"
                    });

                    //Allocate space on the stack for the return value as necessary
                    Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                    Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                    StackItem      returnItem  = new StackItem()
                    {
                        isFloat            = Utilities.IsFloat(retType),
                        sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                        isGCManaged        = retTypeInfo.IsGCManaged,
                        isValue            = retTypeInfo.IsValueType
                    };
                    //We do not push the return value onto the stack unless it has size > 0
                    //We do not push the return value onto our stack at this point - it is pushed after the call is done

                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        if (returnItem.isFloat)
                        {
                            //SUPPORT - floats
                            throw new NotSupportedException("Cannot handle float return values!");
                        }
                        else if (returnItem.sizeOnStackInBytes == 4)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$zero"
                            });
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$zero"
                            });
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Word, Src = "$zero"
                            });
                        }
                        else
                        {
                            throw new NotSupportedException("Invalid return stack operand size!");
                        }
                    }


                    //Append the actual call
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = "$t0"
                    });



                    //After a call, we need to remove the return value and parameters from the stack
                    //This is most easily done by just adding the total number of bytes for params and
                    //return value to the stack pointer ($sp register).

                    //Stores the number of bytes to add
                    int bytesToAdd = 0;
                    //All the parameters for the method that was called
                    List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();
                    //Go through each one
                    if (!methodToCall.IsStatic)
                    {
                        allParams.Insert(0, methodToCall.DeclaringType);
                    }
                    foreach (Type aParam in allParams)
                    {
                        //Pop the parameter off our stack
                        //(Note: Return value was never pushed onto our stack. See above)
                        conversionState.CurrentStackFrame.Stack.Pop();
                        //Add the size of the parameter to the total number of bytes to pop
                        bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                    }
                    //If the number of bytes to add to skip over params is > 0
                    if (bytesToAdd > 0)
                    {
                        //If there is a return value on the stack
                        if (returnItem.sizeOnStackInBytes != 0)
                        {
                            //We need to store the return value then pop all the params

                            //We now push the return value onto our stack as,
                            //after all is said and done below, it will be the
                            //top item on the stack
                            conversionState.CurrentStackFrame.Stack.Push(returnItem);

                            //SUPPORT - floats (with above)

                            //Pop the return value into the $t0 register
                            //We will push it back on after params are skipped over.
                            if (returnItem.sizeOnStackInBytes == 4)
                            {
                                conversionState.Append(new ASMOps.Pop()
                                {
                                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                                });
                            }
                            else if (returnItem.sizeOnStackInBytes == 8)
                            {
                                conversionState.Append(new ASMOps.Pop()
                                {
                                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                                });
                                conversionState.Append(new ASMOps.Pop()
                                {
                                    Size = ASMOps.OperandSize.Word, Dest = "$t3"
                                });
                            }
                        }
                        //Skip over the params
                        conversionState.Append(new ASMOps.Add()
                        {
                            Src1 = "$sp", Src2 = bytesToAdd.ToString(), Dest = "$sp"
                        });
                        //If necessary, push the return value onto the stack.
                        if (returnItem.sizeOnStackInBytes != 0)
                        {
                            //SUPPORT - floats (with above)

                            //The return value was stored in $t0
                            //So push it back onto the stack
                            if (returnItem.sizeOnStackInBytes == 4)
                            {
                                conversionState.Append(new ASMOps.Push()
                                {
                                    Size = ASMOps.OperandSize.Word, Src = "$t0"
                                });
                            }
                            else if (returnItem.sizeOnStackInBytes == 8)
                            {
                                conversionState.Append(new ASMOps.Push()
                                {
                                    Size = ASMOps.OperandSize.Word, Src = "$t3"
                                });
                                conversionState.Append(new ASMOps.Push()
                                {
                                    Size = ASMOps.OperandSize.Word, Src = "$t0"
                                });
                            }
                        }
                    }
                    //No params to skip over but we might still need to store return value
                    else if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //The return value will be the top item on the stack.
                        //So all we need to do is push the return item onto our stack.
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);
                    }
                }
            }
            else if (methodToCall is ConstructorInfo)
            {
                throw new NotSupportedException("How the hell are we getting callvirts to constructor methods?!");
            }
        }
예제 #10
0
파일: Dup.cs 프로젝트: zrbruce/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// If either value is &lt; 4 bytes in length or
        /// operands are not of the same size.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Pop item to duplicate
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            if (itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Duplicate float vals not suppported yet!");
            }

            if (itemA.sizeOnStackInBytes == 4)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0"
                });
            }
            else if (itemA.sizeOnStackInBytes == 8)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t3"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t3"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t3"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0"
                });
            }
            else
            {
                throw new NotSupportedException("Stack item size not supported by duplicate op!");
            }

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = itemA.isFloat,
                sizeOnStackInBytes = itemA.sizeOnStackInBytes,
                isGCManaged        = itemA.isGCManaged,
                isValue            = itemA.isValue
            });
            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = itemA.isFloat,
                sizeOnStackInBytes = itemA.sizeOnStackInBytes,
                isGCManaged        = itemA.isGCManaged,
                isValue            = itemA.isValue
            });
        }
예제 #11
0
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     try
     {
         conversionState.CurrentStackFrame.Stack.Push(new StackItem()
         {
             isFloat            = false,
             sizeOnStackInBytes = 4,
             isGCManaged        = false
         });
     }
     catch
     {
         throw new NotSupportedException("The metadata token specifies a fieldref or methodref which isn't supported yet!");
     }
 }
예제 #12
0
파일: Dup.cs 프로젝트: zrbruce/FlingOS
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = itemA.isFloat,
                sizeOnStackInBytes = itemA.sizeOnStackInBytes,
                isGCManaged        = itemA.isGCManaged,
                isValue            = itemA.isValue
            });
            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = itemA.isFloat,
                sizeOnStackInBytes = itemA.sizeOnStackInBytes,
                isGCManaged        = itemA.isGCManaged,
                isValue            = itemA.isValue
            });
        }
예제 #13
0
파일: Call.cs 프로젝트: sramos30/FlingOS
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            MethodBase methodToCall = theOp.MethodToCall;

            Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall);

            if (methodToCall is MethodInfo)
            {
                Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                StackItem      returnItem  = new StackItem()
                {
                    isFloat            = Utilities.IsFloat(retType),
                    sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                    isGCManaged        = retTypeInfo.IsGCManaged
                };

                int         bytesToAdd = 0;
                List <Type> allParams  = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();
                if (!methodToCall.IsStatic)
                {
                    allParams.Insert(0, methodToCall.DeclaringType);
                }
                foreach (Type aParam in allParams)
                {
                    conversionState.CurrentStackFrame.Stack.Pop();
                    bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                }
                if (bytesToAdd > 0)
                {
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);
                    }
                }
                else if (returnItem.sizeOnStackInBytes != 0)
                {
                    conversionState.CurrentStackFrame.Stack.Push(returnItem);
                }
            }
            else if (methodToCall is ConstructorInfo)
            {
                ConstructorInfo aConstructor = (ConstructorInfo)methodToCall;
                if (aConstructor.IsStatic)
                {
                    //Static constructors do not have parameters or return values
                }
                else
                {
                    ParameterInfo[] allParams = methodToCall.GetParameters();
                    foreach (ParameterInfo aParam in allParams)
                    {
                        conversionState.CurrentStackFrame.Stack.Pop();
                    }
                }
            }
        }
예제 #14
0
파일: Call.cs 프로젝트: sramos30/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if any argument or the return value is a floating point number.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            MethodBase methodToCall = theOp.MethodToCall;

            Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall);

            conversionState.AddExternalLabel(methodToCallInfo.ID);

            //The method to call is a method base
            //A method base can be either a method info i.e. a normal method
            //or a constructor method. The two types are treated separately.
            if (methodToCall is MethodInfo)
            {
                //Allocate space on the stack for the return value as necessary
                Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                StackItem      returnItem  = new StackItem()
                {
                    isFloat            = Utilities.IsFloat(retType),
                    sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                    isGCManaged        = retTypeInfo.IsGCManaged
                };
                //We do not push the return value onto the stack unless it has size > 0
                //We do not push the return value onto our stack at this point - it is pushed after the call is done

                if (returnItem.sizeOnStackInBytes != 0)
                {
                    if (returnItem.isFloat)
                    {
                        //SUPPORT - floats
                        throw new NotSupportedException("Cannot handle float return values!");
                    }
                    else if (returnItem.sizeOnStackInBytes == 4)
                    {
                        conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Dword, Src = "0"
                        });
                    }
                    else if (returnItem.sizeOnStackInBytes == 8)
                    {
                        conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Dword, Src = "0"
                        });
                        conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Dword, Src = "0"
                        });
                    }
                    else
                    {
                        throw new NotSupportedException("Invalid return stack operand size!");
                    }
                }

                //Append the actual call
                conversionState.Append(new ASMOps.Call()
                {
                    Target = methodToCallInfo.ID
                });

                //After a call, we need to remove the return value and parameters from the stack
                //This is most easily done by just adding the total number of bytes for params and
                //return value to the stack pointer (ESP register).

                //Stores the number of bytes to add
                int bytesToAdd = 0;
                //All the parameters for the method that was called
                List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();
                //Go through each one
                if (!methodToCall.IsStatic)
                {
                    allParams.Insert(0, methodToCall.DeclaringType);
                }
                foreach (Type aParam in allParams)
                {
                    //Pop the paramter off our stack
                    //(Note: Return value was never pushed onto our stack. See above)
                    conversionState.CurrentStackFrame.Stack.Pop();
                    //Add the size of the paramter to the total number of bytes to pop
                    bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                }
                //If the number of bytes to add to skip over params is > 0
                if (bytesToAdd > 0)
                {
                    //If there is a return value on the stack
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //We need to store the return value then pop all the params

                        //We now push the return value onto our stack as,
                        //after all is said and done below, it will be the
                        //top item on the stack
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);

                        //SUPPORT - floats (with above)

                        //Pop the return value into the eax register
                        //We will push it back on after params are skipped over.
                        if (returnItem.sizeOnStackInBytes == 4)
                        {
                            conversionState.Append(new ASMOps.Pop()
                            {
                                Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                            });
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            conversionState.Append(new ASMOps.Pop()
                            {
                                Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                            });
                            conversionState.Append(new ASMOps.Pop()
                            {
                                Size = ASMOps.OperandSize.Dword, Dest = "EDX"
                            });
                        }
                    }
                    //Skip over the params
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src = bytesToAdd.ToString(), Dest = "ESP"
                    });
                    //If necessary, push the return value onto the stack.
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //SUPPORT - floats (with above)

                        //The return value was stored in eax
                        //So push it back onto the stack
                        if (returnItem.sizeOnStackInBytes == 4)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Dword, Src = "EAX"
                            });
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Dword, Src = "EDX"
                            });
                            conversionState.Append(new ASMOps.Push()
                            {
                                Size = ASMOps.OperandSize.Dword, Src = "EAX"
                            });
                        }
                    }
                }
                //No params to skip over but we might still need to store return value
                else if (returnItem.sizeOnStackInBytes != 0)
                {
                    //The return value will be the top item on the stack.
                    //So all we need to do is push the return item onto our stack.
                    conversionState.CurrentStackFrame.Stack.Push(returnItem);
                }
            }
            else if (methodToCall is ConstructorInfo)
            {
                ConstructorInfo aConstructor = (ConstructorInfo)methodToCall;
                if (aConstructor.IsStatic)
                {
                    //Static constructors do not have parameters or return values

                    //Append the actual call
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = methodToCallInfo.ID
                    });
                }
                else
                {
                    //Append the actual call
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = methodToCallInfo.ID
                    });

                    //After a call, we need to remove the parameters from the stack
                    //This is most easily done by just adding the total number of bytes for params
                    //to the stack pointer (ESP register).

                    //Stores the number of bytes to add
                    int bytesToAdd = 0;
                    //All the parameters for the method that was called
                    ParameterInfo[] allParams = methodToCall.GetParameters();
                    //Go through each one
                    foreach (ParameterInfo aParam in allParams)
                    {
                        //Pop the paramter off our stack
                        //(Note: Return value was never pushed onto our stack. See above)
                        conversionState.CurrentStackFrame.Stack.Pop();
                        //Add the size of the paramter to the total number of bytes to pop
                        bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam.ParameterType).SizeOnStackInBytes;
                    }
                    //Add 4 bytes for the instance ref
                    bytesToAdd += 4;
                    //If the number of bytes to add to skip over params is > 0
                    if (bytesToAdd > 0)
                    {
                        //Skip over the params
                        conversionState.Append(new ASMOps.Add()
                        {
                            Src = bytesToAdd.ToString(), Dest = "ESP"
                        });
                    }
                }
            }
        }
        void Next()
        {
            Int32 offset = m_position;
            OpCode opCode = OpCodes.Nop;
            int token = 0;

            // read first 1 or 2 bytes as opCode
            Byte code = ReadByte();
            if (code != 0xFE)
                opCode = s_OneByteOpCodes[code];
            else
            {
                code = ReadByte();
                opCode = s_TwoByteOpCodes[code];
            }

            //Console.WriteLine("opcode: " + opCode);

            current = new ILOp();
            //current.opType = opCode.OpCodeType;
            current.opCode = opCode;
            //current.opType = opCode.OperandType;

            switch (opCode.OperandType)
            {
                case OperandType.InlineNone:
                    //ilg.Emit(opCode);
                    break;
                case OperandType.ShortInlineBrTarget:
                    SByte shortDelta = ReadSByte();
                    //ilg.Emit(opCode, shortDelta);
                    break;
                case OperandType.InlineBrTarget:
                    Int32 delta = ReadInt32();
                    //ilg.Emit(opCode, delta);
                    break;
                case OperandType.ShortInlineI:
                    byte int8 = ReadByte();
                    //ilg.Emit(opCode, int8);
                    break;
                case OperandType.InlineI:
                    Int32 int32 = ReadInt32();
                    //ilg.Emit(opCode, int32);
                    break;
                case OperandType.InlineI8:
                    Int64 int64 = ReadInt64();
                    //ilg.Emit(opCode, int64);
                    break;
                case OperandType.ShortInlineR:
                    Single float32 = ReadSingle();
                    //ilg.Emit(opCode, float32);
                    break;
                case OperandType.InlineR:
                    Double float64 = ReadDouble();
                    //ilg.Emit(opCode, float64);
                    break;
                case OperandType.ShortInlineVar:
                    Byte index8 = ReadByte();
                    //ilg.Emit(opCode, index8);
                    break;
                case OperandType.InlineVar:
                    UInt16 index16 = ReadUInt16();
                    //ilg.Emit(opCode, index16);
                    break;
                case OperandType.InlineString:
                    token = ReadInt32();
                    current.operandType = "String";
                    current.operand = m_enclosingMethod.Module.ResolveString(token);
                    //ilg.Emit(opCode, m_enclosingMethod.Module.ResolveString(token));
                    break;
                case OperandType.InlineSig:
                    token = ReadInt32();
                    //ilg.Emit(opCode, m_enclosingMethod.Module.ResolveSignature(token));
                    throw new NotImplementedException();
                    break;
                case OperandType.InlineField:
                    token = ReadInt32();
                    FieldInfo fi = m_enclosingMethod.Module.ResolveField(token);
                    current.operandType = "Reflection.FieldInfo";
                    current.operand = fi.DeclaringType.FullName + Type.Delimiter + fi.Name;
                    //ilg.Emit(opCode, m_enclosingMethod.Module.ResolveField(token));
                    break;
                case OperandType.InlineType:
                    token = ReadInt32();
                    current.operandType = "Type";
                    Type t = m_enclosingMethod.Module.ResolveType(token);
                    current.operand = t.FullName;
                    //ilg.Emit(opCode, m_enclosingMethod.Module.ResolveType(token));
                    break;
                case OperandType.InlineTok:
                    token = ReadInt32();
                    //ilg.Emit(opCode, token);
                    break;
                case OperandType.InlineMethod:
                    token = ReadInt32();
                    MethodInfo mi = (MethodInfo)m_enclosingMethod.Module.ResolveMethod(token);
                    current.operandType = "Reflection.MethodInfo";
                    current.operand = mi.DeclaringType.FullName + Type.Delimiter + mi.Name;
                    //ilg.Emit(opCode, mi);
                    break;
                case OperandType.InlineSwitch:

                    throw new NotImplementedException();

                    Int32 cases = ReadInt32();
                    Int32[] deltas = new Int32[cases];
                    for (Int32 i = 0; i < cases; i++) deltas[i] = ReadInt32();
                    break;

                default:
                    throw new BadImageFormatException("unexpected OperandType " + opCode.OperandType);
            }
        }
예제 #16
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            MethodBase methodToCall = theOp.MethodToCall;

            Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall);

            if (methodToCall is MethodInfo)
            {
                if (typeof(Delegate).IsAssignableFrom(((MethodInfo)methodToCall).DeclaringType))
                {
                    List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();

                    Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                    Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                    StackItem      returnItem  = new StackItem()
                    {
                        isFloat            = Utilities.IsFloat(retType),
                        sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                        isGCManaged        = retTypeInfo.IsGCManaged,
                        isValue            = retTypeInfo.IsValueType
                    };


                    int bytesToAdd = 4;
                    foreach (Type aParam in allParams)
                    {
                        conversionState.CurrentStackFrame.Stack.Pop();
                        bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                    }

                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);
                    }
                }
                else
                {
                    string methodIDValueWanted = methodToCallInfo.IDValue.ToString();
                    int    currOpPosition      = conversionState.PositionOf(theOp);

                    Types.TypeInfo declaringTypeInfo = conversionState.TheILLibrary.GetTypeInfo(methodToCall.DeclaringType);

                    Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                    Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                    StackItem      returnItem  = new StackItem()
                    {
                        isFloat            = Utilities.IsFloat(retType),
                        sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                        isGCManaged        = retTypeInfo.IsGCManaged,
                        isValue            = retTypeInfo.IsValueType
                    };

                    int         bytesToAdd = 0;
                    List <Type> allParams  = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();
                    if (!methodToCall.IsStatic)
                    {
                        allParams.Insert(0, methodToCall.DeclaringType);
                    }
                    foreach (Type aParam in allParams)
                    {
                        conversionState.CurrentStackFrame.Stack.Pop();
                        bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                    }
                    if (bytesToAdd > 0)
                    {
                        if (returnItem.sizeOnStackInBytes != 0)
                        {
                            conversionState.CurrentStackFrame.Stack.Push(returnItem);
                        }
                    }
                    else if (returnItem.sizeOnStackInBytes != 0)
                    {
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);
                    }
                }
            }
        }
예제 #17
0
파일: Div.cs 프로젝트: sramos30/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if divide operands are floating point numbers or if attempting to divide 64-bit numbers.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown if either operand is &lt; 4 bytes long.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Pop in reverse order to push
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();


            if (itemB.sizeOnStackInBytes < 4 ||
                itemA.sizeOnStackInBytes < 4)
            {
                throw new InvalidOperationException("Invalid stack operand sizes!");
            }
            else if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Divide floats is unsupported!");
            }
            else
            {
                if (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 4)
                {
                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t1"
                    });
                    //Pop item A
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    if ((OpCodes)theOp.opCode.Value == OpCodes.Div_Un)
                    {
                        //Do the division
                        conversionState.Append(new ASMOps.Div()
                        {
                            Arg1 = "$t0", Arg2 = "$t1", Signed = false
                        });
                    }
                    else
                    {
                        //Do the division
                        conversionState.Append(new ASMOps.Div()
                        {
                            Arg1 = "$t0", Arg2 = "$t1", Signed = true
                        });
                    }
                    //Result stored in $t0
                    conversionState.Append(new ASMOps.Mflo()
                    {
                        Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged        = false
                    });
                }
                else if ((itemA.sizeOnStackInBytes == 8 &&
                          itemB.sizeOnStackInBytes == 4) ||
                         (itemA.sizeOnStackInBytes == 4 &&
                          itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! They should be the 32-32 or 64-64.");
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                         itemB.sizeOnStackInBytes == 8)
                {
                    //SUPPORT - 64-bit division
                    throw new NotSupportedException("64-bit by 64-bit division not supported yet!");
                }
            }
        }
예제 #18
0
파일: Starg.cs 프로젝트: zrbruce/FlingOS
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     conversionState.CurrentStackFrame.Stack.Pop();
 }
예제 #19
0
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Store the return value
            //Get the return type
            Type retType = (conversionState.Input.TheMethodInfo.IsConstructor ?
                            typeof(void) : ((MethodInfo)conversionState.Input.TheMethodInfo.UnderlyingInfo).ReturnType);

            Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
            //Get the size of the return type on stack
            int retSize = retTypeInfo.SizeOnStackInBytes;

            //If the size isn't 0 (i.e. isn't "void" which has no return value)
            if (retSize != 0)
            {
                //Pop the return value off our stack
                StackItem retItem = conversionState.CurrentStackFrame.Stack.Pop();

                //If it is float, well, we don't support it yet...
                if (retItem.isFloat)
                {
                    //SUPPORT - floats
                    throw new NotSupportedException("Floats return type not supported yet!");
                }
                //Otherwise, store the return value at [ebp+8]
                //[ebp+8] because that is last "argument"
                //      - read the calling convention spec
                else if (retSize == 4)
                {
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "8($fp)", Src = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                    });
                }
                else if (retSize == 8)
                {
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "8($fp)", Src = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                    });

                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "12($fp)", Src = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                    });
                }
                else
                {
                    throw new NotSupportedException("Return type size not supported / invalid!");
                }
            }

            //Once return value is off the stack, remove the locals
            //Deallocate stack space for locals
            //Only bother if there are any locals
            if (conversionState.Input.TheMethodInfo.LocalInfos.Count > 0)
            {
                //Get the total size of all locals
                int totalBytes = 0;
                foreach (Types.VariableInfo aLocal in conversionState.Input.TheMethodInfo.LocalInfos)
                {
                    totalBytes += aLocal.TheTypeInfo.SizeOnStackInBytes;
                }
                //Move esp past the locals
                conversionState.Append(new ASMOps.Add()
                {
                    Src1 = "$sp", Src2 = totalBytes.ToString(), Dest = "$sp"
                });
            }

            //Restore ebp to previous method's ebp
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$fp"
            });
            //This pop also takes last value off the stack which
            //means top item is the return address
            //So ret command can now be correctly executed.
        }
예제 #20
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if field to load is a floating value or the field to load
        /// is not of size 4 or 8 bytes.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            conversionState.CurrentStackFrame.Stack.Pop();

            Types.TypeInfo arrayTypeInfo = conversionState.GetArrayTypeInfo();
            int            lengthOffset  = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "length").OffsetInBytes;

            int currOpPosition = conversionState.PositionOf(theOp);

            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);

            // 1. Check array reference is not null
            //      1.1. Move array ref into eax
            //      1.2. Compare eax (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            // 2. Load array length


            //      1.1. Move array ref into eax
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[ESP]", Dest = "EAX"
            });
            //      1.2. Compare eax (array ref) to 0
            conversionState.Append(new ASMOps.Cmp()
            {
                Arg1 = "EAX", Arg2 = "0"
            });
            //      1.3. If not zero, jump to continue execution further down
            conversionState.Append(new ASMOps.Jmp()
            {
                JumpType = ASMOps.JmpOp.JumpNotZero, DestILPosition = currOpPosition, Extension = "ContinueExecution1"
            });
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            conversionState.Append(new ASMOps.Call()
            {
                Target = "GetEIP"
            });
            conversionState.AddExternalLabel("GetEIP");
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "ContinueExecution1"
            });

            //2. Load array length
            //  - Pop array ref
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Dword, Dest = "ECX"
            });
            //  - Load length from array ref
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[ECX+" + lengthOffset.ToString() + "]", Dest = "EAX"
            });
            //  - Push array length
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Dword, Src = "EAX"
            });

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = false,
                sizeOnStackInBytes = 4,
                isGCManaged        = false,
                isValue            = true
            });
        }
예제 #21
0
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
 }
예제 #22
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if constant is a floating point number.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            int currOpPosition = conversionState.PositionOf(theOp);

            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);
            conversionState.AddExternalLabel(conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID);

            Type elementType = null;
            bool pushValue   = true;
            int  sizeToPush  = 4;
            bool signExtend  = true;
            bool isFloat     = false;

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Ldelem:
            {
                signExtend = false;
                //Load the metadata token used to get the type info
                int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Get the type info for the element type
                elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);
            }
            break;

            case OpCodes.Ldelema:
            {
                signExtend = false;
                //Load the metadata token used to get the type info
                int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Get the type info for the element type
                elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);

                pushValue = false;
            }
            break;

            case OpCodes.Ldelem_R4:
            case OpCodes.Ldelem_R8:
                //TODO - Add more LdElem op variants support
                throw new NotSupportedException("Ldelem op variant not supported yet!");

            case OpCodes.Ldelem_I1:
                sizeToPush  = 1;
                elementType = typeof(sbyte);
                break;

            case OpCodes.Ldelem_I2:
                sizeToPush  = 2;
                elementType = typeof(Int16);
                break;

            case OpCodes.Ldelem_U1:
                sizeToPush  = 1;
                signExtend  = false;
                elementType = typeof(byte);
                break;

            case OpCodes.Ldelem_U2:
                sizeToPush  = 2;
                signExtend  = false;
                elementType = typeof(UInt16);
                break;

            case OpCodes.Ldelem_Ref:
                signExtend  = false;
                elementType = null;
                break;

            case OpCodes.Ldelem_U4:
                signExtend  = false;
                elementType = typeof(UInt32);
                break;

            case OpCodes.Ldelem_I4:
                elementType = typeof(Int32);
                break;

            case OpCodes.Ldelem_I8:
                sizeToPush  = 8;
                elementType = typeof(Int64);
                break;
            }

            if (isFloat)
            {
                //TODO - Support floats
                throw new NotSupportedException("LdElem for floats not supported yet!");
            }

            //Get element from array and push the value onto the stack
            //                   (or for LdElemA push the address of the value)

            //This involves:
            // 1. Check array reference is not null
            //          - If it is, throw NullReferenceException
            // 2. Check array element type is correct
            //          - If not, throw ArrayTypeMismatchException
            // 3. Check index to get is > -1 and < array length
            //          - If not, throw IndexOutOfRangeException
            // 4. Calculate address of element
            // 5. Push the element onto the stack

            //Stack setup upon entering this op: (top-most downwards)
            // 0. Index of element to get as Int32 (word)
            // 1. Array object reference as address (word)

            Types.TypeInfo arrayTypeInfo = conversionState.GetArrayTypeInfo();

            // 1. Check array reference is not null
            //      1.1. Move array ref into $t0
            //      1.2. Compare $t0 (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException

            //      1.1. Move array ref into $t0
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "4($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //      1.2. Compare $t0 (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            conversionState.Append(new ASMOps.Branch()
            {
                Src1 = "$t0", BranchType = ASMOps.BranchOp.BranchNotZero, DestILPosition = currOpPosition, Extension = "Continue1", UnsignedTest = true
            });
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            conversionState.Append(new ASMOps.Call()
            {
                Target = "GetEIP"
            });
            conversionState.AddExternalLabel("GetEIP");
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue1"
            });

            // 2. Check array element type is correct
            //      2.1. Move element type ref into $t0
            //      2.2. Move element type ref from array object into $t1
            //      2.3. Compare $t0 to $t1
            //      2.4. If the same, jump to continue execution further down
            //      2.5. Otherwise, call Exceptions.ThrowArrayTypeMismatchException

            //string ContinueExecutionLabel2 = ContinueExecutionLabelBase + "2";
            ////      2.1. Move element type ref into $t0
            int elemTypeOffset = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "elemType").OffsetInBytes;

            // 3. Check index to get is > -1 and < array length
            //      3.1. Move index into $t0
            //      3.2. Move array length into $t1
            //      3.2. Compare $t0 to 0
            //      3.3. Jump if greater than to next test condition (3.5)
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            //      3.5. Compare $t0 to $t1
            //      3.6. Jump if less than to continue execution further down
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException

            //      3.1. Move index into $t0
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "0($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //      3.2. Move array length into $t2
            //              - Calculate the offset of the field from the start of the array object
            int lengthOffset = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "length").OffsetInBytes;

            //              - Move array ref into $t1
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "4($sp)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //              - Move length value (offset($t1)) into $t1
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = lengthOffset.ToString() + "($t1)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t1", "$t1", lengthOffset, 4);
            //      3.2. Compare $t0 to 0
            //      3.3. Jump if greater than to next test condition (3.5)
            conversionState.Append(new ASMOps.Branch()
            {
                Src1 = "$t0", Src2 = "$zero", BranchType = ASMOps.BranchOp.BranchGreaterThanEqual, DestILPosition = currOpPosition, Extension = "Continue3_1", UnsignedTest = false
            });
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue3_1"
            });
            //      3.5. Compare $t0 to $t1
            //      3.6. Jump if less than to continue execution further down
            conversionState.Append(new ASMOps.Branch()
            {
                Src1 = "$t0", Src2 = "$t1", BranchType = ASMOps.BranchOp.BranchLessThan, DestILPosition = currOpPosition, Extension = "Continue3_2", UnsignedTest = false
            });
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue3_2"
            });
            // 4. Calculate address of element
            //      4.1. Pop index into $t1
            //      4.2. Pop array ref into $t0
            //      4.3. Move element type ref (from array ref) into $t0
            //      4.4. Move IsValueType (from element ref type) into $t2
            //      4.5. If IsValueType, continue to 4.6., else goto 4.8.
            //      4.6. Move Size (from element type ref) into $t0
            //      4.7. Skip over 4.8.
            //      4.8. Move StackSize (from element type ref) into $t0
            //      4.9. Mulitply $t0 by $t1 (index by element size)
            //      4.10. Move array ref into $t1
            //      4.11. Add enough to go past Kernel.FOS_System.Array fields
            //      4.12. Add $t0 and $t1 (array ref + fields + (index * element size))

            //      4.1. Pop index into $t1
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t1"
            });
            //      4.2. Move array ref into $t0
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "0($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //      4.3. Move element type ref (from array ref) into $t0
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = elemTypeOffset.ToString() + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", elemTypeOffset, 4);
            //      4.4. Move IsValueType (from element ref type) into $t2
            int isValueTypeOffset = conversionState.GetTypeFieldOffset("IsValueType");

            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
            });
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = isValueTypeOffset.ToString() + "($t0)", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t2", isValueTypeOffset, 1);
            //      4.5. If IsValueType, continue to 4.6., else goto 4.8.
            conversionState.Append(new ASMOps.Branch()
            {
                Src1 = "$t2", BranchType = ASMOps.BranchOp.BranchZero, DestILPosition = currOpPosition, Extension = "Continue4_1", UnsignedTest = true
            });
            //      4.6. Move Size (from element type ref) into $t0
            int sizeOffset = conversionState.GetTypeFieldOffset("Size");

            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = sizeOffset.ToString() + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", sizeOffset, 4);
            //      4.7. Skip over 4.8.
            conversionState.Append(new ASMOps.Branch()
            {
                BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "Continue4_2"
            });
            //      4.8. Move StackSize (from element type ref) into $t0
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue4_1"
            });
            int stackSizeOffset = conversionState.GetTypeFieldOffset("StackSize");

            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = stackSizeOffset + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", stackSizeOffset, 4);
            //      4.9. Mulitply $t0 by $t1 (index by element size)
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue4_2"
            });
            conversionState.Append(new ASMOps.Mul()
            {
                Src1 = "$t1", Src2 = "$t0", Signed = true
            });
            //      4.10. Pop array ref into $t1
            conversionState.Append(new ASMOps.Mflo()
            {
                Dest = "$t0"
            });
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t1"
            });
            //      4.11. Add enough to go past Kernel.FOS_System.Array fields
            int allFieldsOffset = 0;

            #region Offset calculation
            {
                Types.FieldInfo highestOffsetFieldInfo = arrayTypeInfo.FieldInfos.Where(x => !x.IsStatic).OrderByDescending(x => x.OffsetInBytes).First();
                Types.TypeInfo  fieldTypeInfo          = conversionState.TheILLibrary.GetTypeInfo(highestOffsetFieldInfo.UnderlyingInfo.FieldType);
                allFieldsOffset = highestOffsetFieldInfo.OffsetInBytes + (fieldTypeInfo.IsValueType ? fieldTypeInfo.SizeOnHeapInBytes : fieldTypeInfo.SizeOnStackInBytes);
            }
            #endregion
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$t1", Src2 = allFieldsOffset.ToString(), Dest = "$t1"
            });
            //      4.12. Add $t0 and $t1 (array ref + fields + (index * element size))
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$t1", Src2 = "$t0", Dest = "$t0"
            });

            // 5. Push the element onto the stack
            //      5.1. Push value at ($t0) (except for LdElemA op in which case just push address)
            if (pushValue)
            {
                switch (sizeToPush)
                {
                case 1:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 1, signExtend);
                    break;

                case 2:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Halfword, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 2, signExtend);

                    break;

                case 4:
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 4);
                    break;

                case 8:
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 4);
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "4($t0)", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t2", 4, 4);
                    break;
                }
                if (sizeToPush == 8)
                {
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t2"
                    });
                }
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t1"
                });
            }
            else
            {
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0"
                });
            }

            //      5.2. Pop index and array ref from our stack
            conversionState.CurrentStackFrame.Stack.Pop();
            conversionState.CurrentStackFrame.Stack.Pop();
            //      5.3. Push element onto our stack
            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = sizeToPush > 4 ? 8 : 4,
                isFloat            = isFloat,
                isNewGCObject      = false,
                isGCManaged        = pushValue ? (elementType == null || conversionState.TheILLibrary.GetTypeInfo(elementType).IsGCManaged) : false
            });
        }
예제 #23
0
 public OpNeg(ILOp val)
 {
     this.Val = val;
 }
예제 #24
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            Type elementType = null;
            bool pushValue   = true;
            int  sizeToPush  = 4;
            bool isFloat     = false;

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Ldelem:
            {
                int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);
            }
            break;

            case OpCodes.Ldelema:
            {
                int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);

                pushValue = false;
            }
            break;

            case OpCodes.Ldelem_R4:
            case OpCodes.Ldelem_R8:
                throw new NotSupportedException("Ldelem op variant not supported yet!");

            case OpCodes.Ldelem_I1:
                sizeToPush  = 1;
                elementType = typeof(sbyte);
                break;

            case OpCodes.Ldelem_I2:
                sizeToPush  = 2;
                elementType = typeof(Int16);
                break;

            case OpCodes.Ldelem_U1:
                sizeToPush  = 1;
                elementType = typeof(byte);
                break;

            case OpCodes.Ldelem_U2:
                sizeToPush  = 2;
                elementType = typeof(UInt16);
                break;

            case OpCodes.Ldelem_Ref:
                elementType = null;
                break;

            case OpCodes.Ldelem_U4:
                elementType = typeof(UInt32);
                break;

            case OpCodes.Ldelem_I4:
                elementType = typeof(Int32);
                break;

            case OpCodes.Ldelem_I8:
                sizeToPush  = 8;
                elementType = typeof(Int64);
                break;
            }

            //      5.2. Pop index and array ref from our stack
            conversionState.CurrentStackFrame.Stack.Pop();
            conversionState.CurrentStackFrame.Stack.Pop();
            //      5.3. Push element onto our stack
            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = sizeToPush > 4 ? 8 : 4,
                isFloat            = isFloat,
                isNewGCObject      = false,
                isGCManaged        = pushValue ? (elementType == null || conversionState.TheILLibrary.GetTypeInfo(elementType).IsGCManaged) : false
            });
        }
예제 #25
0
파일: Shl.cs 프로젝트: sramos30/FlingOS
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            //Pop in reverse order to push
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            if (itemA.sizeOnStackInBytes == 4 &&
                itemB.sizeOnStackInBytes == 4)
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat            = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged        = false
                });
            }
            else if ((itemA.sizeOnStackInBytes == 8 &&
                      itemB.sizeOnStackInBytes == 4))
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat            = false,
                    sizeOnStackInBytes = 8,
                    isGCManaged        = false
                });
            }
            else if (itemA.sizeOnStackInBytes == 8 &&
                     itemB.sizeOnStackInBytes == 8)
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat            = false,
                    sizeOnStackInBytes = 8,
                    isGCManaged        = false
                });
            }
        }
예제 #26
0
        public static void DoExecute(Cosmos.Assembler.Assembler Assembler, MethodInfo aMethod, MethodBase aTargetMethod, uint aTargetMethodUID, ILOpCode aOp, bool debugEnabled)
        {
            string xCurrentMethodLabel = GetLabel(aMethod, aOp.Position);

            // mTargetMethodInfo = GetService<IMetaDataInfoService>().GetMethodInfo(mMethod
            //   , mMethod, mMethodDescription, null, mCurrentMethodInfo.DebugMode);
            string xNormalAddress = "";

            if (aTargetMethod.IsStatic || !aTargetMethod.IsVirtual || aTargetMethod.IsFinal)
            {
                xNormalAddress = LabelName.Get(aTargetMethod);
            }
            // mMethodIdentifier = GetService<IMetaDataInfoService>().GetMethodIdLabel(mMethod);

            int  xArgCount   = aTargetMethod.GetParameters().Length;
            uint xReturnSize = 0;
            var  xMethodInfo = aTargetMethod as SysReflection.MethodInfo;

            if (xMethodInfo != null)
            {
                xReturnSize = Align(SizeOfType(xMethodInfo.ReturnType), 4);
            }
            // Extracted from MethodInformation: Calculated offset
            //             var xRoundedSize = ReturnSize;
            //if (xRoundedSize % 4 > 0) {
            //    xRoundedSize += (4 - (ReturnSize % 4));
            //}



            //ExtraStackSize = (int)xRoundedSize;
            uint xExtraStackSize = Call.GetStackSizeToReservate(aTargetMethod);
            uint xThisOffset     = 0;
            var  xParameters     = aTargetMethod.GetParameters();

            foreach (var xItem in xParameters)
            {
                xThisOffset += Align(SizeOfType(xItem.ParameterType), 4);
            }

            // This is finding offset to self? It looks like we dont need offsets of other
            // arguments, but only self. If so can calculate without calculating all fields
            // Might have to go to old data structure for the offset...
            // Can we add this method info somehow to the data passed in?
            // mThisOffset = mTargetMethodInfo.Arguments[0].Offset;


            new Comment(Assembler, "ThisOffset = " + xThisOffset);
            Call.DoNullReferenceCheck(Assembler, debugEnabled, xThisOffset);

            //             Action xEmitCleanup = delegate() {
            //                                       foreach (MethodInformation.Argument xArg in mTargetMethodInfo.Arguments) {
            //                                           new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = xArg.Size };
            //                                       }

            //                                   };

            //EmitCompareWithNull( Assembler,
            //                    mCurrentMethodInfo,
            //                    delegate( CPUx86.Compare c )
            //                    {
            //                        c.DestinationReg = CPUx86.Registers.ESP;
            //                        c.DestinationIsIndirect = true;
            //                        c.DestinationDisplacement = mThisOffset;
            //                    },
            //                    mLabelName,
            //                    mLabelName + "_AfterNullRefCheck",
            //                    xEmitCleanup,
            //                    ( int )mCurrentILOffset,
            //                    GetService<IMetaDataInfoService>().GetTypeIdLabel( typeof( NullReferenceException ) ),
            //                    GetService<IMetaDataInfoService>().GetTypeInfo( typeof( NullReferenceException ) ),
            //                    GetService<IMetaDataInfoService>().GetMethodInfo( typeof( NullReferenceException ).GetConstructor( Type.EmptyTypes ), false ),
            //                    GetServiceProvider() );
            // todo: add exception support

            new Label(xCurrentMethodLabel + ".AfterNullRefCheck");

            if (!String.IsNullOrEmpty(xNormalAddress))
            {
                if (xExtraStackSize > 0)
                {
                    new CPUx86.Sub {
                        DestinationReg = CPUx86.Registers.ESP, SourceValue = (uint)xExtraStackSize
                    };
                }
                new CPUx86.Call {
                    DestinationLabel = xNormalAddress
                };
            }
            else
            {
                /*
                 * On the stack now:
                 * $esp                 Params
                 * $esp + mThisOffset   This
                 */

                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = (int)xThisOffset
                };
                new CPUx86.Push {
                    DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true
                };
                new CPUx86.Push {
                    DestinationValue = aTargetMethodUID
                };
                new CPUx86.Call {
                    DestinationLabel = LabelName.Get(VTablesImplRefs.GetMethodAddressForTypeRef)
                };
                if (xExtraStackSize > 0)
                {
                    xThisOffset -= xExtraStackSize;
                }

                /*
                 * On the stack now:
                 * $esp                 Params
                 * $esp + mThisOffset   This
                 */

                //Call.EmitExceptionLogic( Assembler,
                //                        mCurrentILOffset,
                //                        mCurrentMethodInfo,
                //                        mLabelName + "_AfterAddressCheck",
                //                        true,
                //                        xEmitCleanup );

                new Label(xCurrentMethodLabel + ".AfterAddressCheck");
                if (xMethodInfo.DeclaringType == typeof(object))
                {
                    /*
                     * On the stack now:
                     * $esp                     method to call
                     * $esp + 4                 Params
                     * $esp + mThisOffset + 4   This
                     */
                    // we need to see if $this is a boxed object, and if so, we need to box it
                    new CPUx86.Mov {
                        DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = (int)(xThisOffset + 4)
                    };
                    //new CPUx86.Compare { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = ( ( uint )InstanceTypeEnum.BoxedValueType ), Size = 32 };

                    //InstanceTypeEnum.BoxedValueType == 3 =>
                    new CPUx86.Compare {
                        DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 3, Size = 32
                    };

                    /*
                     * On the stack now:
                     * $esp                 Params
                     * $esp + mThisOffset   This
                     *
                     * EAX contains the method to call
                     */
                    new CPUx86.ConditionalJump {
                        Condition = CPUx86.ConditionalTestEnum.NotEqual, DestinationLabel = xCurrentMethodLabel + ".NotBoxedThis"
                    };
                    new CPUx86.Pop {
                        DestinationReg = CPUx86.Registers.ECX
                    };

                    /*
                     * On the stack now:
                     * $esp                 Params
                     * $esp + mThisOffset   This
                     *
                     * ECX contains the method to call
                     */
                    new CPUx86.Mov {
                        DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = (int)xThisOffset
                    };

                    /*
                     * On the stack now:
                     * $esp                 Params
                     * $esp + mThisOffset   This
                     *
                     * ECX contains the method to call
                     * EAX contains $This, but boxed
                     */

                    //new CPUx86.Add { DestinationReg = CPUx86.Registers.EAX, SourceValue = ( uint )ObjectImpl.FieldDataOffset };

                    //public const int FieldDataOffset = 12; // ObjectImpl says that. so..
                    new CPUx86.Add {
                        DestinationReg = CPUx86.Registers.EAX, SourceValue = 12
                    };
                    new CPUx86.Mov {
                        DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)xThisOffset, SourceReg = CPUx86.Registers.EAX
                    };

                    /*
                     * On the stack now:
                     * $esp                 Params
                     * $esp + mThisOffset   Pointer to address inside box
                     *
                     * ECX contains the method to call
                     */
                    new CPUx86.Push {
                        DestinationReg = CPUx86.Registers.ECX
                    };

                    /*
                     * On the stack now:
                     * $esp                    Method to call
                     * $esp + 4                Params
                     * $esp + mThisOffset + 4  This
                     */
                }
                new Label(xCurrentMethodLabel + ".NotBoxedThis");
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EAX
                };
                if (xExtraStackSize > 0)
                {
                    new CPUx86.Sub {
                        DestinationReg = CPUx86.Registers.ESP, SourceValue = xExtraStackSize
                    };
                }
                new CPUx86.Call {
                    DestinationReg = CPUx86.Registers.EAX
                };
                new Label(xCurrentMethodLabel + ".AfterNotBoxedThis");
            }
            ILOp.EmitExceptionLogic(Assembler, aMethod, aOp, true,
                                    delegate()
            {
                var xResultSize = xReturnSize;
                if (xResultSize % 4 != 0)
                {
                    xResultSize += 4 - (xResultSize % 4);
                }
                for (int i = 0; i < xResultSize / 4; i++)
                {
                    new CPUx86.Add {
                        DestinationReg = CPUx86.Registers.ESP, SourceValue = 4
                    };
                }
            });
            new Label(xCurrentMethodLabel + ".NoExceptionAfterCall");
            new Comment(Assembler, "Argument Count = " + xParameters.Length.ToString());
        }
예제 #27
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            MethodBase constructorMethod = theOp.MethodToCall;
            Type       objectType        = constructorMethod.DeclaringType;

            if (typeof(Delegate).IsAssignableFrom(objectType))
            {
                StackItem funcPtrItem = conversionState.CurrentStackFrame.Stack.Pop();;
                conversionState.CurrentStackFrame.Stack.Pop();
                conversionState.CurrentStackFrame.Stack.Push(funcPtrItem);
                return;
            }

            Types.MethodInfo constructorMethodInfo = conversionState.TheILLibrary.GetMethodInfo(constructorMethod);

            ParameterInfo[] allParams = constructorMethod.GetParameters();
            foreach (ParameterInfo aParam in allParams)
            {
                conversionState.CurrentStackFrame.Stack.Pop();
            }

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = false,
                sizeOnStackInBytes = 4,
                isNewGCObject      = true,
                isGCManaged        = true
            });
        }
예제 #28
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if either or both values to 'or' are floating point values.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown if either or both values to multiply are not 4 or 8 bytes
        /// in size or if the values are of different size.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Pop in reverse order to push
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();


            if (itemB.sizeOnStackInBytes < 4 ||
                itemA.sizeOnStackInBytes < 4)
            {
                throw new InvalidOperationException("Invalid stack operand sizes!");
            }
            else if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Add floats is unsupported!");
            }
            else
            {
                if (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 4)
                {
                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t1"
                    });
                    //Pop item A
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t1", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
                else if ((itemA.sizeOnStackInBytes == 8 &&
                          itemB.sizeOnStackInBytes == 4) ||
                         (itemA.sizeOnStackInBytes == 4 &&
                          itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! They should be the same size.");
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                         itemB.sizeOnStackInBytes == 8)
                {
                    //Pop item B to $t2:$t1
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t1"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t2"
                    });
                    //Pop item A to $t3:$t0
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t3"
                    });
                    //Or $t2:$t1 with $t3:$t0
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t1", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t2", Src2 = "$t3", Dest = "$t3"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t3"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
            }
        }
예제 #29
0
파일: NewArr.cs 프로젝트: zrbruce/FlingOS
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     conversionState.CurrentStackFrame.Stack.Push(new StackItem()
     {
         isFloat            = false,
         sizeOnStackInBytes = 4,
         isNewGCObject      = true,
         isGCManaged        = true,
         isValue            = false
     });
 }
예제 #30
0
파일: OpNone.cs 프로젝트: quajak/IL2CPU
        protected override void DoInterpretStackTypes(ref bool aSituationChanged)
        {
            base.DoInterpretStackTypes(ref aSituationChanged);
            switch (OpCode)
            {
            case Code.Add:
            case Code.Add_Ovf:
            case Code.Add_Ovf_Un:
            case Code.Mul:
            case Code.Mul_Ovf:
            case Code.Mul_Ovf_Un:
            case Code.Div:
            case Code.Div_Un:
            case Code.Sub:
            case Code.Sub_Ovf:
            case Code.Sub_Ovf_Un:
            case Code.Rem:
            case Code.Rem_Un:
            case Code.Xor:
            case Code.And:
            case Code.Or:
                if (StackPushTypes[0] != null)
                {
                    return;
                }
                if (!StackPopTypes.Contains(null))
                {
                    // PopTypes set, but PushType not yet, so fill it.

                    if (StackPopTypes[0] == typeof(bool) && StackPopTypes[1] == typeof(bool))
                    {
                        StackPushTypes[0] = typeof(bool);
                        aSituationChanged = true;
                        return;
                    }

                    if ((StackPopTypes[0] == typeof(bool) && StackPopTypes[1] == typeof(Int32)) ||
                        (StackPopTypes[0] == typeof(Int32) && StackPopTypes[1] == typeof(bool)))
                    {
                        StackPushTypes[0] = typeof(Int32);
                        aSituationChanged = true;
                        return;
                    }

                    if ((StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(uint *)) ||
                        (StackPopTypes[0] == typeof(uint *) && StackPopTypes[1] == typeof(IntPtr)))
                    {
                        StackPushTypes[0] = typeof(uint *);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(UIntPtr) && StackPopTypes[1] == typeof(uint *)) ||
                        (StackPopTypes[0] == typeof(uint *) && StackPopTypes[1] == typeof(UIntPtr)))
                    {
                        StackPushTypes[0] = typeof(uint *);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(byte *)) ||
                        (StackPopTypes[0] == typeof(byte *) && StackPopTypes[1] == typeof(uint)))
                    {
                        StackPushTypes[0] = typeof(byte *);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(byte *)) ||
                        (StackPopTypes[0] == typeof(byte *) && StackPopTypes[1] == typeof(int)))
                    {
                        StackPushTypes[0] = typeof(byte *);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(byte *)) ||
                        (StackPopTypes[0] == typeof(byte *) && StackPopTypes[1] == typeof(IntPtr)))
                    {
                        StackPushTypes[0] = typeof(byte *);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(char *)) ||
                        (StackPopTypes[0] == typeof(char *) && StackPopTypes[1] == typeof(IntPtr)))
                    {
                        StackPushTypes[0] = typeof(char *);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(UIntPtr) && StackPopTypes[1] == typeof(char *)) ||
                        (StackPopTypes[0] == typeof(char *) && StackPopTypes[1] == typeof(UIntPtr)))
                    {
                        StackPushTypes[0] = typeof(char *);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(uint)) ||
                        (StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(IntPtr)))
                    {
                        StackPushTypes[0] = typeof(UIntPtr);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(UIntPtr)) ||
                        (StackPopTypes[0] == typeof(UIntPtr) && StackPopTypes[1] == typeof(int)))
                    {
                        StackPushTypes[0] = typeof(UIntPtr);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(IntPtr)) ||
                        (StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(int)))
                    {
                        StackPushTypes[0] = typeof(IntPtr);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(uint)) ||
                        (StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(int)))
                    {
                        StackPushTypes[0] = typeof(int);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(short) && StackPopTypes[1] == typeof(ushort)) ||
                        (StackPopTypes[0] == typeof(ushort) && StackPopTypes[1] == typeof(short)))
                    {
                        StackPushTypes[0] = typeof(short);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(byte)) ||
                        (StackPopTypes[0] == typeof(byte) && StackPopTypes[1] == typeof(int)))
                    {
                        StackPushTypes[0] = typeof(int);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(short)) ||
                        (StackPopTypes[0] == typeof(short) && StackPopTypes[1] == typeof(int)))
                    {
                        StackPushTypes[0] = typeof(int);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(long) && StackPopTypes[1] == typeof(ulong)) ||
                        (StackPopTypes[0] == typeof(ulong) && StackPopTypes[1] == typeof(long)))
                    {
                        StackPushTypes[0] = typeof(long);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(ushort)) ||
                        (StackPopTypes[0] == typeof(ushort) && StackPopTypes[1] == typeof(int)))
                    {
                        StackPushTypes[0] = typeof(int);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(byte) && StackPopTypes[1] == typeof(uint)) ||
                        (StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(byte)))
                    {
                        StackPushTypes[0] = typeof(int);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(ushort) && StackPopTypes[1] == typeof(uint)) ||
                        (StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(ushort)))
                    {
                        StackPushTypes[0] = typeof(uint);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(char)) ||
                        (StackPopTypes[0] == typeof(char) && StackPopTypes[1] == typeof(int)))
                    {
                        StackPushTypes[0] = typeof(int);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(UIntPtr)) ||
                        (StackPopTypes[0] == typeof(UIntPtr) && StackPopTypes[1] == typeof(IntPtr)))
                    {
                        StackPushTypes[0] = typeof(UIntPtr);
                        aSituationChanged = true;
                        return;
                    }
                    if (StackPopTypes[0] == typeof(IntPtr) && StackPopTypes[1] == typeof(IntPtr))
                    {
                        StackPushTypes[0] = typeof(IntPtr);
                        aSituationChanged = true;
                        return;
                    }
                    if (StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(uint))
                    {
                        StackPushTypes[0] = typeof(uint);
                        aSituationChanged = true;
                        return;
                    }
                    if (StackPopTypes[0] == typeof(uint) && StackPopTypes[1] == typeof(char))
                    {
                        StackPushTypes[0] = typeof(uint);
                        aSituationChanged = true;
                        return;
                    }
                    if (StackPopTypes[0] == typeof(byte) && StackPopTypes[1] == typeof(byte))
                    {
                        StackPushTypes[0] = typeof(byte);
                        aSituationChanged = true;
                        return;
                    }

                    if (StackPopTypes[0] == typeof(byte) && StackPopTypes[1] == typeof(ushort) ||
                        StackPopTypes[0] == typeof(ushort) && StackPopTypes[1] == typeof(byte))
                    {
                        StackPushTypes[0] = typeof(ushort);
                        aSituationChanged = true;
                        return;
                    }
                    if (StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(int))
                    {
                        StackPushTypes[0] = typeof(int);
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(bool)) ||
                        (StackPopTypes[0] == typeof(bool) && StackPopTypes[1] == typeof(int)))

                    {
                        StackPushTypes[0] = typeof(int);
                        aSituationChanged = true;
                        return;
                    }
                    if (StackPopTypes[0] == typeof(ushort) && StackPopTypes[1] == typeof(ushort))
                    {
                        StackPushTypes[0] = typeof(ushort);
                        aSituationChanged = true;
                        return;
                    }
                    //Changed
                    if (StackPopTypes[0] == typeof(short) && StackPopTypes[1] == typeof(short))
                    {
                        StackPushTypes[0] = typeof(short);
                        aSituationChanged = true;
                        return;
                    }
                    if (StackPopTypes[0] == typeof(long) && StackPopTypes[1] == typeof(long))
                    {
                        StackPushTypes[0] = typeof(long);
                        aSituationChanged = true;
                        return;
                    }
                    if (StackPopTypes[0] == typeof(ulong) && StackPopTypes[1] == typeof(ulong))
                    {
                        StackPushTypes[0] = typeof(ulong);
                        aSituationChanged = true;
                        return;
                    }
                    if (StackPopTypes[0] == typeof(Double) && StackPopTypes[1] == typeof(Double))
                    {
                        StackPushTypes[0] = typeof(Double);
                        aSituationChanged = true;
                        return;
                    }
                    if (StackPopTypes[0] == typeof(Single) && StackPopTypes[1] == typeof(Single))
                    {
                        StackPushTypes[0] = typeof(Single);
                        aSituationChanged = true;
                        return;
                    }
                    if (StackPopTypes[0] == typeof(Char) && StackPopTypes[1] == typeof(Char))
                    {
                        StackPushTypes[0] = typeof(Char);
                        aSituationChanged = true;
                        return;
                    }

                    if ((StackPopTypes[0] == typeof(int) && StackPopTypes[1] == typeof(sbyte)) ||
                        (StackPopTypes[0] == typeof(sbyte) && StackPopTypes[1] == typeof(int)))
                    {
                        StackPushTypes[0] = typeof(int);
                        aSituationChanged = true;
                        return;
                    }
                    if (StackPopTypes[0] == StackPopTypes[1] && StackPopTypes[0].IsPointer)
                    {
                        StackPushTypes[0] = StackPopTypes[0];
                        aSituationChanged = true;
                        return;
                    }
                    if (StackPopTypes[0] == typeof(int) &&
                        StackPopTypes[1].IsPointer)
                    {
                        StackPushTypes[0] = StackPopTypes[1];
                        aSituationChanged = true;
                        return;
                    }
                    if ((StackPopTypes[0] == typeof(IntPtr) || StackPopTypes[0] == typeof(UIntPtr)) &&
                        StackPopTypes[1].IsPointer)
                    {
                        StackPushTypes[0] = StackPopTypes[1];
                        aSituationChanged = true;
                        return;
                    }
                    if (OpCode == Code.Add &&
                        ((StackPopTypes[0] == typeof(IntPtr) && (StackPopTypes[1].IsPointer || StackPopTypes[1].IsByRef)) ||
                         ((StackPopTypes[0].IsPointer || StackPopTypes[0].IsByRef) && StackPopTypes[1] == typeof(IntPtr))))
                    {
                        if (StackPopTypes[0] == typeof(IntPtr))
                        {
                            StackPushTypes[0] = StackPopTypes[1];
                        }
                        else
                        {
                            StackPushTypes[0] = StackPopTypes[0];
                        }
                        aSituationChanged = true;
                        return;
                    }

                    throw new NotImplementedException(string.Format("{0} on types '{1}' and '{2}' not yet implemented!", OpCode, StackPopTypes[0], StackPopTypes[1]));
                }
                break;

            case Code.Localloc:
                StackPushTypes[0] = typeof(void *);
                aSituationChanged = true;
                return;

            case Code.Stelem_I2:
                var xTypeValue = StackPopTypes[0];
                if (xTypeValue == null)
                {
                    return;
                }

                if (xTypeValue == typeof(byte) ||
                    xTypeValue == typeof(char) ||
                    xTypeValue == typeof(short) ||
                    xTypeValue == typeof(ushort) ||
                    xTypeValue == typeof(int))
                {
                    return;
                }
                throw new NotImplementedException(String.Format("Stelem_I2 storing type '{0}' is not implemented!", xTypeValue));

            case Code.Shl:
            case Code.Shr:
            case Code.Shr_Un:
                xTypeValue = StackPopTypes[1];
                var xTypeShift = StackPopTypes[0];
                if (xTypeValue == null || xTypeShift == null)
                {
                    return;
                }
                if (xTypeValue == typeof(int) && xTypeShift == typeof(int))
                {
                    StackPushTypes[0] = typeof(int);
                    aSituationChanged = true;
                    return;
                }
                if (xTypeValue == typeof(byte) && xTypeShift == typeof(int))
                {
                    StackPushTypes[0] = typeof(int);
                    aSituationChanged = true;
                    return;
                }
                if (xTypeValue == typeof(long) && xTypeShift == typeof(int))
                {
                    StackPushTypes[0] = typeof(long);
                    aSituationChanged = true;
                    return;
                }
                if (xTypeValue == typeof(IntPtr) && xTypeShift == typeof(int))
                {
                    StackPushTypes[0] = typeof(int);
                    aSituationChanged = true;
                    return;
                }
                if (xTypeValue == typeof(int) && xTypeShift == typeof(IntPtr))
                {
                    StackPushTypes[0] = typeof(int);
                    aSituationChanged = true;
                    return;
                }
                if (xTypeValue == typeof(ushort) && xTypeShift == typeof(int))
                {
                    StackPushTypes[0] = typeof(int);
                    aSituationChanged = true;
                    return;
                }
                if (xTypeValue == typeof(char) && xTypeShift == typeof(int))
                {
                    StackPushTypes[0] = typeof(int);
                    aSituationChanged = true;
                    return;
                }
                if (xTypeValue == typeof(uint) && xTypeShift == typeof(int))
                {
                    StackPushTypes[0] = typeof(int);
                    aSituationChanged = true;
                    return;
                }
                if (xTypeValue == typeof(long) && xTypeShift == typeof(IntPtr))
                {
                    StackPushTypes[0] = typeof(long);
                    aSituationChanged = true;
                    return;
                }
                if (xTypeValue == typeof(IntPtr) && xTypeShift == typeof(IntPtr))
                {
                    StackPushTypes[0] = typeof(IntPtr);
                    aSituationChanged = true;
                    return;
                }
                if (xTypeValue == typeof(IntPtr) && xTypeShift == typeof(IntPtr))
                {
                    StackPushTypes[0] = typeof(IntPtr);
                    aSituationChanged = true;
                    return;
                }
                if (xTypeValue == typeof(ulong) && xTypeShift == typeof(int))
                {
                    StackPushTypes[0] = typeof(ulong);
                    aSituationChanged = true;
                    return;
                }
                if (xTypeValue == typeof(sbyte) && xTypeShift == typeof(int))
                {
                    StackPushTypes[0] = typeof(int);
                    aSituationChanged = true;
                    return;
                }
                if (xTypeValue == typeof(short) && xTypeShift == typeof(int))
                {
                    StackPushTypes[0] = typeof(int);
                    aSituationChanged = true;
                    return;
                }
                throw new NotImplementedException(String.Format("{0} with types {1} and {2} is not implemented!", OpCode, xTypeValue.FullName, xTypeShift.FullName));

            case Code.Ldelem_Ref:
                if (StackPushTypes[0] != null)
                {
                    return;
                }
                var xTypeArray = StackPopTypes[1];
                if (xTypeArray == null)
                {
                    return;
                }
                if (!xTypeArray.IsArray)
                {
                    throw new Exception("Ldelem Array type is not an array (Actual = " + xTypeArray.FullName + ")");
                }
                StackPushTypes[0] = xTypeArray.GetElementType();
                aSituationChanged = true;
                break;

            case Code.Not:
            case Code.Neg:
                if (StackPushTypes[0] != null)
                {
                    return;
                }
                if (StackPopTypes[0] != null)
                {
                    StackPushTypes[0] = StackPopTypes[0];
                    aSituationChanged = true;
                    return;
                }
                break;

            case Code.Dup:
                if (StackPushTypes[0] != null && StackPushTypes[1] != null)
                {
                    return;
                }
                if (StackPopTypes[0] != null)
                {
                    StackPushTypes[0] = StackPopTypes[0];
                    StackPushTypes[1] = StackPopTypes[0];
                    aSituationChanged = true;
                    return;
                }
                return;

            case Code.Stind_I1:
                if (StackPopTypes[1] == null || StackPopTypes[0] == null)
                {
                    return;
                }
                if (!ILOp.IsIntegralType(StackPopTypes[0]))
                {
                    throw new Exception("Wrong value type: " + StackPopTypes[0].FullName);
                }
                if (!ILOp.IsPointer(StackPopTypes[1]))
                {
                    throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName);
                }
                break;

            case Code.Stind_I2:
                if (StackPopTypes[1] == null || StackPopTypes[0] == null)
                {
                    return;
                }
                if (!ILOp.IsIntegralType(StackPopTypes[0]))
                {
                    throw new Exception("Wrong value type: " + StackPopTypes[0].FullName);
                }
                if (!ILOp.IsPointer(StackPopTypes[1]))
                {
                    throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName);
                }
                break;

            case Code.Stind_I4:
                if (StackPopTypes[1] == null || StackPopTypes[0] == null)
                {
                    return;
                }
                if (!ILOp.IsIntegralType(StackPopTypes[0]))
                {
                    throw new Exception("Wrong value type: " + StackPopTypes[0].FullName);
                }
                if (!ILOp.IsPointer(StackPopTypes[1]))
                {
                    throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName);
                }
                break;

            case Code.Stind_I8:
                if (StackPopTypes[1] == null || StackPopTypes[0] == null)
                {
                    return;
                }
                if (!ILOp.IsIntegralType(StackPopTypes[0]))
                {
                    throw new Exception("Wrong value type: " + StackPopTypes[0].FullName);
                }
                if (!ILOp.IsPointer(StackPopTypes[1]))
                {
                    throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName);
                }
                break;

            case Code.Stind_I:
                if (StackPopTypes[1] == null || StackPopTypes[0] == null)
                {
                    return;
                }
                if (!ILOp.IsIntegralTypeOrPointer(StackPopTypes[0]))
                {
                    throw new Exception("Wrong value type: " + StackPopTypes[0].FullName);
                }
                if (!ILOp.IsPointer(StackPopTypes[1]))
                {
                    throw new Exception("Wrong Pointer type: " + StackPopTypes[1].FullName);
                }
                break;

            case Code.Ldind_Ref:
                if (StackPushTypes[0] != null)
                {
                    return;
                }
                if (StackPopTypes[0] == null)
                {
                    return;
                }
                if (!StackPopTypes[0].IsByRef && !StackPopTypes[0].IsPointer)
                {
                    throw new Exception("Invalid ref type: " + StackPopTypes[0].FullName);
                }
                if (StackPopTypes[0].IsPointer)
                {
                    StackPushTypes[0] = typeof(object);
                }
                else
                {
                    StackPushTypes[0] = StackPopTypes[0].GetElementType();
                }
                aSituationChanged = true;
                break;
            }
        }
예제 #31
0
        public static void Assemble(Cosmos.Assembler.Assembler aAssembler, MethodInfo aMethod, OpMethod xMethod, string currentLabel, Type objectType, MethodBase constructor)
        {
            // call cctor:
            if (aMethod != null)
            {
                var xCctor = (objectType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? new ConstructorInfo[0]).SingleOrDefault();
                if (xCctor != null)
                {
                    XS.Call(LabelName.Get(xCctor));
                    ILOp.EmitExceptionLogic(aAssembler, aMethod, xMethod, true, null, ".AfterCCTorExceptionCheck");
                    XS.Label(".AfterCCTorExceptionCheck");
                }
            }

            if (objectType.IsValueType)
            {
                #region Valuetypes

                XS.Comment("ValueType");

                /*
                 * Current sitation on stack:
                 *   $ESP       Arg
                 *   $ESP+..    other items
                 *
                 * What should happen:
                 *  + The stack should be increased to allow space to contain:
                 *         + .ctor arguments
                 *         + struct _pointer_ (ref to start of emptied space)
                 *         + empty space for struct
                 *  + arguments should be copied to the new place
                 *  + old place where arguments were should be cleared
                 *  + pointer should be set
                 *  + call .ctor
                 */

                // Size of return value - we need to make room for this on the stack.
                uint xStorageSize = Align(SizeOfType(objectType), 4);
                XS.Comment("StorageSize: " + xStorageSize);
                if (xStorageSize == 0)
                {
                    throw new Exception("ValueType storage size cannot be 0.");
                }

                //var xStorageSize = aCtorDeclTypeInfo.StorageSize;

                uint xArgSize       = 0;
                var  xParameterList = constructor.GetParameters();
                foreach (var xParam in xParameterList)
                {
                    xArgSize = xArgSize + Align(SizeOfType(xParam.ParameterType), 4);
                }
                XS.Comment("ArgSize: " + xArgSize);

                // Set ESP so we can push the struct ptr
                int xShift = (int)(xArgSize - xStorageSize);
                XS.Comment("Shift: " + xShift);
                if (xShift < 0)
                {
                    XS.Sub(XSRegisters.ESP, (uint)Math.Abs(xShift));
                }
                else if (xShift > 0)
                {
                    XS.Add(XSRegisters.ESP, (uint)xShift);
                }

                // push struct ptr
                XS.Push(XSRegisters.ESP);

                // Shift args
                foreach (var xParam in xParameterList)
                {
                    uint xArgSizeForThis = Align(SizeOfType(xParam.ParameterType), 4);
                    for (int i = 1; i <= xArgSizeForThis / 4; i++)
                    {
                        new CPUx86.Push {
                            DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)xStorageSize
                        };
                    }
                }

                new Call(aAssembler).Execute(aMethod, xMethod);

                // Need to put these *after* the call because the Call pops the args from the stack
                // and we have mucked about on the stack, so this makes it right before the next
                // op.

                #endregion Valuetypes
            }
            else
            {
                // If not ValueType, then we need gc

                var xParams = constructor.GetParameters();

                // array length + 8
                bool xHasCalcSize = false;

                #region Special string handling
                // try calculating size:
                if (constructor.DeclaringType == typeof(string))
                {
                    if (xParams.Length == 1 &&
                        xParams[0].ParameterType == typeof(char[]))
                    {
                        xHasCalcSize = true;
                        XS.Set(EAX, ESP, sourceIsIndirect: true);

                        // EAX contains a memory handle now, lets dereference it to a pointer
                        XS.Set(EAX, EAX, sourceIsIndirect: true);
                        XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceDisplacement: 8);
                        XS.Set(XSRegisters.EDX, 2);
                        XS.Multiply(XSRegisters.EDX);
                        XS.Push(XSRegisters.EAX);
                    }
                    else if (xParams.Length == 3 &&
                             (xParams[0].ParameterType == typeof(char[]) || xParams[0].ParameterType == typeof(char *)) &&
                             xParams[1].ParameterType == typeof(int) &&
                             xParams[2].ParameterType == typeof(int))
                    {
                        xHasCalcSize = true;
                        XS.Set(EAX, ESP, sourceIsIndirect: true);
                        XS.ShiftLeft(XSRegisters.EAX, 1);
                        XS.Push(XSRegisters.EAX);
                    }
                    else if (xParams.Length == 2 &&
                             xParams[0].ParameterType == typeof(char) &&
                             xParams[1].ParameterType == typeof(int))
                    {
                        xHasCalcSize = true;
                        XS.Set(EAX, ESP, sourceIsIndirect: true);
                        XS.ShiftLeft(XSRegisters.EAX, 1);
                        XS.Push(XSRegisters.EAX);
                    }
                    else
                    {
                        throw new NotImplementedException("In NewObj, a string ctor implementation is missing!");
                    }
                }
                #endregion Special string handling

                uint xMemSize   = GetStorageSize(objectType);
                int  xExtraSize = 12; // additional size for set values after alloc
                XS.Push((uint)(xMemSize + xExtraSize));
                if (xHasCalcSize)
                {
                    XS.Pop(XSRegisters.EAX);
                    XS.Add(ESP, EAX, destinationIsIndirect: true);
                }

                // todo: probably we want to check for exceptions after calling Alloc
                XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef));
                XS.Label(".AfterAlloc");
                XS.Push(ESP, isIndirect: true);
                XS.Push(ESP, isIndirect: true);

                // it's on the stack now 3 times. Once from the Alloc return value, twice from the pushes

                //? ?? uint xObjSize;// = 0;
                //int xGCFieldCount = ( from item in aCtorDeclTypeInfo.Fields.Values
                //where item.NeedsGC
                //select item ).Count();

                //int xGCFieldCount = ( from item in aCtorDeclTypeInfo.Fields.Values
                //where item.NeedsGC
                //select item ).Count();
                int xGCFieldCount = objectType.GetFields().Count(x => x.FieldType.IsValueType);

                // todo: use a cleaner approach here. this class shouldnt assemble the string
                string strTypeId = GetTypeIDLabel(constructor.DeclaringType);

                XS.Pop(XSRegisters.EAX);
                XS.Set(EAX, EAX, sourceIsIndirect: true);
                XS.Set(EBX, strTypeId, sourceIsIndirect: true);
                XS.Set(EAX, EBX, destinationIsIndirect: true);
                XS.Set(EAX, (uint)InstanceTypeEnum.NormalObject, destinationDisplacement: 4, size: RegisterSize.Int32);
                XS.Set(EAX, (uint)xGCFieldCount, destinationDisplacement: 8, size: RegisterSize.Int32);
                uint xSize = (uint)(from item in xParams
                                    let xQSize = Align(SizeOfType(item.ParameterType), 4)
                                                 select(int) xQSize).Take(xParams.Length).Sum();

                foreach (var xParam in xParams)
                {
                    uint xParamSize = Align(SizeOfType(xParam.ParameterType), 4);
                    new Comment(aAssembler, String.Format("Arg {0}: {1}", xParam.Name, xParamSize));
                    for (int i = 0; i < xParamSize; i += 4)
                    {
                        new CPUx86.Push {
                            DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize + 4)
                        };
                    }
                }

                XS.Call(LabelName.Get(constructor));
                // should the complete error handling happen by ILOp.EmitExceptionLogic?
                if (aMethod != null)
                {
                    // todo: only happening for real methods now, not for ctor's ?
                    XS.Test(XSRegisters.ECX, 2);
                    string xNoErrorLabel = currentLabel + ".NoError" + LabelName.LabelCount.ToString();
                    XS.Jump(CPUx86.ConditionalTestEnum.Equal, xNoErrorLabel);

                    //for( int i = 1; i < aCtorMethodInfo.Arguments.Length; i++ )
                    //{
                    //    new CPUx86.Add
                    //    {
                    //        DestinationReg = CPUx86.Registers.ESP,
                    //        SourceValue = ( aCtorMethodInfo.Arguments[ i ].Size % 4 == 0
                    //             ? aCtorMethodInfo.Arguments[ i ].Size
                    //             : ( ( aCtorMethodInfo.Arguments[ i ].Size / 4 ) * 4 ) + 1 )
                    //    };
                    //}
                    PushAlignedParameterSize(constructor);

                    // an exception occurred, we need to cleanup the stack, and jump to the exit
                    XS.Add(XSRegisters.ESP, 4);

                    //new Comment(aAssembler, "[ Newobj.Execute cleanup start count = " + aAssembler.Stack.Count.ToString() + " ]");
                    //foreach( var xStackInt in Assembler.Stack )
                    //{
                    //    new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = ( uint )xStackInt.Size };
                    //}

                    new Comment(aAssembler, "[ Newobj.Execute cleanup end ]");
                    Jump_Exception(aMethod);
                    XS.Label(xNoErrorLabel);
                }
                XS.Pop(XSRegisters.EAX);

                //for( int i = 1; i < aCtorMethodInfo.Arguments.Length; i++ )
                //{
                //    new CPUx86.Add
                //    {
                //        DestinationReg = CPUx86.Registers.ESP,
                //        SourceValue = ( aCtorMethodInfo.Arguments[ i ].Size % 4 == 0
                //             ? aCtorMethodInfo.Arguments[ i ].Size
                //             : ( ( aCtorMethodInfo.Arguments[ i ].Size / 4 ) * 4 ) + 1 )
                //    };
                //}
                PushAlignedParameterSize(constructor);

                XS.Push(XSRegisters.EAX);
            }
        }
예제 #32
0
 public ILOpSpec(ILOp op, OpCode opcode)
 {
     Op = op;
     OpCode = opcode;
 }