From 40acf8cce24afe80388639b804f9ae8c0b779d81 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 25 Jul 2008 15:33:02 -0600 Subject: mesa: glsl: assorted fixes for resolving polymorphic functions Plus, - fix some issues in casting function arguments to format param types. - fix some vec/mat constructor bugs - find/report more syntax/semantic errors --- src/mesa/shader/slang/slang_codegen.c | 178 +++++++++++++------ src/mesa/shader/slang/slang_compile.c | 30 +++- src/mesa/shader/slang/slang_compile_variable.c | 22 ++- src/mesa/shader/slang/slang_emit.c | 6 + src/mesa/shader/slang/slang_simplify.c | 226 ++++++++++++++----------- src/mesa/shader/slang/slang_simplify.h | 28 +++ src/mesa/shader/slang/slang_typeinfo.c | 100 ++++++----- src/mesa/shader/slang/slang_typeinfo.h | 3 +- 8 files changed, 391 insertions(+), 202 deletions(-) diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 2f9e147b87..ad9cf06e27 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -1178,7 +1178,8 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun, slang_operation_copy(inlined, fun->body); /*** XXX review this */ - assert(inlined->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE); + assert(inlined->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE || + inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE); inlined->type = SLANG_OPER_BLOCK_NEW_SCOPE; #if 0 @@ -1710,22 +1711,51 @@ print_funcs(struct slang_function_scope_ *scope, const char *name) * all of them... */ static slang_function * -_slang_find_function_by_argc(struct slang_function_scope_ *scope, +_slang_find_function_by_argc(slang_function_scope *scope, const char *name, int numArgs) { - GLuint i; - for (i = 0; i < scope->num_functions; i++) { - slang_function *f = &scope->functions[i]; - if (strcmp(name, (char*) f->header.a_name) == 0 - /*&& numArgs == f->param_count*/) - return f; + while (scope) { + GLuint i; + for (i = 0; i < scope->num_functions; i++) { + slang_function *f = &scope->functions[i]; + if (strcmp(name, (char*) f->header.a_name) == 0) { + int haveRetValue = _slang_function_has_return_value(f); + if (numArgs == f->param_count - haveRetValue) + return f; + } + } + scope = scope->outer_scope; } - if (scope->outer_scope) - return _slang_find_function_by_argc(scope->outer_scope, name, numArgs); + return NULL; } +static slang_function * +_slang_find_function_by_max_argc(slang_function_scope *scope, + const char *name) +{ + slang_function *maxFunc = NULL; + GLuint maxArgs = 0; + + while (scope) { + GLuint i; + for (i = 0; i < scope->num_functions; i++) { + slang_function *f = &scope->functions[i]; + if (strcmp(name, (char*) f->header.a_name) == 0) { + if (f->param_count > maxArgs) { + maxArgs = f->param_count; + maxFunc = f; + } + } + } + scope = scope->outer_scope; + } + + return maxFunc; +} + + /** * Generate a new slang_function which is a constructor for a user-defined * struct type. @@ -1783,16 +1813,20 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str) * return T; */ { + slang_variable_scope *scope; slang_variable *var; GLint i; fun->body = slang_operation_new(1); - fun->body->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE; + fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE; fun->body->num_children = numFields + 2; fun->body->children = slang_operation_new(numFields + 2); + scope = fun->body->locals; + scope->outer_scope = fun->parameters; + /* create local var 't' */ - var = slang_variable_scope_grow(fun->parameters); + var = slang_variable_scope_grow(scope); var->a_name = slang_atom_pool_atom(A->atoms, "t"); var->type = fun->header.type; @@ -1802,7 +1836,7 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str) decl = &fun->body->children[0]; decl->type = SLANG_OPER_VARIABLE_DECL; - decl->locals = _slang_variable_scope_new(fun->parameters); + decl->locals = _slang_variable_scope_new(scope); decl->a_id = var->a_name; } @@ -1811,7 +1845,7 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str) slang_operation *assign = &fun->body->children[1 + i]; assign->type = SLANG_OPER_ASSIGN; - assign->locals = _slang_variable_scope_new(fun->parameters); + assign->locals = _slang_variable_scope_new(scope); assign->num_children = 2; assign->children = slang_operation_new(2); @@ -1819,21 +1853,21 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str) slang_operation *lhs = &assign->children[0]; lhs->type = SLANG_OPER_FIELD; - lhs->locals = _slang_variable_scope_new(fun->parameters); + lhs->locals = _slang_variable_scope_new(scope); lhs->num_children = 1; lhs->children = slang_operation_new(1); lhs->a_id = str->fields->variables[i]->a_name; lhs->children[0].type = SLANG_OPER_IDENTIFIER; lhs->children[0].a_id = var->a_name; - lhs->children[0].locals = _slang_variable_scope_new(fun->parameters); + lhs->children[0].locals = _slang_variable_scope_new(scope); #if 0 lhs->children[1].num_children = 1; lhs->children[1].children = slang_operation_new(1); lhs->children[1].children[0].type = SLANG_OPER_IDENTIFIER; lhs->children[1].children[0].a_id = str->fields->variables[i]->a_name; - lhs->children[1].children->locals = _slang_variable_scope_new(fun->parameters); + lhs->children[1].children->locals = _slang_variable_scope_new(scope); #endif } @@ -1841,7 +1875,7 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str) slang_operation *rhs = &assign->children[1]; rhs->type = SLANG_OPER_IDENTIFIER; - rhs->locals = _slang_variable_scope_new(fun->parameters); + rhs->locals = _slang_variable_scope_new(scope); rhs->a_id = str->fields->variables[i]->a_name; } } @@ -1851,12 +1885,12 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str) slang_operation *ret = &fun->body->children[numFields + 1]; ret->type = SLANG_OPER_RETURN; - ret->locals = _slang_variable_scope_new(fun->parameters); + ret->locals = _slang_variable_scope_new(scope); ret->num_children = 1; ret->children = slang_operation_new(1); ret->children[0].type = SLANG_OPER_IDENTIFIER; ret->children[0].a_id = var->a_name; - ret->children[0].locals = _slang_variable_scope_new(fun->parameters); + ret->children[0].locals = _slang_variable_scope_new(scope); } } @@ -1889,6 +1923,27 @@ _slang_locate_struct_constructor(slang_assemble_ctx *A, const char *name) } + +static GLboolean +_slang_is_vec_mat_type(const char *name) +{ + static const char *vecmat_types[] = { + "float", "int", "bool", + "vec2", "vec3", "vec4", + "ivec2", "ivec3", "ivec4", + "bvec2", "bvec3", "bvec4", + "mat2", "mat3", "mat4", + "mat2x3", "mat2x4", "mat3x2", "mat3x4", "mat4x2", "mat4x3", + NULL + }; + int i; + for (i = 0; vecmat_types[i]; i++) + if (_mesa_strcmp(name, vecmat_types[i]) == 0) + return GL_TRUE; + return GL_FALSE; +} + + /** * Assemble a function call, given a particular function name. * \param name the function's name (operators like '*' are possible). @@ -1901,29 +1956,53 @@ _slang_gen_function_call_name(slang_assemble_ctx *A, const char *name, const GLuint param_count = oper->num_children; slang_atom atom; slang_function *fun; + GLboolean error; atom = slang_atom_pool_atom(A->atoms, name); if (atom == SLANG_ATOM_NULL) return NULL; /* - * Use 'name' to find the function to call + * First, try to find function by name and exact argument type matching. */ fun = _slang_locate_function(A->space.funcs, atom, params, param_count, - &A->space, A->atoms, A->log); + &A->space, A->atoms, A->log, &error); + + if (error) { + slang_info_log_error(A->log, + "Function '%s' not found (check argument types)", + name); + return NULL; + } if (!fun) { + /* Next, try locating a constructor function for a user-defined type */ fun = _slang_locate_struct_constructor(A, name); } - if (!fun) { - /* A function with exactly the right parameters/types was not found. - * Try adapting the parameters. + if (!fun && _slang_is_vec_mat_type(name)) { + /* Next, if this call looks like a vec() or mat() constructor call, + * try "unwinding" the args to satisfy a constructor. */ + fun = _slang_find_function_by_max_argc(A->space.funcs, name); + if (fun) { + if (!_slang_adapt_call(oper, fun, &A->space, A->atoms, A->log)) { + slang_info_log_error(A->log, + "Function '%s' not found (check argument types)", + name); + return NULL; + } + } + } + + if (!fun) { + /* Next, try casting args to the types of the formal parameters */ int numArgs = oper->num_children; fun = _slang_find_function_by_argc(A->space.funcs, name, numArgs); - if (!fun || !_slang_adapt_call(oper, fun, &A->space, A->atoms, A->log)) { - slang_info_log_error(A->log, "Function '%s' not found (check argument types)", name); + if (!fun || !_slang_cast_func_params(oper, fun, &A->space, A->atoms, A->log)) { + slang_info_log_error(A->log, + "Function '%s' not found (check argument types)", + name); return NULL; } assert(fun); @@ -2910,6 +2989,7 @@ _slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper) /*n->Store = _slang_clone_ir_storage_swz(n->Store, */ n->Writemask = WRITEMASK_X << index; } + assert(n->Store); return n; } else { @@ -2954,11 +3034,17 @@ _slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper) } } + if (!array->Store) { + slang_info_log_error(A->log, "Invalid array"); + return NULL; + } + elem = new_node2(IR_ELEMENT, array, index); elem->Store = _slang_new_ir_storage_relative(constIndex, elemSize, array->Store); + assert(elem->Store->Parent); /* XXX try to do some array bounds checking here */ return elem; } @@ -2988,6 +3074,22 @@ print_vars(slang_variable_scope *s) #endif +#if 0 +static void +_slang_undeclare_vars(slang_variable_scope *locals) +{ + if (locals->num_variables > 0) { + int i; + for (i = 0; i < locals->num_variables; i++) { + slang_variable *v = locals->variables[i]; + printf("undeclare %s at %p\n", (char*) v->a_name, v); + v->declared = GL_FALSE; + } + } +} +#endif + + /** * Generate IR tree for a slang_operation (AST node) */ @@ -3007,6 +3109,7 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) _slang_pop_var_table(A->vartable); + /*_slang_undeclare_vars(oper->locals);*/ /*print_vars(oper->locals);*/ if (n) @@ -3031,27 +3134,6 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) tree = new_seq(tree, n); } -#if 00 - if (oper->locals->num_variables > 0) { - int i; - /* - printf("\n****** Deallocate vars in scope!\n"); - */ - for (i = 0; i < oper->locals->num_variables; i++) { - slang_variable *v = oper->locals->variables + i; - if (v->aux) { - slang_ir_storage *store = (slang_ir_storage *) v->aux; - /* - printf(" Deallocate var %s\n", (char*) v->a_name); - */ - assert(store->File == PROGRAM_TEMPORARY); - assert(store->Index >= 0); - _slang_free_temp(A->vartable, store->Index, store->Size); - } - } - } -#endif - /*print_vars(oper->locals);*/ return tree; } else { diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c index 862d0741ff..60539f19b6 100644 --- a/src/mesa/shader/slang/slang_compile.c +++ b/src/mesa/shader/slang/slang_compile.c @@ -337,9 +337,10 @@ convert_to_array(slang_parse_ctx * C, slang_variable * var, static GLboolean parse_struct_field_var(slang_parse_ctx * C, slang_output_ctx * O, - slang_variable * var, const slang_type_specifier * sp) + slang_variable * var, slang_atom a_name, + const slang_type_specifier * sp) { - var->a_name = parse_identifier(C); + var->a_name = a_name; if (var->a_name == SLANG_ATOM_NULL) return GL_FALSE; @@ -372,12 +373,19 @@ parse_struct_field(slang_parse_ctx * C, slang_output_ctx * O, return 0; do { + slang_atom a_name; slang_variable *var = slang_variable_scope_grow(st->fields); if (!var) { slang_info_log_memory(C->L); return 0; } - if (!parse_struct_field_var(C, &o, var, sp)) + a_name = parse_identifier(C); + if (_slang_locate_variable(st->fields, a_name, GL_FALSE)) { + slang_info_log_error(C->L, "duplicate field '%s'", (char *) a_name); + return 0; + } + + if (!parse_struct_field_var(C, &o, var, a_name, sp)) return 0; } while (*C->I++ != FIELD_NONE); @@ -1579,11 +1587,22 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O, const slang_fully_specified_type * type) { slang_variable *var; + slang_atom a_name; /* empty init declatator (without name, e.g. "float ;") */ if (*C->I++ == VARIABLE_NONE) return 1; + a_name = parse_identifier(C); + + /* check if name is already in this scope */ + if (_slang_locate_variable(O->vars, a_name, GL_FALSE)) { + slang_info_log_error(C->L, + "declaration of '%s' conflicts with previous declaration", + (char *) a_name); + return 0; + } + /* make room for the new variable and initialize it */ var = slang_variable_scope_grow(O->vars); if (!var) { @@ -1593,7 +1612,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O, /* copy the declarator qualifier type, parse the identifier */ var->type.qualifier = type->qualifier; - var->a_name = parse_identifier(C); + var->a_name = a_name; if (var->a_name == SLANG_ATOM_NULL) return 0; @@ -1657,6 +1676,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O, A.space.vars = O->vars; A.program = O->program; A.vartable = O->vartable; + A.log = C->L; A.curFuncEndLabel = NULL; if (!_slang_codegen_global_variable(&A, var, C->type)) return 0; @@ -2265,7 +2285,7 @@ compile_shader(GLcontext *ctx, slang_code_object * object, GLboolean success; grammar id = 0; -#if 0 /* for debug */ +#if 1 /* for debug */ _mesa_printf("********* COMPILE SHADER ***********\n"); _mesa_printf("%s\n", shader->Source); _mesa_printf("************************************\n"); diff --git a/src/mesa/shader/slang/slang_compile_variable.c b/src/mesa/shader/slang/slang_compile_variable.c index b26c18e38d..3428b49e16 100644 --- a/src/mesa/shader/slang/slang_compile_variable.c +++ b/src/mesa/shader/slang/slang_compile_variable.c @@ -267,6 +267,7 @@ slang_variable_construct(slang_variable * var) var->size = 0; var->isTemp = GL_FALSE; var->aux = NULL; + var->declared = 0; return 1; } @@ -325,16 +326,23 @@ slang_variable_copy(slang_variable * x, const slang_variable * y) } +/** + * Search for named variable in given scope. + * \param all if true, search parent scopes too. + */ slang_variable * _slang_locate_variable(const slang_variable_scope * scope, const slang_atom a_name, GLboolean all) { - GLuint i; - - for (i = 0; i < scope->num_variables; i++) - if (a_name == scope->variables[i]->a_name) - return scope->variables[i]; - if (all && scope->outer_scope != NULL) - return _slang_locate_variable(scope->outer_scope, a_name, 1); + while (scope) { + GLuint i; + for (i = 0; i < scope->num_variables; i++) + if (a_name == scope->variables[i]->a_name) + return scope->variables[i]; + if (all) + scope = scope->outer_scope; + else + scope = NULL; + } return NULL; } diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 9bff055ad5..f1af6902ea 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -256,6 +256,12 @@ storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st) } assert(st->File >= 0); +#if 1 /* XXX temporary */ + if (st->File == PROGRAM_UNDEFINED) { + slang_ir_storage *st0 = (slang_ir_storage *) st; + st0->File = PROGRAM_TEMPORARY; + } +#endif assert(st->File < PROGRAM_UNDEFINED); src->File = st->File; diff --git a/src/mesa/shader/slang/slang_simplify.c b/src/mesa/shader/slang/slang_simplify.c index c34bef2164..c4bf0175be 100644 --- a/src/mesa/shader/slang/slang_simplify.c +++ b/src/mesa/shader/slang/slang_simplify.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.5.2 + * Version: 7.1 * - * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2008 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,11 +23,11 @@ */ /** - * \file slang_assemble_typeinfo.c - * slang type info - * \author Michal Krol + * Functions for constant folding, built-in constant lookup, and function + * call casting. */ + #include "main/imports.h" #include "main/macros.h" #include "main/get.h" @@ -314,17 +314,18 @@ _slang_simplify(slang_operation *oper, /** - * Adapt the arguments for a function call to match the parameters of - * the given function. - * This is for: - * 1. converting/casting argument types to match parameters - * 2. breaking up vector/matrix types into individual components to - * satisfy constructors. + * Insert casts to try to adapt actual parameters to formal parameters for a + * function call when an exact match for the parameter types is not found. + * Example: + * void foo(int i, bool b) {} + * x = foo(3.15, 9); + * Gets translated into: + * x = foo(int(3.15), bool(9)) */ GLboolean -_slang_adapt_call(slang_operation *callOper, const slang_function *fun, - const slang_name_space * space, - slang_atom_pool * atoms, slang_info_log *log) +_slang_cast_func_params(slang_operation *callOper, const slang_function *fun, + const slang_name_space * space, + slang_atom_pool * atoms, slang_info_log *log) { const GLboolean haveRetValue = _slang_function_has_return_value(fun); const int numParams = fun->param_count - haveRetValue; @@ -332,95 +333,9 @@ _slang_adapt_call(slang_operation *callOper, const slang_function *fun, int dbg = 0; if (dbg) - printf("Adapt %d args to %d parameters for %s\n", - callOper->num_children, numParams, (char *) fun->header.a_name); + printf("Adapt call of %d args to func %s (%d params)\n", + callOper->num_children, (char*) fun->header.a_name, numParams); - /* Only try adapting for constructors */ - if (fun->kind != SLANG_FUNC_CONSTRUCTOR) - return GL_FALSE; - - if (callOper->num_children != numParams) { - /* number of arguments doesn't match number of parameters */ - - if (fun->kind == SLANG_FUNC_CONSTRUCTOR) { - /* For constructor calls, we can try to unroll vector/matrix args - * into individual floats/ints and try to match the function params. - */ - for (i = 0; i < numParams; i++) { - slang_typeinfo argType; - GLint argSz, j; - - /* Get type of arg[i] */ - if (!slang_typeinfo_construct(&argType)) - return GL_FALSE; - if (!_slang_typeof_operation_(&callOper->children[i], space, - &argType, atoms, log)) { - slang_typeinfo_destruct(&argType); - return GL_FALSE; - } - - /* - paramSz = _slang_sizeof_type_specifier(¶mVar->type.specifier); - assert(paramSz == 1); - */ - argSz = _slang_sizeof_type_specifier(&argType.spec); - if (argSz > 1) { - slang_operation origArg; - /* break up arg[i] into components */ - if (dbg) - printf("Break up arg %d from 1 to %d elements\n", i, argSz); - - slang_operation_construct(&origArg); - slang_operation_copy(&origArg, - &callOper->children[i]); - - /* insert argSz-1 new children/args */ - for (j = 0; j < argSz - 1; j++) { - (void) slang_operation_insert(&callOper->num_children, - &callOper->children, i); - } - - /* replace arg[i+j] with subscript/index oper */ - for (j = 0; j < argSz; j++) { - callOper->children[i + j].type = SLANG_OPER_SUBSCRIPT; - callOper->children[i + j].num_children = 2; - callOper->children[i + j].children = slang_operation_new(2); - slang_operation_copy(&callOper->children[i + j].children[0], - &origArg); - callOper->children[i + j].children[1].type - = SLANG_OPER_LITERAL_INT; - callOper->children[i + j].children[1].literal[0] = (GLfloat) j; - } - - } - } /* for i */ - } - else { - /* non-constructor function: number of args must match number - * of function params. - */ - return GL_FALSE; /* caller will record an error msg */ - } - } - - if (callOper->num_children < (GLuint) numParams) { - /* still not enough args for all params */ - return GL_FALSE; - } - else if (callOper->num_children > (GLuint) numParams) { - /* now too many arguments */ - /* XXX this isn't always an error, see spec */ - return GL_FALSE; - } - - /* - * Second phase, argument casting. - * Example: - * void foo(int i, bool b) {} - * x = foo(3.15, 9); - * Gets translated into: - * x = foo(int(3.15), bool(9)) - */ for (i = 0; i < numParams; i++) { slang_typeinfo argType; slang_variable *paramVar = fun->parameters->variables[i]; @@ -448,6 +363,12 @@ _slang_adapt_call(slang_operation *callOper, const slang_function *fun, slang_operation_copy(child, &callOper->children[i]); child->locals->outer_scope = callOper->children[i].locals; +#if 0 + if (_slang_sizeof_type_specifier(&argType.spec) > + _slang_sizeof_type_specifier(¶mVar->type.specifier)) { + } +#endif + callOper->children[i].type = SLANG_OPER_CALL; callOper->children[i].a_id = slang_atom_pool_atom(atoms, constructorName); callOper->children[i].num_children = 1; @@ -457,6 +378,107 @@ _slang_adapt_call(slang_operation *callOper, const slang_function *fun, slang_typeinfo_destruct(&argType); } + if (dbg) { + printf("===== New call to %s with cast arguments ===============\n", + (char*) fun->header.a_name); + slang_print_tree(callOper, 5); + } + + return GL_TRUE; +} + + +/** + * Adapt the arguments for a function call to match the parameters of + * the given function. + * This is for: + * 1. converting/casting argument types to match parameters + * 2. breaking up vector/matrix types into individual components to + * satisfy constructors. + */ +GLboolean +_slang_adapt_call(slang_operation *callOper, const slang_function *fun, + const slang_name_space * space, + slang_atom_pool * atoms, slang_info_log *log) +{ + const GLboolean haveRetValue = _slang_function_has_return_value(fun); + const int numParams = fun->param_count - haveRetValue; + int i; + int dbg = 0; + + if (dbg) + printf("Adapt %d args to %d parameters for %s\n", + callOper->num_children, numParams, (char *) fun->header.a_name); + + /* Only try adapting for constructors */ + if (fun->kind != SLANG_FUNC_CONSTRUCTOR) + return GL_FALSE; + + if (callOper->num_children != numParams) { + /* number of arguments doesn't match number of parameters */ + + /* For constructor calls, we can try to unroll vector/matrix args + * into individual floats/ints and try to match the function params. + */ + for (i = 0; i < numParams; i++) { + slang_typeinfo argType; + GLint argSz, j; + + /* Get type of arg[i] */ + if (!slang_typeinfo_construct(&argType)) + return GL_FALSE; + if (!_slang_typeof_operation_(&callOper->children[i], space, + &argType, atoms, log)) { + slang_typeinfo_destruct(&argType); + return GL_FALSE; + } + + /* + paramSz = _slang_sizeof_type_specifier(¶mVar->type.specifier); + assert(paramSz == 1); + */ + argSz = _slang_sizeof_type_specifier(&argType.spec); + if (argSz > 1) { + slang_operation origArg; + /* break up arg[i] into components */ + if (dbg) + printf("Break up arg %d from 1 to %d elements\n", i, argSz); + + slang_operation_construct(&origArg); + slang_operation_copy(&origArg, &callOper->children[i]); + + /* insert argSz-1 new children/args */ + for (j = 0; j < argSz - 1; j++) { + (void) slang_operation_insert(&callOper->num_children, + &callOper->children, i); + } + + /* replace arg[i+j] with subscript/index oper */ + for (j = 0; j < argSz; j++) { + callOper->children[i + j].type = SLANG_OPER_SUBSCRIPT; + callOper->children[i + j].locals = _slang_variable_scope_new(callOper->locals); + callOper->children[i + j].num_children = 2; + callOper->children[i + j].children = slang_operation_new(2); + slang_operation_copy(&callOper->children[i + j].children[0], + &origArg); + callOper->children[i + j].children[1].type + = SLANG_OPER_LITERAL_INT; + callOper->children[i + j].children[1].literal[0] = (GLfloat) j; + } + } + } + } + + if (callOper->num_children < (GLuint) numParams) { + /* still not enough args for all params */ + return GL_FALSE; + } + else if (callOper->num_children > (GLuint) numParams) { + /* now too many arguments */ + /* just truncate */ + callOper->num_children = (GLuint) numParams; + } + if (dbg) { printf("===== New call to %s with adapted arguments ===============\n", (char*) fun->header.a_name); diff --git a/src/mesa/shader/slang/slang_simplify.h b/src/mesa/shader/slang/slang_simplify.h index b3840ee9df..8689c23b1a 100644 --- a/src/mesa/shader/slang/slang_simplify.h +++ b/src/mesa/shader/slang/slang_simplify.h @@ -1,3 +1,26 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 2005-2008 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ #ifndef SLANG_SIMPLIFY_H #define SLANG_SIMPLIFY_H @@ -13,6 +36,11 @@ _slang_simplify(slang_operation *oper, slang_atom_pool * atoms); +extern GLboolean +_slang_cast_func_params(slang_operation *callOper, const slang_function *fun, + const slang_name_space * space, + slang_atom_pool * atoms, slang_info_log *log); + extern GLboolean _slang_adapt_call(slang_operation *callOper, const slang_function *fun, const slang_name_space * space, diff --git a/src/mesa/shader/slang/slang_typeinfo.c b/src/mesa/shader/slang/slang_typeinfo.c index 8a1c3abf48..26f9f6ca85 100644 --- a/src/mesa/shader/slang/slang_typeinfo.c +++ b/src/mesa/shader/slang/slang_typeinfo.c @@ -273,6 +273,7 @@ slang_type_specifier_compatible(const slang_type_specifier * x, GLboolean slang_typeinfo_construct(slang_typeinfo * ti) { + /*_mesa_bzero(ti, sizeof(*ti));*/ slang_type_specifier_ctr(&ti->spec); ti->array_len = 0; return GL_TRUE; @@ -304,10 +305,16 @@ _slang_typeof_function(slang_atom a_name, slang_function **funFound, slang_atom_pool *atoms, slang_info_log *log) { + GLboolean error; + *funFound = _slang_locate_function(space->funcs, a_name, params, - num_params, space, atoms, log); + num_params, space, atoms, log, &error); + if (error) + return GL_FALSE; + if (!*funFound) return GL_TRUE; /* yes, not false */ + return slang_type_specifier_copy(spec, &(*funFound)->header.type.specifier); } @@ -755,51 +762,66 @@ slang_function * _slang_locate_function(const slang_function_scope * funcs, slang_atom a_name, slang_operation * args, GLuint num_args, const slang_name_space * space, slang_atom_pool * atoms, - slang_info_log *log) + slang_info_log *log, GLboolean *error) { + slang_typeinfo arg_ti[100]; GLuint i; - for (i = 0; i < funcs->num_functions; i++) { - slang_function *f = &funcs->functions[i]; - const GLuint haveRetValue = _slang_function_has_return_value(f); - GLuint j; - - if (a_name != f->header.a_name) - continue; - if (f->param_count - haveRetValue != num_args) - continue; - - /* compare parameter / argument types */ - for (j = 0; j < num_args; j++) { - slang_typeinfo ti; - - if (!slang_typeinfo_construct(&ti)) - return NULL; - if (!_slang_typeof_operation_(&args[j], space, &ti, atoms, log)) { - slang_typeinfo_destruct(&ti); - return NULL; + *error = GL_FALSE; + + /* determine type of each argument */ + assert(num_args < 100); + for (i = 0; i < num_args; i++) { + if (!slang_typeinfo_construct(&arg_ti[i])) + return NULL; + if (!_slang_typeof_operation_(&args[i], space, &arg_ti[i], atoms, log)) { + return NULL; + } + } + + /* loop over function scopes */ + while (funcs) { + + /* look for function with matching name and argument/param types */ + for (i = 0; i < funcs->num_functions; i++) { + slang_function *f = &funcs->functions[i]; + const GLuint haveRetValue = _slang_function_has_return_value(f); + GLuint j; + + if (a_name != f->header.a_name) + continue; + if (f->param_count - haveRetValue != num_args) + continue; + + /* compare parameter / argument types */ + for (j = 0; j < num_args; j++) { + if (!slang_type_specifier_compatible(&arg_ti[j].spec, + &f->parameters->variables[j]->type.specifier)) { + /* param/arg types don't match */ + break; + } + + /* "out" and "inout" formal parameter requires the actual + * argument to be an l-value. + */ + if (!arg_ti[j].can_be_referenced && + (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT || + f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT)) { + /* param is not an lvalue! */ + *error = GL_TRUE; + return NULL; + } } - if (!slang_type_specifier_compatible(&ti.spec, - &f->parameters->variables[j]->type.specifier)) { - slang_typeinfo_destruct(&ti); - break; + + if (j == num_args) { + /* name and args match! */ + return f; } - slang_typeinfo_destruct(&ti); - - /* "out" and "inout" formal parameter requires the actual - * parameter to be l-value. - */ - if (!ti.can_be_referenced && - (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT || - f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT)) - break; } - if (j == num_args) - return f; + + funcs = funcs->outer_scope; } - if (funcs->outer_scope != NULL) - return _slang_locate_function(funcs->outer_scope, a_name, args, - num_args, space, atoms, log); + return NULL; } diff --git a/src/mesa/shader/slang/slang_typeinfo.h b/src/mesa/shader/slang/slang_typeinfo.h index 8a36fc3422..960e99bda2 100644 --- a/src/mesa/shader/slang/slang_typeinfo.h +++ b/src/mesa/shader/slang/slang_typeinfo.h @@ -73,7 +73,8 @@ _slang_locate_function(const struct slang_function_scope_ *funcs, slang_atom name, struct slang_operation_ *params, GLuint num_params, const slang_name_space *space, - slang_atom_pool *atoms, slang_info_log *log); + slang_atom_pool *atoms, slang_info_log *log, + GLboolean *error); extern GLboolean -- cgit v1.2.3