Matteo Bruni : d3dcompiler: Parse "while" loops.

Alexandre Julliard julliard at winehq.org
Fri Sep 21 14:22:41 CDT 2012


Module: wine
Branch: master
Commit: 5fc67931b809330d609236f102179d9e1a237127
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5fc67931b809330d609236f102179d9e1a237127

Author: Matteo Bruni <mbruni at codeweavers.com>
Date:   Fri Sep 21 16:25:56 2012 +0200

d3dcompiler: Parse "while" loops.

---

 dlls/d3dcompiler_43/d3dcompiler_private.h |   14 +++
 dlls/d3dcompiler_43/hlsl.y                |  142 +++++++++++++++++++++++++++++
 2 files changed, 156 insertions(+), 0 deletions(-)

diff --git a/dlls/d3dcompiler_43/d3dcompiler_private.h b/dlls/d3dcompiler_43/d3dcompiler_private.h
index 22207c9..03fe66c 100644
--- a/dlls/d3dcompiler_43/d3dcompiler_private.h
+++ b/dlls/d3dcompiler_43/d3dcompiler_private.h
@@ -707,6 +707,7 @@ enum hlsl_ir_node_type
     HLSL_IR_EXPR,
     HLSL_IR_FUNCTION_DECL,
     HLSL_IR_IF,
+    HLSL_IR_LOOP,
     HLSL_IR_JUMP,
     HLSL_IR_SWIZZLE,
 };
@@ -768,6 +769,13 @@ struct hlsl_ir_if
     struct list *else_instrs;
 };
 
+struct hlsl_ir_loop
+{
+    struct hlsl_ir_node node;
+    /* loop condition is stored in the body (as "if (!condition) break;") */
+    struct list *body;
+};
+
 struct hlsl_ir_assignment
 {
     struct hlsl_ir_node node;
@@ -1068,6 +1076,12 @@ static inline struct hlsl_ir_if *if_from_node(const struct hlsl_ir_node *node)
     return CONTAINING_RECORD(node, struct hlsl_ir_if, node);
 }
 
+static inline struct hlsl_ir_loop *loop_from_node(const struct hlsl_ir_node *node)
+{
+    assert(node->type == HLSL_IR_LOOP);
+    return CONTAINING_RECORD(node, struct hlsl_ir_loop, node);
+}
+
 BOOL add_declaration(struct hlsl_scope *scope, struct hlsl_ir_var *decl, BOOL local_var) DECLSPEC_HIDDEN;
 struct hlsl_ir_var *get_variable(struct hlsl_scope *scope, const char *name) DECLSPEC_HIDDEN;
 void free_declaration(struct hlsl_ir_var *decl) DECLSPEC_HIDDEN;
diff --git a/dlls/d3dcompiler_43/hlsl.y b/dlls/d3dcompiler_43/hlsl.y
index 7bce054..491a826 100644
--- a/dlls/d3dcompiler_43/hlsl.y
+++ b/dlls/d3dcompiler_43/hlsl.y
@@ -256,6 +256,130 @@ static void declare_predefined_types(struct hlsl_scope *scope)
     add_type_to_scope(scope, type);
 }
 
