Пример #1
0
        /// <summary>
        /// Formats the tree to look nicely.
        /// </summary>
        public static void PositionNodesNicely(BonsaiNode root, Vector2 anchor)
        {
            // Sort parent-child connections so formatter uses latest changes.
            foreach (BonsaiNode node in TreeTraversal.PreOrder(root))
            {
                node.SortChildren();
            }

            var positioning = new FormatPositioning();

            foreach (BonsaiNode node in TreeTraversal.PostOrder(root))
            {
                PositionHorizontal(node, positioning);
            }

            foreach (BonsaiNode node in TreeTraversal.PreOrder(root))
            {
                PositionVertical(node);
            }

            // Move the entire subtree to the anchor.
            Vector2 offset = EditorSingleDrag.StartDrag(root, root.Center);

            EditorSingleDrag.SetSubtreePosition(root, anchor, offset);
        }
        public AttributeStore(ICompilation compilation, IErrorReporter errorReporter)
        {
            _errorReporter        = errorReporter;
            _assemblyStore        = new Dictionary <IAssembly, AttributeList>();
            _entityStore          = new Dictionary <IEntity, AttributeList>();
            _assemblyTransformers = new List <Tuple <IAssembly, PluginAttributeBase> >();
            _entityTransformers   = new List <Tuple <IEntity, PluginAttributeBase> >();

            foreach (var a in compilation.Assemblies)
            {
                ReadAssemblyAttributes(a, _assemblyTransformers);
            }

            foreach (var t in compilation.Assemblies.SelectMany(a => TreeTraversal.PostOrder(a.TopLevelTypeDefinitions, t => t.NestedTypes)))
            {
                foreach (var m in t.Methods)
                {
                    ReadEntityAttributes(m, _entityTransformers);
                }
                foreach (var p in t.Properties)
                {
                    if (p.CanGet)
                    {
                        ReadEntityAttributes(p.Getter, _entityTransformers);
                    }
                    if (p.CanSet)
                    {
                        ReadEntityAttributes(p.Setter, _entityTransformers);
                    }
                    ReadEntityAttributes(p, _entityTransformers);
                }
                foreach (var f in t.Fields)
                {
                    ReadEntityAttributes(f, _entityTransformers);
                }
                foreach (var e in t.Events)
                {
                    if (e.CanAdd)
                    {
                        ReadEntityAttributes(e.AddAccessor, _entityTransformers);
                    }
                    if (e.CanRemove)
                    {
                        ReadEntityAttributes(e.RemoveAccessor, _entityTransformers);
                    }
                    ReadEntityAttributes(e, _entityTransformers);
                }
                ReadEntityAttributes(t, _entityTransformers);
            }
        }
