コード例 #1
0
 private StackOfLocals(StackOfLocals template)
 {
     if (template.elements != null)
     {
         this.elements = (TempVariable[])template.elements.Clone();
     }
     this.top  = template.top;
     this.body = template.body;
 }
コード例 #2
0
        private IStatement TransferStack(IStatement statement, StackOfLocals targetStack)
        {
            BasicBlock block = new BasicBlock(0);

            this.operandStack.TransferTo(targetStack, block.Statements);
            block.Statements.Add(statement);
            this.operandStack = targetStack.Clone(this.block);
            return(block);
        }
コード例 #3
0
        internal void Visit(BasicBlock block)
        {
            this.block        = block;
            this.operandStack = new StackOfLocals(this.body);
            this.codePointsToAnalyze.Enqueue(new CodePoint()
            {
                statements = block.Statements, index = 0, operandStack = this.operandStack
            });

            while (this.codePointsToAnalyze.Count > 0)
            {
                CodePoint codePoint = this.codePointsToAnalyze.Dequeue();
                if (codePoint.operandStack == null)
                {
                    //Can only get here for a code point with a label and labels are only created if there a branches to them.
                    //Sooner or later the branch must be encountered and then this code point will get an operand stack from the branch.
                    if (this.codePointsToAnalyze.Count == 0)
                    {
                        //But if we get here, there are NO other code blocks, so we'll loop forever if we just put codePoint back on the queue with an empty stack.
                        //Start with an empty stack and just carry on.
                        codePoint.operandStack = new StackOfLocals(this.body);
                    }
                    else
                    {
                        this.codePointsToAnalyze.Enqueue(codePoint); //keep looking for the branch.
                        continue;
                    }
                }
                this.operandStack = codePoint.operandStack.Clone(this.block);
                List <IStatement> statements = codePoint.statements;
                for (int i = codePoint.index; i < statements.Count; i++)
                {
                    statements[i] = this.Visit(statements[i]);
                    if (this.visitedUnconditionalBranch)
                    {
                        this.visitedUnconditionalBranch = false;
                        if (i + 1 < statements.Count)
                        {
                            ILabeledStatement /*?*/ label = statements[i + 1] as ILabeledStatement;
                            if (label == null)
                            {
                                continue;  //Unreachable code. Need to carry on though, since it may contain the only branch to a label.
                            }
                            this.codePointsToAnalyze.Enqueue(new CodePoint()
                            {
                                statements = statements, index = i + 1
                            });
                        }
                        break;
                    }
                }
            }
        }
コード例 #4
0
        /// <summary>
        /// Visits the specified block statement.
        /// </summary>
        /// <param name="blockStatement">The block statement.</param>
        /// <returns></returns>
        public override IBlockStatement Visit(BlockStatement blockStatement)
        {
            var savedBlock     = this.block;
            BasicBlock /*?*/ b = blockStatement as BasicBlock;

            for (; ;)
            {
                if (b != null)
                {
                    this.block = b;
                    int statementCount     = b.Statements.Count;
                    BasicBlock /*?*/ bnext = null;
                    if (statementCount > 1 && b.Statements[statementCount - 2] is IGotoStatement)
                    {
                        bnext = b.Statements[--statementCount] as BasicBlock;
                        if (bnext != null)
                        {
                            b.Statements.RemoveAt(statementCount);
                        }
                    }
                    b.Statements = this.Visit(b.Statements);
                    if (bnext == null || bnext.Statements.Count == 0)
                    {
                        break;
                    }
                    ILabeledStatement labeledStatement = bnext.Statements[0] as ILabeledStatement;
                    if (labeledStatement != null)
                    {
                        StackOfLocals newStack = null;
                        if (this.stackFor.TryGetValue(labeledStatement, out newStack))
                        {
                            this.operandStack.TransferTo(newStack, b.Statements);
                            this.operandStack = newStack;
                            this.stackFor.Remove(labeledStatement);
                        }
                    }
                    b.Statements.Add(bnext);
                    b = bnext;
                }
                else
                {
                    blockStatement.Statements = Visit(blockStatement.Statements);
                    break;
                }
            }
            this.block = savedBlock;
            return(blockStatement);
        }
コード例 #5
0
        public override List <IStatement> Visit(List <IStatement> statements)
        {
            List <IStatement> newList = new List <IStatement>();

            foreach (var statement in statements)
            {
                BasicBlock bb = statement as BasicBlock;
                if (bb != null && bb.Statements.Count > 0)
                {
                    ILabeledStatement labeledStatement = bb.Statements[0] as ILabeledStatement;
                    if (labeledStatement != null)
                    {
                        StackOfLocals newStack = null;
                        if (this.stackFor.TryGetValue(labeledStatement, out newStack))
                        {
                            this.operandStack.TransferTo(newStack, newList);
                            this.operandStack = newStack;
                            this.stackFor.Remove(labeledStatement);
                        }
                    }
                }
                IStatement newStatement;

                newStatement = this.Visit(statement);

                if (newStatement is IBlockStatement && !(statement is IBlockStatement))
                {
                    newList.AddRange(((IBlockStatement)newStatement).Statements);
                }
                else
                {
                    newList.Add(newStatement);
                }
            }
            return(newList);
        }
