glsl: Link glsl_test with pthreads library.
[mesa.git] / src / glsl / ast_function.cpp
index 605ab8c297e96c2b46df08cea10615d6a737016b..cbff9d8b452ba9fab7afda1f8cc6ab12fe03af3b 100644 (file)
@@ -41,8 +41,7 @@ process_parameters(exec_list *instructions, exec_list *actual_parameters,
 {
    unsigned count = 0;
 
-   foreach_list (n, parameters) {
-      ast_node *const ast = exec_node_data(ast_node, n, link);
+   foreach_list_typed(ast_node, ast, link, parameters) {
       ir_rvalue *result = ast->hir(instructions, state);
 
       ir_constant *const constant = result->constant_expression_value();
@@ -82,9 +81,7 @@ prototype_string(const glsl_type *return_type, const char *name,
    ralloc_asprintf_append(&str, "%s(", name);
 
    const char *comma = "";
-   foreach_list(node, parameters) {
-      const ir_variable *const param = (ir_variable *) node;
-
+   foreach_in_list(const ir_variable, param, parameters) {
       ralloc_asprintf_append(&str, "%s%s", comma, param->type->name);
       comma = ", ";
    }
@@ -93,6 +90,57 @@ prototype_string(const glsl_type *return_type, const char *name,
    return str;
 }
 
+static bool
+verify_image_parameter(YYLTYPE *loc, _mesa_glsl_parse_state *state,
+                       const ir_variable *formal, const ir_variable *actual)
+{
+   /**
+    * From the ARB_shader_image_load_store specification:
+    *
+    * "The values of image variables qualified with coherent,
+    *  volatile, restrict, readonly, or writeonly may not be passed
+    *  to functions whose formal parameters lack such
+    *  qualifiers. [...] It is legal to have additional qualifiers
+    *  on a formal parameter, but not to have fewer."
+    */
+   if (actual->data.image_coherent && !formal->data.image_coherent) {
+      _mesa_glsl_error(loc, state,
+                       "function call parameter `%s' drops "
+                       "`coherent' qualifier", formal->name);
+      return false;
+   }
+
+   if (actual->data.image_volatile && !formal->data.image_volatile) {
+      _mesa_glsl_error(loc, state,
+                       "function call parameter `%s' drops "
+                       "`volatile' qualifier", formal->name);
+      return false;
+   }
+
+   if (actual->data.image_restrict && !formal->data.image_restrict) {
+      _mesa_glsl_error(loc, state,
+                       "function call parameter `%s' drops "
+                       "`restrict' qualifier", formal->name);
+      return false;
+   }
+
+   if (actual->data.image_read_only && !formal->data.image_read_only) {
+      _mesa_glsl_error(loc, state,
+                       "function call parameter `%s' drops "
+                       "`readonly' qualifier", formal->name);
+      return false;
+   }
+
+   if (actual->data.image_write_only && !formal->data.image_write_only) {
+      _mesa_glsl_error(loc, state,
+                       "function call parameter `%s' drops "
+                       "`writeonly' qualifier", formal->name);
+      return false;
+   }
+
+   return true;
+}
+
 /**
  * Verify that 'out' and 'inout' actual parameters are lvalues.  Also, verify
  * that 'const_in' formal parameters (an extension in our IR) correspond to
@@ -107,12 +155,11 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
    exec_node *actual_ir_node  = actual_ir_parameters.head;
    exec_node *actual_ast_node = actual_ast_parameters.head;
 
-   foreach_list(formal_node, &sig->parameters) {
+   foreach_in_list(const ir_variable, formal, &sig->parameters) {
       /* The lists must be the same length. */
       assert(!actual_ir_node->is_tail_sentinel());
       assert(!actual_ast_node->is_tail_sentinel());
 
-      const ir_variable *const formal = (ir_variable *) formal_node;
       const ir_rvalue *const actual = (ir_rvalue *) actual_ir_node;
       const ast_expression *const actual_ast =
         exec_node_data(ast_expression, actual_ast_node, link);
@@ -131,6 +178,24 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
         return false;
       }
 
+      /* Verify that shader_in parameters are shader inputs */
+      if (formal->data.must_be_shader_input) {
+         ir_variable *var = actual->variable_referenced();
+         if (var && var->data.mode != ir_var_shader_in) {
+            _mesa_glsl_error(&loc, state,
+                             "parameter `%s` must be a shader input",
+                             formal->name);
+            return false;
+         }
+
+         if (actual->ir_type == ir_type_swizzle) {
+            _mesa_glsl_error(&loc, state,
+                             "parameter `%s` must not be swizzled",
+                             formal->name);
+            return false;
+         }
+      }
+
       /* Verify that 'out' and 'inout' actual parameters are lvalues. */
       if (formal->data.mode == ir_var_function_out
           || formal->data.mode == ir_var_function_inout) {
@@ -180,6 +245,13 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
         }
       }
 
+      if (formal->type->is_image() &&
+          actual->variable_referenced()) {
+         if (!verify_image_parameter(&loc, state, formal,
+                                     actual->variable_referenced()))
+            return false;
+      }
+
       actual_ir_node  = actual_ir_node->next;
       actual_ast_node = actual_ast_node->next;
    }
@@ -293,15 +365,10 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
     * call takes place.  Since we haven't emitted the call yet, we'll place
     * the post-call conversions in a temporary exec_list, and emit them later.
     */
-   exec_list_iterator actual_iter = actual_parameters->iterator();
-   exec_list_iterator formal_iter = sig->parameters.iterator();
-
-   while (actual_iter.has_next()) {
-      ir_rvalue *actual = (ir_rvalue *) actual_iter.get();
-      ir_variable *formal = (ir_variable *) formal_iter.get();
-
-      assert(actual != NULL);
-      assert(formal != NULL);
+   foreach_two_lists(formal_node, &sig->parameters,
+                     actual_node, actual_parameters) {
+      ir_rvalue *actual = (ir_rvalue *) actual_node;
+      ir_variable *formal = (ir_variable *) formal_node;
 
       if (formal->type->is_numeric() || formal->type->is_boolean()) {
         switch (formal->data.mode) {
@@ -323,9 +390,6 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
            break;
         }
       }
-
-      actual_iter.next();
-      formal_iter.next();
    }
 
    /* If the function call is a constant expression, don't generate any
@@ -344,14 +408,17 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
    ir_dereference_variable *deref = NULL;
    if (!sig->return_type->is_void()) {
       /* Create a new temporary to hold the return value. */
+      char *const name = ir_variable::temporaries_allocate_names
+         ? ralloc_asprintf(ctx, "%s_retval", sig->function_name())
+         : NULL;
+
       ir_variable *var;
 
-      var = new(ctx) ir_variable(sig->return_type,
-                                ralloc_asprintf(ctx, "%s_retval",
-                                                sig->function_name()),
-                                ir_var_temporary);
+      var = new(ctx) ir_variable(sig->return_type, name, ir_var_temporary);
       instructions->push_tail(var);
 
+      ralloc_free(name);
+
       deref = new(ctx) ir_dereference_variable(var);
    }
    ir_call *call = new(ctx) ir_call(sig, deref, actual_parameters);
@@ -386,20 +453,21 @@ match_function_by_name(const char *name,
       goto done; /* no match */
 
    if (f != NULL) {
+      /* In desktop GL, the presence of a user-defined signature hides any
+       * built-in signatures, so we must ignore them.  In contrast, in ES2
+       * user-defined signatures add new overloads, so we must consider them.
+       */
+      bool allow_builtins = state->es_shader || !f->has_user_signature();
+
       /* Look for a match in the local shader.  If exact, we're done. */
       bool is_exact = false;
       sig = local_sig = f->matching_signature(state, actual_parameters,
-                                              &is_exact);
+                                              allow_builtins, &is_exact);
       if (is_exact)
         goto done;
 
-      if (!state->es_shader && f->has_user_signature()) {
-        /* In desktop GL, the presence of a user-defined signature hides any
-         * built-in signatures, so we must ignore them.  In contrast, in ES2
-         * user-defined signatures add new overloads, so we must proceed.
-         */
+      if (!allow_builtins)
         goto done;
-      }
    }
 
    /* Local shader has no exact candidates; check the built-ins. */
@@ -428,9 +496,7 @@ print_function_prototypes(_mesa_glsl_parse_state *state, YYLTYPE *loc,
    if (f == NULL)
       return;
 
-   foreach_list (node, &f->signatures) {
-      ir_function_signature *sig = (ir_function_signature *) node;
-
+   foreach_in_list(ir_function_signature, sig, &f->signatures) {
       if (sig->is_builtin() && !sig->is_builtin_available(state))
          continue;
 
@@ -450,17 +516,24 @@ no_matching_function_error(const char *name,
                           exec_list *actual_parameters,
                           _mesa_glsl_parse_state *state)
 {
-   char *str = prototype_string(NULL, name, actual_parameters);
-   _mesa_glsl_error(loc, state,
-                    "no matching function for call to `%s'; candidates are:",
-                    str);
-   ralloc_free(str);
+   gl_shader *sh = _mesa_glsl_get_builtin_function_shader();
 
-   print_function_prototypes(state, loc, state->symbols->get_function(name));
+   if (state->symbols->get_function(name) == NULL
+      && (!state->uses_builtin_functions
+          || sh->symbols->get_function(name) == NULL)) {
+      _mesa_glsl_error(loc, state, "no function with name '%s'", name);
+   } else {
+      char *str = prototype_string(NULL, name, actual_parameters);
+      _mesa_glsl_error(loc, state,
+                       "no matching function for call to `%s'; candidates are:",
+                       str);
+      ralloc_free(str);
+
+      print_function_prototypes(state, loc, state->symbols->get_function(name));
 
-   if (state->uses_builtin_functions) {
-      gl_shader *sh = _mesa_glsl_get_builtin_function_shader();
-      print_function_prototypes(state, loc, sh->symbols->get_function(name));
+      if (state->uses_builtin_functions) {
+         print_function_prototypes(state, loc, sh->symbols->get_function(name));
+      }
    }
 }
 
@@ -633,8 +706,7 @@ process_vec_mat_constructor(exec_list *instructions,
    bool all_parameters_are_constant = true;
 
    /* Type cast each parameter and, if possible, fold constants. */
-   foreach_list_safe(n, &actual_parameters) {
-      ir_rvalue *ir = (ir_rvalue *) n;
+   foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) {
       ir_rvalue *result = ir;
 
       /* Apply implicit conversions (not the scalar constructor rules!). See
@@ -644,7 +716,7 @@ process_vec_mat_constructor(exec_list *instructions,
             glsl_type::get_instance(GLSL_TYPE_FLOAT,
                                     ir->type->vector_elements,
                                     ir->type->matrix_columns);
-         if (result->type->can_implicitly_convert_to(desired_type)) {
+         if (result->type->can_implicitly_convert_to(desired_type, state)) {
             /* Even though convert_component() implements the constructor
              * conversion rules (not the implicit conversion rules), its safe
              * to use it here because we already checked that the implicit
@@ -692,12 +764,22 @@ process_vec_mat_constructor(exec_list *instructions,
    instructions->push_tail(var);
 
    int i = 0;
-   foreach_list(node, &actual_parameters) {
-      ir_rvalue *rhs = (ir_rvalue *) node;
-      ir_rvalue *lhs = new(ctx) ir_dereference_array(var,
-                                                     new(ctx) ir_constant(i));
 
-      ir_instruction *assignment = new(ctx) ir_assignment(lhs, rhs, NULL);
+   foreach_in_list(ir_rvalue, rhs, &actual_parameters) {
+      ir_instruction *assignment = NULL;
+
+      if (var->type->is_matrix()) {
+         ir_rvalue *lhs = new(ctx) ir_dereference_array(var,
+                                             new(ctx) ir_constant(i));
+         assignment = new(ctx) ir_assignment(lhs, rhs, NULL);
+      } else {
+         /* use writemask rather than index for vector */
+         assert(var->type->is_vector());
+         assert(i < 4);
+         ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
+         assignment = new(ctx) ir_assignment(lhs, rhs, NULL, (unsigned)(1 << i));
+      }
+
       instructions->push_tail(assignment);
 
       i++;
@@ -762,8 +844,7 @@ process_array_constructor(exec_list *instructions,
    bool all_parameters_are_constant = true;
 
    /* Type cast each parameter and, if possible, fold constants. */
-   foreach_list_safe(n, &actual_parameters) {
-      ir_rvalue *ir = (ir_rvalue *) n;
+   foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) {
       ir_rvalue *result = ir;
 
       /* Apply implicit conversions (not the scalar constructor rules!). See
@@ -773,7 +854,7 @@ process_array_constructor(exec_list *instructions,
            glsl_type::get_instance(GLSL_TYPE_FLOAT,
                                    ir->type->vector_elements,
                                    ir->type->matrix_columns);
-        if (result->type->can_implicitly_convert_to(desired_type)) {
+        if (result->type->can_implicitly_convert_to(desired_type, state)) {
            /* Even though convert_component() implements the constructor
             * conversion rules (not the implicit conversion rules), its safe
             * to use it here because we already checked that the implicit
@@ -813,8 +894,7 @@ process_array_constructor(exec_list *instructions,
    instructions->push_tail(var);
 
    int i = 0;
-   foreach_list(node, &actual_parameters) {
-      ir_rvalue *rhs = (ir_rvalue *) node;
+   foreach_in_list(ir_rvalue, rhs, &actual_parameters) {
       ir_rvalue *lhs = new(ctx) ir_dereference_array(var,
                                                     new(ctx) ir_constant(i));
 
@@ -835,8 +915,8 @@ static ir_constant *
 constant_record_constructor(const glsl_type *constructor_type,
                            exec_list *parameters, void *mem_ctx)
 {
-   foreach_list(node, parameters) {
-      ir_constant *constant = ((ir_instruction *) node)->as_constant();
+   foreach_in_list(ir_instruction, node, parameters) {
+      ir_constant *constant = node->as_constant();
       if (constant == NULL)
         return NULL;
       node->replace_with(constant);
@@ -910,8 +990,7 @@ emit_inline_vector_constructor(const glsl_type *type,
 
       memset(&data, 0, sizeof(data));
 
-      foreach_list(node, parameters) {
-        ir_rvalue *param = (ir_rvalue *) node;
+      foreach_in_list(ir_rvalue, param, parameters) {
         unsigned rhs_components = param->type->components();
 
         /* Do not try to assign more components to the vector than it has!
@@ -968,8 +1047,7 @@ emit_inline_vector_constructor(const glsl_type *type,
       }
 
       base_component = 0;
-      foreach_list(node, parameters) {
-        ir_rvalue *param = (ir_rvalue *) node;
+      foreach_in_list(ir_rvalue, param, parameters) {
         unsigned rhs_components = param->type->components();
 
         /* Do not try to assign more components to the vector than it has!
@@ -1255,8 +1333,7 @@ emit_inline_matrix_constructor(const glsl_type *type,
       unsigned col_idx = 0;
       unsigned row_idx = 0;
 
-      foreach_list (node, parameters) {
-        ir_rvalue *const rhs = (ir_rvalue *) node;
+      foreach_in_list(ir_rvalue, rhs, parameters) {
         const unsigned components_remaining_this_column = rows - row_idx;
         unsigned rhs_components = rhs->type->components();
         unsigned rhs_base = 0;
@@ -1501,9 +1578,8 @@ ast_function_expression::hir(exec_list *instructions,
       unsigned nonmatrix_parameters = 0;
       exec_list actual_parameters;
 
-      foreach_list (n, &this->expressions) {
-        ast_node *ast = exec_node_data(ast_node, n, link);
-        ir_rvalue *result = ast->hir(instructions, state)->as_rvalue();
+      foreach_list_typed(ast_node, ast, link, &this->expressions) {
+        ir_rvalue *result = ast->hir(instructions, state);
 
         /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec:
          *
@@ -1582,9 +1658,7 @@ ast_function_expression::hir(exec_list *instructions,
        * need to break them up into a series of column vectors.
        */
       if (constructor_type->base_type != GLSL_TYPE_FLOAT) {
-        foreach_list_safe(n, &actual_parameters) {
-           ir_rvalue *matrix = (ir_rvalue *) n;
-
+        foreach_in_list_safe(ir_rvalue, matrix, &actual_parameters) {
            if (!matrix->type->is_matrix())
               continue;
 
@@ -1608,9 +1682,7 @@ ast_function_expression::hir(exec_list *instructions,
       bool all_parameters_are_constant = true;
 
       /* Type cast each parameter and, if possible, fold constants.*/
-      foreach_list_safe(n, &actual_parameters) {
-        ir_rvalue *ir = (ir_rvalue *) n;
-
+      foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) {
         const glsl_type *desired_type =
            glsl_type::get_instance(constructor_type->base_type,
                                    ir->type->vector_elements,
@@ -1688,14 +1760,12 @@ ast_aggregate_initializer::hir(exec_list *instructions,
 {
    void *ctx = state;
    YYLTYPE loc = this->get_location();
-   const char *name;
 
    if (!this->constructor_type) {
       _mesa_glsl_error(&loc, state, "type of C-style initializer unknown");
       return ir_rvalue::error_value(ctx);
    }
-   const glsl_type *const constructor_type =
-      this->constructor_type->glsl_type(&name, state);
+   const glsl_type *const constructor_type = this->constructor_type;
 
    if (!state->ARB_shading_language_420pack_enable) {
       _mesa_glsl_error(&loc, state, "C-style initialization requires the "
@@ -1703,12 +1773,12 @@ ast_aggregate_initializer::hir(exec_list *instructions,
       return ir_rvalue::error_value(ctx);
    }
 
-   if (this->constructor_type->is_array) {
+   if (constructor_type->is_array()) {
       return process_array_constructor(instructions, constructor_type, &loc,
                                        &this->expressions, state);
    }
 
-   if (this->constructor_type->structure) {
+   if (constructor_type->is_record()) {
       return process_record_constructor(instructions, constructor_type, &loc,
                                         &this->expressions, state);
    }