private Instruction InjectIlForCatch(ILProcessor processor, Instruction beforeReturn, ReferenceContainer references) { /* stloc.2 nop ldloc.2 call void [Yalf]Yalf.Log::TraceException(class [mscorlib]System.Exception) nop ldloc.0 ldloc.2 callvirt instance void [Yalf]Yalf.IContext::PreserveStackTrace(class [mscorlib]System.Exception) nop rethrow */ var exceptionVariable = new VariableDefinition(references.ExceptionType); body.Variables.Add(exceptionVariable); var beginCatch = beforeReturn.Prepend(processor.Create(OpCodes.Stloc, exceptionVariable), processor); beginCatch.Append( processor.Create(OpCodes.Nop), processor) .AppendLdloc(processor, exceptionVariable.Index) .Append(processor.Create(OpCodes.Call, references.TraceExceptionMethod), processor) .Append(processor.Create(OpCodes.Nop), processor) .AppendLdloc(processor, contextVar.Index) .AppendLdloc(processor, exceptionVariable.Index) .Append(processor.Create(OpCodes.Callvirt, references.PreserveStackTraceMethod), processor) .Append(processor.Create(OpCodes.Nop), processor) .Append(processor.Create(OpCodes.Rethrow), processor); return beginCatch; }
private Instruction InjectIlForFinaly(ILProcessor processor, Instruction beforeReturn, ReferenceContainer references) { // wrapped in nop (for try catch handling) // load context then call dispose /* nop ldloc.0 callvirt instance void [Yalf]Yalf.IContext::Dispose() nop endfinally */ var beginFinally = beforeReturn.Prepend(processor.Create(OpCodes.Nop), processor); beginFinally.AppendLdloc(processor, contextVar.Index) .Append(processor.Create(OpCodes.Callvirt, references.DisposeMethod), processor) .Append(processor.Create(OpCodes.Nop), processor) .Append(processor.Create(OpCodes.Endfinally), processor); return beginFinally; }
void InjectContext(ILProcessor processor, Instruction firstInstruction, MethodDefinition method, ReferenceContainer references) { /* nop ldstr "Namespace.Class.Method" ldc.i4.1 newarr object stloc.s CS$0$0001 ldloc.s CS$0$0001 ldc.i4.0 ldarg.1 box int32 stelem.ref ldloc.s CS$0$0001 call class [Yalf]Yalf.IContext [Yalf]Yalf.Log::MethodContext(string, object[]) stloc.0 */ contextVar = new VariableDefinition(references.IContextType); body.Variables.Insert(0, contextVar); int objectParamsArrayIndex = method.AddVariable<object[]>(); // Generate MethodContext calling method name var builder = new StringBuilder(); builder.Append(string.Join(".", method.DeclaringType.Namespace, FormatType(method.DeclaringType), FormatMethod(method))); var current = firstInstruction .Prepend(processor.Create(OpCodes.Ldstr, builder.ToString()), processor); // Create object[] for MethodContext current = current .AppendLdcI4(processor, method.Parameters.Count) .Append(processor.Create(OpCodes.Newarr, method.Module.ImportType<object>()), processor) .AppendStloc(processor, objectParamsArrayIndex); var nonStaticMethodAddOne = method.IsStatic ? 0 : 1; // Set object[] values for (int i = 0; i < method.Parameters.Count; i++) { current = current .AppendLdloc(processor, objectParamsArrayIndex) .AppendLdcI4(processor, i); var paramType = method.Parameters[i].ParameterType; if (paramType.MetadataType == MetadataType.UIntPtr || paramType.MetadataType == MetadataType.FunctionPointer || paramType.MetadataType == MetadataType.IntPtr || paramType.MetadataType == MetadataType.Pointer) { // don't store pointer types into object[] (we can't ToString them anyway) // store type name as string instead current = current.AppendLdstr(processor, paramType.FullName); } else { current = current .AppendLdarg(processor, i + nonStaticMethodAddOne) .AppendBoxAndResolveRefIfNecessary(processor, paramType); } current = current.Append(processor.Create(OpCodes.Stelem_Ref), processor); } // Call Log.MethodContext current .AppendLdloc(processor, objectParamsArrayIndex) .Append(processor.Create(OpCodes.Call, references.MethodContextMethod), processor) .AppendStloc(processor, contextVar.Index); }