Reputation: 181044
I'm currently diving into the inner workings of .net, which means IL. As an exercise, I want to build a brainf..k compiler for .net (yes, they already exist, but as said it's for learning purposes).
For the moment I'm just writing some text files that contain .il and compile them with ilasm, which works. But I wonder if I could/should go one level deeper and write bytecode directly?
My "concern" is the Windows PE Stuff when compiling an EXE - instead of ilasm I would need some sort of Bytecode linker that would take my MSIL/CIL bytecode and generate the PE Stuff for it?
Or do compilers "only" compile their language to IL and execute ilasm? Is there a managed version of it that I can call/embed from my compiler?
Upvotes: 31
Views: 6175
Reputation: 391594
Why not simply use the Reflection.Emit api to produce a in-memory assembly with the compiled code and then save it to disk? Should be a lot easier than writing out .IL files.
Links:
If you want to go down this road, if you ask more specific questions here on SO you'll get plenty of example of how to define a dynamic assembly and save it to disk.
Here's an example:
using System;
using System.Reflection.Emit;
using System.Reflection;
namespace SO2598958
{
class Program
{
static void Main()
{
AssemblyBuilder asm = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("TestOutput"),
AssemblyBuilderAccess.RunAndSave);
ModuleBuilder mod = asm.DefineDynamicModule("TestOutput.exe",
"TestOutput.exe");
TypeBuilder type = mod.DefineType("Program", TypeAttributes.Class);
MethodBuilder main = type.DefineMethod("Main",
MethodAttributes.Public | MethodAttributes.Static);
ILGenerator il = main.GetILGenerator();
il.Emit(OpCodes.Ldstr, "Hello world!");
il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine",
BindingFlags.Public | BindingFlags.Static,
null, new Type[] { typeof(String) }, null));
il.Emit(OpCodes.Ret);
type.CreateType();
asm.SetEntryPoint(main);
asm.Save("TestOutput.exe");
}
}
}
You can download the test solution file from here. Direct link to zip file with solution here.
If you first compile and run this program, it'll produce a new exe file on disk, called TestOutput, which you can then execute in order to have "Hello World!" printed on the console.
Upvotes: 29
Reputation: 41
you can look a .net compiler very simple there :
http://msdn.microsoft.com/en-us/magazine/cc136756.aspx
Upvotes: 1
Reputation: 41
You can look there: http://msdn.microsoft.com/es-es/library/system.reflection.emit.aspx
Upvotes: 0
Reputation: 3800
Reflection.Emit is going to be more straight forward for your purposes, but you may want to look at the Common Compiler Infrastructure project on CodePlex too.
Here is the summary from the project page for that project:
Microsoft Research Common Compiler Infrastructure (CCI) is a set of libraries and an application programming interface (API) that supports some of the functionality that is common to compilers and related programming tools.
The CCI Metadata API allows applications to efficiently analyze or modify .NET assemblies, modules, and debugging (PDB) files. CCI Metadata supports the functionality of the .NET System.Reflection and System.Reflection.Emit APIs, but with much better performance. It also provides additional functionality that is not available in either .NET API.
That project has a PeWriter/PeReader among all the other things you would need to write a .net compiler (ILGenerator, Metadata helpers, etc.).
Upvotes: 2
Reputation: 5123
If i understood your question correctly, you will at the very least violate portability, by implementing jitting directly. Leave this stuff to .NET, Mono, Whatever teams. So i think you shouldn't. But about a 'could' part of your question - i think you can skip IL, and compile into whatever you want (as far as i know, MonoTouch, MonoDroid, etc do that): From Wikipedia
Unlike Mono applications MonoTouch "Apps" are compiled down to machine code targeted specifically at the Apple iPhone.
Upvotes: -3
Reputation: 186068
System.Reflection.Emit
provides facilities to create IL code in a statically-typed way without having to generate and compile text files with IL.
Upvotes: 3