Example #1
0
        public TraceMethod(MethodDefinition method, CustomAttribute a, bool isEmpty = true)
        {
            Method         = method;
            IsEmpty        = isEmpty;
            EventAttribute = a;
            if (a == null)
            {
                return;
            }

            Id       = (int)a.ConstructorArguments[0].Value;
            Level    = TraceMethod.GetProp <EventLevel, EventLevel?>(a, "Level", v => v);
            Keywords = TraceMethod.GetProp <EventKeywords, EventKeywords?>(a, "Keywords", v => v);
            Task     = TraceMethod.GetProp <EventTask, NamedConst <int> >(a, "Task", v => NamedConst.Existing(v.ToString(), (int)v));
            Opcode   = TraceMethod.GetProp <EventOpcode, NamedConst <int> >(a, "Opcode", v => NamedConst.Existing(v.ToString(), (int)v));

            if (Task != null)
            {
                log.Trace($"{method} {Task.Name}={Task.Value} - exists: {Task.Exists}");
            }
            if (Opcode != null)
            {
                log.Trace($"{method} {Opcode.Name}={Opcode.Value} - exists: {Opcode.Exists}");
            }
        }
Example #2
0
        protected void UpdateEventAttribute(MethodDefinition target, TraceMethod metadata)
        {
            var ea = metadata.EventAttribute;

            if (ea == null)
            {
                target.CustomAttributes.Add(ea = module.NewAttr(typeDefs.EventAttribute, metadata.Id));
            }
            else
            {
                ea = target.CustomAttributes.Named("EventAttribute");
            }

            if (metadata.Task != null)
            {
                if (!metadata.Task.Exists)
                {
                    AddConst <int>(ensureTasks.Value, module.ImportReference(typeDefs.EventTask), metadata.Task);
                }

                ea.SetPropertyValue("Task", typeDefs.EventTask, metadata.Task.Value);
            }

            if (metadata.Opcode != null)
            {
                if (!metadata.Opcode.Exists)
                {
                    AddConst <int>(ensureOpcodes.Value, module.ImportReference(typeDefs.EventOpcode), metadata.Opcode);
                }

                ea.SetPropertyValue("Opcode", typeDefs.EventOpcode, metadata.Opcode.Value);
            }
        }
Example #3
0
        protected virtual IEnumerable <TraceMethod> GetTraceMethods()
        {
            var maxId   = 0;
            var loggers = Type.Methods.Where(IsTraceMethod);
            var needsId = new List <TraceMethod>();
            var all     = new List <TraceMethod>();

            foreach (var logger in loggers)
            {
                var ea     = logger.CustomAttributes.Named("EventAttribute");
                var method = new TraceMethod(logger, ea, !logger.HasBody);

                if (ea == null)
                {
                    needsId.Add(method);
                }
                else if (method.Id > maxId)
                {
                    maxId = method.Id;
                }

                all.Add(method);
            }

            foreach (var method in needsId)
            {
                method.Id = ++maxId;
            }

            TryGenerateTasks(all);

            return(all);
        }
Example #4
0
            protected override MethodDefinition ImplementTraceMethod(TraceMethod metadata)
            {
                var source    = metadata.Method;
                var newMethod = new MethodDefinition(source.Name, MethodAttributes.Public, module.ImportReference(source.ReturnType));

                target.Methods.Add(newMethod);

                foreach (var p in source.Parameters)
                {
                    newMethod.Parameters.Add(new ParameterDefinition(p.Name, p.Attributes, module.ImportReference(p.ParameterType)));
                }

                source.CopyAttrsTo(newMethod);

                SetTraceMethodBody(newMethod, metadata, EmitGuardedTracers);
                UpdateEventAttribute(newMethod, metadata);

                return(newMethod);
            }