コード例 #6
0
        internal void TransferTo(StackOfLocals targetStack, List <IStatement> list)
        {
            Contract.Requires(targetStack != null);
            Contract.Requires(list != null);
            Contract.Requires(Contract.ForAll(list, x => x != null));

            for (int i = 0; i <= this.top && i <= targetStack.top; i++)
            {
                Contract.Assert(this.top >= 0);
                Contract.Assert(this.top < this.elements.Length);
                var sourceLocal = this.elements[i];
                Contract.Assert(targetStack.top >= 0);
                Contract.Assume(targetStack.elements != null);
                Contract.Assume(targetStack.top < targetStack.elements.Length);
                var targetLocal = targetStack.elements[i];
                Contract.Assume(targetLocal != null);
                if (sourceLocal == targetLocal)
                {
                    continue;
                }
                if (targetLocal.turnIntoPopValueExpression)
                {
                    sourceLocal.turnIntoPopValueExpression = true;
                }
                else if (sourceLocal.turnIntoPopValueExpression)
                {
                    targetLocal.turnIntoPopValueExpression = true;
                }
                else
                {
                    Contract.Assume(this.body.numberOfReferences != null);
                    this.body.numberOfReferences[sourceLocal]++;
                    Contract.Assume(this.body.numberOfAssignments != null);
                    this.body.numberOfAssignments[targetLocal]++;
                    var targetType = targetLocal.Type;
                    var sourceType = sourceLocal.Type;
                    var mergedType = TypeHelper.MergedType(TypeHelper.StackType(targetType), TypeHelper.StackType(sourceType));
                    if (targetType != mergedType && !(targetType.TypeCode == PrimitiveTypeCode.Boolean && mergedType.TypeCode == PrimitiveTypeCode.Int32))
                    {
                        targetLocal.Type = mergedType;
                        targetType       = mergedType;
                        if (targetType is Dummy || sourceType is Dummy)
                        {
                            targetLocal.isPolymorphic = true;
                        }
                    }
                    var target = new TargetExpression()
                    {
                        Definition = targetLocal, Type = targetType
                    };
                    var source = new BoundExpression()
                    {
                        Definition = sourceLocal, Type = sourceType
                    };
                    var assigment = new Assignment()
                    {
                        Target = target, Source = source, Type = targetType
                    };
                    list.Add(new ExpressionStatement()
                    {
                        Expression = assigment
                    });
                }
            }
            //Contract.Assume(this.top < 0 || Contract.ForAll(0, this.top+1, i => this.elements[i] != null));
        }
コード例 #7
0
        public override IStatement Visit(IStatement statement)
        {
            IGotoStatement gotoStatement = statement as IGotoStatement;

            if (gotoStatement != null)
            {
                this.visitedUnconditionalBranch = true;
                foreach (object ob in this.path)
                {
                    if (ob is IConditionalStatement)
                    {
                        this.visitedUnconditionalBranch = false;
                    }
                }
                StackOfLocals newStack = null;
                if (this.stackFor.TryGetValue(gotoStatement.TargetStatement, out newStack))
                {
                    return(this.TransferStack(gotoStatement, newStack));
                }
                this.stackFor.Add(gotoStatement.TargetStatement, this.operandStack.Clone(this.block));
                return(gotoStatement);
            }
            ILabeledStatement labeledStatement = statement as ILabeledStatement;

            if (labeledStatement != null)
            {
                StackOfLocals newStack = null;
                if (this.stackFor.TryGetValue(labeledStatement, out newStack))
                {
                    return(this.TransferStack(labeledStatement, newStack));
                }
                this.stackFor.Add(labeledStatement, this.operandStack.Clone(this.block));
                return(labeledStatement);
            }
            PushStatement /*?*/ push = statement as PushStatement;

            if (push != null)
            {
                push.ValueToPush = this.Visit(push.ValueToPush);
                this.tempCounter = this.body.localVariablesAndTemporaries.Count;
                var temp = new TempVariable()
                {
                    Name = this.body.host.NameTable.GetNameFor("__temp_" + this.tempCounter++)
                };
                temp.Type = push.ValueToPush.Type;
                this.operandStack.Push(temp);
                this.body.numberOfReferences.Add(temp, 0);
                var ctc = push.ValueToPush as ICompileTimeConstant;
                // "push null" doesn't tell us enough to know what type it really is
                if (ctc != null && ctc.Value == null) // REVIEW: need to make sure the type is a reference type?
                {
                    temp.isPolymorphic = true;
                }
                var be = push.ValueToPush as IBoundExpression;
                if (be != null)
                {
                    var sourceLocal = be.Definition as TempVariable;
                    if (sourceLocal != null && sourceLocal.isPolymorphic)
                    {
                        temp.isPolymorphic = true;
                    }
                }
                if (push.ValueToPush.Type is IManagedPointerTypeReference)
                {
                    temp.turnIntoPopValueExpression = true;
                    return(statement);
                }
                this.body.localVariablesAndTemporaries.Add(temp);
                if (this.block.LocalVariables == null)
                {
                    this.block.LocalVariables = new List <ILocalDefinition>();
                }
                this.block.LocalVariables.Add(temp);
                this.body.numberOfAssignments.Add(temp, 1);
                return(new ExpressionStatement()
                {
                    Expression = new Assignment()
                    {
                        Target = new TargetExpression()
                        {
                            Definition = temp
                        }, Source = push.ValueToPush
                    },
                    Locations = push.Locations
                });
            }
            if (statement is EndFilter || statement is EndFinally)
            {
                this.visitedUnconditionalBranch = true;
                return(statement);
            }
            if (statement is SwitchInstruction)
            {
                return(statement);
            }
            return(base.Visit(statement));
        }