d3dcompiler: Properly support function overloads.
This commit is contained in:
parent
deb00c9460
commit
6897f9aa35
|
@ -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) \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue