Example #1
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xType   = (OpType)aOpCode;
            var xTypeID = GetTypeIDLabel(xType.Value);

            var xCurrentMethodLabel       = GetLabel(aMethod, aOpCode);
            var xAfterIsInstanceCallLabel = xCurrentMethodLabel + "_After_IsInstance_Call";
            var xInvalidCastLabel         = xCurrentMethodLabel + "_InvalidCast";
            var xNextPositionLabel        = GetLabel(aMethod, aOpCode.NextPosition);

            XS.Set(EAX, ESP, sourceDisplacement: 4);

            XS.Compare(EAX, 0);
            XS.Jump(ConditionalTestEnum.Zero, xNextPositionLabel);
            XS.Push(EAX, isIndirect: true);
            XS.Push(xTypeID, isIndirect: true);
            XS.Push(Convert.ToUInt32(xType.Value.IsInterface));

            MethodBase xMethodIsInstance = VTablesImplRefs.IsInstanceRef;

            Call.DoExecute(Assembler, aMethod, xMethodIsInstance, aOpCode, xCurrentMethodLabel, xAfterIsInstanceCallLabel, DebugEnabled);

            XS.Label(xAfterIsInstanceCallLabel);

            XS.Pop(EAX);

            XS.Compare(EAX, 0);
            XS.Jump(ConditionalTestEnum.Equal, xInvalidCastLabel);

            XS.Jump(xNextPositionLabel);

            XS.Label(xInvalidCastLabel);
            XS.Call(LabelName.Get(ExceptionHelperRefs.ThrowInvalidCastExceptionRef));
        }
Example #2
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            OpType xType = (OpType)aOpCode;

            if (IsReferenceType(xType.Value))
            {
                return;
            }

            uint   xSize   = Align(SizeOfType(xType.Value), 4);
            string xTypeID = GetTypeIDLabel(xType.Value);

            XS.Push(ObjectUtils.FieldDataOffset + xSize);
            XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef));
            XS.Pop(ESI);
            XS.Set(EBX, xTypeID, sourceIsIndirect: true);
            XS.Set(ESI, EBX, destinationIsIndirect: true);
            XS.Set(ESI, (uint)ObjectUtils.InstanceTypeEnum.BoxedValueType, destinationDisplacement: 4, size: RegisterSize.Int32);
            new Comment(Assembler, "xSize is " + xSize);
            for (int i = 0; i < (xSize / 4); i++)
            {
                XS.Pop(EDX);
                XS.Set(ESI, EDX, destinationDisplacement: (ObjectUtils.FieldDataOffset + (i * 4)), size: RegisterSize.Int32);
            }
            XS.Push(ESI);
            XS.Push(0);
        }
Example #3
0
 protected void ThrowOverflowException()
 {
     new CPU.Call
     {
         DestinationLabel = LabelName.Get(typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public))
     };
 }
Example #4
0
        // this code is mostly copied from Newarr.cs in Il2CPU, just the code to find the size and length is different
        public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
        {
            string     xTypeID   = ILOp.GetTypeIDLabel(typeof(Array));
            MethodBase xCtor     = typeof(Array).GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)[0];
            string     xCtorName = LabelName.Get(xCtor);

            XS.Set(ECX, EBP, sourceDisplacement: 8);  // size
            XS.Set(EDX, EBP, sourceDisplacement: 12); // length



            XS.Push(ECX);                                 // size of element
            XS.Set(EAX, ECX);
            XS.Multiply(EDX);                             // total element size
            XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // total array size
            XS.Push(EAX);
            XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef));
            XS.Label(".AfterAlloc");
            XS.Pop(EAX);
            XS.Pop(ESI);
            XS.Push(EAX);
            XS.Push(ESP, isIndirect: true);
            XS.Push(ESP, isIndirect: true);
            // it's on the stack 3 times now, once from the return value, twice from the pushes;

            XS.Pop(EAX);
            XS.Set(EBX, xTypeID, sourceIsIndirect: true);  // array type id
            XS.Set(EAX, EBX, destinationIsIndirect: true); // array type id
            XS.Set(EAX, (uint)ObjectUtils.InstanceTypeEnum.Array, destinationDisplacement: 4, destinationIsIndirect: true);
            XS.Set(EAX, ESI, destinationDisplacement: 8, destinationIsIndirect: true);
            XS.Set(EAX, ECX);
            XS.Push(0);
            XS.Call(xCtorName);
            XS.Push(0);
        }
Example #5
0
 protected void ThrowNotImplementedException(string aMessage)
 {
     XS.Push(LdStr.GetContentsArrayName(aMessage));
     new CPU.Call {
         DestinationLabel = LabelName.Get(typeof(ExceptionHelper).GetMethod("ThrowNotImplemented", BindingFlags.Static | BindingFlags.Public))
     };
 }
Example #6
0
 public static void SetAllStates(bool state)
 {
     Instance.maskState.list.Clear();
     if (state)
     {
         Instance.maskState.list.AddRange(LabelName.Get());
     }
 }
Example #7
0
 protected void ThrowNotImplementedException(string aMessage)
 {
     new CPU.Push {
         DestinationRef = Cosmos.Assembler.ElementReference.New(LdStr.GetContentsArrayName(aMessage))
     };
     new CPU.Call {
         DestinationLabel = LabelName.Get(typeof(ExceptionHelper).GetMethod("ThrowNotImplemented", BindingFlags.Static | BindingFlags.Public))
     };
 }
Example #8
0
        public static void DoExecute(Cosmos.Assembler.Assembler assembler, _MethodInfo aMethod, string field, Type declaringType, ILOpCode aCurrentOpCode)
        {
            // call cctor:
            var xCctor = (declaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? new ConstructorInfo[0]).SingleOrDefault();

            if (xCctor != null)
            {
                XS.Call(LabelName.Get(xCctor));
                if (aCurrentOpCode != null)
                {
                    ILOp.EmitExceptionLogic(assembler, aMethod, aCurrentOpCode, true, null, ".AfterCCTorExceptionCheck");
                    XS.Label(".AfterCCTorExceptionCheck");
                }
            }
            string xDataName = field;

            XS.Push(xDataName);
        }
Example #9
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xType = (ILOpCodes.OpType)aOpCode;

            uint xSize = SizeOfType(xType.Value.GetElementType() ?? xType.Value);

            string     xTypeID   = GetTypeIDLabel(xType.Value.GetElementType() ?? xType.Value);
            MethodBase xCtor     = typeof(Array).GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)[0];
            string     xCtorName = LabelName.Get(xCtor);

            XS.Comment("Element Size = " + xSize);
            XS.Pop(EAX); // element count
            XS.Push(EAX);
            XS.Set(EDX, xSize);
            XS.Multiply(EDX);                             // total element size
            XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // total array size
            XS.Push(EAX);
            //XS.Push(0x4E3A44A9);
            //XS.LiteralCode("Call DebugStub_SendSimpleNumber");
            //XS.Pop(EAX);
            //XS.Push(".AfterAlloc");
            //XS.LiteralCode("Call DebugStub_SendSimpleNumber");
            //XS.Pop(EAX);
            XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef));
            XS.Label(".AfterAlloc");
            XS.Pop(EAX); // location
            //XS.LiteralCode("Call DebugStub_SendSimpleNumber");
            XS.Pop(ESI); // element count
            XS.Push(EAX);
            XS.Push(ESP, isIndirect: true);
            XS.Push(ESP, isIndirect: true);
            // it's on the stack 3 times now, once from the return value, twice from the pushes;

            XS.Pop(EAX);
            XS.Set(EBX, xTypeID, sourceIsIndirect: true);                                 // array type id
            XS.Set(EAX, EBX, destinationIsIndirect: true);                                // array type id
            XS.Set(EAX, (uint)ObjectUtils.InstanceTypeEnum.Array, destinationDisplacement: 4, destinationIsIndirect: true);
            XS.Set(EAX, ESI, destinationDisplacement: 8, destinationIsIndirect: true);    // element count
            XS.Set(EAX, xSize, destinationDisplacement: 12, destinationIsIndirect: true); // element size
            XS.Push(0);
            XS.Call(xCtorName);
            XS.Push(0);
        }
