Ejemplo n.º 1
0
 protected virtual void RunChild(MethodInfo method, Object notifier)
 {
     if (alreadyCalled.HasValue && alreadyCalled.Value)
     {
         return;
     }
     alreadyCalled = true;
     try
     {
         MethodBlock(method)();
     }
     finally
     {
         alreadyCalled = null;
     }
 }
Ejemplo n.º 2
0
        public void Test2()
        {
            var classBlock = new ClassBlock("TestClass");

            var method1 = new MethodBlock("LoopName");

            method1.Parameters = new FieldBlock[]
            {
                new FieldBlock("name", typeof(string).ToDynamic())
            };

            IfBlock   if1   = new IfBlock();
            ElseBlock else1 = new ElseBlock();

            if1.Condition = new OperationBlock(
                new GetterBlock(method1.Parameters[0], new PropertyBlock("Length", null)),
                OperationType.Equal,
                new ValueBlock(3));

            if1.Add(new ReturnBlock(method1.Parameters[0]));

            else1.Add(new ReturnBlock(new ValueBlock("!")));

            method1.Add(if1);
            method1.Add(else1);

            classBlock.AddMethod(method1);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Removes all unused blocks
        /// </summary>
        /// <param name="methodBlock"></param>
        /// <returns></returns>
        public static int RemoveUnusedBlocks(MethodBlock methodBlock)
        {
            if (methodBlock is null)
            {
                throw new ArgumentNullException(nameof(methodBlock));
            }

            var isVisiteds = new HashSet <Block>();

            VisitSuccessors(methodBlock.First(), isVisiteds);
            int count = 0;

            foreach (var scopeBlock in methodBlock.Enumerate <ScopeBlock>())
            {
                int c      = 0;
                var blocks = scopeBlock.Blocks;
                for (int i = 0; i < blocks.Count; i++)
                {
                    if (isVisiteds.Contains(blocks[i]))
                    {
                        blocks[i - c] = blocks[i];
                    }
                    else
                    {
                        c++;
                    }
                }
                ((List <Block>)blocks).RemoveRange(blocks.Count - c, c);
                count += c;
            }
            return(count);
Ejemplo n.º 4
0
        /// <summary>
        /// Restores <see cref="MethodDef"/> from <see cref="MethodBlock"/>
        /// </summary>
        /// <param name="methodDef"></param>
        /// <param name="methodBlock"></param>
        public static void FromMethodBlock(this MethodDef methodDef, MethodBlock methodBlock)
        {
            if (methodDef is null)
            {
                throw new ArgumentNullException(nameof(methodDef));
            }
            if (methodBlock is null)
            {
                throw new ArgumentNullException(nameof(methodBlock));
            }

            var body = methodDef.Body;

            if (body is null)
            {
                throw new InvalidOperationException();
            }
            CodeGenerator.Generate(methodBlock, out var instructions, out var exceptionHandlers, out var locals);
            body.Instructions.Clear();
            body.Instructions.AddRange(instructions);
            body.ExceptionHandlers.Clear();
            body.ExceptionHandlers.AddRange(exceptionHandlers);
            body.Variables.Clear();
            body.Variables.AddRange(locals);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Called when receiving a report about a method
        /// </summary>
        /// <param name="methodName"></param>
        /// <param name="methodSig"></param>
        /// <param name="bodySize"></param>
        /// <param name="flags"></param>
        /// <param name="implFlags"></param>
        /// <param name="symbolFileId"></param>
        /// <param name="methodDef"></param>
        public void EnterMethod(string methodName, string methodSig, int bodySize, uint flags, uint implFlags, int symbolFileId, int methodDef)
        {
            currentTypedef.Methods.Add(currentMethod = new MethodEntry
            {
                Type      = currentTypedef,
                Name      = methodName,
                Signature = methodSig,
                BodySize  = bodySize,
                MethodDef = methodDef,
                Flags     = (MethodAttributes)flags,
                ImplFlags = (MethodImplAttributes)implFlags
            });

            if (_symbolReader != null)
            {
                var           token = new SymbolToken(methodDef);
                ISymbolMethod method;
                try
                {
                    method = _symbolReader.GetMethod(token);
                    var count = method.SequencePointCount;

                    int[]             offsets = new int[count];
                    int[]             sls     = new int[count];
                    int[]             scs     = new int[count];
                    int[]             els     = new int[count];
                    int[]             ecs     = new int[count];
                    ISymbolDocument[] docs    = new ISymbolDocument[count];

                    method.GetSequencePoints(offsets, docs, sls, scs, els, ecs);

                    for (int i = 0; i < count; i++)
                    {
                        MethodBlock block = new MethodBlock();
                        block.Offset = offsets[i];
                        var fileId = GetFileIdentifier(docs[i].URL);
                        if (fileId > 0 && sls[i] != 0xFEEFEE)
                        {
                            block.Start = new Position {
                                Column = scs[i], Line = sls[i]
                            };
                            block.End = new Position {
                                Column = ecs[i], Line = els[i]
                            };
                            block.File = fileId;
                        }
                        currentMethod.Blocks.Add(block);
                    }

                    docs = null;
                }
                catch (Exception ex)
                {
                }
                finally
                {
                    method = null;
                }
            }
        }
Ejemplo n.º 6
0
        public CSyntacticUnit FromMethodBlock(MethodBlock mb)
        {
            BuildCCodeUnitsCollection(mb);
            CCodeFragment  fragment = new CCodeFragment(code_units_collection);
            CSyntacticUnit unit     = new CSyntacticUnit(fragment);

            return(unit);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Converts a method block into instructions
        /// </summary>
        /// <param name="methodBlock"></param>
        /// <param name="instructions"></param>
        /// <param name="exceptionHandlers"></param>
        /// <param name="locals"></param>
        public static void Generate(MethodBlock methodBlock, out IList <Instruction> instructions, out IList <ExceptionHandler> exceptionHandlers, out IList <Local> locals)
        {
            var generator = new CodeGenerator();

            generator.Layout(methodBlock);
            instructions      = generator.GenerateInstructions();
            exceptionHandlers = generator.GenerateExceptionHandlers();
            locals            = GenerateLocals((List <Instruction>)instructions);
            generator.Cleanup();
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Sorts all blocks in <paramref name="methodBlock"/>
        /// NOTICE: Do NOT use it to remove unsed blocks! Please call <see cref="BlockCleaner.RemoveUnusedBlocks(MethodBlock)"/> first!
        /// </summary>
        /// <param name="methodBlock"></param>
        public static void Sort(MethodBlock methodBlock)
        {
            if (methodBlock is null)
            {
                throw new ArgumentNullException(nameof(methodBlock));
            }

            object contextKey = new object();

            foreach (var basicBlock in methodBlock.Enumerate <BasicBlock>())
            {
                if (basicBlock.Successors.Count == 0)
                {
                    basicBlock.Contexts.Set(contextKey, BlockContext.Empty);
                    continue;
                }

                var block = (Block)basicBlock;
                // block is jump source (jump from)
                bool flag = false;

                /*
                 * There are three situations and they appear in order
                 * 1. Jump out of scope
                 * 2. Add target(s) successfully (only appear once)
                 * 3. Self-loop
                 * When we add target(s) successfully, we should break do-while loop.
                 */
                do
                {
                    if (!block.Contexts.TryGet <BlockContext>(contextKey, out var context))
                    {
                        context = block.Contexts.Set(contextKey, new BlockContext());
                    }
                    var targets = context.Targets;
                    var scope   = block.Scope;

                    flag |= AddTarget(targets, scope, basicBlock.FallThroughNoThrow);
                    flag |= AddTarget(targets, scope, basicBlock.CondTargetNoThrow);
                    var switchTargets = basicBlock.SwitchTargetsNoThrow;
                    if (!(switchTargets is null))
                    {
                        foreach (var switchTarget in switchTargets)
                        {
                            flag |= AddTarget(targets, scope, switchTarget);
                        }
                    }
                    // target is jump destination (jump to)

                    block = block.Scope;
                } while (!flag && !(block is MethodBlock));
Ejemplo n.º 9
0
        private bool IsTokenAfterMethodBlock(Token token, MethodBlock mb)
        {
            if (token.line == mb.Ref.End.Line && token.col > mb.Ref.End.Column)
            {
                return(true);
            }

            if (token.line > mb.Ref.End.Line)
            {
                return(true);
            }

            return(false);
        }
Ejemplo n.º 10
0
        private bool IsTokenBelongMethodBlock(Token token, MethodBlock mb)
        {
            if (token.line == mb.Start.Line && token.col >= mb.Start.Column)
            {
                return(true);
            }

            if (token.line > mb.Start.Line && token.line < mb.Ref.End.Line)
            {
                return(true);
            }

            if (token.line == mb.Ref.End.Line && token.col <= mb.Ref.End.Column)
            {
                return(true);
            }

            return(false);
        }
Ejemplo n.º 11
0
        private void Layout(MethodBlock methodBlock)
        {
            var lastTryBlocks = new List <TryBlock>();
            int index         = 0;

            _basicBlocks = new List <BasicBlock>();

            foreach (var block in methodBlock.Enumerate <Block>())
            {
                if (block is BasicBlock basicBlock)
                {
                    basicBlock.Contexts.Set(this, new BlockContext(index, basicBlock.BranchOpcode, lastTryBlocks));
                    _basicBlocks.Add(basicBlock);
                    lastTryBlocks.Clear();
                    index++;
                }
                else if (block is TryBlock tryBlock)
                {
                    lastTryBlocks.Add(tryBlock);
                }
            }
        }
Ejemplo n.º 12
0
    public void MethodBlockTest()
    {
        int max = 11;

        CodeBlock block = CodeBlock.NewBuilder()
                          .AddStatement("int sum = 0")
                          .BeginControlFlow("for(int i = 0; i <= $A; i++)", max)
                          .AddStatement("sum += i")
                          .BeginControlFlow("if(sum > $A && i % 2 == $A", max, 0)
                          .AddStatement("sum++")
                          .NextControlFlow("else")
                          .AddStatement("sum--")
                          .EndControlFlow()
                          .EndControlFlow()
                          .Build();

        MethodBlock method = MethodBlock.NewBuilder("Testing")
                             .AddModifiers(CodeBuilderUtil.Modifier.PUBLIC, CodeBuilderUtil.Modifier.STATIC)
                             .AddCodeBlock(block)
                             .Build();

        Debug.Log(method);
    }
Ejemplo n.º 13
0
 private void BuildCCodeUnitsCollection(MethodBlock mb)
 {
     code_units_collection = new CCodeUnitsCollection();
     foreach (Token token in iter)
     {
         if (IsTokenBelongMethodBlock(token, mb))
         {
             code_units_collection.Add(ExtCodeUnitCreator.FromToken(token, m_args));
         }
         else
         {
             if (IsTokenAfterMethodBlock(token, mb))
             {
                 const string METHOD_END_TOKEN = "}";
                 if ((token.val == METHOD_END_TOKEN) && (code_units_collection.back().Text != METHOD_END_TOKEN))
                 {
                     code_units_collection.Add(ExtCodeUnitCreator.FromToken(token, m_args));
                 }
                 break;
             }
         }
     }
 }
Ejemplo n.º 14
0
        /// <summary>
        /// Inlines all basic blocks as much as possible.
        /// </summary>
        /// <param name="methodBlock"></param>
        /// <returns></returns>
        public static int Inline(MethodBlock methodBlock)
        {
            if (methodBlock is null)
            {
                throw new ArgumentNullException(nameof(methodBlock));
            }

            int count = 0;

            foreach (var block in methodBlock.Enumerate <Block>())
            {
                if (block is BasicBlock basicBlock)
                {
                    if ((basicBlock.Flags & BlockFlags.NoInlining) == BlockFlags.NoInlining)
                    {
                        continue;
                    }
                    if (basicBlock.IsEmpty && basicBlock.BranchOpcode.Code == Code.Br)
                    {
                        // If basic block is empty and branch opcode is br, we can redirect targets.
                        var fallThrough  = basicBlock.FallThrough;
                        var predecessors = basicBlock.Predecessors.Keys.ToArray();
                        foreach (var predecessor in predecessors)
                        {
                            if (predecessor.FallThroughNoThrow == basicBlock)
                            {
                                predecessor.FallThroughNoThrow = fallThrough;
                            }
                            if (predecessor.CondTargetNoThrow == basicBlock)
                            {
                                predecessor.CondTargetNoThrow = fallThrough;
                            }
                            var switchTargets = predecessor.SwitchTargetsNoThrow;
                            if (!(switchTargets is null))
                            {
                                for (int i = 0; i < switchTargets.Count; i++)
                                {
                                    if (switchTargets[i] == basicBlock)
                                    {
                                        switchTargets[i] = fallThrough;
                                    }
                                }
                            }
                        }
                        basicBlock.BranchOpcode       = OpCodes.Ret;
                        basicBlock.FallThroughNoThrow = null;
                        count++;
                    }
                    else
                    {
                        if (basicBlock.Predecessors.Count != 1 || basicBlock == basicBlock.Scope.First())
                        {
                            continue;
                        }
                        // Can't be inlined if has more than one predecessors or has no predecessor (not used basic block) or basic block is the first in current scope
                        var predecessor = basicBlock.Predecessors.Keys.First();
                        if (predecessor.BranchOpcode.Code != Code.Br || predecessor.Scope != basicBlock.Scope)
                        {
                            continue;
                        }
                        // Only br basic block and in the same scope then we can inline.

                        predecessor.Instructions.AddRange(basicBlock.Instructions);
                        basicBlock.Instructions.Clear();
                        predecessor.BranchOpcode       = basicBlock.BranchOpcode;
                        basicBlock.BranchOpcode        = OpCodes.Ret;
                        predecessor.FallThroughNoThrow = basicBlock.FallThroughNoThrow;
                        basicBlock.FallThroughNoThrow  = null;
                        predecessor.CondTargetNoThrow  = basicBlock.CondTargetNoThrow;
                        basicBlock.CondTargetNoThrow   = null;
                        var switchTargets = basicBlock.SwitchTargetsNoThrow;
                        basicBlock.SwitchTargetsNoThrow  = null;
                        predecessor.SwitchTargetsNoThrow = switchTargets;
                        count++;
                    }
                }
                else if (block is ScopeBlock scopeBlock)
                {
                    // We should fix entry if first basic block is empty.
                    if (!(scopeBlock.FirstBlock is BasicBlock first) || !first.IsEmpty || first.BranchOpcode.Code != Code.Br)
                    {
                        continue;
                    }

                    var blocks      = scopeBlock.Blocks;
                    var fallThrough = first;
                    do
                    {
                        fallThrough = fallThrough.FallThrough;
                    } while (fallThrough.IsEmpty && fallThrough.BranchOpcode.Code == Code.Br && fallThrough.Scope == scopeBlock);
                    // Gets final target basic block
                    var fallThroughParent = fallThrough.GetParent(scopeBlock);
                    // Gets parent of which scope is scopeBlock

                    int index = blocks.IndexOf(fallThroughParent);
                    blocks[0]     = fallThroughParent;
                    blocks[index] = first;
                    // Exchanges index
                }
            }
            return(count);
        }
Ejemplo n.º 15
0
 public void Method(MethodBlock methodBlock)
 {
     ParentBlock.Add(methodBlock);
 }
Ejemplo n.º 16
0
 public static float GetBlockCoverage(MethodBlock block)
 {
     return(block.Length == 0 || block.VisitCount > 0 ? 1 : 0);
 }