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 *
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;
}
}
}
- 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;
}
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);
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);
}
case SpvOpSwitch:
- case SpvOpReturnValue:
case SpvOpUnreachable:
default:
unreachable("Unhandled opcode");
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,