Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart |
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart |
index 162c38a7181493ed8f5709e4434af262a4bba4b7..6dc55c61c613f7335d6077ee7ddabf04422f1772 100644 |
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart |
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart |
@@ -240,9 +240,45 @@ class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive> |
ir.Primitive visitLabeledStatement(ast.LabeledStatement node) { |
ast.Statement body = node.statement; |
- return body is ast.Loop |
- ? visit(body) |
- : giveup(node, 'labeled statement'); |
+ if (body is ast.Loop) return visit(body); |
+ JumpTarget target = elements.getTargetDefinition(body); |
+ JumpCollector jumps = new JumpCollector(target); |
+ irBuilder.state.breakCollectors.add(jumps); |
+ IrBuilder innerBuilder = new IrBuilder.delimited(irBuilder); |
+ withBuilder(innerBuilder, () { |
+ visit(body); |
+ }); |
+ irBuilder.state.breakCollectors.removeLast(); |
+ bool hasBreaks = !jumps.isEmpty; |
+ ir.Continuation joinContinuation; |
+ if (hasBreaks) { |
+ if (innerBuilder.isOpen) { |
+ jumps.addJump(innerBuilder); |
+ } |
+ |
+ // All jumps to the break continuation must be in the scope of the |
+ // continuation's binding. The continuation is bound just outside the |
+ // body to satisfy this property without extra analysis. |
+ // As a consequence, the break continuation needs parameters for all |
+ // local variables in scope at the exit from the body. |
+ List<ir.Parameter> parameters = |
+ new List<ir.Parameter>.generate(irBuilder.environment.length, (i) { |
+ return new ir.Parameter(irBuilder.environment.index2variable[i]); |
+ }); |
+ joinContinuation = new ir.Continuation(parameters); |
+ irBuilder.invokeFullJoin(joinContinuation, jumps, recursive: false); |
+ irBuilder.add(new ir.LetCont(joinContinuation, innerBuilder._root)); |
+ for (int i = 0; i < irBuilder.environment.length; ++i) { |
+ irBuilder.environment.index2value[i] = parameters[i]; |
+ } |
+ } else { |
+ if (innerBuilder._root != null) { |
+ irBuilder.add(innerBuilder._root); |
+ irBuilder._current = innerBuilder._current; |
+ irBuilder.environment = innerBuilder.environment; |
+ } |
+ } |
+ return null; |
} |
visitWhile(ast.While node) { |