Написание компилятора для .net - IL или байт-код? - PullRequest
27 голосов
/ 08 апреля 2010

В настоящее время я погружаюсь во внутреннюю работу .net, что означает IL. В качестве упражнения я хочу создать компилятор brainf..k для .net (да, они уже существуют, но, как уже говорилось, для целей обучения).

На данный момент я просто пишу несколько текстовых файлов, которые содержат .il, и компилирую их с помощью ilasm, который работает. Но мне интересно, смогу ли я / должен пойти на один уровень глубже и написать байт-код напрямую?

Моя "проблема" заключается в Windows PE Stuff при компиляции EXE - вместо ilasm мне понадобится какой-нибудь компоновщик байт-кода, который будет принимать мой байт-код MSIL / CIL и генерировать PE Stuff для него?

Или компиляторы "только" компилируют свой язык в IL и выполняют ilasm? Есть ли управляемая версия, которую я могу вызывать / вставлять из моего компилятора?

Ответы [ 7 ]

27 голосов
/ 08 апреля 2010

Почему бы просто не использовать API Reflection.Emit , чтобы создать сборку в памяти с откомпилированным кодом и затем сохранить ее на диск? Должно быть намного проще, чем писать файлы .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");
        }
    }
}

Файл с тестовым решением можно скачать здесь . Прямая ссылка на zip-файл с решением здесь .

Если вы сначала скомпилируете и запустите эту программу, она создаст новый exe-файл на диске с именем TestOutput, который вы затем сможете выполнить, чтобы получить «Hello World!» напечатано на консоли.

3 голосов
/ 08 апреля 2010

System.Reflection.Emit предоставляет средства для создания кода IL статически типизированным способом без необходимости создавать и компилировать текстовые файлы с помощью IL.

2 голосов
/ 08 апреля 2010

Reflection.Emit будет более прямолинейным для ваших целей, но вы можете посмотреть на проект Common Compiler Infrastructure на CodePlex.

Вот сводка со страницы проекта для этого проекта:

Общая исследовательская инфраструктура (CCI) Microsoft Research - это набор библиотек и интерфейс прикладного программирования (API), который поддерживаетнекоторые функции, общие для компиляторов и связанных с ними инструментов программирования.

API-интерфейс метаданных CCI позволяет приложениям эффективно анализировать или изменять файлы сборок, модулей и отладочных файлов (PDB) .NET.Метаданные CCI поддерживают функциональность API-интерфейсов .NET System.Reflection и System.Reflection.Emit, но имеют гораздо лучшую производительность.Он также предоставляет дополнительные функциональные возможности, которые недоступны ни в .NET API.

В этом проекте есть PeWriter / PeReader среди всех других вещей, которые вам понадобятся для написания компилятора .net (ILGenerator, помощники метаданныхи т. д.).

0 голосов
/ 15 мая 2010

компилятор .net можно посмотреть очень просто:

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

0 голосов
/ 15 мая 2010

Вы можете посмотреть там: http://msdn.microsoft.com/es-es/library/system.reflection.emit.aspx

0 голосов
/ 08 апреля 2010

Если я правильно понял ваш вопрос, вы по крайней мере нарушите переносимость, осуществив джиттинг напрямую.Оставьте все это для .NET, Mono, для любых команд.Так что я думаю, что вы не должны.Но о «возможной» части вашего вопроса - я думаю, что вы можете пропустить IL и скомпилировать что угодно (насколько я знаю, MonoTouch, MonoDroid и т. Д.): Из Википедии

В отличие от приложений Mono «Приложения» MonoTouch компилируются в машинный код, предназначенный специально для Apple iPhone.

0 голосов
/ 08 апреля 2010

С новым DLR можно создавать код с использованием классов .Net. Я не уверен, насколько это защищает вас от фактического IL / байт-кода, так как это то, что вы пытаетесь изучить.

...