开发者

Writing a Compiler for .net - IL or Bytecode?

I'm currently diving into the inner workings of .net, which means I开发者_运维知识库L. 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?


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:

  • Using Reflection.Emit
  • ILGenerator.Emit Method

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.


System.Reflection.Emit provides facilities to create IL code in a statically-typed way without having to generate and compile text files with IL.


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.).


you can look a .net compiler very simple there :

http://msdn.microsoft.com/en-us/magazine/cc136756.aspx


With the new DLR one should be able to do code creation using .Net classes. I'm not sure how much it shields you from the actual IL/bytecode since this is what you are trying to learn.


You can look there: http://msdn.microsoft.com/es-es/library/system.reflection.emit.aspx


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