nir/spirv: Split instruction handling into preamble and body sections
authorJason Ekstrand <jason.ekstrand@intel.com>
Fri, 1 May 2015 21:00:57 +0000 (14:00 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Mon, 31 Aug 2015 23:58:20 +0000 (16:58 -0700)
src/glsl/nir/spirv_to_nir.c

index b9d35766019a677f6fbb726bfccb1111f851f35f..ef42b14c41eea3a03e55166377d70778d1ae9915 100644 (file)
@@ -114,6 +114,28 @@ vtn_string_literal(struct vtn_builder *b, const uint32_t *words,
    return ralloc_strndup(b, (char *)words, (word_count - 2) * sizeof(*words));
 }
 
+typedef bool (*vtn_instruction_handler)(struct vtn_builder *, SpvOp,
+                                        const uint32_t *, unsigned);
+
+static const uint32_t *
+vtn_foreach_instruction(struct vtn_builder *b, const uint32_t *start,
+                        const uint32_t *end, vtn_instruction_handler handler)
+{
+   const uint32_t *w = start;
+   while (w < end) {
+      SpvOp opcode = w[0] & SpvOpCodeMask;
+      unsigned count = w[0] >> SpvWordCountShift;
+      assert(count >= 1 && w + count <= end);
+
+      if (!handler(b, opcode, w, count))
+         return w;
+
+      w += count;
+   }
+   assert(w == end);
+   return w;
+}
+
 static void
 vtn_handle_extension(struct vtn_builder *b, SpvOp opcode,
                      const uint32_t *w, unsigned count)
@@ -714,32 +736,19 @@ vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,
    unreachable("Unhandled opcode");
 }
 
-static void
-vtn_handle_instruction(struct vtn_builder *b, SpvOp opcode,
-                       const uint32_t *w, unsigned count)
+static bool
+vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
+                                const uint32_t *w, unsigned count)
 {
    switch (opcode) {
    case SpvOpSource:
    case SpvOpSourceExtension:
-   case SpvOpMemberName:
-   case SpvOpLine:
+   case SpvOpCompileFlag:
    case SpvOpExtension:
+   case SpvOpExtInstImport:
       /* Unhandled, but these are for debug so that's ok. */
       break;
 
-   case SpvOpName:
-      b->values[w[1]].name = vtn_string_literal(b, &w[2], count - 2);
-      break;
-
-   case SpvOpString:
-      vtn_push_value(b, w[1], vtn_value_type_string)->str =
-         vtn_string_literal(b, &w[2], count - 2);
-      break;
-
-   case SpvOpUndef:
-      vtn_push_value(b, w[2], vtn_value_type_undef);
-      break;
-
    case SpvOpMemoryModel:
       assert(w[1] == SpvAddressingModelLogical);
       assert(w[2] == SpvMemoryModelGLSL450);
@@ -751,20 +760,32 @@ vtn_handle_instruction(struct vtn_builder *b, SpvOp opcode,
       b->execution_model = w[1];
       break;
 
-   case SpvOpLabel: {
-      struct exec_node *list_tail = exec_list_get_tail(b->cf_list);
-      nir_cf_node *tail_node = exec_node_data(nir_cf_node, list_tail, node);
-      assert(tail_node->type == nir_cf_node_block);
-      nir_block *block = nir_cf_node_as_block(tail_node);
+   case SpvOpExecutionMode:
+      unreachable("Execution modes not yet implemented");
+      break;
 
-      assert(exec_list_is_empty(&block->instr_list));
-      vtn_push_value(b, w[1], vtn_value_type_block)->block = block;
+   case SpvOpString:
+      vtn_push_value(b, w[1], vtn_value_type_string)->str =
+         vtn_string_literal(b, &w[2], count - 2);
       break;
-   }
 
-   case SpvOpExtInstImport:
-   case SpvOpExtInst:
-      vtn_handle_extension(b, opcode, w, count);
+   case SpvOpName:
+      b->values[w[1]].name = vtn_string_literal(b, &w[2], count - 2);
+      break;
+
+   case SpvOpMemberName:
+      /* TODO */
+      break;
+
+   case SpvOpLine:
+      break; /* Ignored for now */
+
+   case SpvOpDecorationGroup:
+   case SpvOpDecorate:
+   case SpvOpMemberDecorate:
+   case SpvOpGroupDecorate:
+   case SpvOpGroupMemberDecorate:
+      vtn_handle_decoration(b, opcode, w, count);
       break;
 
    case SpvOpTypeVoid:
@@ -803,6 +824,41 @@ vtn_handle_instruction(struct vtn_builder *b, SpvOp opcode,
       vtn_handle_constant(b, opcode, w, count);
       break;
 
+   case SpvOpVariable:
+      vtn_handle_variables(b, opcode, w, count);
+      break;
+
+   default:
+      return false; /* End of preamble */
+   }
+
+   return true;
+}
+
+static bool
+vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode,
+                            const uint32_t *w, unsigned count)
+{
+   switch (opcode) {
+   case SpvOpLabel: {
+      struct exec_node *list_tail = exec_list_get_tail(b->cf_list);
+      nir_cf_node *tail_node = exec_node_data(nir_cf_node, list_tail, node);
+      assert(tail_node->type == nir_cf_node_block);
+      nir_block *block = nir_cf_node_as_block(tail_node);
+
+      assert(exec_list_is_empty(&block->instr_list));
+      vtn_push_value(b, w[1], vtn_value_type_block)->block = block;
+      break;
+   }
+
+   case SpvOpUndef:
+      vtn_push_value(b, w[2], vtn_value_type_undef);
+      break;
+
+   case SpvOpExtInst:
+      vtn_handle_extension(b, opcode, w, count);
+      break;
+
    case SpvOpVariable:
    case SpvOpVariableArray:
    case SpvOpLoad:
@@ -816,14 +872,6 @@ vtn_handle_instruction(struct vtn_builder *b, SpvOp opcode,
       vtn_handle_variables(b, opcode, w, count);
       break;
 
-   case SpvOpDecorationGroup:
-   case SpvOpDecorate:
-   case SpvOpMemberDecorate:
-   case SpvOpGroupDecorate:
-   case SpvOpGroupMemberDecorate:
-      vtn_handle_decoration(b, opcode, w, count);
-      break;
-
    case SpvOpFunction:
    case SpvOpFunctionEnd:
    case SpvOpFunctionParameter:
@@ -953,6 +1001,8 @@ vtn_handle_instruction(struct vtn_builder *b, SpvOp opcode,
    default:
       unreachable("Unhandled opcode");
    }
+
+   return true;
 }
 
 nir_shader *
@@ -979,17 +1029,15 @@ spirv_to_nir(const uint32_t *words, size_t word_count,
    b->value_id_bound = value_id_bound;
    b->values = ralloc_array(b, struct vtn_value, value_id_bound);
 
-   /* Start handling instructions */
    const uint32_t *word_end = words + word_count;
-   while (words < word_end) {
-      SpvOp opcode = words[0] & SpvOpCodeMask;
-      unsigned count = words[0] >> SpvWordCountShift;
-      assert(words + count <= word_end);
 
-      vtn_handle_instruction(b, opcode, words, count);
+   /* Handle all the preamble instructions */
+   words = vtn_foreach_instruction(b, words, word_end,
+                                   vtn_handle_preamble_instruction);
 
-      words += count;
-   }
+   words = vtn_foreach_instruction(b, words, word_end,
+                                   vtn_handle_body_instruction);
+   assert(words == word_end);
 
    ralloc_free(b);