Probably pointless, but could useful depending on the individual who is interested in IL programming and this snippet is about 140 lines of code. I created it on a whim.
The purpose of this snippet is basically to emit Brainf*ck programming language into IL during runtime in C#:
using System;
using System.Collections.Generic;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.IO;
namespace BFJIT
{
public unsafe class BFJIT
{
public static void ZeroOutMemory(byte* ptr, int size)
{
for (int I = 0; I < size; I++)
ptr[I] = 0;
}
public delegate IntPtr BrainFkCompile();
public BrainFkCompile Compile(string code)
{
var WhileBeginMarkStack = new Stack<Label>();
var WhileEndMarkStack = new Stack<Label>();
var reader = new StringReader(code);
var method = new DynamicMethod($"BrainFk{Guid.NewGuid().ToString().Replace("-", "_")}", typeof(IntPtr), null);
var il = method.GetILGenerator();
// Set the locals
il.DeclareLocal(typeof(byte*));
il.DeclareLocal(typeof(IntPtr));
// Allocate pointer
il.Emit(OpCodes.Ldc_I4, 1048576); // 1 MB Memory
il.EmitCall(OpCodes.Call, typeof(Marshal).GetMethod("AllocHGlobal", new Type[] { typeof(int) }), null);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldloca_S, 1);
il.EmitCall(OpCodes.Call, typeof(IntPtr).GetMethod("ToPointer"), null);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldc_I4, 1048576); // 1 MB Memory
il.EmitCall(OpCodes.Call, typeof(BFJIT).GetMethod("ZeroOutMemory"), null);
int currentCharacter = -1;
do
{
currentCharacter = reader.Read();
switch ((char)currentCharacter)
{
case '>':
{
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Stloc_0);
break;
}
case '<':
{
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Stloc_0);
break;
}
case '+':
{
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldind_U1);
int increment = 1;
while (reader.Peek() == '+')
{
++increment;
reader.Read();
}
il.Emit(OpCodes.Ldc_I4, increment);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Conv_U1);
il.Emit(OpCodes.Stind_I1);
break;
}
case '-':
{
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldind_U1);
int decrement = 1;
while (reader.Peek() == '-')
{
++decrement;
reader.Read();
}
il.Emit(OpCodes.Ldc_I4, decrement);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Conv_U1);
il.Emit(OpCodes.Stind_I1);
break;
}
case '.':
{
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldind_U1);
il.EmitCall(OpCodes.Call, typeof(Console).GetMethod("Write", new[] { typeof(byte) }), null);
break;
}
case '[':
{
Label begin = il.DefineLabel();
Label end = il.DefineLabel();
il.Emit(OpCodes.Br, end);
il.MarkLabel(begin);
WhileBeginMarkStack.Push(begin);
WhileEndMarkStack.Push(end);
break;
}
case ']':
{
il.MarkLabel(WhileEndMarkStack.Pop());
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldind_U1);
il.Emit(OpCodes.Brtrue, WhileBeginMarkStack.Pop());
break;
}
default:
continue;
}
} while (currentCharacter > -1);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ret);
return (BrainFkCompile)method.CreateDelegate(typeof(BrainFkCompile));
}
static unsafe void Main(string[] args)
{
var jitter = new BFJIT();
var func = jitter.Compile("++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.");
Console.WriteLine("Brainfk Compiled");
var ptr = func();
Console.WriteLine();
Console.WriteLine("Program Terminated.");
Marshal.FreeHGlobal(ptr);
Console.ReadLine();
}
}
}