+static struct hlsl_ir_if *loop_condition(struct list *cond_list)
+{
+    struct hlsl_ir_if *out_cond;
+    struct hlsl_ir_expr *not_cond;
+    struct hlsl_ir_node *cond, *operands[3];
+    struct hlsl_ir_jump *jump;
+    unsigned int count = list_count(cond_list);
+
+    if (!count)
+        return NULL;
+    if (count != 1)
+        ERR("Got multiple expressions in a for condition.\n");
+
+    cond = LIST_ENTRY(list_head(cond_list), struct hlsl_ir_node, entry);
+    out_cond = d3dcompiler_alloc(sizeof(*out_cond));
+    if (!out_cond)
+    {
+        ERR("Out of memory.\n");
+        return NULL;
+    }
+    out_cond->node.type = HLSL_IR_IF;
+    operands[0] = cond;
+    operands[1] = operands[2] = NULL;
+    not_cond = new_expr(HLSL_IR_UNOP_LOGIC_NOT, operands, &cond->loc);
+    if (!not_cond)
+    {
+        ERR("Out of memory.\n");
+        d3dcompiler_free(out_cond);
+        return NULL;
+    }
+    out_cond->condition = &not_cond->node;
+    jump = d3dcompiler_alloc(sizeof(*jump));
+    if (!jump)
+    {
+        ERR("Out of memory.\n");
+        d3dcompiler_free(out_cond);
+        d3dcompiler_free(not_cond);
+        return NULL;
+    }
+    jump->node.type = HLSL_IR_JUMP;
+    jump->type = HLSL_IR_JUMP_BREAK;
+    out_cond->then_instrs = d3dcompiler_alloc(sizeof(*out_cond->then_instrs));
+    if (!out_cond->then_instrs)
+    {
+        ERR("Out of memory.\n");
+        d3dcompiler_free(out_cond);
+        d3dcompiler_free(not_cond);
+        d3dcompiler_free(jump);
+        return NULL;
+    }
+    list_init(out_cond->then_instrs);
+    list_add_head(out_cond->then_instrs, &jump->node.entry);
+
+    return out_cond;
+}
+
+enum loop_type
+{
+    LOOP_FOR,
+    LOOP_WHILE,
+    LOOP_DO_WHILE
+};
+
+static struct list *create_loop(enum loop_type type, struct list *init, struct list *cond,
+        struct list *iter, struct list *body, struct source_location *loc)
+{
+    struct list *list = NULL;
+    struct hlsl_ir_loop *loop = NULL;
+    struct hlsl_ir_if *cond_jump = NULL;
+
+    list = d3dcompiler_alloc(sizeof(*list));
+    if (!list)
+        goto oom;
+    list_init(list);
+
+    if (init)
+        list_move_head(list, init);
+
+    loop = d3dcompiler_alloc(sizeof(*loop));
+    if (!loop)
+        goto oom;
+    loop->node.type = HLSL_IR_LOOP;
+    loop->node.loc = *loc;
+    list_add_tail(list, &loop->node.entry);
+    loop->body = d3dcompiler_alloc(sizeof(*loop->body));
+    if (!loop->body)
+        goto oom;
+    list_init(loop->body);
+
+    cond_jump = loop_condition(cond);
+    if (!cond_jump)
+        goto oom;
+
+    if (type != LOOP_DO_WHILE)
+        list_add_tail(loop->body, &cond_jump->node.entry);
+
+    list_move_tail(loop->body, body);
+
+    if (iter)
+        list_move_tail(loop->body, iter);
+
+    if (type == LOOP_DO_WHILE)
+        list_add_tail(loop->body, &cond_jump->node.entry);
+
+    d3dcompiler_free(init);
+    d3dcompiler_free(cond);
+    d3dcompiler_free(iter);
+    d3dcompiler_free(body);
+    return list;
+
+oom:
+    ERR("Out of memory.\n");
+    if (loop)
+        d3dcompiler_free(loop->body);
+    d3dcompiler_free(loop);
+    d3dcompiler_free(cond_jump);
+    d3dcompiler_free(list);
+    free_instr_list(init);
+    free_instr_list(cond);
+    free_instr_list(iter);
+    free_instr_list(body);
+    return NULL;
+}
+
 static unsigned int initializer_size(struct list *initializer)
 {
     unsigned int count = 0;
@@ -573,6 +697,7 @@ static BOOL add_typedef(DWORD modifiers, struct hlsl_type *orig_type, struct lis
 %type <list> compound_statement
 %type <list> jump_statement
 %type <list> selection_statement
+%type <list> loop_statement
 %type <function> func_declaration
 %type <function> func_prototype
 %type <parameter> parameter
@@ -1167,6 +1292,7 @@ statement:                declaration_statement
                         | compound_statement
                         | jump_statement
                         | selection_statement
+                        | loop_statement
 
                           /* FIXME: add rule for return with no value */
 jump_statement:           KW_RETURN expr ';'
@@ -1227,6 +1353,22 @@ if_body:                  statement
                                 $$.else_instrs = $3;
                             }
 
+loop_statement:           KW_WHILE '(' expr ')' statement
+                            {
+                                struct source_location loc;
+                                struct list *cond = d3dcompiler_alloc(sizeof(*cond));
+
+                                if (!cond)
+                                {
+                                    ERR("Out of memory.\n");
+                                    return -1;
+                                }
+                                list_init(cond);
+                                list_add_head(cond, &$3->entry);
+                                set_location(&loc, &@1);
+                                $$ = create_loop(LOOP_WHILE, NULL, cond, NULL, $5, &loc);
+                            }
+
 expr_statement:           ';'
                             {
                                 $$ = d3dcompiler_alloc(sizeof(*$$));




More information about the wine-cvs mailing list