Пример #3
0
        public void Optimize(DecompilerContext context, ILBlock method, ILAstOptimizationStep abortBeforeStep = ILAstOptimizationStep.None)
        {
            this.context    = context;
            this.typeSystem = context.CurrentMethod.Module.TypeSystem;
            this.method     = method;

            if (abortBeforeStep == ILAstOptimizationStep.RemoveRedundantCode)
            {
                return;
            }
            RemoveRedundantCode(method);

            if (abortBeforeStep == ILAstOptimizationStep.ReduceBranchInstructionSet)
            {
                return;
            }
            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                ReduceBranchInstructionSet(block);
            }
            // ReduceBranchInstructionSet runs before inlining because the non-aggressive inlining heuristic
            // looks at which type of instruction consumes the inlined variable.

            if (abortBeforeStep == ILAstOptimizationStep.InlineVariables)
            {
                return;
            }
            // Works better after simple goto removal because of the following debug pattern: stloc X; br Next; Next:; ldloc X
            ILInlining inlining1 = new ILInlining(method);

            inlining1.InlineAllVariables();

            if (abortBeforeStep == ILAstOptimizationStep.CopyPropagation)
            {
                return;
            }
            inlining1.CopyPropagation();

            if (abortBeforeStep == ILAstOptimizationStep.YieldReturn)
            {
                return;
            }
            YieldReturnDecompiler.Run(context, method);

            if (abortBeforeStep == ILAstOptimizationStep.PropertyAccessInstructions)
            {
                return;
            }
            IntroducePropertyAccessInstructions(method);

            if (abortBeforeStep == ILAstOptimizationStep.SplitToMovableBlocks)
            {
                return;
            }
            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                SplitToBasicBlocks(block);
            }

            if (abortBeforeStep == ILAstOptimizationStep.TypeInference)
            {
                return;
            }
            // Types are needed for the ternary operator optimization
            TypeAnalysis.Run(context, method);

            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                bool modified;
                do
                {
                    modified = false;

                    if (abortBeforeStep == ILAstOptimizationStep.SimplifyShortCircuit)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(new SimpleControlFlow(context, method).SimplifyShortCircuit);

                    if (abortBeforeStep == ILAstOptimizationStep.SimplifyTernaryOperator)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(new SimpleControlFlow(context, method).SimplifyTernaryOperator);

                    if (abortBeforeStep == ILAstOptimizationStep.SimplifyNullCoalescing)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(new SimpleControlFlow(context, method).SimplifyNullCoalescing);

                    if (abortBeforeStep == ILAstOptimizationStep.JoinBasicBlocks)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(new SimpleControlFlow(context, method).JoinBasicBlocks);

                    if (abortBeforeStep == ILAstOptimizationStep.TransformDecimalCtorToConstant)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(TransformDecimalCtorToConstant);
                    modified |= block.RunOptimization(SimplifyLdcI4ConvI8);

                    if (abortBeforeStep == ILAstOptimizationStep.SimplifyLdObjAndStObj)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(SimplifyLdObjAndStObj);

                    if (abortBeforeStep == ILAstOptimizationStep.TransformArrayInitializers)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(TransformArrayInitializers);

                    if (abortBeforeStep == ILAstOptimizationStep.TransformObjectInitializers)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(TransformObjectInitializers);

                    if (abortBeforeStep == ILAstOptimizationStep.MakeAssignmentExpression)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(MakeAssignmentExpression);
                    modified |= block.RunOptimization(MakeCompoundAssignments);

                    if (abortBeforeStep == ILAstOptimizationStep.IntroducePostIncrement)
                    {
                        return;
                    }
                    modified |= block.RunOptimization(IntroducePostIncrement);

                    if (abortBeforeStep == ILAstOptimizationStep.InlineVariables2)
                    {
                        return;
                    }
                    modified |= new ILInlining(method).InlineAllInBlock(block);
                    new ILInlining(method).CopyPropagation();
                } while(modified);
            }

            if (abortBeforeStep == ILAstOptimizationStep.FindLoops)
            {
                return;
            }
            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                new LoopsAndConditions(context).FindLoops(block);
            }

            if (abortBeforeStep == ILAstOptimizationStep.FindConditions)
            {
                return;
            }
            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                new LoopsAndConditions(context).FindConditions(block);
            }

            if (abortBeforeStep == ILAstOptimizationStep.FlattenNestedMovableBlocks)
            {
                return;
            }
            FlattenBasicBlocks(method);

            if (abortBeforeStep == ILAstOptimizationStep.RemoveRedundantCode2)
            {
                return;
            }
            RemoveRedundantCode(method);

            if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval)
            {
                return;
            }
            new GotoRemoval().RemoveGotos(method);

            if (abortBeforeStep == ILAstOptimizationStep.DuplicateReturns)
            {
                return;
            }
            DuplicateReturnStatements(method);

            if (abortBeforeStep == ILAstOptimizationStep.ReduceIfNesting)
            {
                return;
            }
            ReduceIfNesting(method);

            if (abortBeforeStep == ILAstOptimizationStep.InlineVariables3)
            {
                return;
            }
            // The 2nd inlining pass is necessary because DuplicateReturns and the introduction of ternary operators
            // open up additional inlining possibilities.
            new ILInlining(method).InlineAllVariables();

            if (abortBeforeStep == ILAstOptimizationStep.CachedDelegateInitialization)
            {
                return;
            }
            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                for (int i = 0; i < block.Body.Count; i++)
                {
                    // TODO: Move before loops
                    CachedDelegateInitializationWithField(block, ref i);
                    CachedDelegateInitializationWithLocal(block, ref i);
                }
            }

            if (abortBeforeStep == ILAstOptimizationStep.IntroduceFixedStatements)
            {
                return;
            }
            // we need post-order traversal, not pre-order, for "fixed" to work correctly
            foreach (ILBlock block in TreeTraversal.PostOrder <ILNode>(method, n => n.GetChildren()).OfType <ILBlock>())
            {
                for (int i = block.Body.Count - 1; i >= 0; i--)
                {
                    // TODO: Move before loops
                    if (i < block.Body.Count)
                    {
                        IntroduceFixedStatements(block.Body, i);
                    }
                }
            }

            if (abortBeforeStep == ILAstOptimizationStep.RecombineVariables)
            {
                return;
            }
            RecombineVariables(method);

            if (abortBeforeStep == ILAstOptimizationStep.TypeInference2)
            {
                return;
            }
            TypeAnalysis.Reset(method);
            TypeAnalysis.Run(context, method);

            if (abortBeforeStep == ILAstOptimizationStep.RemoveRedundantCode3)
            {
                return;
            }
            GotoRemoval.RemoveRedundantCode(method);

            // ReportUnassignedILRanges(method);
        }
