public static bool AllPathsReturn(FunctionSymbol symbol, BoundBlockStatement body) { if (symbol.ReturnType == TypeSymbol.Void) { return(true); } if (!body.IsValid) { return(false); } var graph = Create(body); foreach (var toEnd in graph.End.Incoming) { if (!toEnd.From.Statements.Any()) { return(false); } if (toEnd.From.Statements.Last().Kind != BoundNodeKind.BoundReturnStatement) { return(false); } } return(true); }
public List <BasicBlock> Build(BoundBlockStatement boundBlock) { foreach (var statement in boundBlock.Statements) { switch (statement.Kind) { case BoundNodeKind.BoundExpressionStatement: case BoundNodeKind.BoundVariableDeclarationStatement: case BoundNodeKind.BoundNopStatement: statements.Add(statement); break; case BoundNodeKind.BoundLabelStatement: EndBlock(); statements.Add(statement); break; case BoundNodeKind.BoundConditionalGotoStatement: case BoundNodeKind.BoundGotoStatement: case BoundNodeKind.BoundReturnStatement: statements.Add(statement); EndBlock(); break; default: throw new Exception("Unexpected kind"); } } EndBlock(); return(blocks); }
protected virtual BoundStatement RewriteBlockStatement(BoundBlockStatement node) { var builder = (ImmutableArray <BoundStatement> .Builder?)null; for (var i = 0; i < node.Statements.Length; i++) { var oldStatement = node.Statements[i]; var newStatement = RewriteStatement(oldStatement); if (newStatement != oldStatement) { if (builder is null) { builder = ImmutableArray.CreateBuilder <BoundStatement>(node.Statements.Length); for (var j = 0; j < i; j++) { builder.Add(node.Statements[j]); } } } if (!(builder is null)) { builder.Add(newStatement); } } if (builder is null) { return(node); } return(new BoundBlockStatement(builder.MoveToImmutable(), node.IsValid)); }
internal static ControlFlowGraph Create(BoundBlockStatement body) { var basicBuilder = new BasicBlockBuilder(); var blocks = basicBuilder.Build(body); var graphBuilder = new GraphBuilder(); return(graphBuilder.Build(blocks)); }