Example #10
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            Cosmos.IL2CPU.ILOpCodes.OpType xType = (Cosmos.IL2CPU.ILOpCodes.OpType)aOpCode;

            uint xSize = SizeOfType(xType.Value);

            //TODO cache it to reduce calculation
            string     xTypeID   = GetTypeIDLabel(typeof(Array));
            MethodBase xCtor     = typeof(Array).GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)[0];
            string     xCtorName = LabelName.Get(xCtor);

            new Comment(Assembler, "Element Size = " + xSize);
            // element count is on the stack
            XS.Pop(XSRegisters.ESI);
            XS.Push(XSRegisters.ESI);
            //Assembler.StackSizes.Push(xElementCountSize);
            XS.Push(xSize);
            new Mul(Assembler).Execute(aMethod, aOpCode);
            // the total items size is now on the stack
            XS.Push((ObjectImpl.FieldDataOffset + 4));
            new Add(Assembler).Execute(aMethod, aOpCode);
            // the total array size is now on the stack.
            XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef));
            XS.Push(ESP, isIndirect: true);
            XS.Push(ESP, isIndirect: true);
            // it's on the stack 3 times now, once from the return value, twice from the pushes;

            XS.Pop(XSRegisters.EAX);
            XS.Set(EAX, EAX, sourceIsIndirect: true);
            XS.Set(EBX, xTypeID, sourceIsIndirect: true);
            XS.Set(EAX, EBX, destinationIsIndirect: true);
            XS.Add(XSRegisters.EAX, 4);
            new CPUx86.Mov {
                DestinationReg = CPUx86.RegistersEnum.EAX, DestinationIsIndirect = true, SourceValue = (uint)InstanceTypeEnum.Array, Size = 32
            };
            XS.Add(XSRegisters.EAX, 4);
            XS.Set(EAX, ESI, destinationIsIndirect: true, size: RegisterSize.Int32);
            XS.Add(XSRegisters.EAX, 4);
            new CPUx86.Mov {
                DestinationReg = CPUx86.RegistersEnum.EAX, DestinationIsIndirect = true, SourceValue = (uint)xSize, Size = 32
            };
            XS.Call(xCtorName);
        }
Example #11
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            OpType xType = (OpType)aOpCode;

            uint   xSize   = Align(SizeOfType(xType.Value), 4);
            string xTypeID = GetTypeIDLabel(xType.Value);

            new CPUx86.Push {
                DestinationValue = (ObjectImpl.FieldDataOffset + xSize)
            };
            new CPUx86.Call {
                DestinationLabel = LabelName.Get(GCImplementationRefs.AllocNewObjectRef)
            };
            new CPUx86.Pop {
                DestinationReg = CPUx86.Registers.EAX
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EBX, SourceRef = Cosmos.Assembler.ElementReference.New(xTypeID), SourceIsIndirect = true
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ESI, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EBX
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ESI, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = (uint)InstanceTypeEnum.BoxedValueType, Size = 32
            };
            new Comment(Assembler, "xSize is " + xSize);
            for (int i = 0; i < (xSize / 4); i++)
            {
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EDX
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ESI, DestinationIsIndirect = true, DestinationDisplacement = (ObjectImpl.FieldDataOffset + (i * 4)), SourceReg = CPUx86.Registers.EDX, Size = 32
                };
            }
            new CPUx86.Push {
                DestinationReg = CPUx86.RegistersEnum.EAX
            };
        }
Example #12
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackType = aOpCode.StackPopTypes[0];

            var xNoThrowLabel = GetLabel(aMethod, aOpCode) + ".NoThrow";

            switch (SizeOfType(xStackType))
            {
            case 4:
                XS.Pop(EAX);
                XS.And(EAX, 0x7FFFFFFF);

                XS.Compare(EAX, 0x7F800000);
                XS.Jump(ConditionalTestEnum.Below, xNoThrowLabel);

                XS.SSE2.ConvertSS2SD(XMM0, EAX);
                XS.Sub(ESP, 8);
                XS.SSE2.MoveSD(ESP, XMM0, true);

                break;

            case 8:
                XS.Set(EAX, ESP, sourceDisplacement: 4);

                XS.And(EAX, 0x7FFFFFFF);
                XS.Compare(EAX, 0x7F800000);
                XS.Jump(ConditionalTestEnum.Below, xNoThrowLabel);

                break;

            default:
                throw new NotImplementedException();
            }

            XS.Call(LabelName.Get(ExceptionHelperRefs.ThrowNotFiniteNumberExceptionRef));

            XS.Label(xNoThrowLabel);
        }
Example #13
0
        public static void DoExecute(Cosmos.Assembler.Assembler assembler, MethodInfo aMethod, string field, Type declaringType, ILOpCode aCurrentOpCode)
        {
            // call cctor:
            var xCctor = (declaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? new ConstructorInfo[0]).SingleOrDefault();

            if (xCctor != null)
            {
                new CPUx86.Call
                {
                    DestinationLabel = LabelName.Get(xCctor)
                };
                if (aCurrentOpCode != null)
                {
                    ILOp.EmitExceptionLogic(assembler, aMethod, aCurrentOpCode, true, null, ".AfterCCTorExceptionCheck");
                    new Label(".AfterCCTorExceptionCheck");
                }
            }
            string xDataName = field;

            new CPUx86.Push
            {
                DestinationRef = Cosmos.Assembler.ElementReference.New(xDataName)
            };
        }
