[PATCH v3 1/3] d3dcompiler: Store derefs as an offset to a variable.

Zebediah Figura z.figura12 at gmail.com
Fri May 22 15:45:29 CDT 2020


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
v3: Always emit a mul expr in new_array_deref(), now that we're storing the
offset in components.

 dlls/d3dcompiler_43/d3dcompiler_private.h |  24 +---
 dlls/d3dcompiler_43/hlsl.y                | 131 ++++++++++++----------
 dlls/d3dcompiler_43/utils.c               |  76 ++-----------
 3 files changed, 86 insertions(+), 145 deletions(-)

diff --git a/dlls/d3dcompiler_43/d3dcompiler_private.h b/dlls/d3dcompiler_43/d3dcompiler_private.h
index 387e932a6cc..31cf1ed582d 100644
--- a/dlls/d3dcompiler_43/d3dcompiler_private.h
+++ b/dlls/d3dcompiler_43/d3dcompiler_private.h
@@ -841,30 +841,10 @@ struct hlsl_ir_swizzle
     DWORD swizzle;
 };
 
-enum hlsl_ir_deref_type
-{
-    HLSL_IR_DEREF_VAR,
-    HLSL_IR_DEREF_ARRAY,
-    HLSL_IR_DEREF_RECORD,
-};
-
 struct hlsl_deref
 {
-    enum hlsl_ir_deref_type type;
-    union
-    {
-        struct hlsl_ir_var *var;
-        struct
-        {
-            struct hlsl_ir_node *array;
-            struct hlsl_ir_node *index;
-        } array;
-        struct
-        {
-            struct hlsl_ir_node *record;
-            struct hlsl_struct_field *field;
-        } record;
-    } v;
+    struct hlsl_ir_var *var;
+    struct hlsl_ir_node *offset;
 };
 
 struct hlsl_ir_deref
