glsl: Optimize ir_triop_lrp(x, y, a) with a = 0.0f or 1.0f
[mesa.git] / src / glsl / ast_function.cpp
index dfdbc55c575fc7abd56c6b51a05da2c239116adc..26f72cf8e95ad343e8e0b772b467181087b62859 100644 (file)
@@ -83,7 +83,7 @@ prototype_string(const glsl_type *return_type, const char *name,
 
    const char *comma = "";
    foreach_list(node, parameters) {
-      const ir_instruction *const param = (ir_instruction *) node;
+      const ir_variable *const param = (ir_variable *) node;
 
       ralloc_asprintf_append(&str, "%s%s", comma, param->type->name);
       comma = ", ";
@@ -132,12 +132,13 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
       }
 
       /* Verify that 'out' and 'inout' actual parameters are lvalues. */
-      if (formal->mode == ir_var_out || formal->mode == ir_var_inout) {
+      if (formal->mode == ir_var_function_out
+          || formal->mode == ir_var_function_inout) {
         const char *mode = NULL;
         switch (formal->mode) {
-        case ir_var_out:   mode = "out";   break;
-        case ir_var_inout: mode = "inout"; break;
-        default:           assert(false);  break;
+        case ir_var_function_out:   mode = "out";   break;
+        case ir_var_function_inout: mode = "inout"; break;
+        default:                    assert(false);  break;
         }
 
         /* This AST-based check catches errors like f(i++).  The IR-based
@@ -152,8 +153,11 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
            return false;
         }
 
-        if (actual->variable_referenced()
-            && actual->variable_referenced()->read_only) {
+        ir_variable *var = actual->variable_referenced();
+        if (var)
+           var->assigned = true;
+
+        if (var && var->read_only) {
            _mesa_glsl_error(&loc, state,
                             "function parameter '%s %s' references the "
                             "read-only variable '%s'",
@@ -180,7 +184,7 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
  */
 static ir_rvalue *
 generate_call(exec_list *instructions, ir_function_signature *sig,
-             YYLTYPE *loc, exec_list *actual_parameters,
+             exec_list *actual_parameters,
              ir_call **call_ir,
              struct _mesa_glsl_parse_state *state)
 {
@@ -207,13 +211,13 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
       if (formal->type->is_numeric() || formal->type->is_boolean()) {
         switch (formal->mode) {
         case ir_var_const_in:
-        case ir_var_in: {
+        case ir_var_function_in: {
            ir_rvalue *converted
               = convert_component(actual, formal->type);
            actual->replace_with(converted);
            break;
         }
-        case ir_var_out:
+        case ir_var_function_out:
            if (actual->type != formal->type) {
               /* To convert an out parameter, we need to create a
                * temporary variable to hold the value before conversion,
@@ -251,7 +255,7 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
               actual->replace_with(deref_tmp_2);
            }
            break;
-        case ir_var_inout:
+        case ir_var_function_inout:
            /* Inout parameters should never require conversion, since that
             * would require an implicit conversion to exist both to and
             * from the formal parameter type, and there are no
@@ -272,10 +276,11 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
    /* If the function call is a constant expression, don't generate any
     * instructions; just generate an ir_constant.
     *
-    * Function calls were first allowed to be constant expressions in GLSL 1.20.
+    * Function calls were first allowed to be constant expressions in GLSL
+    * 1.20 and GLSL ES 3.00.
     */
-   if (state->language_version >= 120) {
-      ir_constant *value = sig->constant_expression_value(actual_parameters);
+   if (state->is_version(120, 300)) {
+      ir_constant *value = sig->constant_expression_value(actual_parameters, NULL);
       if (value != NULL) {
         return value;
       }
@@ -321,7 +326,8 @@ match_function_by_name(const char *name,
       goto done; /* no match */
 
    /* Is the function hidden by a variable (impossible in 1.10)? */
-   if (state->language_version != 110 && state->symbols->get_variable(name))
+   if (!state->symbols->separate_function_namespace
+       && state->symbols->get_variable(name))
       goto done; /* no match */
 
    if (f != NULL) {
@@ -449,8 +455,7 @@ convert_component(ir_rvalue *src, const glsl_type *desired_type)
         result = new(ctx) ir_expression(ir_unop_i2u, src);
         break;
       case GLSL_TYPE_FLOAT:
-        result = new(ctx) ir_expression(ir_unop_i2u,
-                 new(ctx) ir_expression(ir_unop_f2i, src));
+        result = new(ctx) ir_expression(ir_unop_f2u, src);
         break;
       case GLSL_TYPE_BOOL:
         result = new(ctx) ir_expression(ir_unop_i2u,
@@ -1240,9 +1245,8 @@ ast_function_expression::hir(exec_list *instructions,
       }
 
       if (constructor_type->is_array()) {
-        if (state->language_version <= 110) {
-           _mesa_glsl_error(& loc, state,
-                            "array constructors forbidden in GLSL 1.10");
+         if (!state->check_version(120, 300, &loc,
+                                   "array constructors forbidden")) {
            return ir_rvalue::error_value(ctx);
         }
 
@@ -1365,11 +1369,11 @@ ast_function_expression::hir(exec_list *instructions,
        *    "It is an error to construct matrices from other matrices. This
        *    is reserved for future use."
        */
-      if (state->language_version == 110 && matrix_parameters > 0
-         && constructor_type->is_matrix()) {
-        _mesa_glsl_error(& loc, state, "cannot construct `%s' from a "
-                         "matrix in GLSL 1.10",
-                         constructor_type->name);
+      if (matrix_parameters > 0
+          && constructor_type->is_matrix()
+          && !state->check_version(120, 100, &loc,
+                                   "cannot construct `%s' from a matrix",
+                                   constructor_type->name)) {
         return ir_rvalue::error_value(ctx);
       }
 
@@ -1498,7 +1502,7 @@ ast_function_expression::hir(exec_list *instructions,
         /* an error has already been emitted */
         value = ir_rvalue::error_value(ctx);
       } else {
-        value = generate_call(instructions, sig, &loc, &actual_parameters,
+        value = generate_call(instructions, sig, &actual_parameters,
                               &call, state);
       }