Пример #4
0
 public void Run(ILFunction function, ILTransformContext context)
 {
     try {
         if (this.context != null)
         {
             throw new InvalidOperationException("Reentrancy in " + nameof(TransformDisplayClassUsage));
         }
         this.context = context;
         var decompilationContext = new SimpleTypeResolveContext(context.Function.Method);
         // Traverse nested functions in post-order:
         // Inner functions are transformed before outer functions
         foreach (var f in function.Descendants.OfType <ILFunction>())
         {
             foreach (var v in f.Variables.ToArray())
             {
                 if (context.Settings.YieldReturn && HandleMonoStateMachine(function, v, decompilationContext, f))
                 {
                     continue;
                 }
                 if ((context.Settings.AnonymousMethods || context.Settings.ExpressionTrees) && IsClosure(context, v, out ITypeDefinition closureType, out var inst))
                 {
                     if (!CanRemoveAllReferencesTo(context, v))
                     {
                         continue;
                     }
                     if (inst is StObj || inst is StLoc)
                     {
                         instructionsToRemove.Add(inst);
                     }
                     AddOrUpdateDisplayClass(f, v, closureType, inst, localFunctionClosureParameter: false);
                     continue;
                 }
                 if (context.Settings.LocalFunctions && f.Kind == ILFunctionKind.LocalFunction && v.Kind == VariableKind.Parameter && v.Index > -1 && f.Method.Parameters[v.Index.Value] is IParameter p && LocalFunctionDecompiler.IsClosureParameter(p, decompilationContext))
                 {
                     AddOrUpdateDisplayClass(f, v, ((ByReferenceType)p.Type).ElementType.GetDefinition(), f.Body, localFunctionClosureParameter: true);
                     continue;
                 }
                 AnalyzeUseSites(v);
             }
         }
         VisitILFunction(function);
         if (instructionsToRemove.Count > 0)
         {
             context.Step($"Remove instructions", function);
             foreach (var store in instructionsToRemove)
             {
                 if (store.Parent is Block containingBlock)
                 {
                     containingBlock.Instructions.Remove(store);
                 }
             }
         }
         foreach (var f in TreeTraversal.PostOrder(function, f => f.LocalFunctions))
         {
             RemoveDeadVariableInit.ResetHasInitialValueFlag(f, context);
         }
     } finally {
         instructionsToRemove.Clear();
         displayClasses.Clear();
         fieldAssignmentsWithVariableValue.Clear();
         this.context = null;
     }
 }