IL2X experimental .NET Runtime


So I have been working on a experimental .NET runtime in my free time that compiles .NET IL to C89 and am getting faster performance results than .NET Native (which was a pleasant surprise). Its also even faster when compiling with the GCC or Clang on Windows.

Here is a IL2X WASM demo running a RayTraceBenchmark (Try it out!):

Now compare IL2X to Mono AOT:

Here are the benchmark results between different .NET Runtimes (IL2X beats them all):!29408&ithint=file%2Cxlsx&authkey=!AHCOVIoafw_umyA

Here are the compiled.exe files for VC++, GCC and Clang:!Alt5wRhQYKD7geViEuyq7JieoLDjVA

The IL2X project is on GitHub located here:

IL2X has comes with its own portable .NET Core based corelib that is/will be designed to run anywhere. The more features I add to the portable corelib the closer I get to translating the official .NET Standard libs. I still have missing instruction support and implementation details but its coming along well.

What IL2X does to get its performance is translate the evaluation stack into normal local stack variables that in tern the C compilers can optimize away. This results in a super fast, small and highly portable runtime. Also the code can be compiled on any CPU, ARM, MIPS, RISC-V etc.

I want to be clear the IL2X runtime isn’t ready for anybody to use and is still considered experimental and a work in progress.


Here is an example of the C# thats compiled to IL which in turn gets translated to C.

C# example

public static Vec3 Normal(Sphere sphere, Vec3 pos)
    return Vec3.Normalize(pos - sphere.Center);

IL translated to C89

t_TestAppPortabledll_RayTraceBenchmark_Vec3 m_1_TestAppPortabledll_RayTraceBenchmark_Sphere_Normal_1(t_TestAppPortabledll_RayTraceBenchmark_Sphere* p_sphere, t_TestAppPortabledll_RayTraceBenchmark_Vec3 p_pos)
	t_TestAppPortabledll_RayTraceBenchmark_Vec3 e_s0_t0;
	t_TestAppPortabledll_RayTraceBenchmark_Sphere* e_s1_t0;
	t_TestAppPortabledll_RayTraceBenchmark_Vec3 e_s1_t1;
	t_TestAppPortabledll_RayTraceBenchmark_Vec3 l_var_0;
	e_s0_t0 = p_pos;
	e_s1_t0 = p_sphere;
	e_s1_t1 = e_s1_t0->f_1_Center;
	e_s0_t0 = m_2_TestAppPortabledll_RayTraceBenchmark_Vec3_op_Subtraction_2(e_s0_t0, e_s1_t1);
	e_s0_t0 = m_2_TestAppPortabledll_RayTraceBenchmark_Vec3_Normalize_11(e_s0_t0);
	l_var_0 = e_s0_t0;
	goto IL_0015;
	e_s0_t0 = l_var_0;
	return e_s0_t0;

I’m actually really interested in this. I’ve been spending a lot of time porting things to the IBM i (or OS/400) ILE environment (as opposed to the Unix compatibility layer), and I will have a look at it later on today.

Porting things to ILE is usually a good measure of code quality/portability. The ILE is effectively a DeathStation 9000 where a lot of the undefined elements of the Cnn standards behave differently. Fir example, the native character code set is EBCDIC, so hacks as doing math with char constants to achieve e.g. to_lower() functionality will not work. The environment is also a 128bit address space, and (technically) there is no disk I/O (disk/file I/O are paging operations). In addition to that, it’s big endian and has very strict buffer and pointer restrictions since it had tagged/secure pointers for decades by now, which results in ‘dirty’ buffer ‘magic’ not working.

I can only poke around in it tonight when I get back from work, but I could get you access to a machine to potentially test things if you’re interested.

1 Like

so hacks as doing math with char constants to achieve e.g. to_lower() functionality will not work.

Well, they do work, it’s just that the characters have way different byte codes. And the “section” layouts are backwords from ASCII (EBCDIC does lower, upper, numbers).
And I never really looked at it before, but for some bizarre reason the case range is non contiguous.


I would be happy to test this on IBM i. Keep in mind IL2X is still in very early stages.

I can always just send you the portable C code you can try to compile on that system.

.NET Foundation Website | Blog | Projects | Code of Conduct