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 ILas开发者_Go百科m to attain this? Thank you.
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.
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.
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.
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.
精彩评论