/// stloc V_1(dynamic.isevent (target)) /// if (logic.not(ldloc V_1)) Block IL_004a { /// stloc V_2(dynamic.getmember B(target)) /// } /// if (logic.not(ldloc V_1)) Block IL_0149 { /// dynamic.setmember.compound B(target, dynamic.binary.operator AddAssign(ldloc V_2, value)) /// } else Block IL_0151 { /// dynamic.invokemember.invokespecial.discard add_B(target, value) /// } /// => /// if (logic.not(dynamic.isevent (target))) Block IL_0149 { /// dynamic.setmember.compound B(target, dynamic.binary.operator AddAssign(dynamic.getmember B(target), value)) /// } else Block IL_0151 { /// dynamic.invokemember.invokespecial.discard add_B(target, value) /// } public void Run(Block block, int pos, StatementTransformContext context) { if (!(pos + 3 < block.Instructions.Count && block.Instructions[pos].MatchStLoc(out var flagVar, out var inst) && inst is DynamicIsEventInstruction isEvent)) { return; } if (!(flagVar.IsSingleDefinition && flagVar.LoadCount == 2)) { return; } if (!(MatchLhsCacheIfInstruction(block.Instructions[pos + 1], flagVar, out var dynamicGetMemberStore))) { return; } if (!(dynamicGetMemberStore.MatchStLoc(out var getMemberVar, out inst) && inst is DynamicGetMemberInstruction getMemberInst)) { return; } foreach (var descendant in block.Instructions[pos + 2].Descendants) { if (!MatchIsEventAssignmentIfInstruction(descendant, isEvent, flagVar, getMemberVar, out var setMemberInst, out var getMemberVarUse, out var isEventConditionUse)) { continue; } context.Step("DynamicIsEventAssignmentTransform", block.Instructions[pos]); // Collapse duplicate condition getMemberVarUse.ReplaceWith(getMemberInst); isEventConditionUse.ReplaceWith(isEvent); block.Instructions.RemoveRange(pos, 2); // Reuse ExpressionTransforms ExpressionTransforms.TransformDynamicSetMemberInstruction(setMemberInst, context); context.RequestRerun(); break; } }
public void Run(ILFunction function, ILTransformContext context) { if (!(function.Body is BlockContainer container && container.Blocks.Count == 1)) { return; } var combinedExit = CombineExits(container.EntryPoint); if (combinedExit == null) { return; } ExpressionTransforms.RunOnSingleStatement(combinedExit, context); }