private void ProcessExternalMethod(MethodBase aMethod) { ILCompiler.Logger.Write("@Processor", aMethod.FullName(), "Processing External Method"); if (!aMethod.IsStatic) { throw new Exception("Non-static extern fields not supported"); } var aAttributeData = (DllImportAttribute)aMethod.GetCustomAttribute(typeof(DllImportAttribute)); if (aAttributeData == null) { throw new Exception("[DllImport]: Invalid Build"); } string xLibName = aAttributeData.Value; string xMethodLabel = aMethod.FullName(); string xMethodName = aAttributeData.EntryPoint == null ? aMethod.Name : aAttributeData.EntryPoint; int xCalliConvention = (int)aAttributeData.CallingConvention; bool IsAtomixCompiled = (xCalliConvention == (int)aMethod.CallingConvention); var xParms = aMethod.GetParameters(); /* * For now assume normal calli method * - Push Library Name * - Push Function Name * - Call Kernel API * - Jump to function address */ Core.AssemblerCode.Add(new Label(xMethodLabel)); // standard calli header Core.AssemblerCode.Add(new Push { DestinationReg = Registers.EBP }); Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.EBP, SourceReg = Registers.ESP }); // load and get address of external function Core.AssemblerCode.Add(new Push { DestinationRef = AddStringData(xLibName) }); Core.AssemblerCode.Add(new Push { DestinationRef = AddStringData(xMethodName) }); Core.AssemblerCode.Add(new Call(Helper.lblImportDll, true)); Core.AssemblerCode.Add(new Test { DestinationReg = Registers.ECX, SourceRef = "0x2" }); Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); int ArgSize = ILHelper.GetArgumentsSize(aMethod); int xReturnSize = ILHelper.GetReturnTypeSize(aMethod); int xRetSize = (ArgSize - xReturnSize); #region _CALLI_HEADER_ if (IsAtomixCompiled) { // push the arguments from left to right for (int i = 0; i < xParms.Length; i++) { int xDisplacement = ILHelper.GetArgumentDisplacement(aMethod, i); int xArgSize = aMethod.GetParameters()[i].ParameterType.SizeOf().Align(); for (int j = 0; j < (xArgSize / 4); j++) { Core.AssemblerCode.Add( new Push { DestinationReg = Registers.EBP, DestinationIndirect = true, DestinationDisplacement = xDisplacement - (j * 4) }); } } if (xRetSize < 0) { Core.AssemblerCode.Add(new Sub { DestinationReg = Registers.ESP, SourceRef = "0x" + (-xRetSize).ToString("x") }); xRetSize = 0; } } else if (xCalliConvention == (int)CallingConvention.StdCall) { // push arguments to the stack from right to left for (int i = xParms.Length - 1; i >= 0; i--) { int xDisplacement = ILHelper.GetArgumentDisplacement(aMethod, i); int xArgSize = aMethod.GetParameters()[i].ParameterType.SizeOf().Align(); for (int j = 0; j < (xArgSize / 4); j++) { Core.AssemblerCode.Add( new Push { DestinationReg = Registers.EBP, DestinationIndirect = true, DestinationDisplacement = xDisplacement - (j * 4) }); } } } #endregion // Call the function Core.AssemblerCode.Add(new Call("EAX")); #region _CALLI_FOOTER_ if (xReturnSize > 0) { var xOffset = ILHelper.GetResultCodeOffset(xReturnSize, ArgSize); if (IsAtomixCompiled) { // For return type Method for (int i = 0; i < xReturnSize / 4; i++) { Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.EBP, DestinationIndirect = true, DestinationDisplacement = (xOffset + (i * 4)), SourceReg = Registers.EAX }); } } else if (xCalliConvention == (int)CallingConvention.StdCall) { if (xReturnSize > 8) { throw new Exception("[Extern]: Unsupported Return Size for StdCall"); } Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.EBP, DestinationIndirect = true, DestinationDisplacement = xOffset, SourceReg = Registers.EAX }); if (xReturnSize == 8) { Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.EBP, DestinationIndirect = true, DestinationDisplacement = (xOffset + 4), SourceReg = Registers.EAX }); } } } #endregion Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.ECX, SourceRef = "0x0" }); Core.AssemblerCode.Add(new Leave()); Core.AssemblerCode.Add(new Ret { Address = (byte)xRetSize }); BuildDefinations.Add(aMethod); }
private void ProcessDelegate(MethodBase xMethod) { var lbl = xMethod.FullName(); var lbl_exception = lbl + ".Error"; var lbl_end = lbl + ".End"; Core.AssemblerCode.Add(new Label(lbl)); // Calli header Core.AssemblerCode.Add(new Push { DestinationReg = Registers.EBP }); Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.EBP, SourceReg = Registers.ESP }); if (lbl.Contains("ctor")) { // Load Argument ((Ldarg)MSIL[ILCode.Ldarg]).Execute2(0, xMethod); Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EBX }); ((Ldarg)MSIL[ILCode.Ldarg]).Execute2(2, xMethod); // The pointer Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); Core.AssemblerCode.Add(new Add { DestinationReg = Registers.EBX, SourceRef = "0xC" }); Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.EBX, DestinationIndirect = true, SourceReg = Registers.EAX }); ((Ldarg)MSIL[ILCode.Ldarg]).Execute2(1, xMethod); // The Object Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); Core.AssemblerCode.Add(new Add { DestinationReg = Registers.EBX, SourceRef = "0x4" }); Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.EBX, DestinationIndirect = true, SourceReg = Registers.EAX }); // calli footer Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.ECX, SourceRef = "0x0" }); Core.AssemblerCode.Add(new Leave()); Core.AssemblerCode.Add(new Ret { Address = 0xC }); // Memory location + Object + Intptr } else if (lbl.Contains("Invoke")) { // Load Reference ((Ldarg)MSIL[ILCode.Ldarg]).Execute2(0, xMethod); Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); Core.AssemblerCode.Add(new Add { DestinationReg = Registers.EAX, SourceRef = "0xC" }); // If it is a non static field than get its parent Type memory location (object in constructor) if (!xMethod.IsStatic) { Core.AssemblerCode.Add(new Push { DestinationReg = Registers.EAX, DestinationDisplacement = 0x4, DestinationIndirect = true }); } var xParms = xMethod.GetParameters(); int xSize = ILHelper.GetArgumentsSize(xMethod); // Load arguments to throw int xArgSize; for (ushort i = 1; i <= xParms.Length; i++) { // New Code int xDisplacement = ILHelper.GetArgumentDisplacement(xMethod, i); if (xMethod.IsStatic) { xArgSize = xMethod.GetParameters()[i].ParameterType.SizeOf().Align(); } else { xArgSize = xMethod.GetParameters()[i - 1].ParameterType.SizeOf().Align(); } for (int j = 0; j < (xArgSize / 4); j++) { Core.AssemblerCode.Add( new Push { DestinationReg = Registers.EBP, DestinationIndirect = true, DestinationDisplacement = xDisplacement - (j * 4) }); } } // Call the function Core.AssemblerCode.Add(new Call("[EAX]")); // Check for anytype of exception Core.AssemblerCode.Add(new Test { DestinationReg = Registers.ECX, SourceRef = "0x2" }); Core.AssemblerCode.Add(new Jmp { Condition = ConditionalJumpEnum.JNE, DestinationRef = lbl_exception }); // calli footer Core.AssemblerCode.Add(new Label(lbl_end)); Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.ECX, SourceRef = "0x0" }); Core.AssemblerCode.Add(new Label(lbl_exception)); int xReturnSize = ILHelper.GetReturnTypeSize(xMethod); if (xReturnSize > 0) { // For return type Method var xOffset = ILHelper.GetResultCodeOffset(xReturnSize, xSize); for (int i = 0; i < xReturnSize / 4; i++) { Core.AssemblerCode.Add(new Pop { DestinationReg = Registers.EAX }); Core.AssemblerCode.Add(new Mov { DestinationReg = Registers.EBP, DestinationIndirect = true, DestinationDisplacement = (int)(xOffset + ((i + 0) * 4)), SourceReg = Registers.EAX }); } } byte xRetSize = (byte)Math.Max(0, xSize - xReturnSize); Core.AssemblerCode.Add(new Leave()); Core.AssemblerCode.Add(new Ret { Address = xRetSize }); // Parameter + Memory } BuildDefinations.Add(xMethod); }