views:

225

answers:

4

Hi, I am trying to create a backend of my language for .NET platform. The front-end and interpreter written in Delphi. Unmanaged API just allows type definitions but no emiting of MSIL.

What ways exist to generate MSIL from unmanaged code? Without using Reflection.Emit and using ILasm to attain this? Thank you.

+3  A: 

From unmanaged code? TBH, the best suggestion I have is either "use P/Invoke", or "figure out what it is meant to do, and re-implement it".

Even if you can find something to port the unmanaged code, and even if it works - it isn't exactly going to leverage the framework. And it isn't exactly 1:1 between unmanaged and managed.

Marc Gravell
I need an API what allow me to emit MSIL directly(read from native Delphi) with out using unmanaged-managed marshaling(Pinvoke,reverse pinvoke, IJW, COM). Do you suggest me to generate PE Files assembles myself?
Sergey Antonov
+1  A: 

You're making it difficult. The Irony and Common Compiler Infrastructure libraries available at Codeplex.com are out, they are targeted to compilers implemented in managed code. The next option is using the unmanaged metadata interfaces, like IMetaDataAssemblyEmit, IMetaDataAssemblyImport, IMetaDataEmit2. These COM interfaces are however declared in the cor.h SDK header file, suitable only for consumption by a C/C++ program. There is no type library available for them. Short from painstakingly copying the interface declarations, you'd need some kind of tool to convert these to Delphi declarations. Not sure if that exists.

Hans Passant
I translated(cor.h corhdr.h) to pas files manually 2 days ago. So Unmanaged API is available to native side front end of my compiler. But API does not support for emiting MSIL for method implementation.
Sergey Antonov
ICeeGen is obsolete. I don't know of a replacement.
Hans Passant
+1  A: 

MSIL or CIL is essentially the .Net equivalent of machine code. When you parse a language and translate it into machine code, what you have is a compiler. Early compilers in any language will usually generate their machine code manually. That is, for each kind of command or expression in the source language, write a "template" of assembler instructions to translate it into. As you work through the intermediate representation of the program, select the corresponding template, fill in the program-specific details, and emit the CIL. For a stack-based language like CIL, it should be fairly easy to chain together the templates from multiple statements; the output stack of one statement is the input stack to the next.

You'll want to familiarize yourself with the CIL instruction set.

The fact that your compiler is unmanaged code doesn't matter. You can generate CIL text from whatever kind of program you want. When it's ready, send it through ilasm to create an assembly from it.

Rob Kennedy
Rob, I have read the ECMA335 as well as "Expert .NET 2.0" by Serge Lidin 3 years ago. (So ilAsm is just my an other friend). Rob, can you ask Barry Kelly or may be Remobjects guys how they solve this problem. Or may be they all use mixed mode C++.
Sergey Antonov
Prism compiler is built with Prism and is a 100% .NET application.
Robert Love
Thank you, Robert.
Sergey Antonov
+3  A: 

Delphi's .NET code generator emits IL as bytecode directly into memory, much like x86 code generation, though with appropriate headers etc. That is, the code generator directly emits bytes, exception tables etc., corresponding to the encoded IL format. It doesn't do this with an API, but rather the old-fashioned way: write the code a byte at a time.

Later, Delphi's built-in linker works with IMetaDataEmit etc. to generate metadata, and IMetaDataEmit::SetRVA to tell the metadata where the code is going to be located in the executable. The metadata is copied out with IMetaDataEmit::SaveToMemory and then copied out into the PE that the linker has been building up, with the CLR header correspondingly patched to point to the metadata start.

It's a lot of code, some of it fiddly, as it's much of it is threaded through Delphi's existing x86 linker, which does things like branch optimization and elimination of unused code (smart linking) which strictly speaking isn't generally necessary for .NET.

If we were to do it all again, we might very well avoid the .NET APIs for creating metadata, and generate the whole thing straight from the spec. The APIs ended up being a black box for optimization, and added up to a substantial amount of compilation time.

Barry Kelly
Thank you, Barry.
Sergey Antonov