Console works again.

This commit is contained in:
mterwoord_cp 2007-10-11 18:04:03 +00:00
parent 0110fc3a18
commit 8431877010
22 changed files with 277 additions and 31 deletions

View file

@ -0,0 +1,18 @@
using System;
using System.Linq;
namespace Indy.IL2CPU.Assembler.X86 {
[OpCode(0xFFFFFFFF, "cmpxchg")]
public class CmpXchg: Instruction {
public readonly string Destination;
public readonly string Source;
public CmpXchg(string aDestination, string aSource) {
Destination = aDestination;
Source = aSource;
}
public override string ToString() {
return "cmpxchg " + Destination + ", " + Source;
}
}
}

View file

@ -53,6 +53,7 @@
<Compile Include="And.cs" />
<Compile Include="Assembler.cs" />
<Compile Include="Call.cs" />
<Compile Include="CmpXchg.cs" />
<Compile Include="Compare.cs" />
<Compile Include="Not.cs" />
<Compile Include="ShiftLeft.cs" />

View file

@ -12,7 +12,7 @@ namespace Indy.IL2CPU.Assembler {
public static string FilterStringForIncorrectChars(string aName) {
string xTempResult = aName;
foreach (char c in new char[] { '.', ',', '+', '$', '<', '>', '{', '}', '-', '`', '\'', '/', '\\', ' ', '(', ')', '[', ']' }) {
foreach (char c in new char[] { '.', ',', '+', '$', '<', '>', '{', '}', '-', '`', '\'', '/', '\\', ' ', '(', ')', '[', ']', '*' }) {
xTempResult = xTempResult.Replace(c, '_');
}
return xTempResult;

View file

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace Indy.IL2CPU.IL.X86.Win32.CustomImplementations.System {
public static class ConsoleImpl {
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern unsafe bool WriteConsole(IntPtr hConsoleOutput, uint* lpBuffer,
uint nNumberOfCharsToWrite, out uint lpNumberOfCharsWritten,
IntPtr lpReserved);
[DllImport("kernel32.dll")]
static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll")]
private static extern bool CloseHandle(IntPtr aHandle);
private const int ConsoleOutHandle = -11;
private static int mInitialized = 0;
private static IntPtr mConsoleOutHandler;
private static void DoInitialize() {
if(mInitialized== 0){
mInitialized = 1;
mConsoleOutHandler = GetStdHandle(ConsoleOutHandle);
}
}
public unsafe static void Write(uint* aData) {
DoInitialize();
uint xCharsWritten;
uint xCharsToWrite = (uint)X86.CustomImplementations.System.StringImpl.get_Length_Normal(aData);
WriteConsole(mConsoleOutHandler, CustomImplementation.System.StringImpl.GetStorageNormal(aData), xCharsToWrite, out xCharsWritten, IntPtr.Zero);
}
public static void WriteLine(string aData) {
Console.Write(aData);
Console.Write(Environment.NewLine);
}
}
}

View file

@ -0,0 +1,35 @@
using System;
using System.Linq;
using System.Reflection;
using Mono.Cecil;
namespace Indy.IL2CPU.IL.X86.Win32.CustomImplementations.System {
public static class ConsoleImplRefs {
public static readonly MethodDefinition WriteRef;
public static readonly MethodDefinition WriteLineRef;
public static readonly AssemblyDefinition RuntimeAssemblyDef;
static ConsoleImplRefs() {
RuntimeAssemblyDef = AssemblyFactory.GetAssembly(typeof (ConsoleImpl).Assembly.Location);
TypeDefinition xType = null;
foreach (ModuleDefinition xMod in RuntimeAssemblyDef.Modules) {
if (xMod.Types.Contains(typeof (ConsoleImpl).FullName)) {
xType = xMod.Types[typeof (ConsoleImpl).FullName];
break;
}
}
if (xType == null) {
throw new Exception("ConsoleImpl type not found!");
}
foreach (FieldInfo xField in typeof (ConsoleImplRefs).GetFields()) {
if (xField.Name.EndsWith("Ref")) {
MethodDefinition xTempMethod = xType.Methods.GetMethod(xField.Name.Substring(0, xField.Name.Length - "Ref".Length)).FirstOrDefault();
if (xTempMethod == null) {
throw new Exception("Method '" + xField.Name.Substring(0, xField.Name.Length - "Ref".Length) + "' not found on RuntimeEngine!");
}
xField.SetValue(null, xTempMethod);
}
}
}
}
}

View file

@ -25,6 +25,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -47,6 +48,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CustomImplementations\System\ConsoleImpl.cs" />
<Compile Include="CustomImplementations\System\ConsoleImplRefs.cs" />
<Compile Include="PInvokes.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RuntimeEngineImpl.cs" />

View file

@ -9,5 +9,18 @@ namespace Indy.IL2CPU.IL.X86.Win32 {
protected override Type GetCustomMethodImplementationOp() {
return typeof(Win32CustomMethodImplementationOp);
}
public override Mono.Cecil.MethodReference GetCustomMethodImplementation(string aOrigMethodName, bool aInMetalMode) {
switch (aOrigMethodName) {
case "System_Void___System_Console_Write___System_String___": {
return CustomImplementations.System.ConsoleImplRefs.WriteRef;
}
case "System_Void___System_Console_WriteLine___System_String___": {
return CustomImplementations.System.ConsoleImplRefs.WriteLineRef;
}
default:
return base.GetCustomMethodImplementation(aOrigMethodName, aInMetalMode);
}
}
}
}

View file

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Indy.IL2CPU.IL.X86.CustomImplementations.System {
public static class ObjectImpl {
}
}

View file

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Mono.Cecil;
namespace Indy.IL2CPU.IL.X86.CustomImplementations.System {
public static class ObjectImplRefs {
public static readonly AssemblyDefinition RuntimeAssemblyDef;
static ObjectImplRefs() {
RuntimeAssemblyDef = AssemblyFactory.GetAssembly(typeof(ObjectImpl).Assembly.Location);
TypeDefinition xType = null;
foreach (ModuleDefinition xMod in RuntimeAssemblyDef.Modules) {
if (xMod.Types.Contains(typeof(ObjectImpl).FullName)) {
xType = xMod.Types[typeof(ObjectImpl).FullName];
break;
}
}
if (xType == null) {
throw new Exception("ObjectImpl type not found!");
}
foreach (FieldInfo xField in typeof(ObjectImplRefs).GetFields()) {
if (xField.Name.EndsWith("Ref")) {
MethodDefinition xTempMethod = xType.Methods.GetMethod(xField.Name.Substring(0, xField.Name.Length - "Ref".Length)).FirstOrDefault();
if (xTempMethod == null) {
throw new Exception("Method '" + xField.Name.Substring(0, xField.Name.Length - "Ref".Length) + "' not found on RuntimeEngine!");
}
xField.SetValue(null, xTempMethod);
}
}
}
}
}

View file

@ -5,14 +5,14 @@ using System.Text;
namespace Indy.IL2CPU.IL.X86.CustomImplementations.System {
public static class StringImpl {
public static unsafe int get_Length_Normal(int* aThis) {
int xArrayPtrNumber = *(aThis + 3);
public static unsafe int get_Length_Normal(uint* aThis) {
int xArrayPtrNumber = (int)*(aThis + 3);
int* xArrayPtr = (int*)xArrayPtrNumber;
return *(xArrayPtr + 2);
}
public static unsafe int get_Length_Metal(int* aThis) {
return *aThis;
public static unsafe int get_Length_Metal(uint* aThis) {
return (int)*aThis;
}
public static byte GetByteFromChar(char aChar) {

View file

@ -127,6 +127,8 @@
<Compile Include="Conv_U8.cs" />
<Compile Include="Cpblk.cs" />
<Compile Include="Cpobj.cs" />
<Compile Include="CustomImplementations\System\ObjectImpl.cs" />
<Compile Include="CustomImplementations\System\ObjectImplRefs.cs" />
<Compile Include="CustomImplementations\System\StringImplRefs.cs" />
<Compile Include="CustomImplementations\System\StringImpl.cs" />
<Compile Include="Div.cs" />

View file

@ -34,15 +34,21 @@ namespace Indy.IL2CPU.IL.X86 {
Move(Assembler, "eax", xDataName);
Pushd(4, "eax");
} else {
string xDataName = Assembler.GetIdentifier("StringLiteral");
var xDataByteArray = new StringBuilder();
// todo: see if we need to output trailing bytes 00 00 or 00 01 depending on whether there are bytes >7F
xDataByteArray.Append(BitConverter.GetBytes(Engine.RegisterType(Engine.GetTypeDefinition("mscorlib", "System.String"))).Aggregate("", (r, b) => r + b + ","));
xDataByteArray.Append(BitConverter.GetBytes(Engine.RegisterType(Engine.GetTypeDefinition("mscorlib", "System.Array"))).Aggregate("", (r, b) => r + b + ","));
xDataByteArray.Append(BitConverter.GetBytes((int)InstanceTypeEnum.Array).Aggregate("", (r, b) => r + b + ","));
xDataByteArray.Append(BitConverter.GetBytes(LiteralStr.Length).Aggregate("", (r, b) => r + b + ","));
xDataByteArray.Append(Encoding.ASCII.GetBytes(LiteralStr).Aggregate("", (r, b) => r + b + ","));
xDataByteArray.Append(Encoding.Unicode.GetBytes(LiteralStr).Aggregate("", (r, b) => r + b + ","));
xDataByteArray.Append("0,");
Assembler.DataMembers.Add(new DataMember(xDataName, "db", xDataByteArray.ToString().TrimEnd(',')));
string xDataVal = xDataByteArray.ToString().TrimEnd(',');
string xDataName = (from item in Assembler.DataMembers
where item.DefaultValue == xDataVal
select item.Name).FirstOrDefault();
if (String.IsNullOrEmpty(xDataName)) {
xDataName = Assembler.GetIdentifier("StringLiteral");
Assembler.DataMembers.Add(new DataMember(xDataName, "db", xDataByteArray.ToString().TrimEnd(',')));
}
Pushd(4, xDataName);
new Newobj() {
Assembler = Assembler,

View file

@ -19,9 +19,6 @@ namespace Indy.IL2CPU.IL.X86 {
// todo: refactor all Ldelem variants to use this method for emitting
public static void Assemble(CPU.Assembler aAssembler, int aElementSize) {
if(aElementSize % 4 != 0) {
throw new ArgumentException("ElementSize should be divisible by 4", "aElementSize");
}
aAssembler.Add(new CPUx86.Pop("eax"));
aAssembler.Add(new CPUx86.Move("edx", "0" + aElementSize.ToString("X") + "h"));
aAssembler.Add(new CPUx86.Multiply("edx"));
@ -29,11 +26,26 @@ namespace Indy.IL2CPU.IL.X86 {
aAssembler.Add(new CPUx86.Pop("edx"));
aAssembler.Add(new CPUx86.Add("edx", "eax"));
aAssembler.Add(new CPUx86.Move("eax", "edx"));
for (int i = 0; i < (aElementSize / 4); i++) {
aAssembler.Add(new CPUx86.Pushd("[eax]"));
if (i != 0) {
int xSizeLeft = aElementSize;
while(xSizeLeft > 0) {
if(xSizeLeft >= 4) {
aAssembler.Add(new CPUx86.Push("dword [eax]"));
aAssembler.Add(new CPUx86.Add("eax", "4"));
aAssembler.Add(new CPUx86.Pushd("eax"));
xSizeLeft -= 4;
}else {
if(xSizeLeft >= 2) {
aAssembler.Add(new CPUx86.Push("word [eax]"));
aAssembler.Add(new CPUx86.Add("eax", "2"));
xSizeLeft -= 2;
}else {
if(xSizeLeft >= 1) {
aAssembler.Add(new CPUx86.Push("byte [eax]"));
aAssembler.Add(new CPUx86.Add("eax", "1"));
xSizeLeft -= 1;
}else {
throw new Exception("Size left: " + xSizeLeft);
}
}
}
}
aAssembler.StackSizes.Pop();

View file

@ -12,7 +12,7 @@ namespace Indy.IL2CPU.IL.X86 {
}
public override void DoAssemble() {
Pop("eax");
Pushd(2, "word [eax]");
Push(Assembler, 2, "word [eax]");
}
}
}

View file

@ -33,7 +33,7 @@ namespace Indy.IL2CPU.IL.X86 {
Move(Assembler, "dword [eax + 4]", "0" + InstanceTypeEnum.NormalObject.ToString("X") + "h");
//Pushd("ecx");
for (int i = 0; i < CtorDef.Parameters.Count; i++) {
Assembler.Add(new CPUx86.Pushd("[ebp - 010h]"));
Assembler.Add(new CPUx86.Pushd("[esp + 0x8]"));
}
Call(new CPU.Label(CtorDef).Name);
Pop("eax");

View file

@ -11,6 +11,7 @@ namespace Indy.IL2CPU.IL.X86 {
: base(aInstruction, aMethodInfo) {
}
public override void DoAssemble() {
JumpAlways(".END__OF__METHOD");
}
}
}

View file

@ -2,8 +2,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mono.Cecil.Cil;
using Indy.IL2CPU.Assembler;
using CPU = Indy.IL2CPU.Assembler.X86;
using Instruction=Mono.Cecil.Cil.Instruction;
namespace Indy.IL2CPU.IL.X86 {
public class X86MethodFooterOp: MethodFooterOp {
@ -45,16 +46,15 @@ namespace Indy.IL2CPU.IL.X86 {
}
public static void AssembleFooter(int aReturnSize, Assembler.Assembler aAssembler, int[] aLocalsSizes, int aTotalArgsSize) {
aAssembler.Add(new Label(".END__OF__METHOD"));
if (aReturnSize > 0) {
if (aReturnSize > 4) {
throw new Exception("ReturnValue sizes larger than 4 not supported yet");
}
aAssembler.Add(new Assembler.X86.Pop("eax"));
aAssembler.StackSizes.Pop();
}
for (int j = (aLocalsSizes.Length - 1); j >= 0; j--) {
int xLocalSize = aLocalsSizes[j];
aAssembler.StackSizes.Pop();
aAssembler.Add(new CPU.Add("esp", "0x" + xLocalSize.ToString("X")));
}
aAssembler.Add(new CPU.Pop("ebp"));

View file

@ -2,7 +2,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using CPU = Indy.IL2CPU.Assembler;
using CPUx86 = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
public abstract class X86OpCodeMap: OpCodeMap {
@ -41,7 +42,7 @@ namespace Indy.IL2CPU.IL.X86 {
case "System_Int32___System_String_get_Length____": {
if (aInMetalMode) {
return CustomImplementations.System.StringImplRefs.get_Length_MetalRef;
}else {
} else {
return CustomImplementations.System.StringImplRefs.get_Length_NormalRef;
}
}
@ -55,5 +56,57 @@ namespace Indy.IL2CPU.IL.X86 {
return base.GetCustomMethodImplementation(aOrigMethodName, aInMetalMode);
}
}
public override bool HasCustomAssembleImplementation(string aMethodName, bool aInMetalMode) {
switch (aMethodName) {
case "System_Object___System_Threading_Interlocked_CompareExchange___System_Object___System_Object__System_Object___": {
return true;
}
case "System_Int32___System_Threading_Interlocked_CompareExchange___System_Int32___System_Int32__System_Int32___": {
return true;
}
case "System_String___System_String_FastAllocateString___System_Int32___": {
return true;
}
default:
return base.HasCustomAssembleImplementation(aMethodName, aInMetalMode);
}
}
public override void DoCustomAssembleImplementation(string aMethodName, bool aInMetalMode, Indy.IL2CPU.Assembler.Assembler aAssembler, MethodInformation aMethodInfo) {
switch (aMethodName) {
case "System_Object___System_Threading_Interlocked_CompareExchange___System_Object___System_Object__System_Object___": {
Assemble_System_Threading_Interlocked_CompareExchange__Object(aAssembler, aMethodInfo);
break;
}
case "System_Int32___System_Threading_Interlocked_CompareExchange___System_Int32___System_Int32__System_Int32___": {
Assemble_System_Threading_Interlocked_CompareExchange__Object(aAssembler, aMethodInfo);
break;
}
default:
base.DoCustomAssembleImplementation(aMethodName, aInMetalMode, aAssembler, aMethodInfo);
break;
}
}
private static void Assemble_System_Threading_Interlocked_CompareExchange__Object(Assembler.Assembler aAssembler, MethodInformation aMethodInfo) {
//arguments:
// 0: location
// 1: value
// 2: comparand
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[2].VirtualAddresses, aMethodInfo.Arguments[2].Size);
aAssembler.Add(new CPUx86.Pop("eax"));
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[1].VirtualAddresses, aMethodInfo.Arguments[1].Size);
aAssembler.Add(new CPUx86.Pop("edx"));
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0].VirtualAddresses, aMethodInfo.Arguments[0].Size);
aAssembler.Add(new CPUx86.Pop("ecx"));
aAssembler.Add(new CPUx86.Pushd("[ecx]"));
aAssembler.Add(new CPUx86.Pop("ecx"));
aAssembler.Add(new CPUx86.CmpXchg("ecx", "edx"));
Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0].VirtualAddresses, aMethodInfo.Arguments[0].Size);
aAssembler.Add(new CPUx86.Pop("eax"));
aAssembler.Add(new CPUx86.Move("[eax]", "ecx"));
aAssembler.Add(new CPUx86.Pushd("eax"));
}
}
}

View file

@ -49,15 +49,19 @@ namespace Indy.IL2CPU.IL.X86 {
// }
// }
// if (xNeedsExtras) {
string xStringMethodSuffix = "W";
if(Assembler.InMetalMode) {
xStringMethodSuffix = "A";
}
if (!TheMethod.PInvokeInfo.IsNoMangle) {
if (TheMethod.PInvokeInfo.IsCharSetUnicode) {
xMethodName += "A";// for now, strings are ASCII
xMethodName += xStringMethodSuffix;
} else {
if (TheMethod.PInvokeInfo.IsCharSetAnsi) {
xMethodName += "A";
xMethodName += xStringMethodSuffix;
} else {
if (TheMethod.PInvokeInfo.IsCharSetAuto) {
xMethodName += "A";// for now, strings are ASCII
xMethodName += xStringMethodSuffix;
}
}
}

View file

@ -18,13 +18,21 @@ namespace Indy.IL2CPU.CustomImplementation.System {
aStorage = aChars;
}
public static uint GetStorageMetal(uint aStringPtr) {
[MethodAlias(Name = "System.String System.String.FastAllocateString(System.Int32)")]
public static String FastAllocateString(int aLength) {
Char[] xItems = new Char[aLength];
return new String(xItems);
}
public static unsafe uint* GetStorageMetal(uint* aStringPtr) {
return aStringPtr;
}
public static uint GetStorageNormal(uint aStringPtr) {
uint xResult = aStringPtr;
xResult = xResult + 12;
public static unsafe uint* GetStorageNormal(uint* aStringPtr) {
uint* xResult = aStringPtr;
xResult = xResult + 3;
xResult = (uint*)(*xResult);
xResult += 3;
return xResult;
}
}

View file

@ -882,6 +882,9 @@ namespace Indy.IL2CPU {
if (xField.IsStatic) {
continue;
}
if(xField.HasConstant) {
Console.WriteLine("Field is constant: " + xField.GetFullName());
}
int xFieldSize;
TypeSpecification xTypeSpec = xField.FieldType as TypeSpecification;
if (xTypeSpec != null) {

View file

@ -6,7 +6,7 @@ using System.Text;
namespace Indy.IL2CPU {
partial class RuntimeEngine {
public static uint HeapHandle = 0;
public const uint InitialHeapSize = 1024;
public const uint InitialHeapSize = 4096;
public const uint MaximumHeapSize = 10 * 1024 * InitialHeapSize; // 10 megabytes
public static void Heap_Initialize() {
//HeapHandle = PInvokes.Kernel32_HeapCreate(0, InitialHeapSize, MaximumHeapSize);