private StackOfLocals(StackOfLocals template) { if (template.elements != null) { this.elements = (TempVariable[])template.elements.Clone(); } this.top = template.top; this.body = template.body; }
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); }
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; } } } }
/// <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); }
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); }
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)); }
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)); }