Example #14
0
        public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
        {
            // IDT is already initialized but just for base hooks, and asm only.
            // ie Int 1, 3 and GPF
            // This routine updates the IDT now that we have C# running to allow C# hooks to handle
            // the other INTs

            // We are updating the IDT, disable interrupts
            XS.ClearInterruptFlag();

            for (int i = 0; i < 256; i++)
            {
                // These are already mapped, don't remap them.
                // Maybe in the future we can look at ones that are present
                // and skip them, but some we may want to overwrite anyways.
                if (i == 1 || i == 3)
                {
                    continue;
                }

                XS.Set(EAX, "__ISR_Handler_" + i.ToString("X2"));
                XS.Set("_NATIVE_IDT_Contents", AL, destinationDisplacement: (i * 8) + 0);
                XS.Set("_NATIVE_IDT_Contents", AH, destinationDisplacement: (i * 8) + 1);
                XS.Set("_NATIVE_IDT_Contents", 0x8, destinationDisplacement: (i * 8) + 2, size: RegisterSize.Byte8);
                XS.Set("_NATIVE_IDT_Contents", 0x8E, destinationDisplacement: (i * 8) + 5, size: RegisterSize.Byte8);
                XS.ShiftRight(EAX, 16);
                XS.Set("_NATIVE_IDT_Contents", AL, destinationDisplacement: (i * 8) + 6);
                XS.Set("_NATIVE_IDT_Contents", AH, destinationDisplacement: (i * 8) + 7);
            }

            XS.Jump("__AFTER__ALL__ISR__HANDLER__STUBS__");
            var xInterruptsWithParam = new[] { 8, 10, 11, 12, 13, 14 };

            for (int j = 0; j < 256; j++)
            {
                XS.Label("__ISR_Handler_" + j.ToString("X2"));
                XS.Call("__INTERRUPT_OCCURRED__");

                if (Array.IndexOf(xInterruptsWithParam, j) == -1)
                {
                    XS.Push(0);
                }
                XS.Push((uint)j);

                if (j != 0x20)
                {
                    XS.PushAllRegisters();

                    XS.Sub(ESP, 4);
                    XS.Set(EAX, ESP); // preserve old stack address for passing to interrupt handler

                    // store floating point data
                    XS.And(ESP, 0xfffffff0);              // fxsave needs to be 16-byte alligned
                    XS.Sub(ESP, 512);                     // fxsave needs 512 bytes
                    XS.SSE.FXSave(ESP, isIndirect: true); // save the registers
                    XS.Set(EAX, ESP, destinationIsIndirect: true);

                    XS.Push(EAX); //
                    XS.Push(EAX); // pass old stack address (pointer to InterruptContext struct) to the interrupt handler

                    XS.JumpToSegment(8, "__ISR_Handler_" + j.ToString("X2") + "_SetCS");
                    XS.Label("__ISR_Handler_" + j.ToString("X2") + "_SetCS");
                    MethodBase xHandler = GetInterruptHandler((byte)j);
                    if (xHandler == null)
                    {
                        xHandler = GetMethodDef(typeof(Cosmos.Core.INTs).Assembly, typeof(Cosmos.Core.INTs).FullName, "HandleInterrupt_Default", true);
                    }
                    XS.Call(LabelName.Get(xHandler));
                    XS.Pop(EAX);
                    XS.SSE.FXRestore(ESP, isIndirect: true);

                    XS.Set(ESP, EAX); // this restores the stack for the FX stuff, except the pointer to the FX data
                    XS.Add(ESP, 4);   // "pop" the pointer

                    XS.PopAllRegisters();
                }
                else
                {
                    new LiteralAssemblerCode("pushad");
                    new LiteralAssemblerCode("mov eax, ds");
                    new LiteralAssemblerCode("push eax");
                    new LiteralAssemblerCode("mov eax, es");
                    new LiteralAssemblerCode("push eax");
                    new LiteralAssemblerCode("mov eax, fs");
                    new LiteralAssemblerCode("push eax");
                    new LiteralAssemblerCode("mov eax, gs");
                    new LiteralAssemblerCode("push eax");
                    new LiteralAssemblerCode("mov ax, 0x10");
                    new LiteralAssemblerCode("mov ds, ax");
                    new LiteralAssemblerCode("mov es, ax");
                    new LiteralAssemblerCode("mov fs, ax");
                    new LiteralAssemblerCode("mov gs, ax");
                    new LiteralAssemblerCode("mov eax, esp");
                    XS.Set("static_field__Cosmos_Core_INTs_mStackContext", EAX, destinationIsIndirect: true);
                    XS.Call(LabelName.Get(GetMethodDef(typeof(Cosmos.Core.Processing.ProcessorScheduler).Assembly, typeof(Cosmos.Core.Processing.ProcessorScheduler).FullName, "SwitchTask", true)));
                    XS.Set(EAX, "static_field__Cosmos_Core_INTs_mStackContext", sourceIsIndirect: true);
                    new LiteralAssemblerCode("mov esp, eax");
                    new LiteralAssemblerCode("pop eax");
                    new LiteralAssemblerCode("mov gs, eax");
                    new LiteralAssemblerCode("pop eax");
                    new LiteralAssemblerCode("mov fs, eax");
                    new LiteralAssemblerCode("pop eax");
                    new LiteralAssemblerCode("mov es, eax");
                    new LiteralAssemblerCode("pop eax");
                    new LiteralAssemblerCode("mov ds, eax");
                    new LiteralAssemblerCode("popad");
                }

                XS.Add(ESP, 8);
                XS.Label("__ISR_Handler_" + j.ToString("X2") + "_END");
                XS.InterruptReturn();
            }
            XS.Label("__INTERRUPT_OCCURRED__");
            XS.Return();
            XS.Label("__AFTER__ALL__ISR__HANDLER__STUBS__");
            XS.Noop();
            XS.Set(EAX, EBP, sourceDisplacement: 8);
            XS.Compare(EAX, 0);
            XS.Jump(ConditionalTestEnum.Zero, ".__AFTER_ENABLE_INTERRUPTS");

            // reload interrupt list
            XS.Set(EAX, "_NATIVE_IDT_Pointer");
            XS.Set(AsmMarker.Labels[AsmMarker.Type.Processor_IntsEnabled], 1, destinationIsIndirect: true, size: RegisterSize.Byte8);
            XS.LoadIdt(EAX, isIndirect: true);
            // Reenable interrupts
            XS.EnableInterrupts();

            XS.Label(".__AFTER_ENABLE_INTERRUPTS");
        }
Example #15
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());
        }
