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