vkd3d-shader/hlsl: Split declare_vars().

Basically, declare_vars() is separated in three functions:

1. check_invalid_in_out_modifiers(), which is to be called once per
   declaration and emits an error when in or out modifiers are used for
   these non-parameter variables.

2. declare_var(), which now handles one variable at the time and doesn't
   free any memory.

3. initialize_vars(), which takes care of preparing the initialization
   instructions of several variables and frees their struct
   parse_variable_def, using exclusively free_parse_variable_def().

This allows to declare variables individually before the initializer of
the next variable in the same declaration is parsed, which is used in
the following patches.

Also, simplifies memory management.
This commit is contained in:
Francisco Casas 2023-06-26 14:50:16 -04:00 committed by Alexandre Julliard
parent 396edae281
commit a34cf2e64e
Notes: Alexandre Julliard 2023-07-04 23:25:04 +02:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Zebediah Figura (@zfigura)
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/250

View File

@ -1949,47 +1949,38 @@ static bool type_has_numeric_components(struct hlsl_type *type)
return false; return false;
} }
static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, static void check_invalid_in_out_modifiers(struct hlsl_ctx *ctx, unsigned int modifiers,
unsigned int modifiers, const struct vkd3d_shader_location *modifiers_loc, struct list *var_list) const struct vkd3d_shader_location *loc)
{ {
struct parse_variable_def *v, *v_next; modifiers &= (HLSL_STORAGE_IN | HLSL_STORAGE_OUT);
struct hlsl_ir_function_decl *func; if (modifiers)
unsigned int invalid_modifiers;
struct list *statements_list;
struct hlsl_ir_var *var;
struct hlsl_type *type;
bool local = true;
if (basic_type->class == HLSL_CLASS_MATRIX)
assert(basic_type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK);
if (!(statements_list = make_empty_list(ctx)))
{
LIST_FOR_EACH_ENTRY_SAFE(v, v_next, var_list, struct parse_variable_def, entry)
free_parse_variable_def(v);
vkd3d_free(var_list);
return NULL;
}
if (!var_list)
return statements_list;
invalid_modifiers = modifiers & (HLSL_STORAGE_IN | HLSL_STORAGE_OUT);
if (invalid_modifiers)
{ {
struct vkd3d_string_buffer *string; struct vkd3d_string_buffer *string;
if ((string = hlsl_modifiers_to_string(ctx, invalid_modifiers))) if ((string = hlsl_modifiers_to_string(ctx, modifiers)))
hlsl_error(ctx, modifiers_loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
"Modifiers '%s' are not allowed on non-parameter variables.", string->buffer); "Modifiers '%s' are not allowed on non-parameter variables.", string->buffer);
hlsl_release_string_buffer(ctx, string); hlsl_release_string_buffer(ctx, string);
} }
}
LIST_FOR_EACH_ENTRY_SAFE(v, v_next, var_list, struct parse_variable_def, entry) static void declare_var(struct hlsl_ctx *ctx, struct hlsl_type *basic_type,
unsigned int modifiers, const struct vkd3d_shader_location *modifiers_loc, struct parse_variable_def *v)
{ {
struct hlsl_ir_function_decl *func;
struct hlsl_semantic new_semantic;
bool unbounded_res_array = false; bool unbounded_res_array = false;
struct hlsl_ir_var *var;
struct hlsl_type *type;
bool local = true;
char *var_name;
unsigned int i; unsigned int i;
assert(basic_type);
if (basic_type->class == HLSL_CLASS_MATRIX)
assert(basic_type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK);
type = basic_type; type = basic_type;
if (shader_is_sm_5_1(ctx) && type->class == HLSL_CLASS_OBJECT) if (shader_is_sm_5_1(ctx) && type->class == HLSL_CLASS_OBJECT)
@ -2003,8 +1994,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
if (v->arrays.count == 1) if (v->arrays.count == 1)
{ {
hlsl_fixme(ctx, &v->loc, "Unbounded resource arrays."); hlsl_fixme(ctx, &v->loc, "Unbounded resource arrays.");
free_parse_variable_def(v); return;
continue;
} }
else else
{ {
@ -2025,30 +2015,25 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
{ {
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
"Only innermost array size can be implicit."); "Only innermost array size can be implicit.");
free_parse_initializer(&v->initializer);
v->initializer.args_count = 0; v->initializer.args_count = 0;
} }
else if (elem_components == 0) else if (elem_components == 0)
{ {
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
"Cannot declare an implicit size array of a size 0 type."); "Cannot declare an implicit size array of a size 0 type.");
free_parse_initializer(&v->initializer);
v->initializer.args_count = 0; v->initializer.args_count = 0;
} }
else if (size == 0) else if (size == 0)
{ {
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
"Implicit size arrays need to be initialized."); "Implicit size arrays need to be initialized.");
free_parse_initializer(&v->initializer);
v->initializer.args_count = 0; v->initializer.args_count = 0;
} }
else if (size % elem_components != 0) else if (size % elem_components != 0)
{ {
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
"Cannot initialize implicit size array with %u components, expected a multiple of %u.", "Cannot initialize implicit size array with %u components, expected a multiple of %u.",
size, elem_components); size, elem_components);
free_parse_initializer(&v->initializer);
v->initializer.args_count = 0; v->initializer.args_count = 0;
} }
else else
@ -2059,12 +2044,25 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i]); type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i]);
} }
} }
vkd3d_free(v->arrays.sizes);
if (!(var = hlsl_new_var(ctx, v->name, type, &v->loc, &v->semantic, modifiers, &v->reg_reservation))) if (!(var_name = vkd3d_strdup(v->name)))
return;
new_semantic = v->semantic;
if (v->semantic.name)
{ {
free_parse_variable_def(v); if (!(new_semantic.name = vkd3d_strdup(v->semantic.name)))
continue; {
vkd3d_free(var_name);
return;
}
}
if (!(var = hlsl_new_var(ctx, var_name, type, &v->loc, &new_semantic, modifiers, &v->reg_reservation)))
{
hlsl_cleanup_semantic(&new_semantic);
vkd3d_free(var_name);
return;
} }
var->buffer = ctx->cur_buffer; var->buffer = ctx->cur_buffer;
@ -2137,9 +2135,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_INITIALIZER, hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_INITIALIZER,
"Const variable \"%s\" is missing an initializer.", var->name); "Const variable \"%s\" is missing an initializer.", var->name);
hlsl_free_var(var); hlsl_free_var(var);
free_parse_initializer(&v->initializer); return;
vkd3d_free(v);
continue;
} }
if (!hlsl_add_var(ctx, var, local)) if (!hlsl_add_var(ctx, var, local))
@ -2150,10 +2146,36 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
"Variable \"%s\" was already declared in this scope.", var->name); "Variable \"%s\" was already declared in this scope.", var->name);
hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name); hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name);
hlsl_free_var(var); hlsl_free_var(var);
free_parse_initializer(&v->initializer); return;
vkd3d_free(v); }
}
static struct list *initialize_vars(struct hlsl_ctx *ctx, struct list *var_list)
{
struct parse_variable_def *v, *v_next;
struct list *statements_list;
struct hlsl_ir_var *var;
struct hlsl_type *type;
if (!(statements_list = make_empty_list(ctx)))
{
LIST_FOR_EACH_ENTRY_SAFE(v, v_next, var_list, struct parse_variable_def, entry)
{
free_parse_variable_def(v);
}
vkd3d_free(var_list);
return NULL;
}
LIST_FOR_EACH_ENTRY_SAFE(v, v_next, var_list, struct parse_variable_def, entry)
{
/* If this fails, the variable failed to be declared. */
if (!(var = hlsl_get_var(ctx->cur_scope, v->name)))
{
free_parse_variable_def(v);
continue; continue;
} }
type = var->data_type;
if (v->initializer.args_count) if (v->initializer.args_count)
{ {
@ -2168,8 +2190,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
"Expected %u components in initializer, but got %u.", "Expected %u components in initializer, but got %u.",
hlsl_type_component_count(type), size); hlsl_type_component_count(type), size);
free_parse_initializer(&v->initializer); free_parse_variable_def(v);
vkd3d_free(v);
continue; continue;
} }
@ -2188,12 +2209,10 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
add_assignment(ctx, block_to_list(v->initializer.instrs), &load->node, ASSIGN_OP_ASSIGN, v->initializer.args[0]); add_assignment(ctx, block_to_list(v->initializer.instrs), &load->node, ASSIGN_OP_ASSIGN, v->initializer.args[0]);
} }
if (modifiers & HLSL_STORAGE_STATIC) if (var->storage_modifiers & HLSL_STORAGE_STATIC)
hlsl_block_add_block(&ctx->static_initializers, v->initializer.instrs); hlsl_block_add_block(&ctx->static_initializers, v->initializer.instrs);
else else
list_move_tail(statements_list, &v->initializer.instrs->instrs); list_move_tail(statements_list, &v->initializer.instrs->instrs);
vkd3d_free(v->initializer.args);
vkd3d_free(v->initializer.instrs);
} }
else if (var->storage_modifiers & HLSL_STORAGE_STATIC) else if (var->storage_modifiers & HLSL_STORAGE_STATIC)
{ {
@ -2203,32 +2222,33 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
if (type_has_object_components(var->data_type, false)) if (type_has_object_components(var->data_type, false))
{ {
vkd3d_free(v); free_parse_variable_def(v);
continue; continue;
} }
if (!(zero = hlsl_new_uint_constant(ctx, 0, &var->loc))) if (!(zero = hlsl_new_uint_constant(ctx, 0, &var->loc)))
{ {
vkd3d_free(v); free_parse_variable_def(v);
continue; continue;
} }
hlsl_block_add_instr(&ctx->static_initializers, zero); hlsl_block_add_instr(&ctx->static_initializers, zero);
if (!(cast = add_cast(ctx, &ctx->static_initializers.instrs, zero, var->data_type, &var->loc))) if (!(cast = add_cast(ctx, &ctx->static_initializers.instrs, zero, var->data_type, &var->loc)))
{ {
vkd3d_free(v); free_parse_variable_def(v);
continue; continue;
} }
if (!(store = hlsl_new_simple_store(ctx, var, cast))) if (!(store = hlsl_new_simple_store(ctx, var, cast)))
{ {
vkd3d_free(v); free_parse_variable_def(v);
continue; continue;
} }
hlsl_block_add_instr(&ctx->static_initializers, store); hlsl_block_add_instr(&ctx->static_initializers, store);
} }
vkd3d_free(v); free_parse_variable_def(v);
} }
vkd3d_free(var_list); vkd3d_free(var_list);
return statements_list; return statements_list;
} }
@ -4667,6 +4687,7 @@ preproc_directive:
struct_declaration: struct_declaration:
var_modifiers struct_spec variables_def_optional ';' var_modifiers struct_spec variables_def_optional ';'
{ {
struct parse_variable_def *v, *v_next;
struct hlsl_type *type; struct hlsl_type *type;
unsigned int modifiers = $1; unsigned int modifiers = $1;
@ -4682,7 +4703,24 @@ struct_declaration:
if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1)))
YYABORT; YYABORT;
$$ = declare_vars(ctx, type, modifiers, &@1, $3);
check_invalid_in_out_modifiers(ctx, modifiers, &@1);
if ($3)
{
LIST_FOR_EACH_ENTRY_SAFE(v, v_next, $3, struct parse_variable_def, entry)
{
declare_var(ctx, type, modifiers, &@1, v);
}
if (!($$ = initialize_vars(ctx, $3)))
YYABORT;
}
else
{
if (!($$ = make_empty_list(ctx)))
YYABORT;
}
} }
struct_spec: struct_spec:
@ -5526,12 +5564,22 @@ type_spec:
declaration: declaration:
var_modifiers type variables_def ';' var_modifiers type variables_def ';'
{ {
struct parse_variable_def *v, *v_next;
struct hlsl_type *type; struct hlsl_type *type;
unsigned int modifiers = $1; unsigned int modifiers = $1;
if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1)))
YYABORT; YYABORT;
$$ = declare_vars(ctx, type, modifiers, &@1, $3);
check_invalid_in_out_modifiers(ctx, modifiers, &@1);
LIST_FOR_EACH_ENTRY_SAFE(v, v_next, $3, struct parse_variable_def, entry)
{
declare_var(ctx, type, modifiers, &@1, v);
}
if (!($$ = initialize_vars(ctx, $3)))
YYABORT;
} }
variables_def_optional: variables_def_optional: