d3dcompiler: Properly support function overloads.

This commit is contained in:
Matteo Bruni 2012-10-11 19:48:48 +02:00 committed by Alexandre Julliard
parent deb00c9460
commit 6897f9aa35
3 changed files with 220 additions and 39 deletions

View File

@ -752,10 +752,19 @@ struct hlsl_ir_var
struct hlsl_var_allocation *allocation;
};
struct hlsl_ir_function
{
struct wine_rb_entry entry;
const char *name;
struct wine_rb_tree overloads;
BOOL intrinsic;
};
struct hlsl_ir_function_decl
{
struct hlsl_ir_node node;
const char *name;
struct wine_rb_entry entry;
struct hlsl_ir_function *func;
const char *semantic;
struct list *parameters;
struct list *body;
@ -960,6 +969,12 @@ struct parse_variable_def
struct list *initializer;
};
struct parse_function
{
char *name;
struct hlsl_ir_function_decl *decl;
};
struct parse_if_body
{
struct list *then_instrs;
@ -1004,7 +1019,7 @@ struct hlsl_parse_ctx
struct list scopes;
struct list types;
struct list functions;
struct wine_rb_tree functions;
enum hlsl_matrix_majority matrix_majority;
};
@ -1127,18 +1142,21 @@ struct hlsl_ir_node *make_assignment(struct hlsl_ir_node *left, enum parse_assig
DWORD writemask, struct hlsl_ir_node *right) DECLSPEC_HIDDEN;
void push_scope(struct hlsl_parse_ctx *ctx) DECLSPEC_HIDDEN;
BOOL pop_scope(struct hlsl_parse_ctx *ctx) DECLSPEC_HIDDEN;
struct hlsl_ir_function_decl *new_func_decl(const char *name, struct hlsl_type *return_type, struct list *parameters) DECLSPEC_HIDDEN;
struct hlsl_ir_function_decl *new_func_decl(struct hlsl_type *return_type, struct list *parameters) DECLSPEC_HIDDEN;
void init_functions_tree(struct wine_rb_tree *funcs) DECLSPEC_HIDDEN;
void add_function_decl(struct wine_rb_tree *funcs, char *name, struct hlsl_ir_function_decl *decl,
BOOL intrinsic) DECLSPEC_HIDDEN;
struct bwriter_shader *parse_hlsl_shader(const char *text, enum shader_type type, DWORD major, DWORD minor,
const char *entrypoint, char **messages) DECLSPEC_HIDDEN;
const char *debug_hlsl_type(const struct hlsl_type *type) DECLSPEC_HIDDEN;
const char *debug_modifiers(DWORD modifiers) DECLSPEC_HIDDEN;
void debug_dump_ir_function(const struct hlsl_ir_function_decl *func) DECLSPEC_HIDDEN;
void debug_dump_ir_function_decl(const struct hlsl_ir_function_decl *func) DECLSPEC_HIDDEN;
void free_hlsl_type(struct hlsl_type *type) DECLSPEC_HIDDEN;
void free_instr(struct hlsl_ir_node *node) DECLSPEC_HIDDEN;
void free_instr_list(struct list *list) DECLSPEC_HIDDEN;
void free_function(struct hlsl_ir_function_decl *func) DECLSPEC_HIDDEN;
void free_function_rb(struct wine_rb_entry *entry, void *context) DECLSPEC_HIDDEN;
#define MAKE_TAG(ch0, ch1, ch2, ch3) \

View File

