From 16360a4f18fa1ae5034694e7c367ceda0e055aec Mon Sep 17 00:00:00 2001 From: Matteo Bruni Date: Wed, 26 Sep 2012 19:22:35 +0200 Subject: [PATCH] d3dcompiler: Handle simple struct initializers. --- dlls/d3dcompiler_43/d3dcompiler_private.h | 1 + dlls/d3dcompiler_43/hlsl.y | 58 ++++++++++++++++++++++- dlls/d3dcompiler_43/utils.c | 17 +++++++ 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/dlls/d3dcompiler_43/d3dcompiler_private.h b/dlls/d3dcompiler_43/d3dcompiler_private.h index 5ed0bda06a9..de948fab8a0 100644 --- a/dlls/d3dcompiler_43/d3dcompiler_private.h +++ b/dlls/d3dcompiler_43/d3dcompiler_private.h @@ -1122,6 +1122,7 @@ struct hlsl_ir_expr *hlsl_eq(struct hlsl_ir_node *op1, struct hlsl_ir_node *op2, struct hlsl_ir_expr *hlsl_ne(struct hlsl_ir_node *op1, struct hlsl_ir_node *op2, struct source_location *loc) DECLSPEC_HIDDEN; struct hlsl_ir_deref *new_var_deref(struct hlsl_ir_var *var) DECLSPEC_HIDDEN; +struct hlsl_ir_deref *new_record_deref(struct hlsl_ir_node *record, struct hlsl_struct_field *field) DECLSPEC_HIDDEN; struct hlsl_ir_node *make_assignment(struct hlsl_ir_node *left, enum parse_assign_op assign_op, DWORD writemask, struct hlsl_ir_node *right) DECLSPEC_HIDDEN; void push_scope(struct hlsl_parse_ctx *ctx) DECLSPEC_HIDDEN; diff --git a/dlls/d3dcompiler_43/hlsl.y b/dlls/d3dcompiler_43/hlsl.y index d8c0d2b1be9..f9a685a5227 100644 --- a/dlls/d3dcompiler_43/hlsl.y +++ b/dlls/d3dcompiler_43/hlsl.y @@ -502,6 +502,61 @@ static struct hlsl_ir_swizzle *get_swizzle(struct hlsl_ir_node *value, const cha return NULL; } +static void struct_var_initializer(struct list *list, struct hlsl_ir_var *var, struct list *initializer) +{ + struct hlsl_type *type = var->node.data_type; + struct hlsl_ir_node *node; + struct hlsl_struct_field *field; + struct list *cur_node; + struct hlsl_ir_node *assignment; + struct hlsl_ir_deref *deref; + + if (initializer_size(initializer) != components_count_type(type)) + { + hlsl_report_message(var->node.loc.file, var->node.loc.line, var->node.loc.col, HLSL_LEVEL_ERROR, + "structure initializer mismatch"); + free_instr_list(initializer); + return; + } + cur_node = list_head(initializer); + assert(cur_node); + node = LIST_ENTRY(cur_node, struct hlsl_ir_node, entry); + LIST_FOR_EACH_ENTRY(field, type->e.elements, struct hlsl_struct_field, entry) + { + if (!cur_node) + { + d3dcompiler_free(initializer); + return; + } + if (components_count_type(field->type) == components_count_type(node->data_type)) + { + deref = new_record_deref(&var->node, field); + if (!deref) + { + ERR("Out of memory.\n"); + break; + } + deref->node.loc = node->loc; + assignment = make_assignment(&deref->node, ASSIGN_OP_ASSIGN, BWRITERSP_WRITEMASK_ALL, node); + list_add_tail(list, &assignment->entry); + } + else + FIXME("Initializing with \"mismatched\" fields is not supported yet.\n"); + cur_node = list_next(initializer, cur_node); + node = LIST_ENTRY(cur_node, struct hlsl_ir_node, entry); + } + + /* Free initializer elements in excess. */ + while (cur_node) + { + struct list *next = list_next(initializer, cur_node); + free_instr(node); + cur_node = next; + node = LIST_ENTRY(cur_node, struct hlsl_ir_node, entry); + } + d3dcompiler_free(initializer); +} + static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers, struct list *var_list) { struct hlsl_type *type; @@ -599,8 +654,7 @@ static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers, if (type->type == HLSL_CLASS_STRUCT) { - FIXME("Struct var with an initializer.\n"); - free_instr_list(v->initializer); + struct_var_initializer(statements_list, var, v->initializer); d3dcompiler_free(v); continue; } diff --git a/dlls/d3dcompiler_43/utils.c b/dlls/d3dcompiler_43/utils.c index b95764395f9..9f91579b578 100644 --- a/dlls/d3dcompiler_43/utils.c +++ b/dlls/d3dcompiler_43/utils.c @@ -1556,6 +1556,23 @@ struct hlsl_ir_deref *new_var_deref(struct hlsl_ir_var *var) return deref; } +struct hlsl_ir_deref *new_record_deref(struct hlsl_ir_node *record, struct hlsl_struct_field *field) +{ + struct hlsl_ir_deref *deref = d3dcompiler_alloc(sizeof(*deref)); + + if (!deref) + { + ERR("Out of memory.\n"); + return NULL; + } + deref->node.type = HLSL_IR_DEREF; + deref->node.data_type = field->type; + deref->type = HLSL_IR_DEREF_RECORD; + deref->v.record.record = record; + deref->v.record.field = field; + return deref; +} + static enum hlsl_ir_expr_op op_from_assignment(enum parse_assign_op op) { static const enum hlsl_ir_expr_op ops[] =