Example #16
0
                public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
                {
                    int start = 0;

                    for (int i = start; i < 256; i++)
                    {
                        if (i == 1 || i == 3)
                        {
                            //continue; // was used for debugging
                        }

                        XS.Set(XSRegisters.EAX, "_isr" + i.ToString("X2"));
                        XS.Set("_NATIVE_IDT_Contents", XSRegisters.AL, destinationDisplacement: (i * 8) + 0);
                        XS.Set("_NATIVE_IDT_Contents", XSRegisters.AH, destinationDisplacement: (i * 8) + 1);
                        XS.Set("_NATIVE_IDT_Contents", 0x08, destinationDisplacement: (i * 8) + 2, size: XSRegisters.RegisterSize.Byte8);
                        XS.Set("_NATIVE_IDT_Contents", 0x00, destinationDisplacement: (i * 8) + 4, size: XSRegisters.RegisterSize.Byte8);
                        XS.Set("_NATIVE_IDT_Contents", 0x8E, destinationDisplacement: (i * 8) + 5, size: XSRegisters.RegisterSize.Byte8);
                        XS.ShiftRight(XSRegisters.EAX, 16);
                        XS.Set("_NATIVE_IDT_Contents", XSRegisters.AL, destinationDisplacement: (i * 8) + 6);
                        XS.Set("_NATIVE_IDT_Contents", XSRegisters.AH, destinationDisplacement: (i * 8) + 7);
                    }
                    XS.Jump("skip_isrhandlers");
                    var xInterruptsWithParam = new[] { 8, 10, 11, 12, 13, 14 };

                    for (int j = start; j < 256; j++)
                    {
                        XS.Label("_isr" + j.ToString("X2"));
                        XS.ClearInterruptFlag();
                        XS.Call("__INTERRUPT_OCCURRED__");

                        if (global::System.Array.IndexOf(xInterruptsWithParam, j) == -1)
                        {
                            XS.Push(0);
                        }
                        XS.Push((uint)j);
                        XS.Jump("CommonISRBase");
                    }
                    XS.Label("CommonISRBase");
                    XS.PushAllRegisters();
                    XS.Set(XSRegisters.EAX, XSRegisters.ESP);
                    XS.Set("static_field__Kernel_System_Core_ISR_old_esp", XSRegisters.EAX, destinationIsIndirect: true);

                    XS.Sub(XSRegisters.ESP, 4);
                    XS.Set(XSRegisters.EAX, XSRegisters.ESP);

                    XS.And(XSRegisters.ESP, 0xfffffff0);
                    XS.Sub(XSRegisters.ESP, 512);
                    XS.SSE.FXSave(XSRegisters.ESP, isIndirect: true);
                    XS.Set(XSRegisters.EAX, XSRegisters.ESP, destinationIsIndirect: true);

                    XS.Push(XSRegisters.EAX);
                    XS.Push(XSRegisters.EAX);

                    XS.Set("static_field__Kernel_System_Core_ISR_Registers", XSRegisters.EAX, destinationIsIndirect: true);
                    MethodBase xHandler = GetMethodDef(typeof(ISR).Assembly, typeof(ISR).FullName, "CommonISRHandler", true);

                    XS.Call(LabelName.Get(xHandler));

                    XS.Pop(XSRegisters.EAX);
                    XS.SSE.FXRestore(XSRegisters.ESP, isIndirect: true);

                    XS.Set(XSRegisters.ESP, XSRegisters.EAX);
                    XS.Add(XSRegisters.ESP, 4);

                    XS.Set(XSRegisters.EAX, "static_field__Kernel_System_Core_ISR_old_esp", sourceIsIndirect: true);
                    XS.Set(XSRegisters.ESP, XSRegisters.EAX);
                    XS.PopAllRegisters();

                    XS.Add(XSRegisters.ESP, 8);
                    XS.InterruptReturn();
                    XS.Label("skip_isrhandlers");
                }
        public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
        {
            var xAssembler        = aAssembler;
            var xMethodInfo       = (_MethodInfo)aMethodInfo;
            var xMethodBaseAsInfo = xMethodInfo.MethodBase as global::System.Reflection.MethodInfo;

            if (xMethodBaseAsInfo.ReturnType != typeof(void))
            {
                throw new Exception("Events with return type not yet supported!");
            }

            /*
             * EAX contains the GetInvocationList() array at the index at which it was last used
             * EDX contains the index at which the EAX is
             * EBX contains the number of items in the array
             * ECX contains the argument size
             */

            XS.ClearInterruptFlag();

            XS.Comment("Get Invoke list count");
            var xGetInvocationListMethod = typeof(MulticastDelegate).GetMethod("GetInvocationList");

            Ldarg.DoExecute(aAssembler, xMethodInfo, 0);
            XS.Call(LabelName.Get(xGetInvocationListMethod));
            XS.Add(XSRegisters.ESP, 4);
            XS.Pop(XSRegisters.EAX);
            XS.Add(XSRegisters.EAX, 8);
            XS.Set(XSRegisters.EBX, XSRegisters.EAX, sourceIsIndirect: true);

            XS.Comment("Get invoke method");
            XS.Add(XSRegisters.EAX, 8);
            XS.Set(XSRegisters.EDI, XSRegisters.EAX, sourceIsIndirect: true, sourceDisplacement: 4);

            XS.Comment("Get ArgSize");
            int xArgSizeOffset = Ldfld.GetFieldOffset(typeof(global::System.Delegate), "$$ArgSize$$");

            Ldarg.DoExecute(aAssembler, xMethodInfo, 0);
            XS.Add(XSRegisters.ESP, 4);
            XS.Pop(XSRegisters.ECX);
            XS.Add(XSRegisters.ECX, (uint)xArgSizeOffset);
            XS.Set(XSRegisters.ECX, XSRegisters.ECX, sourceIsIndirect: true);

            XS.Comment("Set current invoke list index");
            XS.Set(XSRegisters.EDX, 0);

            XS.Label(".BEGIN_OF_LOOP");
            {
                XS.Compare(XSRegisters.EDX, XSRegisters.EBX);
                XS.Jump(x86.ConditionalTestEnum.GreaterThanOrEqualTo, ".END_OF_INVOKE");

                XS.PushAllRegisters();

                XS.Comment("Check if delegate has $this");
                XS.Set(XSRegisters.EDI, XSRegisters.EBP, sourceDisplacement: Ldarg.GetArgumentDisplacement(xMethodInfo, 0));
                XS.Add(XSRegisters.EDI, 4);
                XS.Set(XSRegisters.EDI, XSRegisters.EDI, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target"));
                XS.Compare(XSRegisters.EDI, 0);
                XS.Jump(x86.ConditionalTestEnum.Zero, ".NO_THIS");
                XS.Label(".HAS_THIS");
                XS.Push(XSRegisters.EDI);
                XS.Push(0);
                XS.Label(".NO_THIS");
                XS.Set(XSRegisters.EDI, XSRegisters.EAX, sourceIsIndirect: true, sourceDisplacement: 4);
                XS.Set(XSRegisters.EDI, XSRegisters.EDI, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.IntPtr System.Delegate._methodPtr"));

                XS.Comment("Check if delegate has args");
                XS.Compare(XSRegisters.ECX, 0);
                XS.Jump(x86.ConditionalTestEnum.Zero, ".NO_ARGS");
                XS.Label(".HAS_ARGS");
                XS.Sub(XSRegisters.ESP, XSRegisters.ECX);
                XS.Push(XSRegisters.EDI);
                XS.Set(XSRegisters.EDI, XSRegisters.ESP);
                XS.Add(XSRegisters.EDI, 4);
                XS.Set(XSRegisters.ESI, XSRegisters.EBP);
                XS.Add(XSRegisters.ESI, 8);
                new x86.Movs {
                    Size = 8, Prefixes = x86.InstructionPrefixes.Repeat
                };
                XS.Pop(XSRegisters.EDI);
                XS.Label(".NO_ARGS");
                XS.Call(XSRegisters.EDI);

                XS.PopAllRegisters();
                XS.Increment(XSRegisters.EDX);
                XS.Jump(".BEGIN_OF_LOOP");
            }

            XS.Label(".END_OF_INVOKE");
            XS.Set(XSRegisters.EDX, XSRegisters.EBP, sourceDisplacement: Ldarg.GetArgumentDisplacement(xMethodInfo, 0));
            XS.Set(XSRegisters.EDX, XSRegisters.EDX, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "$$ReturnsValue$$"));
            XS.Compare(XSRegisters.EDX, 0);
            XS.Jump(x86.ConditionalTestEnum.Equal, ".NO_RETURN");

            XS.Label(".HAS_RETURN");
            XS.Exchange(XSRegisters.EBP, XSRegisters.EDX, destinationDisplacement: 8);
            XS.Exchange(XSRegisters.EBP, XSRegisters.EDX, destinationDisplacement: 4);
            XS.Exchange(XSRegisters.EBP, XSRegisters.EDX, destinationIsIndirect: true);
            XS.Push(XSRegisters.EDX);
            XS.Set(XSRegisters.ESP, XSRegisters.EDI, destinationDisplacement: 12);

            XS.Label(".NO_RETURN");
            XS.EnableInterrupts();
        }
Example #18
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);
            }
        }
Example #19
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 );
        }
Example #20
0
 public static string GetLabel(_MethodInfo aMethod, int aPos)
 {
     return(LabelName.Get(GetLabel(aMethod), aPos));
 }
