diff --git a/dlls/d3dcompiler_43/d3dcompiler_private.h b/dlls/d3dcompiler_43/d3dcompiler_private.h index cb322bc063c..9f7fce12a4c 100644 --- a/dlls/d3dcompiler_43/d3dcompiler_private.h +++ b/dlls/d3dcompiler_43/d3dcompiler_private.h @@ -684,6 +684,7 @@ enum hlsl_ir_node_type { HLSL_IR_VAR = 0, HLSL_IR_CONSTANT, + HLSL_IR_DEREF, }; struct hlsl_ir_node @@ -722,6 +723,33 @@ struct hlsl_ir_var struct hlsl_var_allocation *allocation; }; +enum hlsl_ir_deref_type +{ + HLSL_IR_DEREF_VAR, + HLSL_IR_DEREF_ARRAY, + HLSL_IR_DEREF_RECORD, +}; + +struct hlsl_ir_deref +{ + struct hlsl_ir_node node; + 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; + const char *field; + } record; + } v; +}; + struct hlsl_ir_constant { struct hlsl_ir_node node; @@ -779,6 +807,12 @@ extern struct hlsl_parse_ctx hlsl_ctx DECLSPEC_HIDDEN; void hlsl_message(const char *fmt, ...) PRINTF_ATTR(1,2) DECLSPEC_HIDDEN; +static inline struct hlsl_ir_deref *deref_from_node(const struct hlsl_ir_node *node) +{ + assert(node->type == HLSL_IR_DEREF); + return CONTAINING_RECORD(node, struct hlsl_ir_deref, node); +} + static inline struct hlsl_ir_constant *constant_from_node(const struct hlsl_ir_node *node) { assert(node->type == HLSL_IR_CONSTANT); diff --git a/dlls/d3dcompiler_43/hlsl.y b/dlls/d3dcompiler_43/hlsl.y index 0057d5d0d35..ae1599f2457 100644 --- a/dlls/d3dcompiler_43/hlsl.y +++ b/dlls/d3dcompiler_43/hlsl.y @@ -124,6 +124,7 @@ static DWORD add_modifier(DWORD modifiers, DWORD mod) BOOL boolval; char *name; DWORD modifiers; + struct hlsl_ir_var *var; struct hlsl_ir_node *instr; struct list *list; struct parse_variable_def *variable_def; @@ -243,6 +244,7 @@ static DWORD add_modifier(DWORD modifiers, DWORD mod) %type initializer_expr %type var_modifiers %type expr +%type variable %type array %type semantic %type variable_def @@ -544,11 +546,30 @@ primary_expr: C_FLOAT c->v.value.b[0] = $1; $$ = &c->node; } + | variable + { + struct hlsl_ir_deref *deref = new_var_deref($1); + $$ = deref ? &deref->node : NULL; + } | '(' expr ')' { $$ = $2; } +variable: VAR_IDENTIFIER + { + struct hlsl_ir_var *var; + var = get_variable(hlsl_ctx.cur_scope, $1); + if (!var) + { + hlsl_message("Line %d: variable '%s' not declared\n", + hlsl_ctx.line_no, $1); + set_parse_status(&hlsl_ctx.status, PARSE_ERR); + return 1; + } + $$ = var; + } + postfix_expr: primary_expr { $$ = $1; diff --git a/dlls/d3dcompiler_43/utils.c b/dlls/d3dcompiler_43/utils.c index b15a89a420d..c890fd8d091 100644 --- a/dlls/d3dcompiler_43/utils.c +++ b/dlls/d3dcompiler_43/utils.c @@ -844,6 +844,22 @@ BOOL find_function(const char *name) return FALSE; } +struct hlsl_ir_deref *new_var_deref(struct hlsl_ir_var *var) +{ + 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 = var->node.data_type; + deref->type = HLSL_IR_DEREF_VAR; + deref->v.var = var; + return deref; +} + void push_scope(struct hlsl_parse_ctx *ctx) { struct hlsl_scope *new_scope = d3dcompiler_alloc(sizeof(*new_scope)); @@ -951,6 +967,7 @@ const char *debug_node_type(enum hlsl_ir_node_type type) { "HLSL_IR_VAR", "HLSL_IR_CONSTANT", + "HLSL_IR_DEREF", }; if (type > sizeof(names) / sizeof(names[0])) @@ -1010,6 +1027,25 @@ static void free_ir_constant(struct hlsl_ir_constant *constant) d3dcompiler_free(constant); } +static void free_ir_deref(struct hlsl_ir_deref *deref) +{ + switch (deref->type) + { + case HLSL_IR_DEREF_VAR: + /* Variables are shared among nodes in the tree. */ + break; + case HLSL_IR_DEREF_ARRAY: + free_instr(deref->v.array.array); + free_instr(deref->v.array.index); + break; + case HLSL_IR_DEREF_RECORD: + free_instr(deref->v.record.record); + d3dcompiler_free((void *)deref->v.record.field); + break; + } + d3dcompiler_free(deref); +} + void free_instr(struct hlsl_ir_node *node) { switch (node->type) @@ -1020,6 +1056,9 @@ void free_instr(struct hlsl_ir_node *node) case HLSL_IR_CONSTANT: free_ir_constant(constant_from_node(node)); break; + case HLSL_IR_DEREF: + free_ir_deref(deref_from_node(node)); + break; default: FIXME("Unsupported node type %s\n", debug_node_type(node->type)); }