mesa: glsl: assorted fixes for resolving polymorphic functions
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 25 Jul 2008 21:33:02 +0000 (15:33 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 25 Jul 2008 21:33:02 +0000 (15:33 -0600)
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
src/mesa/shader/slang/slang_compile.c
src/mesa/shader/slang/slang_compile_variable.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_simplify.c
src/mesa/shader/slang/slang_simplify.h
src/mesa/shader/slang/slang_typeinfo.c
src/mesa/shader/slang/slang_typeinfo.h

index 2f9e147b87c78ad67c9f1a21c04031f819f34415..ad9cf06e2751a1242ca9ffcca4b74823b5b1ab13 100644 (file)
@@ -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 {
index 862d0741ff8fc5592f25291cbb8ab88adff558a0..60539f19b6e962fccd704319db182a8373563fbe 100644 (file)
@@ -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");
index b26c18e38d920f29ebaaed87b7c73b566b0170de..3428b49e1667a8204d5ae1fb51292be83d436a51 100644 (file)
@@ -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;
 }
index 9bff055ad5648b6f9002f75f2ca14062a25cb69d..f1af6902ea10f0fe27182853176da93445a4dc91 100644 (file)
@@ -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;
 
index c34bef2164aecebc3538b691b93859d8c641a37b..c4bf0175beff21275219d3a426394d9342bfa973 100644 (file)
@@ -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"),
  */
 
 /**
- * \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(&paramVar->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(&paramVar->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(&paramVar->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);
index b3840ee9df86bb9551b79798124674b6ea24e27c..8689c23b1a040a78a2033e07eb37a5a1c98b8507 100644 (file)
@@ -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,
index 8a1c3abf4807df21510511cf62f0af37fa05e808..26f9f6ca850ed93b2a0474830fe6778f2fd4de19 100644 (file)
@@ -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;
 }
 
index 8a36fc342273825dff274ffd3c8bb2fac468fad4..960e99bda232f9e53229c3b536d53e690fefae92 100644 (file)
@@ -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