Skip to content

Instantly share code, notes, and snippets.

View sgaliamov's full-sized avatar
:octocat:

Salavat Galiamov sgaliamov

:octocat:
  • The Netherlands
View GitHub Profile
Int32 Foo(Int32)
1: .ldarg.0 | 1 # we can see resulting the stack size
2: .ldc.i4.2 | 2
4: .ceq | 1
9: .brfalse Label_0 | 0 # we can see where the branching instruction is pointing
10: .ldc.i4.1 | 1
15: .br Label_1 | 0
Label_0: # named label
16: .ldarg.0 | 1
17: .ldc.i4.3 | 2
using static CustomExtensions.Functions;
...
var foo = new DynamicMethod("Foo", typeof(int), new[] { typeof(int) })
.GetILGenerator()
.UseIlluminator(
enableTraceLogger: true, // enable tracing (optional)
Ret(If(Ceq(Ldarg_0(), Ldc_I4_2()), // condition
Ldc_I4_1(), // then
Add(Ldarg_0(), Ldc_I4_3())))) // else
.CreateDelegate<Func<int, int>>();
if (condition()) {
then();
} else {
otherwise();
}
namespace CustomExtensions
{
public static class Functions
{
public static ILEmitterFunc If(
ILEmitterFunc condition,
ILEmitterFunc then,
ILEmitterFunc @else) => (in ILEmitter il) =>
il.Brfalse(condition, out var otherwise)
.Emit(then)
public static ILEmitter Beq_S(
this ILEmitter self,
in ILEmitterFunc func1,
in ILEmitterFunc func2,
in Label label) {
func1(self);
func2(self);
return self.Beq_S(label);
}
...
public ILEmitter Beq_S(in Label label) {
ValidateJump(label); // can validate that short version of a jump instruction is used correctly.
_il.Emit(OpCodes.Beq_S, label); // pass the right parameter that the instruction needs.
_logger?.Log(OpCodes.Beq_S, label); // embed the logger into each method.
return this;
}
public static ILEmitter Add(this ILEmitter self, in ILEmitterFunc func1, in ILEmitterFunc func2) {
func1(self);
func2(self);
return self.Add(); // and this finally does the real generator.Emit(OpCodes.Add);
}
public delegate ILEmitter ILEmitterFunc(in ILEmitter emitter);
...
public static ILEmitterFunc Add(ILEmitterFunc func1, ILEmitterFunc func2) =>
(in ILEmitter il) => il.Add(func1, func2);
using static Illuminator.Functions;
...
il.Brfalse_S(Ceq(Ldarg_0(), Ldc_I4_2()), out var label) // if (value == 2) {
.Ret(Ldc_I4_1()) // return 1;
.MarkLabel(label) // }
.Ret(Add(Ldarg_0(), Ldc_I4_3())); // return value + 3;
var method = new DynamicMethod("Foo", typeof(int), new[] { typeof(int) });
var generator = method.GetILGenerator();
var label = generator.DefineLabel();
var il = generator.UseIlluminator(); // Creates wrapper
il.Ldarg_0()
.Ldc_I4_2()
.Ceq()
.Brfalse_S(label) // if (value == 2)
.Ldc_I4_1()
.Ret() // return 1