diff options
| author | Brian Paul <brian.paul@tungstengraphics.com> | 2008-07-29 17:29:30 -0600 | 
|---|---|---|
| committer | Brian Paul <brian.paul@tungstengraphics.com> | 2008-07-29 17:29:30 -0600 | 
| commit | 1638edb3256b3b4bd8bc2eb65d02573601ef9a44 (patch) | |
| tree | 6ba3be496e6755148d3dcab371decc90083d5d2e | |
| parent | 6225e51a73a51fa46d839a429f254d7786b1fd18 (diff) | |
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
| -rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 178 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_compile.c | 30 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_compile_variable.c | 22 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 6 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_simplify.c | 231 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_simplify.h | 28 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_typeinfo.c | 94 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_typeinfo.h | 3 | 
8 files changed, 390 insertions, 202 deletions
| diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 03775a3a53..849b6d3561 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -1170,7 +1170,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 @@ -1688,22 +1689,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. @@ -1761,16 +1791,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; @@ -1780,7 +1814,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;        } @@ -1789,7 +1823,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); @@ -1797,21 +1831,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           } @@ -1819,7 +1853,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;           }                 } @@ -1829,12 +1863,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);        }     } @@ -1867,6 +1901,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). @@ -1879,29 +1934,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); @@ -2888,6 +2967,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 { @@ -2932,11 +3012,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;        } @@ -2966,6 +3052,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)   */ @@ -2985,6 +3087,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) @@ -3009,27 +3112,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 b43803b6da..21f1016a6f 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 d53255075f..09ad26f62f 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 e03fc6b863..b729ceca7e 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,14 +23,13 @@   */  /** - * \file slang_assemble_typeinfo.c - * slang type info - * \author Michal Krol + * Functions for constant folding, built-in constant lookup, and function + * call casting.   */ -#include "imports.h" -#include "macros.h" -#include "get.h" +#include "main/imports.h" +#include "main/macros.h" +#include "main/get.h"  #include "slang_compile.h"  #include "slang_codegen.h"  #include "slang_simplify.h" @@ -300,17 +299,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; @@ -318,95 +318,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); - -   /* 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); -               } +      printf("Adapt call of %d args to func %s (%d params)\n", +             callOper->num_children, (char*) fun->header.a_name, numParams); -               /* 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] = 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 < numParams) { -      /* still not enough args for all params */ -      return GL_FALSE; -   } -   else if (callOper->num_children > 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]; @@ -434,6 +348,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; @@ -444,6 +364,107 @@ _slang_adapt_call(slang_operation *callOper, const slang_function *fun,     }     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);        slang_print_tree(callOper, 5); 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 @@ -14,6 +37,11 @@ _slang_simplify(slang_operation *oper,  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,                    slang_atom_pool * atoms, slang_info_log *log); 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; +   *error = GL_FALSE; -      if (a_name != f->header.a_name) -         continue; -      if (f->param_count - haveRetValue != num_args) -         continue; +   /* 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; +      } +   } -      /* compare parameter / argument types */ -      for (j = 0; j < num_args; j++) { -         slang_typeinfo ti; +   /* loop over function scopes */ +   while (funcs) { -         if (!slang_typeinfo_construct(&ti)) -            return NULL; -         if (!_slang_typeof_operation_(&args[j], space, &ti, atoms, log)) { -            slang_typeinfo_destruct(&ti); -            return NULL; -         } -         if (!slang_type_specifier_compatible(&ti.spec, -             &f->parameters->variables[j]->type.specifier)) { -            slang_typeinfo_destruct(&ti); -            break; +      /* 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; +            }           } -         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) { +            /* name and args match! */ +            return f; +         }        } -      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 587331e8b1..fc89fd9345 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 | 
