Signed-off-by: Zebediah Figura zfigura@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("]"); } }