From: Zebediah Figura Subject: [PATCH 5/6] d3dcompiler: Store initializers inside the hlsl_ir_var structure. Message-Id: <20200611214422.275678-5-zfigura@codeweavers.com> Date: Thu, 11 Jun 2020 16:44:21 -0500 In-Reply-To: <20200611214422.275678-1-zfigura@codeweavers.com> References: <20200611214422.275678-1-zfigura@codeweavers.com> This is necessary so that global variable initializers can work correctly (both static and extern). Signed-off-by: Zebediah Figura --- dlls/d3dcompiler_43/d3dcompiler_private.h | 1 + dlls/d3dcompiler_43/hlsl.y | 155 ++++++++++++---------- dlls/d3dcompiler_43/utils.c | 4 + 3 files changed, 93 insertions(+), 67 deletions(-) diff --git a/dlls/d3dcompiler_43/d3dcompiler_private.h b/dlls/d3dcompiler_43/d3dcompiler_private.h index 9feaee0d8ac..bc8734f0148 100644 --- a/dlls/d3dcompiler_43/d3dcompiler_private.h +++ b/dlls/d3dcompiler_43/d3dcompiler_private.h @@ -706,6 +706,7 @@ struct hlsl_ir_var unsigned int modifiers; const struct reg_reservation *reg_reservation; struct list scope_entry, param_entry; + struct list initializer; unsigned int first_write, last_read; }; diff --git a/dlls/d3dcompiler_43/hlsl.y b/dlls/d3dcompiler_43/hlsl.y index 393f8d52fbd..734289f66a5 100644 --- a/dlls/d3dcompiler_43/hlsl.y +++ b/dlls/d3dcompiler_43/hlsl.y @@ -525,6 +525,7 @@ static struct hlsl_ir_var *new_var(const char *name, struct hlsl_type *type, con var->semantic = semantic; var->modifiers = modifiers; var->reg_reservation = reg_reservation; + list_init(&var->initializer); return var; } @@ -770,30 +771,18 @@ static void free_parse_variable_def(struct parse_variable_def *v) d3dcompiler_free(v); } -static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers, struct list *var_list) +static BOOL declare_vars(struct hlsl_type *basic_type, DWORD modifiers, struct list *var_list) { struct hlsl_type *type; struct parse_variable_def *v, *v_next; struct hlsl_ir_var *var; - struct hlsl_ir_node *assignment; BOOL ret, local = TRUE; - struct list *statements_list = d3dcompiler_alloc(sizeof(*statements_list)); if (basic_type->type == HLSL_CLASS_MATRIX) assert(basic_type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK); - if (!statements_list) - { - ERR("Out of memory.\n"); - LIST_FOR_EACH_ENTRY_SAFE(v, v_next, var_list, struct parse_variable_def, entry) - free_parse_variable_def(v); - d3dcompiler_free(var_list); - return NULL; - } - list_init(statements_list); - if (!var_list) - return statements_list; + return TRUE; LIST_FOR_EACH_ENTRY_SAFE(v, v_next, var_list, struct parse_variable_def, entry) { @@ -808,6 +797,7 @@ static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers, continue; } debug_dump_decl(type, modifiers, v->name, v->loc.line); + list_init(&var->initializer); if (hlsl_ctx.cur_scope == hlsl_ctx.globals) { @@ -835,7 +825,6 @@ static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers, if (v->initializer.args_count) { unsigned int size = initializer_size(&v->initializer); - struct hlsl_ir_load *load; TRACE("Variable with initializer.\n"); if (type->type <= HLSL_CLASS_LAST_NUMERIC @@ -862,7 +851,7 @@ static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers, if (type->type == HLSL_CLASS_STRUCT) { - struct_var_initializer(statements_list, var, &v->initializer); + struct_var_initializer(&var->initializer, var, &v->initializer); d3dcompiler_free(v); continue; } @@ -888,19 +877,16 @@ static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers, continue; } - list_move_tail(statements_list, v->initializer.instrs); + list_move_tail(&var->initializer, v->initializer.instrs); d3dcompiler_free(v->initializer.instrs); - - load = new_var_load(var, var->loc); - list_add_tail(statements_list, &load->node.entry); - assignment = make_assignment(&load->node, ASSIGN_OP_ASSIGN, v->initializer.args[0]); d3dcompiler_free(v->initializer.args); - list_add_tail(statements_list, &assignment->entry); + + implicit_conversion(node_from_list(&var->initializer), var->data_type, &var->loc); } d3dcompiler_free(v); } d3dcompiler_free(var_list); - return statements_list; + return TRUE; } static BOOL add_struct_field(struct list *fields, struct hlsl_struct_field *field) @@ -1282,6 +1268,20 @@ static struct hlsl_ir_function_decl *new_func_decl(struct hlsl_type *return_type return decl; } +/* Append an instruction assigning "var" to its own initializer. */ +static BOOL add_assignment_to_initializer(struct hlsl_ir_var *var) +{ + struct hlsl_ir_assignment *assign; + + if (!list_empty(&var->initializer)) + { + if (!(assign = make_simple_assignment(var, node_from_list(&var->initializer)))) + return FALSE; + list_add_tail(&var->initializer, &assign->node.entry); + } + return TRUE; +} + %} %locations @@ -1416,9 +1416,6 @@ static struct hlsl_ir_function_decl *new_func_decl(struct hlsl_type *return_type %type boolean %type base_type %type type -%type declaration_statement -%type declaration -%type struct_declaration %type struct_spec %type named_struct_spec %type unnamed_struct_spec @@ -1566,7 +1563,8 @@ struct_declaration: var_modifiers struct_spec variables_def_optional ';' if (!(type = apply_type_modifiers($2, &modifiers, get_location(&@1)))) YYABORT; - $$ = declare_vars(type, modifiers, $3); + if (!declare_vars(type, modifiers, $3)) + YYABORT; } struct_spec: named_struct_spec @@ -1908,18 +1906,11 @@ base_type: d3dcompiler_free($2); } -declaration_statement: declaration - | struct_declaration - | typedef - { - $$ = d3dcompiler_alloc(sizeof(*$$)); - if (!$$) - { - ERR("Out of memory\n"); - YYABORT; - } - list_init($$); - } +declaration_statement: + + declaration + | struct_declaration + | typedef typedef_type: type | struct_spec @@ -1967,7 +1958,8 @@ declaration: var_modifiers type variables_def ';' if (!(type = apply_type_modifiers($2, &modifiers, get_location(&@1)))) YYABORT; - $$ = declare_vars(type, modifiers, $3); + if (!declare_vars(type, modifiers, $3)) + YYABORT; } variables_def_optional: /* Empty */ @@ -2148,12 +2140,29 @@ statement_list: statement d3dcompiler_free($2); } -statement: declaration_statement - | expr_statement - | compound_statement - | jump_statement - | selection_statement - | loop_statement +statement: + + declaration_statement + { + struct hlsl_ir_var *var; + + /* Append any initializers made by this declaration_statement to the + * instruction list. */ + if (!($$ = d3dcompiler_alloc(sizeof(*$$)))) + YYABORT; + list_init($$); + LIST_FOR_EACH_ENTRY(var, &hlsl_ctx.cur_scope->vars, struct hlsl_ir_var, scope_entry) + { + if (!add_assignment_to_initializer(var)) + YYABORT; + list_move_tail($$, &var->initializer); + } + } + | expr_statement + | compound_statement + | jump_statement + | selection_statement + | loop_statement jump_statement: KW_RETURN expr ';' { @@ -2206,27 +2215,39 @@ if_body: statement $$.else_instrs = $3; } -loop_statement: KW_WHILE '(' expr ')' statement - { - $$ = create_loop(LOOP_WHILE, NULL, $3, NULL, $5, get_location(&@1)); - } - | KW_DO statement KW_WHILE '(' expr ')' ';' - { - $$ = create_loop(LOOP_DO_WHILE, NULL, $5, NULL, $2, get_location(&@1)); - } - | KW_FOR '(' scope_start expr_statement expr_statement expr ')' statement - { - $$ = create_loop(LOOP_FOR, $4, $5, $6, $8, get_location(&@1)); - pop_scope(&hlsl_ctx); - } - | KW_FOR '(' scope_start declaration expr_statement expr ')' statement - { - if (!$4) - hlsl_report_message(get_location(&@4), HLSL_LEVEL_WARNING, - "no expressions in for loop initializer"); - $$ = create_loop(LOOP_FOR, $4, $5, $6, $8, get_location(&@1)); - pop_scope(&hlsl_ctx); - } +loop_statement: + + KW_WHILE '(' expr ')' statement + { + $$ = create_loop(LOOP_WHILE, NULL, $3, NULL, $5, get_location(&@1)); + } + | KW_DO statement KW_WHILE '(' expr ')' ';' + { + $$ = create_loop(LOOP_DO_WHILE, NULL, $5, NULL, $2, get_location(&@1)); + } + | KW_FOR '(' scope_start expr_statement expr_statement expr ')' statement + { + $$ = create_loop(LOOP_FOR, $4, $5, $6, $8, get_location(&@1)); + pop_scope(&hlsl_ctx); + } + | KW_FOR '(' scope_start declaration expr_statement expr ')' statement + { + struct hlsl_ir_var *var; + + $$ = create_loop(LOOP_FOR, NULL, $5, $6, $8, get_location(&@1)); + + /* Prepend any initializers made by this declaration to the + * instruction list. Walk through the list in reverse, so that the + * initializers are executed in the order that they were declared. */ + LIST_FOR_EACH_ENTRY_REV(var, &hlsl_ctx.cur_scope->vars, struct hlsl_ir_var, scope_entry) + { + if (!add_assignment_to_initializer(var)) + YYABORT; + list_move_head($$, &var->initializer); + } + + pop_scope(&hlsl_ctx); + } expr_statement: ';' { diff --git a/dlls/d3dcompiler_43/utils.c b/dlls/d3dcompiler_43/utils.c index 4769ebc399b..e17b830d916 100644 --- a/dlls/d3dcompiler_43/utils.c +++ b/dlls/d3dcompiler_43/utils.c @@ -798,6 +798,10 @@ struct hlsl_ir_var *get_variable(struct hlsl_scope *scope, const char *name) void free_declaration(struct hlsl_ir_var *decl) { + struct hlsl_ir_node *instr, *next; + + LIST_FOR_EACH_ENTRY_SAFE(instr, next, &decl->initializer, struct hlsl_ir_node, entry) + free_instr(instr); d3dcompiler_free((void *)decl->name); d3dcompiler_free((void *)decl->semantic); d3dcompiler_free((void *)decl->reg_reservation); -- 2.27.0