Example #21
0
        /// <summary>
        /// <para>This method implements Multicast Invoke. This means that it should call all delegates
        /// in the current multicast delegate. </para>
        /// <para>The argument size is available in the <code>$$ArgSize$$</code> field. This value is already rounded to 4byte boundaries</para>
        /// </summary>
        /// <param name="aAssembler"></param>
        public override void AssembleNew(Assembler.Assembler aAssembler, object aMethodInfo)
        {
            if (aMethodInfo == null)
            {
                throw new Exception("This AssemblerMethod needs MethodInfo!");
            }

            /*
             * EAX contains the GetInvocationList() array at the index at which it was last used
             * EDX contains the index at which the EAX is
             * EBX contains the number of items in the array
             * ECX contains the argument size
             */
            var xMethodInfo = (MethodInfo)aMethodInfo;

            new Label("____DEBUG_FOR_MULTICAST___");
            //            new CPUx86.Cli();//DEBUG ONLY
            //#warning reenable interupts when issue is fixed!!!
            new Comment("move address of delgate to eax");
            new CPUx86.Mov
            {
                DestinationReg     = CPUx86.Registers.EAX,
                SourceReg          = CPUx86.Registers.EBP,
                SourceIsIndirect   = true,
                SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0)
            };
            var xGetInvocationListMethod = typeof(MulticastDelegate).GetMethod("GetInvocationList");

            new Comment("push address of delgate to stack");
            new CPUx86.Push {
                DestinationReg = CPUx86.Registers.EAX
            };                                                        //addrof this
            new CPUx86.Call {
                DestinationLabel = LabelName.Get(xGetInvocationListMethod)
            };
            new Comment("get address from return value -> eax");
            new CPUx86.Pop {
                DestinationReg = CPUx86.Registers.EAX
            };;                                                        //list
            new Comment("eax+=8 is where the offset where an array's count is");
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 8
            };                                                                        //addrof list.count??
            new Comment("store count in ebx");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EBX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };                                                                                                                  //list.count
            new Comment("eax+=8 is where the offset where an array's items start");
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 8
            };                                                                        //why? -- start of list i think? MtW: the array's .Length is at +8
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceValue = 0
            };
            new Comment("ecx = ptr to delegate object");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0)
            };                                                                                                                                                                                      //addrof the delegate
            new Comment("ecx points to the size of the delegated methods arguments");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true, SourceDisplacement = (Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "$$ArgSize$$"))
            };                                                                                                                                                                                                                    //the size of the arguments to the method? + 12??? -- 12 is the size of the current call stack.. i think
            new CPUx86.Xor {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EDX
            };;                                                                                          //make sure edx is 0
            new Label(".BEGIN_OF_LOOP");
            new CPUx86.Compare {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EBX
            };                                                                                             //are we at the end of this list
            new CPUx86.ConditionalJump {
                Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = ".END_OF_INVOKE_"
            };                                                                                                                //then we better stop
                                                                                                                              //new CPUx86.Compare("edx", 0);
                                                                                                                              //new CPUx86.JumpIfLessOrEqual(".noreturnYet");
                                                                                                                              //new CPUx86.Add("esp", 4);
                                                                                                                              //new CPU.Label(".noreturnYet");
                                                                                                                              //new CPU.Comment("space for the return value");
                                                                                                                              //new CPUx86.Pushd("0");
            new CPUx86.Pushad();
            new Comment("esi points to where we will copy the methods argumetns from");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.ESP
            };
            new Comment("edi = ptr to delegate object");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0)
            };
            new Comment("edi = ptr to delegate object should be a pointer to the delgates context ie (this) for the methods ");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true, SourceDisplacement = (Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target"))
            };                                                                                                                                                                                                                                              //i really dont get the +12. MtW: +12 because of extra header of the type (object type, object id, field count)
            new CPUx86.Compare {
                DestinationReg = CPUx86.Registers.EDI, SourceValue = 0
            };
            new CPUx86.ConditionalJump {
                Condition = CPUx86.ConditionalTestEnum.Zero, DestinationLabel = ".NO_THIS"
            };
            new CPUx86.Push {
                DestinationReg = CPUx86.Registers.EDI
            };

            new Label(".NO_THIS");

            new Comment("make space for us to copy the arguments too");
            new CPUx86.Sub {
                DestinationReg = CPUx86.Registers.ESP, SourceReg = CPUx86.Registers.ECX
            };
            new Comment("move the current delegate to edi");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true
            };
            new Comment("move the methodptr from that delegate to edi ");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.IntPtr System.Delegate._methodPtr")
            };                                                                                                                                                                                                                                               //
            new Comment("save methodptr on the stack");
            new CPUx86.Push {
                DestinationReg = CPUx86.Registers.EDI
            };
            new Comment("move location to copy args to");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.ESP
            };
            new Comment("get above the saved methodptr");
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EDI, SourceValue = 4
            };
            //we allocated the argsize on the stack once, and it we need to get above the original args
            new Comment("we allocated argsize on the stack once");
            new Comment("add 32 for the Pushad + 16 for the current stack + 4 for the return value");
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ESI, SourceValue = 52
            };
            new CPUx86.Movs {
                Size = 8, Prefixes = CPUx86.InstructionPrefixes.Repeat
            };
            new CPUx86.Pop {
                DestinationReg = CPUx86.Registers.EDI
            };
            new CPUx86.Call {
                DestinationReg = CPUx86.Registers.EDI
            };
            new Comment("store return -- return stored into edi after popad");
            //new CPUx86.Move("edx", "[" + MethodInfo.Arguments[0].VirtualAddresses[0] + "]");//addrof the delegate
            //new CPUx86.Move("edx", "[edx+" + (MethodInfo.Arguments[0].TypeInfo.Fields["$$ReturnsValue$$"].Offset + 12) + "]");
            //new CPUx86.Compare(Registers_Old.EDX, 0);
            //new CPUx86.JumpIfEqual(".getReturn");
            //new CPUx86.Move(Registers_Old.EAX, "[esp]");
            //new CPUx86.Move("[esp+0x20]", Registers_Old.EAX);
            //new CPU.Label(".getReturn");
            new Comment("edi = ptr to delegate object");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Cosmos.IL2CPU.X86.IL.Ldarg.GetArgumentDisplacement(xMethodInfo, 0)
            };
            new Comment("edi = ptr to delegate object should be a pointer to the delgates context ie (this) for the methods ");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EDI, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target")
            };                                                                                                                                                                                                                                            //i really dont get the +12, MtW: that's for the object header
                                                                                                                                                                                                                                                          //new CPUx86.Compare("edi", "0");
                                                                                                                                                                                                                                                          //new CPUx86.JumpIfEqual(".noTHIStoPop");
                                                                                                                                                                                                                                                          //new CPUx86.Move("edx", "[" + MethodInfo.Arguments[0].VirtualAddresses[0] + "]");//addrof the delegate
                                                                                                                                                                                                                                                          //new CPUx86.Move("edx", "[edx+" + (MethodInfo.Arguments[0].TypeInfo.Fields["$$ReturnsValue$$"].Offset + 12) + "]");
                                                                                                                                                                                                                                                          //new CPUx86.Compare(Registers_Old.EDX, 0);
                                                                                                                                                                                                                                                          //new JumpIfNotEqual(".needToPopThis");
                                                                                                                                                                                                                                                          //new CPU.Comment("ecx = ptr to delegate object");
                                                                                                                                                                                                                                                          //new CPUx86.Move("ecx", "[" + MethodInfo.Arguments[0].VirtualAddresses[0] + "]");//addrof the delegate
                                                                                                                                                                                                                                                          //new CPU.Comment("ecx points to the size of the delegated methods arguments");
                                                                                                                                                                                                                                                          //new CPUx86.Move("ecx", "[ecx + " + (MethodInfo.Arguments[0].TypeInfo.Fields["$$ArgSize$$"].Offset + 12) + "]");//the size of the arguments to the method? + 12??? -- 12 is the size of the current call stack.. i think
                                                                                                                                                                                                                                                          //new CPUx86.Compare("ecx", "0");
                                                                                                                                                                                                                                                          //new CPUx86.JumpIfLessOrEqual(".noTHIStoPop");
                                                                                                                                                                                                                                                          //new CPU.Label(".needToPopThis");
                                                                                                                                                                                                                                                          //new CPUx86.Pop("edi");
                                                                                                                                                                                                                                                          //new CPUx86.Move("[esp]", "edi");
            new Label(".noTHIStoPop");
            new CPUx86.Popad();
            new CPUx86.INC {
                DestinationReg = CPUx86.Registers.EDX
            };
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 4
            };
            new CPUx86.Jump {
                DestinationLabel = ".BEGIN_OF_LOOP"
            };
            new Label(".END_OF_INVOKE_");
            new Comment("get the return value");
            //new CPUx86.Pop("eax");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = Ldarg.GetArgumentDisplacement(xMethodInfo, 0)
            };                                                                                                                                                                                      //addrof the delegate
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EDX, SourceIsIndirect = true, SourceDisplacement = Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "$$ReturnsValue$$")
            };
            new CPUx86.Compare {
                DestinationReg = CPUx86.Registers.EDX, SourceValue = 0
            };
            new CPUx86.ConditionalJump {
                Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = ".noReturn"
            };
            //may have to expand the return... idk
            new CPUx86.Xchg {
                DestinationReg = CPUx86.Registers.EBP, DestinationIsIndirect = true, DestinationDisplacement = 8, SourceReg = CPUx86.Registers.EDX
            };
            new CPUx86.Xchg {
                DestinationReg = CPUx86.Registers.EBP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceReg = CPUx86.Registers.EDX
            };
            new CPUx86.Xchg {
                DestinationReg = CPUx86.Registers.EBP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EDX
            };
            new CPUx86.Push {
                DestinationReg = CPUx86.Registers.EDX
            };                                                        //ebp
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = 12, SourceReg = CPUx86.Registers.EDI
            };
            new Label(".noReturn");
            //            new CPUx86.Sti();
            //#warning remove this ^ sti call when issue is fixed!!!
            //MethodInfo.Arguments[0].
            //            new CPUx86.Move("ebx", "[eax + " + (MethodInfo.Arguments[0].TypeInfo.Fields["$$ArgSize$$"].Offset + 12) + "]");

            //new CPUx86.Move("eax", CPUx86.Registers_Old.
        }
