2010-04-08 12 views
25

Actualmente estoy inmerso en el funcionamiento interno de .net, lo que significa IL. Como ejercicio, quiero construir un compilador de brainf..k para .net (sí, ya existen, pero como he dicho es para fines de aprendizaje).¿Escribiendo un compilador para .net - IL o Bytecode?

Por el momento estoy escribiendo algunos archivos de texto que contienen .il y compilarlos con ilasm, que funciona. Pero me pregunto si podría/debería ir un nivel más profundo y escribir bytecode directamente?

Mi "preocupación" es la materia de Windows PE al compilar un EXE - en lugar de ilasm ¿Necesitaría algún tipo de enlazador Bytecode que tomaría mi bytecode MSIL/CIL y generaría las cosas PE para él?

¿O los compiladores "solo" compilan su lengua a IL y ejecutan ilasm? ¿Existe una versión administrada de la que pueda llamar/incrustar desde mi compilador?

+0

Tenga en cuenta que realmente no necesita para generar cualquier código nativo real, si se imprime PE: tendrá que generar encabezados PE según lo definido por la especificación de la CLI, y esos incluyen algunos bits ejecutables nativos, pero están completamente predefinidos, es solo un stub que llama a _CorExeMain, por lo que puede generarlo una vez y tratarlo como opaco secuencia de bytes en su compilador. –

Respuesta

27

¿Por qué no utilizar simplemente la api Reflection.Emit para producir un ensamblaje en memoria con el código compilado y luego guardarlo en el disco? Debería ser mucho más fácil que escribir archivos .IL.

Enlaces:

Si quieres ir por este camino, si preguntas más específicas aquí en SO obtendrá un montón de ejemplo de cómo para definir un ensamblaje dinámico y guardarlo en el disco.

He aquí un ejemplo:

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. Enlace directo al archivo comprimido con la solución here.

Si primero compila y ejecuta este programa, producirá un nuevo archivo exe en el disco, llamado TestOutput, que luego puede ejecutar para tener "Hello World!" impreso en la consola.

+0

Se olvidó por completo de Reflection.Emit. Si entiendo esto correctamente, ¿puedo escribir el compilador completo usándolo y AssemblyBuilder? –

+0

Creo que así fue como se realizaron las implementaciones iniciales de IronPython. –

+0

Ver mi código de ejemplo agregado que produce un nuevo ejecutable. –

0

Con el nuevo DLR uno debería ser capaz de hacer la creación de código usando clases .Net. No estoy seguro de cuánto te protege del actual IL/bytecode ya que esto es lo que estás tratando de aprender.

3

System.Reflection.Emit proporciona facilidades para crear código IL de forma estática, sin tener que generar y compilar archivos de texto con IL.

-3

Si entendí su pregunta correctamente, al menos violará la portabilidad, implementando jits directamente. Deje esto en .NET, Mono, lo que sea equipos. Entonces creo que no deberías. Sino de una parte 'podría' de su pregunta - creo que se puede omitir IL, y compilar en lo que quiera (por lo que sé, MonoTouch, MonoDroid, etc hacer eso): De Wikipedia

diferencia Mono aplicaciones MonoTouch "Aplicaciones" se compilan en código de máquina dirigido específicamente al iPhone de Apple.

+0

No, no quiero escribir mi propio .NET Runtime (aún :), solo un código fuente -> .net compiler. –

2

Reflection.Emit va a ser más recta hacia adelante para sus propósitos, pero puede que desee ver en el proyecto Common Compiler Infrastructure en CodePlex también.

Aquí está el resumen de la página del proyecto para ese proyecto:

Microsoft Research Compilador Común Infraestructura (CCI) es un conjunto de bibliotecas y una interfaz de programación de aplicaciones (API) que soporta algunas de la funcionalidad que es común a los compiladores y herramientas de programación relacionadas.

El API CCI metadatos permite aplicaciones para analizar de manera eficiente o modifican ensamblados .NET, módulos y archivos de depuración (PDB). Metadatos de CCI admite la funcionalidad de .NET System.Reflection y System.Reflection.Emit API, pero con mucho mejor rendimiento. También proporciona una funcionalidad adicional que no está disponible en API .NET.

Ese proyecto tiene un PeWriter/PeReader entre todas las otras cosas que se necesitan para escribir un compilador .NET (ayudantes ILGenerator, metadatos, etc.).

Cuestiones relacionadas