예제 #1
0
        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;
        }
예제 #2
0
        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;
        }
예제 #3
0
        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);
        }