Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing a Compiler for .net - IL or Bytecode?

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?

like image 346
Michael Stum Avatar asked Apr 08 '10 10:04

Michael Stum


People also ask

Does .NET use byte code?

NET) are not a bytecode feature, the compiler generates an additional argument to the inner class's constructor and passes the outer object.

Does .NET have a compiler?

NET uses two compilers, Roslyn, to compile C# or VB code into CIL (common intermediate language), and RyuJIT, to run just-in-time compilation of CIL into native code. Both compilers are highly regarded by the . NET community as Microsoft actively improves them.

What is the benefit of compiling into IL code?

In addition to SLaks's answer, compiling to IL enables a degree of cross-language interoperability that generally doesn't exist in interpreted languages. This advantage can be huge for new languages.

Is CLR compiler or interpreter?

The CLR uses JIT compilers to compile the IL code into native code. In Java the byte code is interpreted by a Virtual Machine (JVM). This interpretation caused Java applications to run extremely slow.


2 Answers

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.

like image 84
Lasse V. Karlsen Avatar answered Sep 29 '22 02:09

Lasse V. Karlsen


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

like image 44
Marcelo Cantos Avatar answered Sep 29 '22 02:09

Marcelo Cantos