[PATCH 5/6] d3dcompiler: Store initializers inside the hlsl_ir_var structure.

Zebediah Figura z.figura12 at gmail.com
Thu Jun 11 16:44:21 CDT 2020


This is necessary so that global variable initializers can work correctly (both static and extern).

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 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 <boolval> boolean
 %type <type> base_type
 %type <type> type
-%type <list> declaration_statement
-%type <list> declaration
-%type <list> struct_declaration
 %type <type> struct_spec
 %type <type> named_struct_spec
 %type <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




More information about the wine-devel mailing list