Example #22
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xType   = aMethod.MethodBase.DeclaringType;
            var xOpCode = (OpField)aOpCode;

            SysReflection.FieldInfo xField = xOpCode.Value;

            // call cctor:
            var xCctor = (xField.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic)).SingleOrDefault();

            if (xCctor != null)
            {
                XS.Call(LabelName.Get(xCctor));
                ILOp.EmitExceptionLogic(Assembler, aMethod, aOpCode, true, null, ".AfterCCTorExceptionCheck");
                XS.Label(".AfterCCTorExceptionCheck");
            }

            //Assembler.Stack.Pop();
            //int aExtraOffset;// = 0;
            //bool xNeedsGC = xField.FieldType.IsClass && !xField.FieldType.IsValueType;
            var xSize = SizeOfType(xField.FieldType);
            //if( xNeedsGC )
            //{
            //    aExtraOffset = 12;
            //}

            string xDataName = DataMember.GetStaticFieldName(xField);

            var xTypeNeedsGC = TypeIsReferenceType(xField.FieldType);

            if (xTypeNeedsGC)
            {
                XS.Push(xDataName, isIndirect: true, displacement: 4);
                XS.Push(0);
                return;
            }


            if (xSize >= 4)
            {
                for (int i = 1; i <= (xSize / 4); i++)
                {
                    //	Pop("eax");
                    //	Move(Assembler, "dword [" + mDataName + " + 0x" + (i * 4).ToString("X") + "]", "eax");
                    new CPUx86.Push {
                        DestinationRef = Cosmos.Assembler.ElementReference.New(xDataName), DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize - (i * 4))
                    };
                }
                switch (xSize % 4)
                {
                case 1:
                {
                    XS.Set(XSRegisters.EAX, 0);
                    XS.Set(XSRegisters.AL, xDataName, sourceIsIndirect: true);
                    XS.Push(XSRegisters.EAX);
                    break;
                }

                case 2:
                {
                    XS.Set(XSRegisters.EAX, 0);
                    XS.Set(XSRegisters.AX, xDataName, sourceIsIndirect: true);
                    XS.Push(XSRegisters.EAX);
                    break;
                }

                case 0:
                {
                    break;
                }

                default:
                    //EmitNotImplementedException( Assembler, GetServiceProvider(), "Ldsfld: Remainder size " + ( xSize % 4 ) + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel );
                    throw new NotImplementedException();
                    //break;
                }
            }
            else
            {
                switch (xSize)
                {
                case 1:
                {
                    XS.Set(XSRegisters.EAX, 0);
                    XS.Set(XSRegisters.AL, xDataName, sourceIsIndirect: true);
                    XS.Push(XSRegisters.EAX);
                    break;
                }

                case 2:
                {
                    XS.Set(XSRegisters.EAX, 0);
                    XS.Set(XSRegisters.AX, xDataName, sourceIsIndirect: true);
                    XS.Push(XSRegisters.EAX);
                    break;
                }

                case 0:
                {
                    break;
                }

                default:
                    //EmitNotImplementedException( Assembler, GetServiceProvider(), "Ldsfld: Remainder size " + ( xSize % 4 ) + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel );
                    throw new NotImplementedException();
                    //break;
                }
            }
        }
Example #23
0
 public static string GetLabel(MethodBase aMethod)
 {
     return(LabelName.Get(aMethod));
 }
Example #24
0
 public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
 {
     XS.Push(LabelName.Get(((OpMethod)aOpCode).Value));
 }
Example #25
0
        public static void Assemble(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) ?? Array.Empty <ConstructorInfo>()).SingleOrDefault();
                if (xCctor != null)
                {
                    XS.Call(LabelName.Get(xCctor));
                    EmitExceptionLogic(aAssembler, aMethod, xMethod, true, null, ".AfterCCTorExceptionCheck");
                    XS.Label(".AfterCCTorExceptionCheck");
                }
            }

            if (objectType.IsValueType)
            {
                #region Valuetypes

                XS.Comment("ValueType");
                XS.Comment("Type: " + objectType);

                /*
                 * 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.");
                }

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

                // set source of args copy
                XS.Set(ESI, ESP);

                // allocate space for struct
                XS.Sub(ESP, xStorageSize + 4);

                // set destination and count of args copy
                XS.Set(EDI, ESP);
                XS.Set(ECX, xArgSize / 4);

                // move the args to their new location
                new CPUx86.Movs {
                    Size = 32, Prefixes = CPUx86.InstructionPrefixes.Repeat
                };

                // set struct ptr
                XS.Set(EAX, ESP);
                XS.Add(EAX, xArgSize + 4);
                XS.Set(ESP, EAX, destinationDisplacement: (int)xArgSize);

                XS.Push(EAX);

                var xOpType = new OpType(xMethod.OpCode, xMethod.Position, xMethod.NextPosition, xMethod.Value.DeclaringType, xMethod.CurrentExceptionRegion);
                new Initobj(aAssembler).Execute(aMethod, xOpType);

                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, sourceDisplacement: 4, sourceIsIndirect: true); // address
                        XS.Set(EAX, EAX, sourceDisplacement: 8, sourceIsIndirect: true); // element count
                        XS.Set(EDX, 2);                                                  // element size
                        XS.Multiply(EDX);
                        XS.Push(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(EAX, 1);
                        XS.Push(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(EAX, 1);
                        XS.Push(EAX);
                    }

                    /*
                     * TODO see if something is needed in stack / register to make them really work
                     */
                    else if (xParams.Length == 3 &&
                             (xParams[0].ParameterType == typeof(sbyte *) &&
                              xParams[1].ParameterType == typeof(int) &&
                              xParams[2].ParameterType == typeof(int)))
                    {
                        xHasCalcSize = true;
                        XS.Push(ESP, isIndirect: true);
                    }
                    else if (xParams.Length == 1 && xParams[0].ParameterType == typeof(sbyte *))
                    {
                        xHasCalcSize = true;
                        /* xParams[0] contains a C / ASCII Z string the following ASM is de facto the C strlen() function */
                        var xSByteCountLabel = currentLabel + ".SByteCount";

                        XS.Set(EAX, ESP, sourceIsIndirect: true);
                        XS.Or(ECX, 0xFFFFFFFF);

                        XS.Label(xSByteCountLabel);

                        XS.Increment(EAX);
                        XS.Increment(ECX);

                        XS.Compare(EAX, 0, destinationIsIndirect: true);
                        XS.Jump(CPUx86.ConditionalTestEnum.NotEqual, xSByteCountLabel);

                        XS.Push(ECX);
                    }
                    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(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

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

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

                foreach (var xParam in xParams)
                {
                    uint xParamSize = Align(SizeOfType(xParam.ParameterType), 4);
                    XS.Comment($"Arg {xParam.Name}: {xParamSize}");
                    for (int i = 0; i < xParamSize; i += 4)
                    {
                        XS.Push(ESP, isIndirect: true, displacement: (int)(xSize + 8));
                    }
                }


                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(ECX, 2);
                    string xNoErrorLabel = currentLabel + ".NoError" + LabelName.LabelCount.ToString();
                    XS.Jump(CPUx86.ConditionalTestEnum.Equal, xNoErrorLabel);

                    PushAlignedParameterSize(constructor);

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

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

                PushAlignedParameterSize(constructor);

                XS.Push(EAX);
                XS.Push(0);
            }
        }
