diff --git a/dlls/d3dcompiler_43/d3dcompiler_private.h b/dlls/d3dcompiler_43/d3dcompiler_private.h index de948fab8a0..a6c27d0e10d 100644 --- a/dlls/d3dcompiler_43/d3dcompiler_private.h +++ b/dlls/d3dcompiler_43/d3dcompiler_private.h @@ -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) \ diff --git a/dlls/d3dcompiler_43/hlsl.y b/dlls/d3dcompiler_43/hlsl.y index 738ab3ab7f5..d32710202ef 100644 --- a/dlls/d3dcompiler_43/hlsl.y +++ b/dlls/d3dcompiler_43/hlsl.y @@ -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) diff --git a/dlls/d3dcompiler_43/utils.c b/dlls/d3dcompiler_43/utils.c index 5bd39e8dec5..e5f3f74503e 100644 --- a/dlls/d3dcompiler_43/utils.c +++ b/dlls/d3dcompiler_43/utils.c @@ -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); +}