コード例 #1
0
        private void BuildASTInternal()
        {
            var workList = new Stack <CILBlock>();

            this.PopulateBeginStates(workList);

            var visited = new HashSet <CILBlock>();

            while (workList.Count > 0)
            {
                CILBlock block = workList.Pop();
                if (visited.Contains(block))
                {
                    continue;
                }
                visited.Add(block);

                Debug.Assert(this.blockStates.ContainsKey(block));
                BlockState state = this.blockStates[block];
                Debug.Assert(state.ASTTree == null);

                ILASTTree       tree    = this.BuildAST(block.Content, state.BeginStack);
                ILASTVariable[] remains = tree.StackRemains;
                state.ASTTree           = tree;
                this.blockStates[block] = state;

                // Propagate stack states
                foreach (CILBlock successor in block.Targets)
                {
                    if (!this.blockStates.TryGetValue(successor, out BlockState successorState))
                    {
                        var blockVars = new ILASTVariable[remains.Length];
                        for (int i = 0; i < blockVars.Length; i++)
                        {
                            blockVars[i] = new ILASTVariable
                            {
                                Name         = string.Format("ph_{0:x2}_{1:x2}", successor.Id, i),
                                Type         = remains[i].Type,
                                VariableType = ILASTVariableType.PhiVar
                            }
                        }
                        ;
                        successorState = new BlockState
                        {
                            BeginStack = blockVars
                        };
                        this.blockStates[successor] = successorState;
                    }
                    else
                    {
                        if (successorState.BeginStack.Length != remains.Length)
                        {
                            throw new InvalidProgramException("Inconsistent stack depth.");
                        }
                    }
                    workList.Push(successor);
                }
            }
        }
コード例 #2
0
        private ILASTTree BuildAST(CILInstrList instrs, ILASTVariable[] beginStack)
        {
            var tree      = new ILASTTree();
            var evalStack = new Stack <ILASTVariable>(beginStack);
            Func <int, IILASTNode[]> popArgs = numArgs =>
            {
                var args = new IILASTNode[numArgs];
                for (int i = numArgs - 1; i >= 0; i--)
                {
                    args[i] = evalStack.Pop();
                }
                return(args);
            };

            var prefixes = new List <Instruction>();

            foreach (Instruction instr in instrs)
            {
                if (instr.OpCode.OpCodeType == OpCodeType.Prefix)
                {
                    prefixes.Add(instr);
                    continue;
                }

                int             pushes, pops;
                ILASTExpression expr;
                if (instr.OpCode.Code == Code.Dup)
                {
                    pushes = pops = 1;

                    ILASTVariable arg = evalStack.Peek();
                    expr = new ILASTExpression
                    {
                        ILCode    = Code.Dup,
                        Operand   = null,
                        Arguments = new IILASTNode[] { arg }
                    };
                }
                else
                {
                    instr.CalculateStackUsage(this.method.ReturnType.ElementType != ElementType.Void, out pushes, out pops);
                    Debug.Assert(pushes == 0 || pushes == 1);

                    if (pops == -1)
                    {
                        evalStack.Clear();
                        pops = 0;
                    }

                    expr = new ILASTExpression
                    {
                        ILCode    = instr.OpCode.Code,
                        Operand   = instr.Operand,
                        Arguments = popArgs(pops)
                    };
                    if (expr.Operand is Instruction || expr.Operand is Instruction[])
                    {
                        this.instrReferences.Add(expr);
                    }
                }
                expr.CILInstr = instr;
                if (prefixes.Count > 0)
                {
                    expr.Prefixes = prefixes.ToArray();
                    prefixes.Clear();
                }

                if (pushes == 1)
                {
                    var variable = new ILASTVariable
                    {
                        Name         = string.Format("s_{0:x4}", instr.Offset),
                        VariableType = ILASTVariableType.StackVar
                    };
                    evalStack.Push(variable);

                    tree.Add(new ILASTAssignment
                    {
                        Variable = variable,
                        Value    = expr
                    });
                }
                else
                {
                    tree.Add(expr);
                }
            }
            tree.StackRemains = evalStack.Reverse().ToArray();
            return(tree);
        }
コード例 #3
0
        static void TransformSTELEM(ILASTExpression expr, ModuleDef module, ITypeDefOrRef type, ILASTTree tree, ref int index)
        {
            var array     = module.CorLibTypes.GetTypeRef("System", "Array");
            var setValSig = MethodSig.CreateInstance(module.CorLibTypes.Void, module.CorLibTypes.Object, module.CorLibTypes.Int32);
            var setValRef = new MemberRefUser(module, "SetValue", setValSig, array);

            ILASTVariable tmpVar1, tmpVar2;

            if (expr.Arguments[1] is ILASTVariable)
            {
                tmpVar1 = (ILASTVariable)expr.Arguments[1];
            }
            else
            {
                tmpVar1 = new ILASTVariable {
                    Name         = string.Format("arr_{0:x4}_1", expr.CILInstr.Offset),
                    VariableType = ILASTVariableType.StackVar
                };
                tree.Insert(index++, new ILASTAssignment {
                    Variable = tmpVar1,
                    Value    = (ILASTExpression)expr.Arguments[1]
                });
            }
            if (expr.Arguments[2] is ILASTVariable)
            {
                tmpVar2 = (ILASTVariable)expr.Arguments[2];
            }
            else
            {
                tmpVar2 = new ILASTVariable {
                    Name         = string.Format("arr_{0:x4}_2", expr.CILInstr.Offset),
                    VariableType = ILASTVariableType.StackVar
                };
                tree.Insert(index++, new ILASTAssignment {
                    Variable = tmpVar2,
                    Value    = (ILASTExpression)expr.Arguments[2]
                });
            }

            if (type.IsPrimitive)
            {
                var elem = new ILASTExpression {
                    ILCode    = Code.Box,
                    Operand   = type,
                    Arguments = new[] { tmpVar2 }
                };
                expr.Arguments[2] = tmpVar1;
                expr.Arguments[1] = elem;
            }
            else
            {
                expr.Arguments[2] = tmpVar1;
                expr.Arguments[1] = tmpVar2;
            }
            expr.ILCode  = Code.Call;
            expr.Operand = setValRef;
        }