Example #26
0
        public static void DoExecute(Assembler Assembler, _MethodInfo aMethod, MethodBase aTargetMethod, uint aTargetMethodUID, ILOpCode aOp, bool debugEnabled)
        {
            string xCurrentMethodLabel = GetLabel(aMethod, aOp.Position);
            Type   xPopType            = aOp.StackPopTypes.Last();

            string xNormalAddress = "";

            if (aTargetMethod.IsStatic || !aTargetMethod.IsVirtual || aTargetMethod.IsFinal)
            {
                xNormalAddress = LabelName.Get(aTargetMethod);
            }

            uint xReturnSize = 0;
            var  xMethodInfo = aTargetMethod as MethodInfo;

            if (xMethodInfo != null)
            {
                xReturnSize = Align(SizeOfType(xMethodInfo.ReturnType), 4);
            }

            uint xExtraStackSize = Call.GetStackSizeToReservate(aTargetMethod, xPopType);
            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;

            XS.Comment("ThisOffset = " + xThisOffset);

            if (IsReferenceType(xPopType))
            {
                DoNullReferenceCheck(Assembler, debugEnabled, (int)xThisOffset + 4);
            }
            else
            {
                DoNullReferenceCheck(Assembler, debugEnabled, (int)xThisOffset);
            }

            if (!String.IsNullOrEmpty(xNormalAddress))
            {
                if (xExtraStackSize > 0)
                {
                    XS.Sub(ESP, xExtraStackSize);
                }
                XS.Call(xNormalAddress);
            }
            else
            {
                /*
                 * On the stack now:
                 * $esp                 Params
                 * $esp + mThisOffset   This
                 */
                if ((xPopType.IsPointer) || (xPopType.IsByRef))
                {
                    xPopType = xPopType.GetElementType();
                    string xTypeId = GetTypeIDLabel(xPopType);
                    XS.Push(xTypeId, isIndirect: true);
                }
                else
                {
                    XS.Set(EAX, ESP, sourceDisplacement: (int)xThisOffset + 4);
                    XS.Push(EAX, isIndirect: true);
                }
                XS.Push(aTargetMethodUID);
                XS.Call(LabelName.Get(VTablesImplRefs.GetMethodAddressForTypeRef));
                if (xExtraStackSize > 0)
                {
                    xThisOffset -= xExtraStackSize;
                }

                /*
                 * On the stack now:
                 * $esp                 Params
                 * $esp + mThisOffset   This
                 */
                XS.Pop(ECX);

                XS.Label(xCurrentMethodLabel + ".AfterAddressCheck");

                if (IsReferenceType(xPopType))
                {
                    /*
                     * On the stack now:
                     * $esp + 0              Params
                     * $esp + mThisOffset    This
                     */
                    // we need to see if $this is a boxed object, and if so, we need to box it
                    XS.Set(EAX, ESP, sourceDisplacement: (int)xThisOffset + 4);
                    XS.Compare(EAX, (int)ObjectUtils.InstanceTypeEnum.BoxedValueType, destinationIsIndirect: true, destinationDisplacement: 4, size: RegisterSize.Int32);

                    /*
                     * On the stack now:
                     * $esp                 Params
                     * $esp + mThisOffset   This
                     *
                     * ECX contains the method to call
                     * EAX contains the type pointer (not the handle!!)
                     */
                    XS.Jump(CPU.ConditionalTestEnum.NotEqual, xCurrentMethodLabel + ".NotBoxedThis");

                    /*
                     * On the stack now:
                     * $esp                 Params
                     * $esp + mThisOffset   This
                     *
                     * ECX contains the method to call
                     * EAX contains the type pointer (not the handle!!)
                     */
                    XS.Add(EAX, (uint)ObjectUtils.FieldDataOffset);
                    XS.Set(ESP, EAX, destinationDisplacement: (int)xThisOffset + 4);

                    /*
                     * On the stack now:
                     * $esp                 Params
                     * $esp + mThisOffset   Pointer to address inside box
                     *
                     * ECX contains the method to call
                     */
                }
                XS.Label(xCurrentMethodLabel + ".NotBoxedThis");
                if (xExtraStackSize > 0)
                {
                    XS.Sub(ESP, xExtraStackSize);
                }
                XS.Call(ECX);
                XS.Label(xCurrentMethodLabel + ".AfterNotBoxedThis");
            }
            EmitExceptionLogic(Assembler, aMethod, aOp, true,
                               delegate
            {
                var xStackOffsetBefore = aOp.StackOffsetBeforeExecution.Value;

                uint xPopSize = 0;
                foreach (var type in aOp.StackPopTypes)
                {
                    xPopSize += Align(SizeOfType(type), 4);
                }

                var xResultSize = xReturnSize;
                if (xResultSize % 4 != 0)
                {
                    xResultSize += 4 - (xResultSize % 4);
                }

                EmitExceptionCleanupAfterCall(Assembler, xResultSize, xStackOffsetBefore, xPopSize);
            });
            XS.Label(xCurrentMethodLabel + ".NoExceptionAfterCall");
            XS.Comment("Argument Count = " + xParameters.Length);
        }
Example #27
0
        public static void DoExecute(Cosmos.Assembler.Assembler aAssembler, MethodInfo aMethod, string aFieldId, Type aDeclaringObject, bool aNeedsGC, bool debugEnabled)
        {
            var xType = aMethod.MethodBase.DeclaringType;

            var xFields    = GetFieldsInfo(aDeclaringObject, false);
            var xFieldInfo = (from item in xFields
                              where item.Id == aFieldId
                              select item).Single();
            var xActualOffset = Ldfld.GetFieldOffset(aDeclaringObject, aFieldId);
            var xSize         = xFieldInfo.Size;

            new Comment("Field: " + xFieldInfo.Id);
            new Comment("Type: " + xFieldInfo.FieldType.ToString());
            new Comment("Size: " + xFieldInfo.Size);
            new Comment("Offset: " + xActualOffset + " (includes object header)");

            uint xRoundedSize = Align(xSize, 4);

            DoNullReferenceCheck(aAssembler, debugEnabled, xRoundedSize);
            new Comment("After Nullref check");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = (int)xRoundedSize
            };
            // ECX contains the object pointer now
            if (aNeedsGC)
            {
                // for reference types (or boxed types), ECX actually contains the handle now, so we need to convert it to a memory address
                new Comment("Dereference memory handle now");
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true
                };
            }
            if (debugEnabled)
            {
                new CPUx86.Push {
                    DestinationReg = CPUx86.RegistersEnum.ECX
                };
                new CPUx86.Pop {
                    DestinationReg = CPUx86.RegistersEnum.ECX
                };
            }
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ECX, SourceValue = (uint)(xActualOffset)
            };
            //TODO: Can't we use an x86 op to do a byte copy instead and be faster?
            for (int i = 0; i < (xSize / 4); i++)
            {
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EAX
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((i * 4)), SourceReg = CPUx86.Registers.EAX
                };
            }

            switch (xSize % 4)
            {
            case 1: {
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EAX
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4), SourceReg = CPUx86.Registers.AL
                };
                break;
            }

            case 2: {
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EAX
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4), SourceReg = CPUx86.Registers.AX
                };
                break;
            }

            case 3: {
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EAX
                };
                // move 2 lower bytes
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4), SourceReg = CPUx86.Registers.AX
                };
                // shift third byte to lowest
                new CPUx86.ShiftRight {
                    DestinationReg = CPUx86.Registers.EAX, SourceValue = 16
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4) + 2, SourceReg = CPUx86.Registers.AL
                };
                break;
            }

            case 0: {
                break;
            }

            default:
                throw new Exception("Remainder size " + (xSize % 4) + " not supported!");
            }

