Hello i am generating a class using Reflection.Emit
and i want to know how do you use brfalse
command for conditionals
.
Specifically i do not know how do i translate the IL to OPCODES for the brfalse.s command.
My method has the following form:
object MyMethod()
{
if(isTransaction) //isTransaction is a bool property
return Method1();
else return Method2();
}
Conditional
IL_0000: ldarg.0 // this
IL_0001: call instance bool RediusTests.DaemonBase::get_IsTransaction()
IL_0006: brfalse.s IL_0020 //how is this translated within opcodes?
First branch:
IL_0008:ldarg_0
IL_....... ///INSTRUCTIONS
IL_......
IL_001f:ret
Second branch:
IL_0020:ldarg_0 //How do i specify with OPCODES to jump here?????
IL_.......
IL_......
IL_001f:ret
For the first snippet what would be the argument of brfalse.s
?
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, getIsTransaction);
ilgen.Emit(OpCodes.Brfalse,); //what do i put here in the overload?
As you can see in the last snippet ,last line ,what should i put in the overload of ilgen.Emit
? Nothing , 20 or is there some other code for translating to IL_0020
?
Also isn't the address of the instruction stored at different address of memory on every run of program?Couldn't it change from IL0020
to IL00xx
at future executions?
P.S After receiveing some comprehensive answers this is my version so far:
ILGenerator ilgen = newMethod.GetILGenerator();
Label falseLabel = ilgen.DefineLabel();
Label continueLabel = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, getIsTransaction);
ilgen.Emit(OpCodes.Brtrue,continueLabel); //branching
ilgen.MarkLabel(continueLabel); //true branch
----instructions------
ilgen.Emit(OpCodes.Ret);
ilgen.Emit(OpCodes.Br,continueLabel);
ilgen.MarkLabel(falseLabel); //false branch
--instructions----
ilgen.Emit(OpCodes.Ret);
You never have to deal with code addresses explicitly. In order to jump, you need to define labels:
Label falseLabel = ilgen.DefineLabel();
Label continueLabel = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Call, getIsTransaction);
ilgen.Emit(OpCodes.Brfalse, continueLabel);
// getIsTransaction returned true
...
ilgen.Emit(OpCodes.Br, continueLabel);
ilgen.MarkLabel(falseLabel);
// getIsTransaction returned false
...
ilgen.MarkLabel(continueLabel);