public void VisitBlock(ILAstBlock block) { foreach (var statement in block.Statements) { statement.AcceptVisitor(this); } }
public virtual bool VisitBlock(ILAstBlock block) { bool changed = false; foreach (var statement in block.Statements) { changed |= statement.AcceptVisitor(this); } return(changed); }
public string VisitBlock(ILAstBlock block) => "block";
public override bool VisitBlock(ILAstBlock block) { // Find all assignments of variables, and count the amount of usages for each variable. // If the variable is not used it can be removed. If it is only used once, it can be inlined. bool changed = false; for (var i = 0; i < block.Statements.Count; i++) { // Find assignment statement: var statement = block.Statements[i]; if (statement is ILAssignmentStatement assignmentStatement && !(assignmentStatement.Variable is ILParameter)) { bool removeStatement = true; var usages = assignmentStatement.Variable.UsedBy; // Count usages. switch (usages.Count) { case 0: { if (assignmentStatement.Variable is ILFlagsVariable) { removeStatement = false; } if (assignmentStatement.Value.HasPotentialSideEffects) { // If the value has side effects, it cannot be removed. removeStatement = false; assignmentStatement.ReplaceWith(new ILExpressionStatement((ILExpression)assignmentStatement.Value.Remove())); } else { // Find all variables that are referenced in the statement, and remove them from the // usage lists. var embeddedReferences = assignmentStatement.Value.AcceptVisitor(VariableUsageCollector.Instance); foreach (var reference in embeddedReferences) { reference.Variable.UsedBy.Remove(reference); } } break; } case 1 when assignmentStatement.Variable.IsVirtual // We cannot inline into phi nodes. && !(usages[0].Parent is ILPhiExpression) // We also cannot insert phi nodes in arbitrary expressions other than assignments. && !(assignmentStatement.Value is ILPhiExpression) // Finally, we cannot inline expressions with side effects => depend on order of execution. && (!assignmentStatement.Value.HasPotentialSideEffects || !HasNoSideEffectsInBetween(assignmentStatement, usages[0])): { // Inline the variable's value. InlineVariable(usages[0], assignmentStatement); usages.Clear(); break; } default: { removeStatement = false; break; } } if (removeStatement) { // We applied a transformation, remove the original statement. block.Statements.RemoveAt(i); i--; changed = true; } } } return(changed); }