#if !SKIP_GC_CODE
            if (aNeedsGC)
            {
                new CPUx86.Push {
                    DestinationReg = CPUx86.Registers.ECX
                };
                new CPUx86.Push {
                    DestinationReg = CPUx86.Registers.EAX
                };
                new CPUx86.Call {
                    DestinationLabel = LabelName.Get(GCImplementationRefs.DecRefCountRef)
                };
                new CPUx86.Call {
                    DestinationLabel = LabelName.Get(GCImplementationRefs.DecRefCountRef)
                };
            }
#endif
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ESP, SourceValue = 4
            };
        }
Example #28
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xType   = aMethod.MethodBase.DeclaringType;
            var xOpCode = (ILOpCodes.OpField)aOpCode;

            SysReflection.FieldInfo xField = xOpCode.Value;
            var xIsReferenceType           = TypeIsReferenceType(xField.FieldType);

            // call cctor:
            var xCctor = (xField.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? new ConstructorInfo[0]).SingleOrDefault();

            if (xCctor != null && xCctor.DeclaringType != aMethod.MethodBase.DeclaringType)
            {
                XS.Call(LabelName.Get(xCctor));
                ILOp.EmitExceptionLogic(Assembler, aMethod, aOpCode, true, null, ".AfterCCTorExceptionCheck");
                XS.Label(".AfterCCTorExceptionCheck");
            }

            //int aExtraOffset;// = 0;
            //bool xNeedsGC = xField.FieldType.IsClass && !xField.FieldType.IsValueType;
            uint xSize = SizeOfType(xField.FieldType);

            //if( xNeedsGC )
            //{
            //    aExtraOffset = 12;
            //}
            new Comment(Assembler, "Type = '" + xField.FieldType.FullName /*+ "', NeedsGC = " + xNeedsGC*/);

            uint xOffset = 0;

            var xFields = xField.DeclaringType.GetFields();

            foreach (SysReflection.FieldInfo xInfo in xFields)
            {
                if (xInfo == xField)
                {
                    break;
                }

                xOffset += SizeOfType(xInfo.FieldType);
            }
            string xDataName = DataMember.GetStaticFieldName(xField);

            if (xIsReferenceType)
            {
                XS.Add(XSRegisters.ESP, 4);
                XS.Pop(XSRegisters.EAX);
                XS.Set(ElementReference.New(xDataName).Name, XSRegisters.EAX, destinationIsIndirect: true, destinationDisplacement: 4);
                return;
            }
            for (int i = 0; i < (xSize / 4); i++)
            {
                XS.Pop(XSRegisters.EAX);
                new CPUx86.Mov {
                    DestinationRef = ElementReference.New(xDataName, i * 4), DestinationIsIndirect = true, SourceReg = CPUx86.RegistersEnum.EAX
                };
            }
            switch (xSize % 4)
            {
            case 1:
            {
                XS.Pop(XSRegisters.EAX);
                new CPUx86.Mov {
                    DestinationRef = ElementReference.New(xDataName, (int)((xSize / 4) * 4)), DestinationIsIndirect = true, SourceReg = CPUx86.RegistersEnum.AL
                };
                break;
            }

            case 2:
            {
                XS.Pop(XSRegisters.EAX);
                new CPUx86.Mov {
                    DestinationRef = Cosmos.Assembler.ElementReference.New(xDataName, (int)((xSize / 4) * 4)), DestinationIsIndirect = true, SourceReg = CPUx86.RegistersEnum.AX
                };
                break;
            }

            case 0:
            {
                break;
            }

            default:
                //EmitNotImplementedException(Assembler, GetServiceProvider(), "Ldsfld: Remainder size " + (xSize % 4) + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel);
                throw new NotImplementedException();
                //break;
            }
        }
Example #29
0
        private void LoadBootEntries()
        {
            mBootEntries   = new Dictionary <MethodBase, int?>();
            mForceIncludes = new List <MemberInfo>();

            var xCheckedAssemblies = new List <string>();

            foreach (string xRef in References)
            {
                LogMessage("Checking Reference: " + xRef);
                if (File.Exists(xRef))
                {
                    LogMessage("  Exists");
                    var xAssembly = AssemblyLoadContext.Default.LoadFromAssemblyCacheOrPath(xRef);
                    CheckAssembly(xAssembly);
                }
            }

            void CheckAssembly(Assembly aAssembly)
            {
                // Just for debugging
                //LogMessage("Checking Assembly: " + aAssembly.Location);

                xCheckedAssemblies.Add(aAssembly.GetName().ToString());

                foreach (var xType in aAssembly.GetTypes())
                {
                    var xForceIncludeAttribute = xType.GetCustomAttribute <ForceInclude>();

                    if (xForceIncludeAttribute != null)
                    {
                        ForceInclude(xType, xForceIncludeAttribute);
                    }

                    foreach (var xMethod in xType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
                    {
                        xForceIncludeAttribute = xMethod.GetCustomAttribute <ForceInclude>();

                        if (xForceIncludeAttribute != null)
                        {
                            ForceInclude(xMethod, xForceIncludeAttribute);
                        }

                        var xBootEntryAttribute = xMethod.GetCustomAttribute <BootEntry>();

                        if (xBootEntryAttribute != null)
                        {
                            var xEntryIndex = xBootEntryAttribute.EntryIndex;

                            LogMessage("Boot Entry found: Name: " + xMethod + ", Entry Index: "
                                       + (xEntryIndex.HasValue ? xEntryIndex.Value.ToString() : "null"));

                            if (xMethod.ReturnType != typeof(void))
                            {
                                throw new NotSupportedException("Boot Entry should return void! Method: " + LabelName.Get(xMethod));
                            }

                            if (xMethod.GetParameters().Length != 0)
                            {
                                throw new NotSupportedException("Boot Entry shouldn't have parameters! Method: " + LabelName.Get(xMethod));
                            }

                            mBootEntries.Add(xMethod, xEntryIndex);
                        }
                    }

                    if (xType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                        .Where(m => m.GetCustomAttribute <BootEntry>() != null).Any())
                    {
                        throw new NotSupportedException("Boot Entry should be static! Type: " + LabelName.GetFullName(xType));
                    }
                }

                foreach (var xReference in aAssembly.GetReferencedAssemblies())
                {
                    try
                    {
                        if (!xCheckedAssemblies.Contains(xReference.ToString()))
                        {
                            var xAssembly = AssemblyLoadContext.Default.LoadFromAssemblyName(xReference);

                            if (xAssembly != null)
                            {
                                CheckAssembly(xAssembly);
                            }
                        }
                    }
                    catch (FileNotFoundException)
                    {
                        if (xReference.Name.Contains("Cosmos"))
                        {
                            LogWarning("Cosmos Assembly not found!" + Environment.NewLine +
                                       "Assembly Name: " + xReference.FullName);
                        }
                    }
                }
            }

            if (mBootEntries.Count == 0)
            {
                throw new NotSupportedException("No boot entries found!");
            }

            if (mBootEntries.Where(e => e.Value == null).Count() == 0)
            {
                throw new NotImplementedException("No default boot entries found!");
            }

            mBootEntries = mBootEntries.OrderBy(e => e.Value)
                           .OrderByDescending(e => e.Value.HasValue)
                           .ToDictionary(e => e.Key, e => e.Value);

            if (mBootEntries.Count > 1)
            {
                var xLastEntryIndex = mBootEntries.Values.ElementAt(0);

                for (int i = 1; i < mBootEntries.Count; i++)
                {
                    var xEntryIndex = mBootEntries.Values.ElementAt(i);

                    if (xLastEntryIndex == xEntryIndex)
                    {
                        throw new NotSupportedException("Two boot entries with the same entry index were found! Methods: '" +
                                                        LabelName.GetFullName(mBootEntries.Keys.ElementAt(i - 1)) + "' and '" +
                                                        LabelName.GetFullName(mBootEntries.Keys.ElementAt(i)) + "'");
                    }

                    xLastEntryIndex = xEntryIndex;
                }
            }
        }
Example #30
0
 public static string GetFullName(this MethodBase aMethod)
 {
     return(LabelName.Get(aMethod));
 }