Example #5
0
        protected void SetTraceMethodBody(MethodDefinition target, TraceMethod metadata, bool implementGuard = true)
        {
            target.CustomAttributes.Add(module.NewAttr(typeof(CompilerGeneratedAttribute)));

            var body = target.Body.Instructions;

            body.Clear();

            using (var builder = new BodyBuilder(target))
            {
                var exit = builder.DefineLabel();
                if (implementGuard)
                {
                    body.Add(EmitIsEnabledFallback());
                    body.Add(Instruction.Create(OpCodes.Brfalse, exit));
                }

                body.Add(WriteEvent(builder, target, metadata).ToArray());

                body.Add(exit);
                body.Add(Instruction.Create(OpCodes.Ret));
            }
        }
        public IEnumerable <Instruction> Emit(BodyBuilder builder, MethodDefinition method, TraceMethod metadata)
        {
            log.Warn($"Using WriteEventCore fallback for {method}");

            var parameters = method.Parameters;
            var count      = parameters.Count;

            var data = builder.DeclareLocal(typeDefs.EventDataRef.MakePointerType());
            var item = builder.DeclareLocal(typeDefs.EventDataRef.MakePointerType());

            ////> EventData* data = stackalloc EventData[4];
            yield return(Instruction.Create(OpCodes.Ldc_I4, count));

            yield return(Instruction.Create(OpCodes.Conv_U));

            yield return(Instruction.Create(OpCodes.Sizeof, typeDefs.EventDataRef));

            yield return(Instruction.Create(OpCodes.Mul_Ovf_Un));

            yield return(Instruction.Create(OpCodes.Localloc));

            yield return(Instruction.Create(OpCodes.Stloc, data));

            ////> EventData* item = data
            yield return(Instruction.Create(OpCodes.Ldloc, data));

            yield return(Instruction.Create(OpCodes.Stloc, item));

            var first = true;

            foreach (var p in parameters)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    ////> item ++;
                    yield return(Instruction.Create(OpCodes.Ldloc, item));

                    yield return(Instruction.Create(OpCodes.Sizeof, typeDefs.EventDataRef));

                    yield return(Instruction.Create(OpCodes.Add));

                    yield return(Instruction.Create(OpCodes.Stloc, item));
                }

                ////> item->DataPointer = ...
                ////> item->Size = ...
                var emitter = emitters[ResolveFullName(p)];

                foreach (var i in emitter(builder, item, p))
                {
                    yield return(i);
                }
            }

            yield return(Instruction.Create(OpCodes.Ldarg_0));

            yield return(Instruction.Create(OpCodes.Ldc_I4, metadata.Id));

            yield return(Instruction.Create(OpCodes.Ldc_I4, count));

            yield return(Instruction.Create(OpCodes.Ldloc, data));

            yield return(Instruction.Create(OpCodes.Call, typeDefs.WriteEventCore));
        }
Example #7
0
 protected abstract MethodDefinition ImplementTraceMethod(TraceMethod metadata);
Example #8
0
        private IEnumerable <Instruction> EmitWriteEventFallback(MethodDefinition method, TraceMethod metadata)
        {
            log.Warn($"Using WriteEvent fallback for {method.FullName}");

            yield return(Instruction.Create(OpCodes.Ldarg_0));

            yield return(Instruction.Create(OpCodes.Ldc_I4, metadata.Id));

            var parameters = method.Parameters;
            var count      = parameters.Count;

            yield return(Instruction.Create(OpCodes.Ldc_I4, count));

            yield return(Instruction.Create(OpCodes.Newarr, module.TypeSystem.Object));

            for (var i = 0; i < count; i++)
            {
                yield return(Instruction.Create(OpCodes.Dup));

                yield return(Instruction.Create(OpCodes.Ldc_I4, i));

                yield return(Instruction.Create(OpCodes.Ldarg, parameters[i]));

                if (parameters[i].ParameterType.IsValueType)
                {
                    yield return(Instruction.Create(OpCodes.Box, parameters[i].ParameterType));
                }

                yield return(Instruction.Create(OpCodes.Stelem_Ref));
            }

            yield return(Instruction.Create(OpCodes.Call, typeDefs.WriteEventFallback));
        }
Example #9
0
        private IEnumerable <Instruction> EmitSpecificWriteEvent(BodyBuilder builder, MethodDefinition method, MethodReference writeEvent, TraceMethod metadata)
        {
            yield return(Instruction.Create(OpCodes.Ldarg_0));

            yield return(Instruction.Create(OpCodes.Ldc_I4, metadata.Id));

            foreach (var p in method.Parameters)
            {
                yield return(Instruction.Create(OpCodes.Ldarg, p));

                foreach (var i in EmitConvertCode(p.ParameterType.Resolve(), builder))
                {
                    yield return(i);
                }
            }

            yield return(Instruction.Create(OpCodes.Call, module.ImportReference(writeEvent)));
        }
Example #10
0
        private IEnumerable <Instruction> WriteEvent(BodyBuilder builder, MethodDefinition method, TraceMethod metadata)
        {
            var specificArgs = new[] { module.TypeSystem.Int32 }
            .Concat(method.Parameters
                    .Select(p => ConvertToWriteEventParamType(p.ParameterType.Resolve())));

            var specific = typeDefs.BaseTypeImpl.FindMethod("WriteEvent", specificArgs);

            return(specific != null
                                        ? EmitSpecificWriteEvent(builder, method, specific, metadata)
#if ENABLE_UNSAFE
                                        : unsafeWriteEventBuilder.CanDo(method)
                                                ? unsafeWriteEventBuilder.Emit(builder, method, metadata)
#endif
                                        : EmitWriteEventFallback(method, metadata));
        }