@ -825,7 +825,7 @@ static BOOL add_typedef(DWORD modifiers, struct hlsl_type *orig_type, struct lis
struct hlsl_ir_var *var;
struct hlsl_ir_node *instr;
struct list *list;
struct hlsl_ir_function_decl *function;
struct parse_function function;
struct parse_parameter parameter;
struct parse_variable_def *variable_def;
struct parse_if_body if_body;
@ -1000,8 +1000,8 @@ hlsl_prog: /* empty */
}
| hlsl_prog func_declaration
{
FIXME("Check that the function doesn't conflict with an already declared one.\n");
list_add_tail(&hlsl_ctx.functions, &$2->node.entry);
TRACE("Adding function '%s' to the function list.\n", $2.name);
add_function_decl(&hlsl_ctx.functions, $2.name, $2.decl, FALSE);
}
| hlsl_prog declaration_statement
{
@ -1125,14 +1125,14 @@ field: var_modifiers type variables_def ';'
func_declaration: func_prototype compound_statement
{
TRACE("Function %s parsed.\n", $1->name);
TRACE("Function %s parsed.\n", $1.name);
$$ = $1;
$$->body = $2;
$$.decl->body = $2;
pop_scope(&hlsl_ctx);
}
| func_prototype ';'
{
TRACE("Function prototype for %s.\n", $1->name);
TRACE("Function prototype for %s.\n", $1.name);
$$ = $1;
pop_scope(&hlsl_ctx);
}
@ -1151,13 +1151,15 @@ func_prototype: var_modifiers type var_identifier '(' parameters ')' s
HLSL_LEVEL_ERROR, "void function with a semantic");
}
$$ = new_func_decl($3, $2, $5);
if (!$$)
$$.decl = new_func_decl($2, $5);
if (!$$.decl)
{
ERR("Out of memory.\n");
return -1;
}
$$->semantic = $7;
$$.name = $3;
$$.decl->semantic = $7;
set_location(&$$.decl->node.loc, &@3);
}
compound_statement: '{' '}'
@ -2330,10 +2332,22 @@ static DWORD add_modifier(DWORD modifiers, DWORD mod, const struct YYLTYPE *loc)
return modifiers | mod;
}
static void dump_function_decl(struct wine_rb_entry *entry, void *context)
{
struct hlsl_ir_function_decl *func = WINE_RB_ENTRY_VALUE(entry, struct hlsl_ir_function_decl, entry);
if (func->body)
debug_dump_ir_function_decl(func);
}
static void dump_function(struct wine_rb_entry *entry, void *context)
{
struct hlsl_ir_function *func = WINE_RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry);
wine_rb_for_each_entry(&func->overloads, dump_function_decl, NULL);
}
struct bwriter_shader *parse_hlsl(enum shader_type type, DWORD major, DWORD minor,
const char *entrypoint, char **messages)
{
struct hlsl_ir_function_decl *function, *next_function;
struct hlsl_scope *scope, *next_scope;
struct hlsl_type *hlsl_type, *next_type;
struct hlsl_ir_var *var, *next_var;
@ -2351,7 +2365,7 @@ struct bwriter_shader *parse_hlsl(enum shader_type type, DWORD major, DWORD mino
hlsl_ctx.matrix_majority = HLSL_COLUMN_MAJOR;
list_init(&hlsl_ctx.scopes);
list_init(&hlsl_ctx.types);
list_init(&hlsl_ctx.functions);
init_functions_tree(&hlsl_ctx.functions);
push_scope(&hlsl_ctx);
hlsl_ctx.globals = hlsl_ctx.cur_scope;
@ -2361,14 +2375,8 @@ struct bwriter_shader *parse_hlsl(enum shader_type type, DWORD major, DWORD mino
if (TRACE_ON(hlsl_parser))
{
struct hlsl_ir_function_decl *func;
TRACE("IR dump.\n");
LIST_FOR_EACH_ENTRY(func, &hlsl_ctx.functions, struct hlsl_ir_function_decl, node.entry)
{
if (func->body)
debug_dump_ir_function(func);
}
wine_rb_for_each_entry(&hlsl_ctx.functions, dump_function, NULL);
}
TRACE("Compilation status = %d\n", hlsl_ctx.status);
@ -2390,8 +2398,7 @@ struct bwriter_shader *parse_hlsl(enum shader_type type, DWORD major, DWORD mino
d3dcompiler_free(hlsl_ctx.source_files);
TRACE("Freeing functions IR.\n");
LIST_FOR_EACH_ENTRY_SAFE(function, next_function, &hlsl_ctx.functions, struct hlsl_ir_function_decl, node.entry)
free_function(function);
wine_rb_destroy(&hlsl_ctx.functions, free_function_rb, NULL);
TRACE("Freeing variables.\n");
LIST_FOR_EACH_ENTRY_SAFE(scope, next_scope, &hlsl_ctx.scopes, struct hlsl_scope, entry)

View File

@ -878,14 +878,7 @@ struct hlsl_type *get_type(struct hlsl_scope *scope, const char *name, BOOL recu
BOOL find_function(const char *name)
{
struct hlsl_ir_function_decl *func;
LIST_FOR_EACH_ENTRY(func, &hlsl_ctx.functions, struct hlsl_ir_function_decl, node.entry)
{
if (!strcmp(func->name, name))
return TRUE;
}
return FALSE;
return wine_rb_get(&hlsl_ctx.functions, name) != NULL;
}
unsigned int components_count_type(struct hlsl_type *type)
@ -1762,7 +1755,7 @@ BOOL pop_scope(struct hlsl_parse_ctx *ctx)
return TRUE;
}
struct hlsl_ir_function_decl *new_func_decl(const char *name, struct hlsl_type *return_type, struct list *parameters)
struct hlsl_ir_function_decl *new_func_decl(struct hlsl_type *return_type, struct list *parameters)
{
struct hlsl_ir_function_decl *decl;
@ -1774,12 +1767,117 @@ struct hlsl_ir_function_decl *new_func_decl(const char *name, struct hlsl_type *
}
decl->node.type = HLSL_IR_FUNCTION_DECL;
decl->node.data_type = return_type;
decl->name = name;
decl->parameters = parameters;
return decl;
}
static int compare_param_hlsl_types(const struct hlsl_type *t1, const struct hlsl_type *t2)
{
if (t1->type != t2->type)
{
if (!((t1->type == HLSL_CLASS_SCALAR && t2->type == HLSL_CLASS_VECTOR)
|| (t1->type == HLSL_CLASS_VECTOR && t2->type == HLSL_CLASS_SCALAR)))
return t1->type - t2->type;
}
if (t1->base_type != t2->base_type)
return t1->base_type - t2->base_type;
if (t1->base_type == HLSL_TYPE_SAMPLER && t1->sampler_dim != t2->sampler_dim)
return t1->sampler_dim - t2->sampler_dim;
if (t1->dimx != t2->dimx)
return t1->dimx - t2->dimx;
if (t1->dimy != t2->dimy)
return t1->dimx - t2->dimx;
if (t1->type == HLSL_CLASS_STRUCT)
{
struct list *t1cur, *t2cur;
struct hlsl_struct_field *t1field, *t2field;
int r;
t1cur = list_head(t1->e.elements);
t2cur = list_head(t2->e.elements);
while (t1cur && t2cur)
{
t1field = LIST_ENTRY(t1cur, struct hlsl_struct_field, entry);
t2field = LIST_ENTRY(t2cur, struct hlsl_struct_field, entry);
if ((r = compare_param_hlsl_types(t1field->type, t2field->type)))
return r;
if ((r = strcmp(t1field->name, t2field->name)))
return r;
t1cur = list_next(t1->e.elements, t1cur);
t2cur = list_next(t2->e.elements, t2cur);
}
if (t1cur != t2cur)
return t1cur ? 1 : -1;
return 0;
}
if (t1->type == HLSL_CLASS_ARRAY)
{
if (t1->e.array.elements_count != t2->e.array.elements_count)
return t1->e.array.elements_count - t2->e.array.elements_count;
return compare_param_hlsl_types(t1->e.array.type, t2->e.array.type);
}
return 0;
}
static int compare_function_decl_rb(const void *key, const struct wine_rb_entry *entry)
{
const struct list *params = (const struct list *)key;
const struct hlsl_ir_function_decl *decl = WINE_RB_ENTRY_VALUE(entry, const struct hlsl_ir_function_decl, entry);
int params_count = params ? list_count(params) : 0;
int decl_params_count = decl->parameters ? list_count(decl->parameters) : 0;
int r;
struct list *p1cur, *p2cur;
if (params_count != decl_params_count)
return params_count - decl_params_count;
p1cur = params ? list_head(params) : NULL;
p2cur = decl->parameters ? list_head(decl->parameters) : NULL;
while (p1cur && p2cur)
{
struct hlsl_ir_var *p1, *p2;
p1 = LIST_ENTRY(p1cur, struct hlsl_ir_var, node.entry);
p2 = LIST_ENTRY(p2cur, struct hlsl_ir_var, node.entry);
if ((r = compare_param_hlsl_types(p1->node.data_type, p2->node.data_type)))
return r;
p1cur = list_next(params, p1cur);
p2cur = list_next(decl->parameters, p2cur);
}
return 0;
}
static const struct wine_rb_functions hlsl_ir_function_decl_rb_funcs =
{
d3dcompiler_alloc_rb,
d3dcompiler_realloc_rb,
d3dcompiler_free_rb,
compare_function_decl_rb,
};
static int compare_function_rb(const void *key, const struct wine_rb_entry *entry)
{
const char *name = (const char *)key;
const struct hlsl_ir_function *func = WINE_RB_ENTRY_VALUE(entry, const struct hlsl_ir_function,entry);
return strcmp(name, func->name);
}
static const struct wine_rb_functions function_rb_funcs =
{
d3dcompiler_alloc_rb,
d3dcompiler_realloc_rb,
d3dcompiler_free_rb,
compare_function_rb,
};
void init_functions_tree(struct wine_rb_tree *funcs)
{
if (wine_rb_init(&hlsl_ctx.functions, &function_rb_funcs) == -1)
ERR("Failed to initialize functions rbtree.\n");
}
static const char *debug_base_type(const struct hlsl_type *type)
{
const char *name = "(unknown)";
@ -2198,11 +2296,11 @@ static void debug_dump_instr(const struct hlsl_ir_node *instr)
}
}
void debug_dump_ir_function(const struct hlsl_ir_function_decl *func)
void debug_dump_ir_function_decl(const struct hlsl_ir_function_decl *func)
{
struct hlsl_ir_var *param;
TRACE("Dumping function %s.\n", debugstr_a(func->name));
TRACE("Dumping function %s.\n", debugstr_a(func->func->name));
TRACE("Function parameters:\n");
LIST_FOR_EACH_ENTRY(param, func->parameters, struct hlsl_ir_var, node.entry)
{
@ -2370,11 +2468,69 @@ void free_instr(struct hlsl_ir_node *node)
}
}
void free_function(struct hlsl_ir_function_decl *func)
void free_function_decl(struct hlsl_ir_function_decl *func)
{
d3dcompiler_free((void *)func->name);
d3dcompiler_free((void *)func->semantic);
d3dcompiler_free(func->parameters);
free_instr_list(func->body);
d3dcompiler_free(func);
}
static void free_function_decl_rb(struct wine_rb_entry *entry, void *context)
{
free_function_decl(WINE_RB_ENTRY_VALUE(entry, struct hlsl_ir_function_decl, entry));
}
void free_function(struct hlsl_ir_function *func)
{
wine_rb_destroy(&func->overloads, free_function_decl_rb, NULL);
d3dcompiler_free((void *)func->name);
}
void free_function_rb(struct wine_rb_entry *entry, void *context)
{
free_function(WINE_RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry));
}
void add_function_decl(struct wine_rb_tree *funcs, char *name, struct hlsl_ir_function_decl *decl, BOOL intrinsic)
{
struct hlsl_ir_function *func;
struct wine_rb_entry *func_entry, *old_entry;
func_entry = wine_rb_get(funcs, name);
if (func_entry)
{
func = WINE_RB_ENTRY_VALUE(func_entry, struct hlsl_ir_function, entry);
decl->func = func;
if ((old_entry = wine_rb_get(&func->overloads, decl->parameters)))
{
struct hlsl_ir_function_decl *old_decl =
WINE_RB_ENTRY_VALUE(old_entry, struct hlsl_ir_function_decl, entry);
if (!decl->body)
{
free_function_decl(decl);
d3dcompiler_free(name);
return;
}
wine_rb_remove(&func->overloads, decl->parameters);
free_function_decl(old_decl);
}
wine_rb_put(&func->overloads, decl->parameters, &decl->entry);
d3dcompiler_free(name);
return;
}
func = d3dcompiler_alloc(sizeof(*func));
func->name = name;
if (wine_rb_init(&func->overloads, &hlsl_ir_function_decl_rb_funcs) == -1)
{
ERR("Failed to initialize function rbtree.\n");
d3dcompiler_free(name);
d3dcompiler_free(func);
return;
}
decl->func = func;
wine_rb_put(&func->overloads, decl->parameters, &decl->entry);
func->intrinsic = intrinsic;
wine_rb_put(funcs, func->name, &func->entry);
}