Пример #1
0
        private void BuildASTInternal()
        {
            var workList = new Stack <CILBlock>();

            PopulateBeginStates(workList);

            var visited = new HashSet <CILBlock>();

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

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

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

                // Propagate stack states
                foreach (var successor in block.Targets)
                {
                    BlockState successorState;
                    if (!blockStates.TryGetValue(successor, out successorState))
                    {
                        var blockVars = new ILASTVariable[remains.Length];
                        for (var 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
                        };
                        blockStates[successor] = successorState;
                    }
                    else
                    {
                        if (successorState.BeginStack.Length != remains.Length)
                        {
                            throw new InvalidProgramException("Inconsistent stack depth.");
                        }
                    }
                    workList.Push(successor);
                }
            }
        }
Пример #2
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;
        }
Пример #3
0
        public IRVariable ResolveVRegister(ILASTVariable variable)
        {
            if (variable.VariableType == ILASTVariableType.ExceptionVar)
            {
                return(this.ResolveExceptionVar((ExceptionHandler)variable.Annotation));
            }

            if (this.varMap.TryGetValue(variable, out IRVariable vReg))
            {
                return(vReg);
            }
            vReg = this.AllocateVRegister(variable.Type);
            this.varMap[variable] = vReg;
            return(vReg);
        }
Пример #4
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);
        }
Пример #5
0
        private void PopulateBeginStates(Stack <CILBlock> workList)
        {
            for (int i = 0; i < this.body.ExceptionHandlers.Count; i++)
            {
                ExceptionHandler eh = this.body.ExceptionHandlers[i];
                this.blockStates[this.blockHeaders[eh.TryStart]] = new BlockState
                {
                    BeginStack = new ILASTVariable[0]
                };

                CILBlock handlerBlock = this.blockHeaders[eh.HandlerStart];
                workList.Push(handlerBlock);
                if (eh.HandlerType == ExceptionHandlerType.Fault ||
                    eh.HandlerType == ExceptionHandlerType.Finally)
                {
                    this.blockStates[handlerBlock] = new BlockState
                    {
                        BeginStack = new ILASTVariable[0]
                    };
                }
                else
                {
                    var type = TypeInference.ToASTType(eh.CatchType.ToTypeSig());
                    // Do not process overlapped handler blocks twice
                    if (!this.blockStates.ContainsKey(handlerBlock))
                    {
                        var exVar = new ILASTVariable
                        {
                            Name         = string.Format("ex_{0:x2}", i),
                            Type         = type,
                            VariableType = ILASTVariableType.ExceptionVar,
                            Annotation   = eh
                        };
                        this.blockStates[handlerBlock] = new BlockState
                        {
                            BeginStack = new[] { exVar }
                        };
                    }
                    else
                    {
                        Debug.Assert(this.blockStates[handlerBlock].BeginStack.Length == 1);
                    }

                    if (eh.FilterStart != null)
                    {
                        var filterVar = new ILASTVariable
                        {
                            Name         = string.Format("ef_{0:x2}", i),
                            Type         = type,
                            VariableType = ILASTVariableType.FilterVar,
                            Annotation   = eh
                        };
                        CILBlock filterBlock = this.blockHeaders[eh.FilterStart];
                        workList.Push(filterBlock);
                        this.blockStates[filterBlock] = new BlockState
                        {
                            BeginStack = new[] { filterVar }
                        };
                    }
                }
            }
            this.blockStates[this.basicBlocks[0]] = new BlockState
            {
                BeginStack = new ILASTVariable[0]
            };
            workList.Push(this.basicBlocks[0]);
            foreach (CILBlock block in this.basicBlocks)
            {
                if (block.Sources.Count > 0)
                {
                    continue;
                }
                if (workList.Contains(block))
                {
                    continue;
                }
                this.blockStates[block] = new BlockState
                {
                    BeginStack = new ILASTVariable[0]
                };
                workList.Push(block);
            }
        }
Пример #6
0
        private IRInstrList Translate(BasicBlock <ILASTTree> block)
        {
            this.Block        = block;
            this.Instructions = new IRInstrList();

            bool seenJump = false;

            foreach (IILASTStatement st in block.Content)
            {
                if (st is ILASTPhi)
                {
                    ILASTVariable variable = ((ILASTPhi)st).Variable;
                    this.Instructions.Add(new IRInstruction(IROpCode.POP)
                    {
                        Operand1 = this.Context.ResolveVRegister(variable),
                        ILAST    = st
                    });
                }
                else if (st is ILASTAssignment assignment)
                {
                    IIROperand valueVar = this.Translate(assignment.Value);
                    this.Instructions.Add(new IRInstruction(IROpCode.MOV)
                    {
                        Operand1 = this.Context.ResolveVRegister(assignment.Variable),
                        Operand2 = valueVar,
                        ILAST    = st
                    });
                }
                else if (st is ILASTExpression expr)
                {
                    var opCode = expr.ILCode.ToOpCode();
                    if (!seenJump && (opCode.FlowControl == FlowControl.Cond_Branch ||
                                      opCode.FlowControl == FlowControl.Branch ||
                                      opCode.FlowControl == FlowControl.Return ||
                                      opCode.FlowControl == FlowControl.Throw))
                    {
                        // Add stack remain before jumps
                        foreach (ILASTVariable remain in block.Content.StackRemains)
                        {
                            this.Instructions.Add(new IRInstruction(IROpCode.PUSH)
                            {
                                Operand1 = this.Context.ResolveVRegister(remain),
                                ILAST    = st
                            });
                        }
                        seenJump = true;
                    }
                    this.Translate((ILASTExpression)st);
                }
                else
                {
                    throw new NotSupportedException();
                }
            }
            Debug.Assert(seenJump);

            IRInstrList ret = this.Instructions;

            this.Instructions = null;
            return(ret);
        }