doesn't work, see comments. some progress has been made, though

This commit is contained in:
mterwoord_cp 2007-09-04 17:16:30 +00:00
parent ea41827fda
commit 491be780f8
28 changed files with 170 additions and 97 deletions

View file

@ -1,33 +1,49 @@
using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace HelloWorldMetal {
// Restrictions for Metal compile is that static members only, and no heap usage
// Basic string support is provided by using c strings in data sections
class Program {
// These would be output in the data section. Since no heap exists,
// all are treated as globals and space is fixed and preallocated
static int Level = 0;
static string StringValue = "Hello";
// Restrictions for Metal compile is that static members only, and no heap usage
// Basic string support is provided by using c strings in data sections
class Program {
// These would be output in the data section. Since no heap exists,
// all are treated as globals and space is fixed and preallocated
// MtW:
// Don't make them consts, this will copy the value, and produce
// an ldstr, which Creates (which is evil in Metal mode) a new string.
// declaring as follows makes it reuse the code
public static string Message = "Hello, World";
static void Main() {
// Local variables are ok too, since they are stack based
int i = 0;
// String literals translate to ldstr - these would automatically be pulled out
// and put in the data section. String manipuation not permitted unless the actual
// bytes are modified directly.
//
// Implement the P/Invoke interface. This will allow interfacing to Windows
// and other systems.
//
// Certain statics can have points mapped and replaced with future metal code
// or translations to P/Invokes.
// Such as Console.Write. It can be determined by name and remapped to
// the Win32 calll.
// Console.Write("Hello World");
// For now - lets stick with P/Invoke only - I want to do some more investigation
// around map replacement
// So the current test would be - declare a P/Invoke for writing to console in Win32
// then call it below with "HelloWorld"
}
}
static void Main() {
// Local variables are ok too, since they are stack based
int i = 0;
string theMessage = "Hello, World!";
// String literals translate to ldstr - these would automatically be pulled out
// and put in the data section. String manipuation not permitted unless the actual
// bytes are modified directly.
//
// Implement the P/Invoke interface. This will allow interfacing to Windows
// and other systems.
//
// Certain statics can have points mapped and replaced with future metal code
// or translations to P/Invokes.
// Such as Console.Write. It can be determined by name and remapped to
// the Win32 calll.
// Console.Write("Hello World");
// For now - lets stick with P/Invoke only - I want to do some more investigation
// around map replacement
// So the current test would be - declare a P/Invoke for writing to console in Win32
// then call it below with "HelloWorld"
IntPtr xHandle = GetStdHandle(-11);
uint xCharsWritten = 0;
WriteConsole(xHandle, theMessage, 13, out xCharsWritten, IntPtr.Zero);
}
[DllImport("kernel32.dll")]
static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll")]
static extern bool WriteConsole(IntPtr hConsoleOutput, string lpBuffer,
uint nNumberOfCharsToWrite, out uint lpNumberOfCharsWritten,
IntPtr lpReserved);
}
}

View file

@ -49,6 +49,10 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\HelloWorldMetal\HelloWorldMetal.csproj">
<Project>{B57BEF6D-48D6-49DD-B4C5-893537E0EBB8}</Project>
<Name>HelloWorldMetal</Name>
</ProjectReference>
<ProjectReference Include="..\HelloWorld\HelloWorld.csproj">
<Project>{0267F1AE-CA81-4EBD-86CA-C8E22BE9A6F1}</Project>
<Name>HelloWorld</Name>

View file

@ -14,7 +14,7 @@ namespace IL2CPU {
};
using (FileStream fs = new FileStream(@"output.asm", FileMode.Create)) {
using (StreamWriter br = new StreamWriter(fs)) {
e.Execute("HelloWorld.exe", TargetPlatformEnum.x86, br);
e.Execute("HelloWorldMetal.exe", TargetPlatformEnum.x86, br);
}
}
} catch (Exception E) {

View file

@ -118,6 +118,5 @@ namespace Indy.IL2CPU.Assembler {
}
}
}
}
}

View file

@ -51,13 +51,7 @@ namespace Indy.IL2CPU.Assembler {
xSB.Append("_");
}
xSB.Append("__");
xSB.Replace('.', '_');
xSB.Replace('+', '_');
xSB.Replace('*', '_');
xSB.Replace('[', '_');
xSB.Replace(']', '_');
return xSB.ToString();
return xSB.ToString().Replace('.', '_').Replace('+', '_').Replace('*', '_').Replace('[', '_').Replace(']', '_').Replace('&', '_');
}
}
}

View file

