d3dcompiler: Parse initializer lists using a variable-size array.

Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2019-08-12 10:27:28 -05:00 committed by Alexandre Julliard
parent cfa7f3a3f5
commit fbc9ff506c
2 changed files with 65 additions and 59 deletions

View file

@ -980,6 +980,12 @@ struct parse_colon_attribute
struct reg_reservation *reg_reservation; struct reg_reservation *reg_reservation;
}; };
struct parse_initializer
{
struct hlsl_ir_node **args;
unsigned int args_count;
};
struct parse_variable_def struct parse_variable_def
{ {
struct list entry; struct list entry;
@ -989,7 +995,7 @@ struct parse_variable_def
unsigned int array_size; unsigned int array_size;
const char *semantic; const char *semantic;
struct reg_reservation *reg_reservation; struct reg_reservation *reg_reservation;
struct list *initializer; struct parse_initializer initializer;
}; };
struct parse_function struct parse_function

View file

@ -378,19 +378,26 @@ oom:
return NULL; return NULL;
} }
static unsigned int initializer_size(struct list *initializer) static unsigned int initializer_size(const struct parse_initializer *initializer)
{ {
unsigned int count = 0; unsigned int count = 0, i;
struct hlsl_ir_node *node;
LIST_FOR_EACH_ENTRY(node, initializer, struct hlsl_ir_node, entry) for (i = 0; i < initializer->args_count; ++i)
{ {
count += components_count_type(node->data_type); count += components_count_type(initializer->args[i]->data_type);
} }
TRACE("Initializer size = %u.\n", count); TRACE("Initializer size = %u.\n", count);
return count; return count;
} }
static void free_parse_initializer(struct parse_initializer *initializer)
{
unsigned int i;
for (i = 0; i < initializer->args_count; ++i)
free_instr(initializer->args[i]);
d3dcompiler_free(initializer->args);
}
static struct hlsl_ir_swizzle *new_swizzle(DWORD s, unsigned int components, static struct hlsl_ir_swizzle *new_swizzle(DWORD s, unsigned int components,
struct hlsl_ir_node *val, struct source_location *loc) struct hlsl_ir_node *val, struct source_location *loc)
{ {
@ -488,30 +495,30 @@ static struct hlsl_ir_swizzle *get_swizzle(struct hlsl_ir_node *value, const cha
return NULL; return NULL;
} }
static void struct_var_initializer(struct list *list, struct hlsl_ir_var *var, struct list *initializer) static void struct_var_initializer(struct list *list, struct hlsl_ir_var *var,
struct parse_initializer *initializer)
{ {
struct hlsl_type *type = var->node.data_type; struct hlsl_type *type = var->node.data_type;
struct hlsl_ir_node *node;
struct hlsl_struct_field *field; struct hlsl_struct_field *field;
struct list *cur_node;
struct hlsl_ir_node *assignment; struct hlsl_ir_node *assignment;
struct hlsl_ir_deref *deref; struct hlsl_ir_deref *deref;
unsigned int i = 0;
if (initializer_size(initializer) != components_count_type(type)) if (initializer_size(initializer) != components_count_type(type))
{ {
hlsl_report_message(var->node.loc.file, var->node.loc.line, var->node.loc.col, HLSL_LEVEL_ERROR, hlsl_report_message(var->node.loc.file, var->node.loc.line, var->node.loc.col, HLSL_LEVEL_ERROR,
"structure initializer mismatch"); "structure initializer mismatch");
free_instr_list(initializer); free_parse_initializer(initializer);
return; return;
} }
cur_node = list_head(initializer);
assert(cur_node);
node = LIST_ENTRY(cur_node, struct hlsl_ir_node, entry);
LIST_FOR_EACH_ENTRY(field, type->e.elements, struct hlsl_struct_field, entry) LIST_FOR_EACH_ENTRY(field, type->e.elements, struct hlsl_struct_field, entry)
{ {
if (!cur_node) struct hlsl_ir_node *node = initializer->args[i];
if (i++ >= initializer->args_count)
{ {
d3dcompiler_free(initializer); d3dcompiler_free(initializer->args);
return; return;
} }
if (components_count_type(field->type) == components_count_type(node->data_type)) if (components_count_type(field->type) == components_count_type(node->data_type))
@ -528,19 +535,12 @@ static void struct_var_initializer(struct list *list, struct hlsl_ir_var *var, s
} }
else else
FIXME("Initializing with \"mismatched\" fields is not supported yet.\n"); FIXME("Initializing with \"mismatched\" fields is not supported yet.\n");
cur_node = list_next(initializer, cur_node);
node = LIST_ENTRY(cur_node, struct hlsl_ir_node, entry);
} }
/* Free initializer elements in excess. */ /* Free initializer elements in excess. */
while (cur_node) for (; i < initializer->args_count; ++i)
{ free_instr(initializer->args[i]);
struct list *next = list_next(initializer, cur_node); d3dcompiler_free(initializer->args);
free_instr(node);
cur_node = next;
node = LIST_ENTRY(cur_node, struct hlsl_ir_node, entry);
}
d3dcompiler_free(initializer);
} }
static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers, struct list *var_list) static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers, struct list *var_list)
@ -593,7 +593,7 @@ static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers,
local = FALSE; local = FALSE;
} }
if (var->modifiers & HLSL_MODIFIER_CONST && !(var->modifiers & HLSL_STORAGE_UNIFORM) && !v->initializer) if (var->modifiers & HLSL_MODIFIER_CONST && !(var->modifiers & HLSL_STORAGE_UNIFORM) && !v->initializer.args_count)
{ {
hlsl_report_message(v->loc.file, v->loc.line, v->loc.col, hlsl_report_message(v->loc.file, v->loc.line, v->loc.col,
HLSL_LEVEL_ERROR, "const variable without initializer"); HLSL_LEVEL_ERROR, "const variable without initializer");
@ -611,10 +611,9 @@ static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers,
} }
TRACE("Declared variable %s.\n", var->name); TRACE("Declared variable %s.\n", var->name);
if (v->initializer) if (v->initializer.args_count)
{ {
unsigned int size = initializer_size(v->initializer); unsigned int size = initializer_size(&v->initializer);
struct hlsl_ir_node *node;
TRACE("Variable with initializer.\n"); TRACE("Variable with initializer.\n");
if (type->type <= HLSL_CLASS_LAST_NUMERIC if (type->type <= HLSL_CLASS_LAST_NUMERIC
@ -624,7 +623,7 @@ static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers,
{ {
hlsl_report_message(v->loc.file, v->loc.line, v->loc.col, HLSL_LEVEL_ERROR, hlsl_report_message(v->loc.file, v->loc.line, v->loc.col, HLSL_LEVEL_ERROR,
"'%s' initializer does not match", v->name); "'%s' initializer does not match", v->name);
free_instr_list(v->initializer); free_parse_initializer(&v->initializer);
d3dcompiler_free(v); d3dcompiler_free(v);
continue; continue;
} }
@ -634,43 +633,43 @@ static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers,
{ {
hlsl_report_message(v->loc.file, v->loc.line, v->loc.col, HLSL_LEVEL_ERROR, hlsl_report_message(v->loc.file, v->loc.line, v->loc.col, HLSL_LEVEL_ERROR,
"'%s' initializer does not match", v->name); "'%s' initializer does not match", v->name);
free_instr_list(v->initializer); free_parse_initializer(&v->initializer);
d3dcompiler_free(v); d3dcompiler_free(v);
continue; continue;
} }
if (type->type == HLSL_CLASS_STRUCT) if (type->type == HLSL_CLASS_STRUCT)
{ {
struct_var_initializer(statements_list, var, v->initializer); struct_var_initializer(statements_list, var, &v->initializer);
d3dcompiler_free(v); d3dcompiler_free(v);
continue; continue;
} }
if (type->type > HLSL_CLASS_LAST_NUMERIC) if (type->type > HLSL_CLASS_LAST_NUMERIC)
{ {
FIXME("Initializers for non scalar/struct variables not supported yet.\n"); FIXME("Initializers for non scalar/struct variables not supported yet.\n");
free_instr_list(v->initializer); free_parse_initializer(&v->initializer);
d3dcompiler_free(v); d3dcompiler_free(v);
continue; continue;
} }
if (v->array_size > 0) if (v->array_size > 0)
{ {
FIXME("Initializing arrays is not supported yet.\n"); FIXME("Initializing arrays is not supported yet.\n");
free_instr_list(v->initializer); free_parse_initializer(&v->initializer);
d3dcompiler_free(v); d3dcompiler_free(v);
continue; continue;
} }
if (list_count(v->initializer) > 1) if (v->initializer.args_count > 1)
{ {
FIXME("Complex initializers are not supported yet.\n"); FIXME("Complex initializers are not supported yet.\n");
free_instr_list(v->initializer); free_parse_initializer(&v->initializer);
d3dcompiler_free(v); d3dcompiler_free(v);
continue; continue;
} }
node = LIST_ENTRY(list_head(v->initializer), struct hlsl_ir_node, entry);
assignment = make_assignment(&var->node, ASSIGN_OP_ASSIGN, assignment = make_assignment(&var->node, ASSIGN_OP_ASSIGN,
BWRITERSP_WRITEMASK_ALL, node); BWRITERSP_WRITEMASK_ALL, v->initializer.args[0]);
d3dcompiler_free(v->initializer.args);
list_add_tail(statements_list, &assignment->entry); list_add_tail(statements_list, &assignment->entry);
d3dcompiler_free(v->initializer);
} }
d3dcompiler_free(v); d3dcompiler_free(v);
} }
@ -718,11 +717,11 @@ static struct list *gen_struct_fields(struct hlsl_type *type, DWORD modifiers, s
field->name = v->name; field->name = v->name;
field->modifiers = modifiers; field->modifiers = modifiers;
field->semantic = v->semantic; field->semantic = v->semantic;
if (v->initializer) if (v->initializer.args_count)
{ {
hlsl_report_message(v->loc.file, v->loc.line, v->loc.col, HLSL_LEVEL_ERROR, hlsl_report_message(v->loc.file, v->loc.line, v->loc.col, HLSL_LEVEL_ERROR,
"struct field with an initializer.\n"); "struct field with an initializer.\n");
free_instr_list(v->initializer); free_parse_initializer(&v->initializer);
} }
list_add_tail(list, &field->entry); list_add_tail(list, &field->entry);
d3dcompiler_free(v); d3dcompiler_free(v);
@ -905,6 +904,7 @@ static const struct hlsl_ir_function_decl *get_overloaded_func(struct wine_rb_tr
struct list *list; struct list *list;
struct parse_function function; struct parse_function function;
struct parse_parameter parameter; struct parse_parameter parameter;
struct parse_initializer initializer;
struct parse_variable_def *variable_def; struct parse_variable_def *variable_def;
struct parse_if_body if_body; struct parse_if_body if_body;
enum parse_unary_op unary_op; enum parse_unary_op unary_op;
@ -1028,8 +1028,8 @@ static const struct hlsl_ir_function_decl *get_overloaded_func(struct wine_rb_tr
%type <type> unnamed_struct_spec %type <type> unnamed_struct_spec
%type <list> type_specs %type <list> type_specs
%type <variable_def> type_spec %type <variable_def> type_spec
%type <list> complex_initializer %type <initializer> complex_initializer
%type <list> initializer_expr_list %type <initializer> initializer_expr_list
%type <instr> initializer_expr %type <instr> initializer_expr
%type <modifiers> var_modifiers %type <modifiers> var_modifiers
%type <list> field %type <list> field
@ -1675,9 +1675,10 @@ var_modifiers: /* Empty */
complex_initializer: initializer_expr complex_initializer: initializer_expr
{ {
$$ = d3dcompiler_alloc(sizeof(*$$)); $$.args_count = 1;
list_init($$); if (!($$.args = d3dcompiler_alloc(sizeof(*$$.args))))
list_add_head($$, &$1->entry); YYABORT;
$$.args[0] = $1;
} }
| '{' initializer_expr_list '}' | '{' initializer_expr_list '}'
{ {
@ -1695,14 +1696,17 @@ initializer_expr: assignment_expr
initializer_expr_list: initializer_expr initializer_expr_list: initializer_expr
{ {
$$ = d3dcompiler_alloc(sizeof(*$$)); $$.args_count = 1;
list_init($$); if (!($$.args = d3dcompiler_alloc(sizeof(*$$.args))))
list_add_head($$, &$1->entry); YYABORT;
$$.args[0] = $1;
} }
| initializer_expr_list ',' initializer_expr | initializer_expr_list ',' initializer_expr
{ {
$$ = $1; $$ = $1;
list_add_tail($$, &$3->entry); if (!($$.args = d3dcompiler_realloc($$.args, ($$.args_count + 1) * sizeof(*$$.args))))
YYABORT;
$$.args[$$.args_count++] = $3;
} }
boolean: KW_TRUE boolean: KW_TRUE
@ -2080,7 +2084,6 @@ postfix_expr: primary_expr
| var_modifiers type '(' initializer_expr_list ')' | var_modifiers type '(' initializer_expr_list ')'
{ {
struct hlsl_ir_constructor *constructor; struct hlsl_ir_constructor *constructor;
struct hlsl_ir_node *instr;
TRACE("%s constructor.\n", debug_hlsl_type($2)); TRACE("%s constructor.\n", debug_hlsl_type($2));
if ($1) if ($1)
@ -2097,25 +2100,22 @@ postfix_expr: primary_expr
set_parse_status(&hlsl_ctx.status, PARSE_ERR); set_parse_status(&hlsl_ctx.status, PARSE_ERR);
YYABORT; YYABORT;
} }
if ($2->dimx * $2->dimy != initializer_size($4)) if ($2->dimx * $2->dimy != initializer_size(&$4))
{ {
hlsl_message("Line %u: wrong number of components in constructor.\n", hlsl_message("Line %u: wrong number of components in constructor.\n",
hlsl_ctx.line_no); hlsl_ctx.line_no);
set_parse_status(&hlsl_ctx.status, PARSE_ERR); set_parse_status(&hlsl_ctx.status, PARSE_ERR);
YYABORT; YYABORT;
} }
assert($4.args_count <= ARRAY_SIZE(constructor->args));
constructor = d3dcompiler_alloc(sizeof(*constructor)); constructor = d3dcompiler_alloc(sizeof(*constructor));
constructor->node.type = HLSL_IR_CONSTRUCTOR; constructor->node.type = HLSL_IR_CONSTRUCTOR;
set_location(&constructor->node.loc, &@3); set_location(&constructor->node.loc, &@3);
constructor->node.data_type = $2; constructor->node.data_type = $2;
constructor->args_count = 0; constructor->args_count = $4.args_count;
LIST_FOR_EACH_ENTRY(instr, $4, struct hlsl_ir_node, entry) memcpy(constructor->args, $4.args, $4.args_count * sizeof(*$4.args));
{ d3dcompiler_free($4.args);
constructor->args[constructor->args_count++] = instr;
}
d3dcompiler_free($4);
$$ = &constructor->node; $$ = &constructor->node;
} }