Beispiel #1
0
        private void BuildAstBlocks(ILCompilationUnit result, IDictionary <int, ILVariable> resultVariables)
        {
            foreach (var node in result.ControlFlowGraph.Nodes)
            {
                var ilBlock  = (ILBasicBlock)node.UserData[ILBasicBlock.BasicBlockProperty];
                var astBlock = new ILAstBlock(node);

                foreach (var instruction in ilBlock.Instructions)
                {
                    // Build expression.
                    var expression = BuildExpression(instruction, result);

                    switch (instruction.OpCode.Code)
                    {
                    case ILCode.POP:
                    {
                        // Since we treat registers as variables, we should treat POP instructions as assignment
                        // statements instead of a normal ILExpressionStatement. This makes it easier to apply
                        // analysis and transformations (such as variable inlining) later, in the same way we do
                        // that with normal variables.

                        var registerVar = result.GetOrCreateVariable(instruction.Operand.ToString());
                        var value       = (ILExpression)((IILArgumentsProvider)expression).Arguments[0].Remove();

                        var assignment = new ILAssignmentStatement(registerVar, value);
                        astBlock.Statements.Add(assignment);
                        break;
                    }

                    case ILCode.CALL:
                    {
                        // CALL instructions that call non-void methods store the result in R0.
                        // TODO: Respect frame layout instead of hardcoding R0 as return value.

                        var callAnnotation = (CallAnnotation)instruction.Annotation;

                        var statement = callAnnotation.Function.FrameLayout.ReturnsValue
                                ? (ILStatement) new ILAssignmentStatement(
                            result.GetOrCreateVariable(VMRegisters.R0.ToString()), expression)
                                : new ILExpressionStatement(expression);

                        astBlock.Statements.Add(statement);

                        break;
                    }

                    case ILCode.RET:
                    {
                        // TODO: Respect frame layout instead of hardcoding R0 as return value.
                        var returnExpr = (IILArgumentsProvider)expression;

                        foreach (var use in expression.AcceptVisitor(VariableUsageCollector.Instance))
                        {
                            use.Variable = null;
                        }

                        returnExpr.Arguments.Clear();

                        if (result.FrameLayout.ReturnsValue && !instruction.ProgramState.IgnoreExitKey)
                        {
                            var registerVar = result.GetOrCreateVariable(VMRegisters.R0.ToString());
                            returnExpr.Arguments.Add(new ILVariableExpression(registerVar));
                        }

                        astBlock.Statements.Add(new ILExpressionStatement(expression));
                        break;
                    }

                    default:
                    {
                        // Build statement around expression.
                        var statement = resultVariables.TryGetValue(instruction.Offset, out var resultVariable)
                                ? (ILStatement) new ILAssignmentStatement(resultVariable, expression)
                                : new ILExpressionStatement(expression);

                        astBlock.Statements.Add(statement);
                        break;
                    }
                    }
                }

                node.UserData[ILAstBlock.AstBlockProperty] = astBlock;
            }
        }
 public IEnumerable <ILVariableExpression> VisitAssignmentStatement(ILAssignmentStatement statement)
 {
     return(statement.Value.AcceptVisitor(this));
 }