nir/spirv: Handle function calls
authorJason Ekstrand <jason.ekstrand@intel.com>
Fri, 18 Dec 2015 23:07:16 +0000 (15:07 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Wed, 23 Dec 2015 21:49:56 +0000 (13:49 -0800)
src/glsl/nir/spirv_to_nir.c
src/glsl/nir/spirv_to_nir_private.h

index 07d4789177060431e886d089971c8417b21456d6..d56f9be44475c490fc3cde1f2f5ce7787fcd2015 100644 (file)
@@ -1819,7 +1819,44 @@ static void
 vtn_handle_function_call(struct vtn_builder *b, SpvOp opcode,
                          const uint32_t *w, unsigned count)
 {
-   unreachable("Unhandled opcode");
+   struct nir_function_overload *overload =
+      vtn_value(b, w[3], vtn_value_type_function)->func->impl->overload;
+
+   nir_call_instr *call = nir_call_instr_create(b->nb.shader, overload);
+   for (unsigned i = 0; i < call->num_params; i++) {
+      unsigned arg_id = w[4 + i];
+      struct vtn_value *arg = vtn_untyped_value(b, arg_id);
+      if (arg->value_type == vtn_value_type_deref) {
+         call->params[i] =
+            nir_deref_as_var(nir_copy_deref(call, &arg->deref->deref));
+      } else {
+         struct vtn_ssa_value *arg_ssa = vtn_ssa_value(b, arg_id);
+
+         /* Make a temporary to store the argument in */
+         nir_variable *tmp =
+            nir_local_variable_create(b->impl, arg_ssa->type, "arg_tmp");
+         call->params[i] = nir_deref_var_create(call, tmp);
+
+         vtn_variable_store(b, arg_ssa, call->params[i], arg->type);
+      }
+   }
+
+   nir_variable *out_tmp = NULL;
+   if (!glsl_type_is_void(overload->return_type)) {
+      out_tmp = nir_local_variable_create(b->impl, overload->return_type,
+                                          "out_tmp");
+      call->return_deref = nir_deref_var_create(call, out_tmp);
+   }
+
+   nir_builder_instr_insert(&b->nb, &call->instr);
+
+   if (glsl_type_is_void(overload->return_type)) {
+      vtn_push_value(b, w[2], vtn_value_type_undef);
+   } else {
+      struct vtn_type *rettype = vtn_value(b, w[1], vtn_value_type_type)->type;
+      struct vtn_value *retval = vtn_push_value(b, w[2], vtn_value_type_ssa);
+      retval->ssa = vtn_variable_load(b, call->return_deref, rettype);
+   }
 }
 
 static struct vtn_ssa_value *
@@ -3260,6 +3297,8 @@ vtn_handle_first_cfg_pass_instruction(struct vtn_builder *b, SpvOp opcode,
       const struct glsl_type *result_type =
          vtn_value(b, w[1], vtn_value_type_type)->type->type;
       struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_function);
+      val->func = b->func;
+
       const struct glsl_type *func_type =
          vtn_value(b, w[4], vtn_value_type_type)->type->type;
 
@@ -3290,7 +3329,17 @@ vtn_handle_first_cfg_pass_instruction(struct vtn_builder *b, SpvOp opcode,
             }
          }
       }
-      b->func->overload = overload;
+
+      overload->return_type = glsl_get_function_return_type(func_type);
+
+      b->func->impl = nir_function_impl_create(overload);
+      if (!glsl_type_is_void(overload->return_type)) {
+         b->func->impl->return_var =
+            nir_local_variable_create(b->func->impl,
+                                      overload->return_type, "retval");
+      }
+
+      b->func_param_idx = 0;
       break;
    }
 
@@ -3299,8 +3348,22 @@ vtn_handle_first_cfg_pass_instruction(struct vtn_builder *b, SpvOp opcode,
       b->func = NULL;
       break;
 
-   case SpvOpFunctionParameter:
-      break; /* Does nothing */
+   case SpvOpFunctionParameter: {
+      struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_deref);
+
+      assert(b->func_param_idx < b->func->impl->num_params);
+      unsigned idx = b->func_param_idx++;
+
+      nir_variable *param =
+         nir_local_variable_create(b->func->impl,
+                                   b->func->impl->overload->params[idx].type,
+                                   val->name);
+
+      b->func->impl->params[idx] = param;
+      val->deref = nir_deref_var_create(b, param);
+      val->deref_type = vtn_value(b, w[1], vtn_value_type_type)->type;
+      break;
+   }
 
    case SpvOpLabel: {
       assert(b->block == NULL);
@@ -3723,6 +3786,18 @@ vtn_walk_blocks(struct vtn_builder *b, struct vtn_block *start,
          return;
       }
 
+      case SpvOpReturnValue: {
+         struct vtn_ssa_value *src = vtn_ssa_value(b, w[1]);
+         vtn_variable_store(b, src,
+                            nir_deref_var_create(b, b->impl->return_var),
+                            NULL);
+
+         nir_jump_instr *jump = nir_jump_instr_create(b->shader,
+                                                      nir_jump_return);
+         nir_builder_instr_insert(&b->nb, &jump->instr);
+         return;
+      }
+
       case SpvOpKill: {
          nir_intrinsic_instr *discard =
             nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard);
@@ -3731,7 +3806,6 @@ vtn_walk_blocks(struct vtn_builder *b, struct vtn_block *start,
       }
 
       case SpvOpSwitch:
-      case SpvOpReturnValue:
       case SpvOpUnreachable:
       default:
          unreachable("Unhandled opcode");
@@ -3781,7 +3855,7 @@ spirv_to_nir(const uint32_t *words, size_t word_count,
                            vtn_handle_first_cfg_pass_instruction);
 
    foreach_list_typed(struct vtn_function, func, node, &b->functions) {
-      b->impl = nir_function_impl_create(func->overload);
+      b->impl = func->impl;
       b->const_table = _mesa_hash_table_create(b, _mesa_hash_pointer,
                                                _mesa_key_pointer_equal);
       b->block_table = _mesa_hash_table_create(b, _mesa_hash_pointer,
index 40f0c78ae78b632aaf6167cb973e5043559ae755..edc3461b846fdee70131653fbea4ec68cf879d16 100644 (file)
@@ -61,7 +61,7 @@ struct vtn_block {
 struct vtn_function {
    struct exec_node node;
 
-   nir_function_overload *overload;
+   nir_function_impl *impl;
    struct vtn_block *start_block;
 
    const uint32_t *end;
@@ -204,6 +204,9 @@ struct vtn_builder {
 
    struct vtn_function *func;
    struct exec_list functions;
+
+   /* Current function parameter index */
+   unsigned func_param_idx;
 };
 
 static inline struct vtn_value *