[vm] Add record coverage instructions to statements.

RecordBranchCoverage method introduced in
https://dart-review.googlesource.com/c/sdk/+/224320

RecordBranchCoverage only inserts the RecordCoverage instruction if
the --branch-coverage flag is enabled. It also encodes the branch
coverage and normal coverage token positions differently, so that
source_report.cc can ignore the branch coverage positions (for now).

Next step after this is to add a special RPC to source_report.cc, that
reads and reports the branch coverage positions.

Change-Id: If8ac2cbba7777378e2fb0734aba9624e65c48f2b
TEST=CI (proper tests on the way once I implement the new RPC)
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/224082
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Liam Appelbe <liama@google.com>
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index a5693f8..00c2160 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1294,6 +1294,16 @@
   return Fragment();
 }
 
+Fragment StreamingFlowGraphBuilder::BuildStatementWithBranchCoverage(
+    TokenPosition* position) {
+  TokenPosition pos = TokenPosition::kNoSource;
+  Fragment statement = BuildStatement(&pos);
+  if (position != nullptr) *position = pos;
+  Fragment covered_statement = flow_graph_builder_->RecordBranchCoverage(pos);
+  covered_statement += statement;
+  return covered_statement;
+}
+
 void StreamingFlowGraphBuilder::ReportUnexpectedTag(const char* variant,
                                                     Tag tag) {
   if ((flow_graph_builder_ == nullptr) || (parsed_function() == nullptr)) {
@@ -4462,7 +4472,7 @@
   if (position != nullptr) *position = pos;
 
   TestFragment condition = TranslateConditionForControl();  // read condition.
-  const Fragment body = BuildStatement();                   // read body
+  const Fragment body = BuildStatementWithBranchCoverage();  // read body
 
   Fragment body_entry(condition.CreateTrueSuccessor(flow_graph_builder_));
   body_entry += body;
@@ -4492,7 +4502,7 @@
   const TokenPosition pos = ReadPosition();  // read position.
   if (position != nullptr) *position = pos;
 
-  Fragment body = BuildStatement();  // read body.
+  Fragment body = BuildStatementWithBranchCoverage();  // read body.
 
   if (body.is_closed()) {
     SkipExpression();  // read condition.
@@ -4556,7 +4566,7 @@
   }
 
   Fragment body(body_entry);
-  body += BuildStatement();  // read body.
+  body += BuildStatementWithBranchCoverage();  // read body.
 
   if (body.is_open()) {
     // We allocated a fresh context before the loop which contains captured
@@ -4639,7 +4649,7 @@
   body += StoreLocal(TokenPosition::kNoSource,
                      LookupVariable(variable_kernel_position));
   body += Drop();
-  body += BuildStatement();  // read body.
+  body += BuildStatementWithBranchCoverage();  // read body.
   body += ExitScope(offset);
 
   if (body.is_open()) {
@@ -4699,7 +4709,7 @@
     bool is_default = ReadBool();  // read is_default.
     if (is_default) default_case = i;
     Fragment& body_fragment = body_fragments[i] =
-        BuildStatement();  // read body.
+        BuildStatementWithBranchCoverage();  // read body.
 
     if (body_fragment.entry == nullptr) {
       // Make a NOP in order to ensure linking works properly.
@@ -4885,11 +4895,11 @@
   TestFragment condition = TranslateConditionForControl();
 
   Fragment then_fragment(condition.CreateTrueSuccessor(flow_graph_builder_));
-  then_fragment += BuildStatement();  // read then.
+  then_fragment += BuildStatementWithBranchCoverage();  // read then.
 
   Fragment otherwise_fragment(
       condition.CreateFalseSuccessor(flow_graph_builder_));
-  otherwise_fragment += BuildStatement();  // read otherwise.
+  otherwise_fragment += BuildStatementWithBranchCoverage();  // read otherwise.
 
   if (then_fragment.is_open()) {
     if (otherwise_fragment.is_open()) {
@@ -4967,7 +4977,7 @@
   try_depth_inc();
   {
     TryCatchBlock block(flow_graph_builder_, try_handler_index);
-    try_body += BuildStatement(position);  // read body.
+    try_body += BuildStatementWithBranchCoverage(position);  // read body.
     try_body += Goto(after_try);
   }
   try_depth_dec();
@@ -5020,7 +5030,7 @@
       CatchBlock block(flow_graph_builder_, CurrentException(),
                        CurrentStackTrace(), try_handler_index);
 
-      catch_handler_body += BuildStatement();  // read body.
+      catch_handler_body += BuildStatementWithBranchCoverage();  // read body.
 
       // Note: ExitScope adjusts context_depth_ so even if catch_handler_body
       // is closed we still need to execute ExitScope for its side effect.
@@ -5121,7 +5131,7 @@
   {
     TryFinallyBlock tfb(flow_graph_builder_, finalizer_offset);
     TryCatchBlock tcb(flow_graph_builder_, try_handler_index);
-    try_body += BuildStatement(position);  // read body.
+    try_body += BuildStatementWithBranchCoverage(position);  // read body.
   }
   try_depth_dec();
 
@@ -5134,7 +5144,7 @@
     try_body += Goto(finally_entry);
 
     Fragment finally_body(finally_entry);
-    finally_body += BuildStatement();  // read finalizer.
+    finally_body += BuildStatementWithBranchCoverage();  // read finalizer.
     finally_body += Goto(after_try);
   }
 
@@ -5147,7 +5157,7 @@
                                           /* needs_stacktrace = */ false,
                                           /* is_synthesized = */ true);
   SetOffset(finalizer_offset);
-  finally_body += BuildStatement();  // read finalizer
+  finally_body += BuildStatementWithBranchCoverage();  // read finalizer
   if (finally_body.is_open()) {
     finally_body += LoadLocal(CurrentException());
     finally_body += LoadLocal(CurrentStackTrace());
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 68d7794..8fe4c5c 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -70,6 +70,7 @@
 
   Fragment BuildExpression(TokenPosition* position = nullptr);
   Fragment BuildStatement(TokenPosition* position = nullptr);
+  Fragment BuildStatementWithBranchCoverage(TokenPosition* position = nullptr);
 
   // Kernel offset:
   //   start of function expression -> end of function body statement