spirv: Add a parent field to vtn_cf_node

Cherry-pick'd from 2de5a41595442a02b5375d13082e236e1475c0bf

This makes it easier to crawl up the CF tree when trying to validate the
incoming SPIR-V control-flow.

Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3820>
Change-Id: I5d1417eb6bdfcd4952c81144bbaffee0073ffe17
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/mesa/+/403196
Reviewed-by: John Bauman <jbauman@google.com>
diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c
index 8071129..8bd57fb 100644
--- a/src/compiler/spirv/vtn_cfg.c
+++ b/src/compiler/spirv/vtn_cfg.c
@@ -252,6 +252,7 @@
       b->func = rzalloc(b, struct vtn_function);
 
       b->func->node.type = vtn_cf_node_type_function;
+      b->func->node.parent = NULL;
       list_inithead(&b->func->body);
       b->func->control = w[3];
 
@@ -415,6 +416,7 @@
       struct vtn_case *c = ralloc(b, struct vtn_case);
 
       c->node.type = vtn_cf_node_type_case;
+      c->node.parent = &swtch->node;
       list_inithead(&c->body);
       c->start_block = case_block;
       c->fallthrough = NULL;
@@ -487,7 +489,9 @@
 }
 
 static void
-vtn_cfg_walk_blocks(struct vtn_builder *b, struct list_head *cf_list,
+vtn_cfg_walk_blocks(struct vtn_builder *b,
+                    struct vtn_cf_node *cf_parent,
+                    struct list_head *cf_list,
                     struct vtn_block *start, struct vtn_case *switch_case,
                     struct vtn_block *switch_break,
                     struct vtn_block *loop_break, struct vtn_block *loop_cont,
@@ -500,6 +504,7 @@
          struct vtn_loop *loop = ralloc(b, struct vtn_loop);
 
          loop->node.type = vtn_cf_node_type_loop;
+         loop->node.parent = cf_parent;
          list_inithead(&loop->body);
          list_inithead(&loop->cont_body);
          loop->control = block->merge[3];
@@ -524,9 +529,11 @@
           * possible that the merge block for the loop is the start of
           * another case.
           */
-         vtn_cfg_walk_blocks(b, &loop->body, block, switch_case, NULL,
+         vtn_cfg_walk_blocks(b, &loop->node, &loop->body,
+                             block, switch_case, NULL,
                              new_loop_break, new_loop_cont, NULL );
-         vtn_cfg_walk_blocks(b, &loop->cont_body, new_loop_cont, NULL, NULL,
+         vtn_cfg_walk_blocks(b, &loop->node, &loop->cont_body,
+                             new_loop_cont, NULL, NULL,
                              new_loop_break, NULL, block);
 
          enum vtn_branch_type branch_type =
@@ -547,6 +554,7 @@
       }
 
       vtn_assert(block->node.link.next == NULL);
+      block->node.parent = cf_parent;
       list_addtail(&block->node.link, cf_list);
 
       switch (*block->branch & SpvOpCodeMask) {
@@ -580,6 +588,7 @@
          struct vtn_if *if_stmt = ralloc(b, struct vtn_if);
 
          if_stmt->node.type = vtn_cf_node_type_if;
+         if_stmt->node.parent = cf_parent;
          if_stmt->condition = block->branch[1];
          list_inithead(&if_stmt->then_body);
          list_inithead(&if_stmt->else_body);
@@ -614,11 +623,11 @@
             vtn_assert((*block->merge & SpvOpCodeMask) == SpvOpSelectionMerge);
             struct vtn_block *merge_block = vtn_block(b, block->merge[1]);
 
-            vtn_cfg_walk_blocks(b, &if_stmt->then_body, then_block,
-                                switch_case, switch_break,
+            vtn_cfg_walk_blocks(b, &if_stmt->node, &if_stmt->then_body,
+                                then_block, switch_case, switch_break,
                                 loop_break, loop_cont, merge_block);
-            vtn_cfg_walk_blocks(b, &if_stmt->else_body, else_block,
-                                switch_case, switch_break,
+            vtn_cfg_walk_blocks(b, &if_stmt->node, &if_stmt->else_body,
+                                else_block, switch_case, switch_break,
                                 loop_break, loop_cont, merge_block);
 
             enum vtn_branch_type merge_type =
@@ -657,6 +666,7 @@
          struct vtn_switch *swtch = ralloc(b, struct vtn_switch);
 
          swtch->node.type = vtn_cf_node_type_switch;
+         swtch->node.parent = cf_parent;
          swtch->selector = block->branch[1];
          list_inithead(&swtch->cases);
 
@@ -704,8 +714,8 @@
          vtn_foreach_cf_node(case_node, &swtch->cases) {
             struct vtn_case *cse = vtn_cf_node_as_case(case_node);
             vtn_assert(cse->start_block != break_block);
-            vtn_cfg_walk_blocks(b, &cse->body, cse->start_block, cse,
-                                break_block, loop_break, loop_cont, NULL);
+            vtn_cfg_walk_blocks(b, &cse->node, &cse->body, cse->start_block,
+                                cse, break_block, loop_break, loop_cont, NULL);
          }
 
          /* Finally, we walk over all of the cases one more time and put
@@ -763,7 +773,7 @@
 
    vtn_foreach_cf_node(node, &b->functions) {
       struct vtn_function *func = vtn_cf_node_as_function(node);
-      vtn_cfg_walk_blocks(b, &func->body, func->start_block,
+      vtn_cfg_walk_blocks(b, &func->node, &func->body, func->start_block,
                           NULL, NULL, NULL, NULL, NULL);
    }
 }
diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h
index d709c39..b7eb310 100644
--- a/src/compiler/spirv/vtn_private.h
+++ b/src/compiler/spirv/vtn_private.h
@@ -142,6 +142,7 @@
 
 struct vtn_cf_node {
    struct list_head link;
+   struct vtn_cf_node *parent;
    enum vtn_cf_node_type type;
 };