diff --git a/dlls/d3dcompiler_43/hlsl.y b/dlls/d3dcompiler_43/hlsl.y
index cc868757a26..f66553898f3 100644
--- a/dlls/d3dcompiler_43/hlsl.y
+++ b/dlls/d3dcompiler_43/hlsl.y
@@ -538,8 +538,7 @@ static struct hlsl_ir_assignment *make_simple_assignment(struct hlsl_ir_var *lhs
         return NULL;
 
     init_node(&assign->node, HLSL_IR_ASSIGNMENT, rhs->data_type, rhs->loc);
-    assign->lhs.type = HLSL_IR_DEREF_VAR;
-    assign->lhs.v.var = lhs;
+    assign->lhs.var = lhs;
     assign->rhs = rhs;
     if (type_is_single_reg(lhs->data_type))
         assign->writemask = (1 << lhs->data_type->dimx) - 1;
@@ -547,6 +546,21 @@ static struct hlsl_ir_assignment *make_simple_assignment(struct hlsl_ir_var *lhs
     return assign;
 }
 
+static struct hlsl_ir_constant *new_uint_constant(unsigned int n, const struct source_location loc)
+{
+    struct hlsl_type *type;
+    struct hlsl_ir_constant *c;
+
+    if (!(type = new_hlsl_type(d3dcompiler_strdup("uint"), HLSL_CLASS_SCALAR, HLSL_TYPE_UINT, 1, 1)))
+        return NULL;
+
+    if (!(c = d3dcompiler_alloc(sizeof(*c))))
+        return NULL;
+    init_node(&c->node, HLSL_IR_CONSTANT, type, loc);
+    c->v.value.u[0] = n;
+    return c;
+}
+
 static struct hlsl_ir_deref *new_var_deref(struct hlsl_ir_var *var, const struct source_location loc)
 {
     struct hlsl_ir_deref *deref = d3dcompiler_alloc(sizeof(*deref));
@@ -557,61 +571,75 @@ static struct hlsl_ir_deref *new_var_deref(struct hlsl_ir_var *var, const struct
         return NULL;
     }
     init_node(&deref->node, HLSL_IR_DEREF, var->data_type, loc);
-    deref->src.type = HLSL_IR_DEREF_VAR;
-    deref->src.v.var = var;
+    deref->src.var = var;
     return deref;
 }
 
-static struct hlsl_ir_node *get_var_deref(struct hlsl_ir_node *node)
+static struct hlsl_ir_deref *new_deref(struct hlsl_ir_node *var_node, struct hlsl_ir_node *offset,
+        struct hlsl_type *data_type, const struct source_location loc)
 {
-    struct hlsl_ir_assignment *assign;
+    struct hlsl_ir_node *add = NULL;
     struct hlsl_ir_deref *deref;
     struct hlsl_ir_var *var;
-    char name[27];
 
-    if (node->type == HLSL_IR_DEREF)
-        return node;
+    if (var_node->type == HLSL_IR_DEREF)
+    {
+        const struct hlsl_deref *src = &deref_from_node(var_node)->src;
 
-    sprintf(name, "<deref-%p>", node);
-    if (!(var = new_synthetic_var(name, node->data_type, node->loc)))
-        return NULL;
+        var = src->var;
+        if (src->offset)
+        {
+            if (!(add = new_binary_expr(HLSL_IR_BINOP_ADD, src->offset, offset, loc)))
+                return NULL;
+            list_add_after(&offset->entry, &add->entry);
+            offset = add;
+        }
+    }
+    else
+    {
+        struct hlsl_ir_assignment *assign;
+        char name[27];
 
-    TRACE("Synthesized variable %p for %s node.\n", var, debug_node_type(node->type));
+        sprintf(name, "<deref-%p>", var_node);
+        if (!(var = new_synthetic_var(name, var_node->data_type, var_node->loc)))
+            return NULL;
 
-    if (!(assign = make_simple_assignment(var, node)))
-        return NULL;
-    list_add_after(&node->entry, &assign->node.entry);
+        TRACE("Synthesized variable %p for %s node.\n", var, debug_node_type(var_node->type));
+
+        if (!(assign = make_simple_assignment(var, var_node)))
+            return NULL;
 
-    if (!(deref = new_var_deref(var, var->loc)))
+        list_add_after(&var_node->entry, &assign->node.entry);
+    }
+
+    if (!(deref = d3dcompiler_alloc(sizeof(*deref))))
         return NULL;
-    list_add_after(&assign->node.entry, &deref->node.entry);
-    return &deref->node;
+    init_node(&deref->node, HLSL_IR_DEREF, data_type, loc);
+    deref->src.var = var;
+    deref->src.offset = offset;
+    list_add_after(&offset->entry, &deref->node.entry);
+    return deref;
 }
 
 static struct hlsl_ir_deref *new_record_deref(struct hlsl_ir_node *record,
-        struct hlsl_struct_field *field, const struct source_location loc)
+        const struct hlsl_struct_field *field, const struct source_location loc)
 {
-    struct hlsl_ir_deref *deref;
+    struct hlsl_ir_constant *c;
 
-    if (!(record = get_var_deref(record)))
+    if (!(c = new_uint_constant(field->reg_offset * 4, loc)))
         return NULL;
+    list_add_after(&record->entry, &c->node.entry);
 
-    if (!(deref = d3dcompiler_alloc(sizeof(*deref))))
-        return NULL;
-
-    init_node(&deref->node, HLSL_IR_DEREF, field->type, loc);
-    deref->src.type = HLSL_IR_DEREF_RECORD;
-    deref->src.v.record.record = record;
-    deref->src.v.record.field = field;
-    return deref;
+    return new_deref(record, &c->node, field->type, loc);
 }
 
 static struct hlsl_ir_deref *new_array_deref(struct hlsl_ir_node *array,
         struct hlsl_ir_node *index, const struct source_location loc)
 {
     const struct hlsl_type *expr_type = array->data_type;
-    struct hlsl_ir_deref *deref;
     struct hlsl_type *data_type;
+    struct hlsl_ir_constant *c;
+    struct hlsl_ir_node *mul;
 
     TRACE("Array dereference from type %s.\n", debug_hlsl_type(expr_type));
 
@@ -621,6 +649,7 @@ static struct hlsl_ir_deref *new_array_deref(struct hlsl_ir_node *array,
     }
     else if (expr_type->type == HLSL_CLASS_MATRIX || expr_type->type == HLSL_CLASS_VECTOR)
     {
+        /* This needs to be lowered now, while we still have type information. */
         FIXME("Index of matrix or vector type.\n");
         return NULL;
     }
@@ -633,17 +662,15 @@ static struct hlsl_ir_deref *new_array_deref(struct hlsl_ir_node *array,
         return NULL;
     }
 
-    if (!(array = get_var_deref(array)))
+    if (!(c = new_uint_constant(data_type->reg_size * 4, loc)))
         return NULL;
-
-    if (!(deref = d3dcompiler_alloc(sizeof(*deref))))
+    list_add_after(&index->entry, &c->node.entry);
+    if (!(mul = new_binary_expr(HLSL_IR_BINOP_MUL, index, &c->node, loc)))
         return NULL;
+    list_add_after(&c->node.entry, &mul->entry);
+    index = mul;
 
-    init_node(&deref->node, HLSL_IR_DEREF, data_type, loc);
-    deref->src.type = HLSL_IR_DEREF_ARRAY;
-    deref->src.v.array.array = array;
-    deref->src.v.array.index = index;
-    return deref;
+    return new_deref(array, index, data_type, loc);
 }
 
 static void struct_var_initializer(struct list *list, struct hlsl_ir_var *var,
@@ -2748,22 +2775,6 @@ static unsigned int index_instructions(struct list *instrs, unsigned int index)
     return index;
 }
 
