void visit_subroutine(Subroutine m) { if (m.body == null) { return; } m.entry_block = BasicBlock.entry(); m.return_block = new BasicBlock(); m.exit_block = BasicBlock.exit(); m.return_block.connect(m.exit_block); if (m is Method) { // ensure out parameters are defined at end of method foreach (var param in ((Method)m).get_parameters()) { if (param.direction == ParameterDirection.OUT) { var param_ma = MemberAccess.simple(param.name, param.source_reference); param_ma.symbol_reference = param; m.return_block.add_node(param_ma); } } } current_block = new BasicBlock(); m.entry_block.connect(current_block); current_block.add_node(m); jump_stack.Add(JumpTarget.return_target(m.return_block)); jump_stack.Add(JumpTarget.exit_target(m.exit_block)); m.accept_children(this); jump_stack.RemoveAt(jump_stack.Count - 1); if (current_block != null) { // end of method body reachable if (m.has_result) { Report.error(m.source_reference, "missing return statement at end of subroutine body"); m.error = true; } current_block.connect(m.return_block); } analyze_body(m.entry_block); }