d3dcompiler: Parse variable references in expressions.

This commit is contained in:
Matteo Bruni 2012-06-07 00:19:05 +02:00 committed by Alexandre Julliard
parent 887ef49419
commit 96470dfcb4
3 changed files with 94 additions and 0 deletions

View File

@ -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);

View File

@ -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 <instr> initializer_expr
%type <modifiers> var_modifiers
%type <instr> expr
%type <var> variable
%type <intval> array
%type <name> semantic
%type <variable_def> 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;

View File

@ -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));
}