@ -9,12 +9,17 @@ namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Call)]
public class Call: Op {
public readonly string LabelName;
public readonly bool HasResult;
public Call(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
HasResult = !((MethodReference)aInstruction.Operand).ReturnType.ReturnType.FullName.Contains("System.Void");
LabelName = new Asm.Label((MethodReference)aInstruction.Operand).Name;
}
public void Assemble(string aMethod) {
Call(aMethod);
if(HasResult) {
Push("EAX");
}
}
public override void Assemble() {

View file

@ -18,7 +18,7 @@ namespace Indy.IL2CPU.IL.X86 {
public override void Assemble() {
// Make sure the crawler finds string constructors
DoQueueMethod(typeof(String).Assembly.FullName, typeof(String).FullName, ".ctor");
//DoQueueMethod(typeof(String).Assembly.FullName, typeof(String).FullName, ".ctor");
// todo: see if we need to output trailing bytes 00 00 or 00 01 depending on whether there are bytes >7F
string xDataName = Assembler.GetIdentifier("StringLiteral");
var xDataByteArray = new StringBuilder();
@ -28,10 +28,10 @@ namespace Indy.IL2CPU.IL.X86 {
}
Assembler.DataMembers.Add(new DataMember(xDataName, "db", xDataByteArray.ToString().TrimEnd(',')));
Pushd(xDataName);
new Newobj() {
CtorName = (new Label(typeof(String).FullName, typeof(Char).FullName + "*")).Name,
Assembler = Assembler
}.Assemble();
// new Newobj() {
// CtorName = (new Label(typeof(String).FullName, typeof(Char).FullName + "*")).Name,
// Assembler = Assembler
// }.Assemble();
}
}
}

View file

@ -7,11 +7,27 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Ldloc)]
public class Ldloc: Op {
private int mOffset;
protected void SetLocalIndex(int aIndex, MethodInformation aMethodInfo) {
mOffset = aMethodInfo.Locals[aIndex].Offset + aMethodInfo.Locals[aIndex].Size + 4;
}
public Ldloc(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
int xLocalIndex;
if (Int32.TryParse((aInstruction.Operand ?? "").ToString(), out xLocalIndex)) {
SetLocalIndex(xLocalIndex, aMethodInfo);
}
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
public int Offset {
get {
return mOffset;
}
}
public sealed override void Assemble() {
Push("eax");
Move("eax", "[esp+" + mOffset + "]");
}
}
}

View file

@ -6,12 +6,10 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Ldloc_0)]
public class Ldloc_0: Op {
public class Ldloc_0: Ldloc {
public Ldloc_0(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
SetLocalIndex(0, aMethodInfo);
}
}
}

View file

@ -6,12 +6,10 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Ldloc_1)]
public class Ldloc_1: Op {
public class Ldloc_1: Ldloc {
public Ldloc_1(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
SetLocalIndex(1, aMethodInfo);
}
}
}

View file

@ -6,12 +6,10 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Ldloc_2)]
public class Ldloc_2: Op {
public class Ldloc_2: Ldloc {
public Ldloc_2(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
SetLocalIndex(2, aMethodInfo);
}
}
}

View file

@ -6,12 +6,10 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Ldloc_3)]
public class Ldloc_3: Op {
public class Ldloc_3: Ldloc {
public Ldloc_3(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
SetLocalIndex(3, aMethodInfo);
}
}
}

View file

@ -6,12 +6,9 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Ldloc_S)]
public class Ldloc_S: Op {
public class Ldloc_S: Ldloc {
public Ldloc_S(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
}
}
}

View file

@ -7,11 +7,27 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Ldloca)]
public class Ldloca: Op {
private int mOffset;
protected void SetLocalIndex(int aIndex, MethodInformation aMethodInfo) {
mOffset = aMethodInfo.Locals[aIndex].Offset + aMethodInfo.Locals[aIndex].Size + 4;
}
public Ldloca(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
int xLocalIndex;
if (Int32.TryParse((aInstruction.Operand ?? "").ToString(), out xLocalIndex)) {
SetLocalIndex(xLocalIndex, aMethodInfo);
}
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
public int Offset {
get {
return mOffset;
}
}
public sealed override void Assemble() {
Push("eax");
Move("eax", "[esp+" + mOffset + "]");
}
}
}

View file

@ -6,12 +6,9 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Ldloca_S)]
public class Ldloca_S: Op {
public class Ldloca_S: Ldloca {
public Ldloca_S(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
}
}
}

View file

@ -7,11 +7,17 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Ldsfld)]
public class Ldsfld: Op {
private bool IsIntPtrZero = false;
public Ldsfld(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
IsIntPtrZero = aInstruction.Operand.ToString() == "System.IntPtr System.IntPtr::Zero";
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
if(IsIntPtrZero) {
Pushd("0");
return;
}
throw new NotImplementedException();
}
}
}

