December 31, 2004
It lives!
I finally got my C# to C++ translator doing something useful! It's still early days but I successfully translated a C# program into C++. The C# program was this:
I compiled this with the Microsoft C# compiler, which generated Program.exe and Program.pdb. My translator loaded these two files, extracted all the information (metadata, debug information and MSIL assembly code) and then output this:
It looks like I was right when I said it would not be comprehensible to humans! Anyway, I compiled this C++ function, which generated another executable. I ran that and got the expected output:
Notice all the "#line" directives. These allow me to debug the C# program using a C++ debugger. This is working pretty well. I can set breakpoints in the C# source file (rather than the translated C++ one) and single step through the C# code. I also use the same variable names in the translation so I can see their values in the debugger as I step through. It's just as good as using a C# debugger.
For fun I might try running it on a console. It would be cool to get a screenshot of CodeWarrior debugging a C# program running on a non-Microsoft platform :)
class Program
{
static void Main(string[] args)
{
for (int i = 0; i != 10; ++i)
{
Console.WriteLine("Hello world!");
}
}
}
I compiled this with the Microsoft C# compiler, which generated Program.exe and Program.pdb. My translator loaded these two files, extracted all the information (metadata, debug information and MSIL assembly code) and then output this:
void Main()
{
NativeInt si0;
void* sr0;
NativeInt si1;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L0: {
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
{
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
Int8 CS_36_4_36_0000;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
{
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
Int32 i;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
si0 = 0;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L1: i = si0;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L2: goto L20;
#line 17 "f:/permanent/dev/ilvisitor/test1/program.cs"
L4: sr0 = InternString("Hello world!");
#line 17 "f:/permanent/dev/ilvisitor/test1/program.cs"
L9: ::System::Console::WriteLine((::System::String*) sr0);
#line 17 "f:/permanent/dev/ilvisitor/test1/program.cs"
L14: void(0);
#line 18 "f:/permanent/dev/ilvisitor/test1/program.cs"
L15: void(0);
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L16: si0 = i;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L17: si1 = 1;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L18: si0 = si1 + si0;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L19: i = si0;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L20: si0 = i;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L21: si1 = 10;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L23: si0 = si1 == si0;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L25: si1 = 0;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L26: si0 = si1 == si0;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L28: CS_36_4_36_0000 = si0;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L29: si0 = CS_36_4_36_0000;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
L30: if (si0) goto L4;
#line 15 "f:/permanent/dev/ilvisitor/test1/program.cs"
}
#line 19 "f:/permanent/dev/ilvisitor/test1/program.cs"
L32: return;
#line 19 "f:/permanent/dev/ilvisitor/test1/program.cs"
}
#line 19 "f:/permanent/dev/ilvisitor/test1/program.cs"
}
}
It looks like I was right when I said it would not be comprehensible to humans! Anyway, I compiled this C++ function, which generated another executable. I ran that and got the expected output:
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!
Notice all the "#line" directives. These allow me to debug the C# program using a C++ debugger. This is working pretty well. I can set breakpoints in the C# source file (rather than the translated C++ one) and single step through the C# code. I also use the same variable names in the translation so I can see their values in the debugger as I step through. It's just as good as using a C# debugger.
For fun I might try running it on a console. It would be cool to get a screenshot of CodeWarrior debugging a C# program running on a non-Microsoft platform :)