private IEnumerable <Instruction> StoreStringInEventData(BodyBuilder builder, VariableDefinition item, ParameterDefinition param) { var pinned = builder.DeclareLocal(module.TypeSystem.String.MakePinnedType()); var pointer = builder.DeclareLocal(module.TypeSystem.Char.MakePointerType()); yield return(Instruction.Create(OpCodes.Ldarg, param)); yield return(Instruction.Create(OpCodes.Stloc, pinned)); yield return(Instruction.Create(OpCodes.Ldloc, pinned)); yield return(Instruction.Create(OpCodes.Conv_I)); yield return(Instruction.Create(OpCodes.Stloc, pointer)); var isnull = builder.DefineLabel(); yield return(Instruction.Create(OpCodes.Ldloc, pointer)); yield return(Instruction.Create(OpCodes.Brfalse, isnull)); yield return(Instruction.Create(OpCodes.Ldloc, pointer)); yield return(Instruction.Create(OpCodes.Call, module.ImportReference(RuntimeHelpers_OffsetToStringData_Get))); yield return(Instruction.Create(OpCodes.Add)); yield return(Instruction.Create(OpCodes.Stloc, pointer)); yield return(isnull); yield return(Instruction.Create(OpCodes.Ldloc, item)); yield return(Instruction.Create(OpCodes.Ldloc, pointer)); yield return(Instruction.Create(OpCodes.Call, module.ImportReference(IntPtr_Op_Explicit))); yield return(Instruction.Create(OpCodes.Call, typeDefs.EventDataSetDataPointer)); yield return(Instruction.Create(OpCodes.Ldnull)); yield return(Instruction.Create(OpCodes.Stloc, pinned)); // data[].Size = (SringArg.Length + 1) * 2 yield return(Instruction.Create(OpCodes.Ldloc, item)); yield return(Instruction.Create(OpCodes.Ldarg, param)); yield return(Instruction.Create(OpCodes.Callvirt, module.ImportReference(String_Length_Get))); yield return(Instruction.Create(OpCodes.Ldc_I4_1)); yield return(Instruction.Create(OpCodes.Add)); yield return(Instruction.Create(OpCodes.Ldc_I4_2)); yield return(Instruction.Create(OpCodes.Mul)); yield return(Instruction.Create(OpCodes.Call, typeDefs.EventDataSetSize)); }
private IEnumerable <Instruction> StoreBoolInEventData(BodyBuilder builder, VariableDefinition item, ParameterDefinition param) { var temp = builder.DeclareLocal(module.TypeSystem.Int32, reusable: true); var @true = builder.DefineLabel(); var @next = builder.DefineLabel(); // var temp = param ? 1 : 0; yield return(Instruction.Create(OpCodes.Ldarg, param)); yield return(Instruction.Create(OpCodes.Brtrue, @true)); yield return(Instruction.Create(OpCodes.Ldc_I4_0)); yield return(Instruction.Create(OpCodes.Br, @next)); yield return(@true); yield return(Instruction.Create(OpCodes.Ldc_I4_1)); yield return(@next); yield return(Instruction.Create(OpCodes.Stloc, temp)); ////> item->Data = &temp; yield return(Instruction.Create(OpCodes.Ldloc, item)); yield return(Instruction.Create(OpCodes.Ldloca, temp)); yield return(Instruction.Create(OpCodes.Conv_U)); yield return(Instruction.Create(OpCodes.Call, module.ImportReference(IntPtr_Op_Explicit))); yield return(Instruction.Create(OpCodes.Call, typeDefs.EventDataSetDataPointer)); ////> item->Size = 4; yield return(Instruction.Create(OpCodes.Ldloc, item)); yield return(Instruction.Create(OpCodes.Ldc_I4_4)); yield return(Instruction.Create(OpCodes.Call, typeDefs.EventDataSetSize)); }
private IEnumerable <Instruction> EmitBoolConvertCode(BodyBuilder builder) { var @true = Instruction.Create(OpCodes.Ldc_I4, 1); var endOfBlock = builder.DefineLabel(); yield return(Instruction.Create(OpCodes.Brtrue, @true)); yield return(Instruction.Create(OpCodes.Ldc_I4, 0)); yield return(Instruction.Create(OpCodes.Br, endOfBlock)); yield return(@true); yield return(endOfBlock); }
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 override MethodDefinition BeforeMethod(MethodDefinition method) { if (!method.HasBody) { return(method); } TryDeclareExceptionsForLoggers(method); var calls = callCollector.Collect(method, logDefinitionFactory.IsLogger); if (calls.Length == 0) { return(method); } var collapsed = calls.SplitToSequences(new SameMethodComparer()).ToList(); if (collapsed.Count == 0) { return(method); } log.Info($"Rewriting {method.FullName}"); using (var builder = new BodyBuilder(method)) { foreach (var callGroup in collapsed) { var theCall = callGroup.First(); if (!logDefinitionFactory.TryGet(theCall.Call.TargetMethod().DeclaringType.Resolve(), out var info)) { throw new InvalidOperationException("Log info should have been cached"); } var start = theCall.StartsAt; // where the arguments start var label = builder.DefineLabel(); // jump target var end = callGroup.Last().Call; // the last call/callvirt in the sequence var field = info.DeclareLoggerIn(method.DeclaringType); // the static field containing the logger instance var guard = info.TryFindGuard(end); // the IsXXXEnabled method (optional) if (guard == null) { log.Warn($"There is no IsXXXEnabled defined for {end.TargetMethod()}, no check will be emitted"); } else { builder.InsertBefore(start, Instruction.Create(OpCodes.Ldsfld, field)); builder.InsertBefore(start, Instruction.Create(OpCodes.Callvirt, guard)); builder.InsertBefore(start, Instruction.Create(OpCodes.Brfalse, label)); } var logMethod = info.MapToILog(end); foreach (var call in callGroup) { builder.InsertBefore(call.StartsAt, Instruction.Create(OpCodes.Ldsfld, field)); call.Call.OpCode = OpCodes.Callvirt; call.Call.Operand = logMethod; } if (guard != null) { builder.InsertAfter(end, label); } } } return(method); }