-/* Walk the chain of derefs and retrieve the actual variable we care about. */
-static struct hlsl_ir_var *hlsl_var_from_deref(const struct hlsl_deref *deref)
-{
-    switch (deref->type)
-    {
-        case HLSL_IR_DEREF_VAR:
-            return deref->v.var;
-        case HLSL_IR_DEREF_ARRAY:
-            return hlsl_var_from_deref(&deref_from_node(deref->v.array.array)->src);
-        case HLSL_IR_DEREF_RECORD:
-            return hlsl_var_from_deref(&deref_from_node(deref->v.record.record)->src);
-    }
-    assert(0);
-    return NULL;
-}
-
 /* Compute the earliest and latest liveness for each variable. In the case that
  * a variable is accessed inside of a loop, we promote its liveness to extend
  * to at least the range of the entire loop. Note that we don't need to do this
@@ -2781,10 +2792,12 @@ static void compute_liveness_recurse(struct list *instrs, unsigned int loop_firs
         case HLSL_IR_ASSIGNMENT:
         {
             struct hlsl_ir_assignment *assignment = assignment_from_node(instr);
-            var = hlsl_var_from_deref(&assignment->lhs);
+            var = assignment->lhs.var;
             if (!var->first_write)
                 var->first_write = loop_first ? min(instr->index, loop_first) : instr->index;
             assignment->rhs->last_read = instr->index;
+            if (assignment->lhs.offset)
+                assignment->lhs.offset->last_read = instr->index;
             break;
         }
         case HLSL_IR_CONSTANT:
@@ -2800,10 +2813,10 @@ static void compute_liveness_recurse(struct list *instrs, unsigned int loop_firs
         case HLSL_IR_DEREF:
         {
             struct hlsl_ir_deref *deref = deref_from_node(instr);
-            var = hlsl_var_from_deref(&deref->src);
+            var = deref->src.var;
             var->last_read = loop_last ? max(instr->index, loop_last) : instr->index;
-            if (deref->src.type == HLSL_IR_DEREF_ARRAY)
-                deref->src.v.array.index->last_read = instr->index;
+            if (deref->src.offset)
+                deref->src.offset->last_read = instr->index;
             break;
         }
         case HLSL_IR_EXPR:
diff --git a/dlls/d3dcompiler_43/utils.c b/dlls/d3dcompiler_43/utils.c
index ac9da97f27c..4b1f99de65d 100644
--- a/dlls/d3dcompiler_43/utils.c
+++ b/dlls/d3dcompiler_43/utils.c
@@ -1437,29 +1437,6 @@ static unsigned int invert_swizzle(unsigned int *swizzle, unsigned int writemask
     return new_writemask;
 }
 
-static BOOL validate_lhs_deref(const struct hlsl_ir_node *lhs)
-{
-    struct hlsl_ir_deref *deref;
-
-    if (lhs->type != HLSL_IR_DEREF)
-    {
-        hlsl_report_message(lhs->loc, HLSL_LEVEL_ERROR, "invalid lvalue");
-        return FALSE;
-    }
-
-    deref = deref_from_node(lhs);
-
-    if (deref->src.type == HLSL_IR_DEREF_VAR)
-        return TRUE;
-    if (deref->src.type == HLSL_IR_DEREF_ARRAY)
-        return validate_lhs_deref(deref->src.v.array.array);
-    if (deref->src.type == HLSL_IR_DEREF_RECORD)
-        return validate_lhs_deref(deref->src.v.record.record);
-
-    assert(0);
-    return FALSE;
-}
-
 struct hlsl_ir_node *make_assignment(struct hlsl_ir_node *lhs, enum parse_assign_op assign_op,
         struct hlsl_ir_node *rhs)
 {
@@ -1513,12 +1490,6 @@ struct hlsl_ir_node *make_assignment(struct hlsl_ir_node *lhs, enum parse_assign
         lhs = lhs_inner;
     }
 
-    if (!validate_lhs_deref(lhs))
-    {
-        d3dcompiler_free(assign);
-        return NULL;
-    }
-
     TRACE("Creating proper assignment expression.\n");
     if (writemask == BWRITERSP_WRITEMASK_ALL)
         type = lhs->data_type;
@@ -1562,26 +1533,12 @@ struct hlsl_ir_node *make_assignment(struct hlsl_ir_node *lhs, enum parse_assign
         enum hlsl_ir_expr_op op = op_from_assignment(assign_op);
         struct hlsl_ir_node *expr;
 
-        if (assign->lhs.type != HLSL_IR_DEREF_VAR)
-        {
-            FIXME("LHS expression not supported in compound assignments yet.\n");
-            assign->rhs = rhs;
-        }
-        else
-        {
-            TRACE("Adding an expression for the compound assignment.\n");
-            expr = new_binary_expr(op, lhs, rhs, lhs->loc);
-            list_add_after(&rhs->entry, &expr->entry);
-            assign->rhs = expr;
-        }
-    }
-    else
-    {
-        list_remove(&lhs->entry);
-        /* Don't recursively free the deref; we just copied its members. */
-        d3dcompiler_free(lhs);
-        assign->rhs = rhs;
+        TRACE("Adding an expression for the compound assignment.\n");
+        expr = new_binary_expr(op, lhs, rhs, lhs->loc);
+        list_add_after(&rhs->entry, &expr->entry);
+        rhs = expr;
     }