View file

@ -2,6 +2,7 @@
using System.Linq;
using Indy.IL2CPU.Assembler;
using Indy.IL2CPU.Assembler.X86;
using Mono.Cecil;
using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {

View file

@ -11,7 +11,7 @@ namespace Indy.IL2CPU.IL.X86 {
: base(aInstruction, aMethodInfo) {
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
Pop("eax");
}
}
}

View file

@ -7,11 +7,27 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Stloc)]
public class Stloc: Op {
private int mOffset;
protected void SetLocalIndex(int aIndex, MethodInformation aMethodInfo) {
mOffset = aMethodInfo.Locals[aIndex].Offset + aMethodInfo.Locals[aIndex].Size + 4;
}
public Stloc(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
int xLocalIndex;
if (Int32.TryParse((aInstruction.Operand ?? "").ToString(), out xLocalIndex)) {
SetLocalIndex(xLocalIndex, aMethodInfo);
}
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
public int Offset {
get {
return mOffset;
}
}
public sealed override void Assemble() {
Pop("eax");
Move("[esp+" + mOffset + "]", "eax");
}
}
}

View file

@ -6,15 +6,10 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Stloc_0)]
public class Stloc_0: Op {
public class Stloc_0: Stloc {
public Stloc_0(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
}
public override void Assemble() {
Pop("eax");
Move("[esp+0]", "eax");
//Move("eax", "[esp + " + (aMethodInfo.Locals[aMethodInfo.Locals.Length - 1].Offset + aMethodInfo.Locals[aMethodInfo.Locals.Length - 1].Size + 4) + "]");
//Move("[esp + " + (aMethodInfo.Locals[0].Offset + 4) + "]", "eax");
base.SetLocalIndex(0, aMethodInfo);
}
}
}

View file

@ -6,12 +6,10 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Stloc_1)]
public class Stloc_1: Op {
public class Stloc_1: Stloc {
public Stloc_1(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
base.SetLocalIndex(1, aMethodInfo);
}
}
}

View file

@ -6,12 +6,10 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Stloc_2)]
public class Stloc_2: Op {
public class Stloc_2: Stloc {
public Stloc_2(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
base.SetLocalIndex(2, aMethodInfo);
}
}
}

View file

@ -6,12 +6,10 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Stloc_3)]
public class Stloc_3: Op {
public class Stloc_3: Stloc {
public Stloc_3(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
base.SetLocalIndex(3, aMethodInfo);
}
}
}

View file

@ -6,12 +6,9 @@ using CPU = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.IL.X86 {
[OpCode(Code.Stloc_S)]
public class Stloc_S: Op {
public class Stloc_S: Stloc {
public Stloc_S(Mono.Cecil.Cil.Instruction aInstruction, MethodInformation aMethodInfo)
: base(aInstruction, aMethodInfo) {
}
public override void Assemble() {
throw new NotImplementedException("This file has been autogenerated and not been changed afterwards!");
}
}
}

View file

@ -54,6 +54,7 @@
<Compile Include="OpCodeAttribute.cs" />
<Compile Include="OpCodeMap.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utilities.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Indy.IL2CPU.Assembler\Indy.IL2CPU.Assembler.csproj">

View file

@ -10,6 +10,7 @@ using Cil = Mono.Cecil.Cil;
namespace Indy.IL2CPU.IL {
public abstract class Op {
public delegate void QueueMethodHandler(string aAssembly, string aType, string aMethod);
public abstract void Assemble();
public Op(Instruction aInstruction, MethodInformation aMethodInfo) {

View file

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mono.Cecil;
namespace Indy.IL2CPU.IL {
public class Utilities {
public static string GetUniqueConstName(FieldDefinition aField) {
StringBuilder xSB = new StringBuilder();
xSB.Append("const ");
xSB.Append(aField.FieldType.FullName);
xSB.Append(" ");
xSB.Append(aField.Name);
return FixupIdentifierForAsm(xSB.ToString());
}
public static string FixupIdentifierForAsm(string aIdentifier) {
return aIdentifier.Replace('.', '_').Replace('+', '_').Replace('*', '_').Replace('[', '_').Replace(']', '_').Replace('&', '_');
}
}
}

View file

@ -11,6 +11,10 @@ using Mono.Cecil;
using Mono.Cecil.Cil;
using Instruction = Mono.Cecil.Cil.Instruction;
ERROR
We need a special local vars register in the assembly
namespace Indy.IL2CPU {
public class MethodDefinitionComparer: IComparer<MethodDefinition> {
#region IComparer<MethodDefinition> Members