编写.net的编译器 - IL或字节码?

时间:2010-04-08 10:05:56

标签: .net compiler-construction cil

我目前正在深入研究.net的内部运作,这意味着IL。作为练习,我想为.net构建一个brainf..k编译器(是的,它们已经存在,但正如所说的那样是为了学习目的)。

目前我只是编写一些包含.il的文本文件,并使用ilasm编译它们,这有效。但我想知道我是否可以/应该更深入一级并直接写字节码?

我的“关注点”是编译EXE时的Windows PE Stuff - 而不是ilasm我需要某种Bytecode链接器来获取我的MSIL / CIL字节码并为它生成PE Stuff?

或者编译器“只”将他们的语言编译成IL并执行ilasm?是否有我可以从编译器中调用/嵌入的托管版本?

7 个答案:

答案 0 :(得分:27)

为什么不简单地使用Reflection.Emit api生成带有编译代码的内存中程序集,然后将其保存到磁盘?应该比写出.IL文件容易得多。

链接:

如果您想走这条路,如果您在SO上提出更具体的问题,您将获得有关如何定义动态程序集并将其保存到磁盘的大量示例。

以下是一个例子:

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。使用解决方案here直接链接到zip文件。

如果您首先编译并运行此程序,它将在磁盘上生成一个名为TestOutput的新exe文件,然后您可以执行该文件以获得“Hello World!”打印在控制台上。

答案 1 :(得分:3)

System.Reflection.Emit提供了以静态类型方式创建IL代码的工具,而无需使用IL生成和编译文本文件。

答案 2 :(得分:2)

Reflection.Emit会更直接地用于您的目的,但您也可以查看CodePlex上的Common Compiler Infrastructure项目。

以下是该项目项目页面的摘要:

  

Microsoft Research Common Compiler   基础设施(CCI)是一套   库和应用程序   编程接口(API)   支持一些功能   这对编译器来说很常见   相关的编程工具。

     

CCI元数据API允许   应用程序有效分析或   修改.NET程序集,模块和   调试(PDB)文件。 CCI元数据   支持.NET的功能   System.Reflection和   System.Reflection.Emit API,但有   更好的表现。它也是   提供其他功能   在.NET API中不可用。

该项目在编写.net编译器(ILGenerator,元数据帮助程序等)所需的所有其他内容中都有PeWriter / PeReader。

答案 3 :(得分:0)

使用新的DLR,应该能够使用.Net类创建代码。我不确定它对你实际的IL /字节码有多大的保护,因为这是你想要学习的东西。

答案 4 :(得分:0)

答案 5 :(得分:0)

你可以在那里看一个非常简单的.net编译器:

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

答案 6 :(得分:-3)

如果我理解你的问题,你至少会违反可移植性,直接实施jitting。把这些东西留给.NET,Mono,无论哪支球队。所以我认为你不应该。但关于你的问题的“可能”部分 - 我认为你可以跳过IL,并编译成你想要的任何东西(据我所知,MonoTouch,MonoDroid等)这样做: 来自维基百科

  

与Mono应用程序不同,MonoTouch“Apps”被编译为专门针对Apple iPhone的机器代码。