+    assign->rhs = rhs;
 
     return &assign->node;
 }
@@ -1879,23 +1836,14 @@ static void debug_dump_ir_var(const struct hlsl_ir_var *var)
 
 static void debug_dump_deref(const struct hlsl_deref *deref)
 {
-    switch (deref->type)
+    wine_dbg_printf("deref(");
+    debug_dump_ir_var(deref->var);
+    wine_dbg_printf(")");
+    if (deref->offset)
     {
-        case HLSL_IR_DEREF_VAR:
-            wine_dbg_printf("deref(");
-            debug_dump_ir_var(deref->v.var);
-            wine_dbg_printf(")");
-            break;
-        case HLSL_IR_DEREF_ARRAY:
-            debug_dump_src(deref->v.array.array);
-            wine_dbg_printf("[");
-            debug_dump_src(deref->v.array.index);
-            wine_dbg_printf("]");
-            break;
-        case HLSL_IR_DEREF_RECORD:
-            debug_dump_src(deref->v.record.record);
-            wine_dbg_printf(".%s", debugstr_a(deref->v.record.field->name));
-            break;
+        wine_dbg_printf("[");
+        debug_dump_src(deref->offset);
+        wine_dbg_printf("]");
     }
 }
 
-- 
2.26.2




More information about the wine-devel mailing list