nir: move to compiler/
[mesa.git] / src / glsl / ast_function.cpp
index cbff9d8b452ba9fab7afda1f8cc6ab12fe03af3b..0eb456a2b1f448729ef5e9be9a0d46f754b4fe48 100644 (file)
 
 #include "glsl_symbol_table.h"
 #include "ast.h"
-#include "glsl_types.h"
+#include "compiler/glsl_types.h"
 #include "ir.h"
 #include "main/core.h" /* for MIN2 */
+#include "main/shaderobj.h"
 
 static ir_rvalue *
 convert_component(ir_rvalue *src, const glsl_type *desired_type);
@@ -141,6 +142,33 @@ verify_image_parameter(YYLTYPE *loc, _mesa_glsl_parse_state *state,
    return true;
 }
 
+static bool
+verify_first_atomic_parameter(YYLTYPE *loc, _mesa_glsl_parse_state *state,
+                                   ir_variable *var)
+{
+   if (!var ||
+       (!var->is_in_shader_storage_block() &&
+        var->data.mode != ir_var_shader_shared)) {
+      _mesa_glsl_error(loc, state, "First argument to atomic function "
+                       "must be a buffer or shared variable");
+      return false;
+   }
+   return true;
+}
+
+static bool
+is_atomic_function(const char *func_name)
+{
+   return !strcmp(func_name, "atomicAdd") ||
+          !strcmp(func_name, "atomicMin") ||
+          !strcmp(func_name, "atomicMax") ||
+          !strcmp(func_name, "atomicAnd") ||
+          !strcmp(func_name, "atomicOr") ||
+          !strcmp(func_name, "atomicXor") ||
+          !strcmp(func_name, "atomicExchange") ||
+          !strcmp(func_name, "atomicCompSwap");
+}
+
 /**
  * Verify that 'out' and 'inout' actual parameters are lvalues.  Also, verify
  * that 'const_in' formal parameters (an extension in our IR) correspond to
@@ -230,18 +258,10 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
                             actual->variable_referenced()->name);
            return false;
         } else if (!actual->is_lvalue()) {
-            /* Even though ir_binop_vector_extract is not an l-value, let it
-             * slop through.  generate_call will handle it correctly.
-             */
-            ir_expression *const expr = ((ir_rvalue *) actual)->as_expression();
-            if (expr == NULL
-                || expr->operation != ir_binop_vector_extract
-                || !expr->operands[0]->is_lvalue()) {
-               _mesa_glsl_error(&loc, state,
-                                "function parameter '%s %s' is not an lvalue",
-                                mode, formal->name);
-               return false;
-            }
+            _mesa_glsl_error(&loc, state,
+                             "function parameter '%s %s' is not an lvalue",
+                             mode, formal->name);
+            return false;
         }
       }
 
@@ -255,6 +275,23 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
       actual_ir_node  = actual_ir_node->next;
       actual_ast_node = actual_ast_node->next;
    }
+
+   /* The first parameter of atomic functions must be a buffer variable */
+   const char *func_name = sig->function_name();
+   bool is_atomic = is_atomic_function(func_name);
+   if (is_atomic) {
+      const ir_rvalue *const actual = (ir_rvalue *) actual_ir_parameters.head;
+
+      const ast_expression *const actual_ast =
+         exec_node_data(ast_expression, actual_ast_parameters.head, link);
+      YYLTYPE loc = actual_ast->get_location();
+
+      if (!verify_first_atomic_parameter(&loc, state,
+                                         actual->variable_referenced())) {
+         return false;
+      }
+   }
+
    return true;
 }
 
@@ -333,12 +370,8 @@ fix_parameter(void *mem_ctx, ir_rvalue *actual, const glsl_type *formal_type,
 
    ir_rvalue *lhs = actual;
    if (expr != NULL && expr->operation == ir_binop_vector_extract) {
-      rhs = new(mem_ctx) ir_expression(ir_triop_vector_insert,
-                                       expr->operands[0]->type,
-                                       expr->operands[0]->clone(mem_ctx, NULL),
-                                       rhs,
-                                       expr->operands[1]->clone(mem_ctx, NULL));
-      lhs = expr->operands[0]->clone(mem_ctx, NULL);
+      lhs = new(mem_ctx) ir_dereference_array(expr->operands[0]->clone(mem_ctx, NULL),
+                                              expr->operands[1]->clone(mem_ctx, NULL));
    }
 
    ir_assignment *const assignment_2 = new(mem_ctx) ir_assignment(lhs, rhs);
@@ -355,6 +388,8 @@ fix_parameter(void *mem_ctx, ir_rvalue *actual, const glsl_type *formal_type,
 static ir_rvalue *
 generate_call(exec_list *instructions, ir_function_signature *sig,
              exec_list *actual_parameters,
+              ir_variable *sub_var,
+             ir_rvalue *array_idx,
              struct _mesa_glsl_parse_state *state)
 {
    void *ctx = state;
@@ -392,13 +427,54 @@ 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.
+   /* Section 4.3.2 (Const) of the GLSL 1.10.59 spec says:
+    *
+    *     "Initializers for const declarations must be formed from literal
+    *     values, other const variables (not including function call
+    *     paramaters), or expressions of these.
+    *
+    *     Constructors may be used in such expressions, but function calls may
+    *     not."
+    *
+    * Section 4.3.3 (Constant Expressions) of the GLSL 1.20.8 spec says:
+    *
+    *     "A constant expression is one of
+    *
+    *         ...
+    *
+    *         - a built-in function call whose arguments are all constant
+    *           expressions, with the exception of the texture lookup
+    *           functions, the noise functions, and ftransform. The built-in
+    *           functions dFdx, dFdy, and fwidth must return 0 when evaluated
+    *           inside an initializer with an argument that is a constant
+    *           expression."
+    *
+    * Section 5.10 (Constant Expressions) of the GLSL ES 1.00.17 spec says:
+    *
+    *     "A constant expression is one of
+    *
+    *         ...
+    *
+    *         - a built-in function call whose arguments are all constant
+    *           expressions, with the exception of the texture lookup
+    *           functions."
+    *
+    * Section 4.3.3 (Constant Expressions) of the GLSL ES 3.00.4 spec says:
+    *
+    *     "A constant expression is one of
+    *
+    *         ...
     *
-    * Function calls were first allowed to be constant expressions in GLSL
-    * 1.20 and GLSL ES 3.00.
+    *         - a built-in function call whose arguments are all constant
+    *           expressions, with the exception of the texture lookup
+    *           functions.  The built-in functions dFdx, dFdy, and fwidth must
+    *           return 0 when evaluated inside an initializer with an argument
+    *           that is a constant expression."
+    *
+    * If the function call is a constant expression, don't generate any
+    * instructions; just generate an ir_constant.
     */
-   if (state->is_version(120, 300)) {
+   if (state->is_version(120, 100)) {
       ir_constant *value = sig->constant_expression_value(actual_parameters, NULL);
       if (value != NULL) {
         return value;
@@ -421,7 +497,8 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
 
       deref = new(ctx) ir_dereference_variable(var);
    }
-   ir_call *call = new(ctx) ir_call(sig, deref, actual_parameters);
+
+   ir_call *call = new(ctx) ir_call(sig, deref, actual_parameters, sub_var, array_idx);
    instructions->push_tail(call);
 
    /* Also emit any necessary out-parameter conversions. */
@@ -489,6 +566,71 @@ done:
    return sig;
 }
 
+static ir_function_signature *
+match_subroutine_by_name(const char *name,
+                         exec_list *actual_parameters,
+                         struct _mesa_glsl_parse_state *state,
+                         ir_variable **var_r)
+{
+   void *ctx = state;
+   ir_function_signature *sig = NULL;
+   ir_function *f, *found = NULL;
+   const char *new_name;
+   ir_variable *var;
+   bool is_exact = false;
+
+   new_name = ralloc_asprintf(ctx, "%s_%s", _mesa_shader_stage_to_subroutine_prefix(state->stage), name);
+   var = state->symbols->get_variable(new_name);
+   if (!var)
+      return NULL;
+
+   for (int i = 0; i < state->num_subroutine_types; i++) {
+      f = state->subroutine_types[i];
+      if (strcmp(f->name, var->type->without_array()->name))
+         continue;
+      found = f;
+      break;
+   }
+
+   if (!found)
+      return NULL;
+   *var_r = var;
+   sig = found->matching_signature(state, actual_parameters,
+                                  false, &is_exact);
+   return sig;
+}
+
+static ir_rvalue *
+generate_array_index(void *mem_ctx, exec_list *instructions,
+                     struct _mesa_glsl_parse_state *state, YYLTYPE loc,
+                     const ast_expression *array, ast_expression *idx,
+                     const char **function_name, exec_list *actual_parameters)
+{
+   if (array->oper == ast_array_index) {
+      /* This handles arrays of arrays */
+      ir_rvalue *outer_array = generate_array_index(mem_ctx, instructions,
+                                                    state, loc,
+                                                    array->subexpressions[0],
+                                                    array->subexpressions[1],
+                                                    function_name, actual_parameters);
+      ir_rvalue *outer_array_idx = idx->hir(instructions, state);
+
+      YYLTYPE index_loc = idx->get_location();
+      return _mesa_ast_array_index_to_hir(mem_ctx, state, outer_array,
+                                          outer_array_idx, loc,
+                                          index_loc);
+   } else {
+      ir_variable *sub_var = NULL;
+      *function_name = array->primary_expression.identifier;
+
+      match_subroutine_by_name(*function_name, actual_parameters,
+                               state, &sub_var);
+
+      ir_rvalue *outer_array_idx = idx->hir(instructions, state);
+      return new(mem_ctx) ir_dereference_array(sub_var, outer_array_idx);
+   }
+}
+
 static void
 print_function_prototypes(_mesa_glsl_parse_state *state, YYLTYPE *loc,
                           ir_function *f)
@@ -573,6 +715,9 @@ convert_component(ir_rvalue *src, const glsl_type *desired_type)
         result = new(ctx) ir_expression(ir_unop_i2u,
                  new(ctx) ir_expression(ir_unop_b2i, src));
         break;
+      case GLSL_TYPE_DOUBLE:
+        result = new(ctx) ir_expression(ir_unop_d2u, src);
+        break;
       }
       break;
    case GLSL_TYPE_INT:
@@ -586,6 +731,9 @@ convert_component(ir_rvalue *src, const glsl_type *desired_type)
       case GLSL_TYPE_BOOL:
         result = new(ctx) ir_expression(ir_unop_b2i, src);
         break;
+      case GLSL_TYPE_DOUBLE:
+        result = new(ctx) ir_expression(ir_unop_d2i, src);
+        break;
       }
       break;
    case GLSL_TYPE_FLOAT:
@@ -599,6 +747,9 @@ convert_component(ir_rvalue *src, const glsl_type *desired_type)
       case GLSL_TYPE_BOOL:
         result = new(ctx) ir_expression(ir_unop_b2f, desired_type, src, NULL);
         break;
+      case GLSL_TYPE_DOUBLE:
+        result = new(ctx) ir_expression(ir_unop_d2f, desired_type, src, NULL);
+        break;
       }
       break;
    case GLSL_TYPE_BOOL:
@@ -613,8 +764,27 @@ convert_component(ir_rvalue *src, const glsl_type *desired_type)
       case GLSL_TYPE_FLOAT:
         result = new(ctx) ir_expression(ir_unop_f2b, desired_type, src, NULL);
         break;
+      case GLSL_TYPE_DOUBLE:
+         result = new(ctx) ir_expression(ir_unop_d2b, desired_type, src, NULL);
+         break;
       }
       break;
+   case GLSL_TYPE_DOUBLE:
+      switch (b) {
+      case GLSL_TYPE_INT:
+         result = new(ctx) ir_expression(ir_unop_i2d, src);
+         break;
+      case GLSL_TYPE_UINT:
+         result = new(ctx) ir_expression(ir_unop_u2d, src);
+         break;
+      case GLSL_TYPE_BOOL:
+         result = new(ctx) ir_expression(ir_unop_f2d,
+                  new(ctx) ir_expression(ir_unop_b2f, src));
+         break;
+      case GLSL_TYPE_FLOAT:
+         result = new(ctx) ir_expression(ir_unop_f2d, desired_type, src, NULL);
+         break;
+      }
    }
 
    assert(result != NULL);
@@ -711,9 +881,9 @@ process_vec_mat_constructor(exec_list *instructions,
 
       /* Apply implicit conversions (not the scalar constructor rules!). See
        * the spec quote above. */
-      if (constructor_type->is_float()) {
+      if (constructor_type->base_type != result->type->base_type) {
          const glsl_type *desired_type =
-            glsl_type::get_instance(GLSL_TYPE_FLOAT,
+            glsl_type::get_instance(constructor_type->base_type,
                                     ir->type->vector_elements,
                                     ir->type->matrix_columns);
          if (result->type->can_implicitly_convert_to(desired_type, state)) {
@@ -835,25 +1005,30 @@ process_array_constructor(exec_list *instructions,
 
    if (is_unsized_array) {
       constructor_type =
-        glsl_type::get_array_instance(constructor_type->element_type(),
+        glsl_type::get_array_instance(constructor_type->fields.array,
                                       parameter_count);
       assert(constructor_type != NULL);
       assert(constructor_type->length == parameter_count);
    }
 
    bool all_parameters_are_constant = true;
+   const glsl_type *element_type = constructor_type->fields.array;
 
    /* Type cast each parameter and, if possible, fold constants. */
    foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) {
       ir_rvalue *result = ir;
 
+      const glsl_base_type element_base_type =
+         constructor_type->fields.array->base_type;
+
       /* Apply implicit conversions (not the scalar constructor rules!). See
        * the spec quote above. */
-      if (constructor_type->element_type()->is_float()) {
-        const glsl_type *desired_type =
-           glsl_type::get_instance(GLSL_TYPE_FLOAT,
-                                   ir->type->vector_elements,
-                                   ir->type->matrix_columns);
+      if (element_base_type != result->type->base_type) {
+         const glsl_type *desired_type =
+            glsl_type::get_instance(element_base_type,
+                                    ir->type->vector_elements,
+                                    ir->type->matrix_columns);
+
         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
@@ -864,12 +1039,34 @@ process_array_constructor(exec_list *instructions,
         }
       }
 
-      if (result->type != constructor_type->element_type()) {
+      if (constructor_type->fields.array->is_unsized_array()) {
+         /* As the inner parameters of the constructor are created without
+          * knowledge of each other we need to check to make sure unsized
+          * parameters of unsized constructors all end up with the same size.
+          *
+          * e.g we make sure to fail for a constructor like this:
+          * vec4[][] a = vec4[][](vec4[](vec4(0.0), vec4(1.0)),
+          *                       vec4[](vec4(0.0), vec4(1.0), vec4(1.0)),
+          *                       vec4[](vec4(0.0), vec4(1.0)));
+          */
+         if (element_type->is_unsized_array()) {
+             /* This is the first parameter so just get the type */
+            element_type = result->type;
+         } else if (element_type != result->type) {
+            _mesa_glsl_error(loc, state, "type error in array constructor: "
+                             "expected: %s, found %s",
+                             element_type->name,
+                             result->type->name);
+            return ir_rvalue::error_value(ctx);
+         }
+      } else if (result->type != constructor_type->fields.array) {
         _mesa_glsl_error(loc, state, "type error in array constructor: "
                          "expected: %s, found %s",
-                         constructor_type->element_type()->name,
+                         constructor_type->fields.array->name,
                          result->type->name);
          return ir_rvalue::error_value(ctx);
+      } else {
+         element_type = result->type;
       }
 
       /* Attempt to convert the parameter to a constant valued expression.
@@ -886,6 +1083,14 @@ process_array_constructor(exec_list *instructions,
       ir->replace_with(result);
    }
 
+   if (constructor_type->fields.array->is_unsized_array()) {
+      constructor_type =
+        glsl_type::get_array_instance(element_type,
+                                      parameter_count);
+      assert(constructor_type != NULL);
+      assert(constructor_type->length == parameter_count);
+   }
+
    if (all_parameters_are_constant)
       return new(ctx) ir_constant(constructor_type, &actual_parameters);
 
@@ -961,11 +1166,15 @@ emit_inline_vector_constructor(const glsl_type *type,
    ir_variable *var = new(ctx) ir_variable(type, "vec_ctor", ir_var_temporary);
    instructions->push_tail(var);
 
-   /* There are two kinds of vector constructors.
+   /* There are three kinds of vector constructors.
     *
     *  - Construct a vector from a single scalar by replicating that scalar to
     *    all components of the vector.
     *
+    *  - Construct a vector from at least a matrix. This case should already
+    *    have been taken care of in ast_function_expression::hir by breaking
+    *    down the matrix into a series of column vectors.
+    *
     *  - Construct a vector from an arbirary combination of vectors and
     *    scalars.  The components of the constructor parameters are assigned
     *    to the vector in order until the vector is full.
@@ -1012,6 +1221,9 @@ emit_inline_vector_constructor(const glsl_type *type,
               case GLSL_TYPE_FLOAT:
                  data.f[i + base_component] = c->get_float_component(i);
                  break;
+              case GLSL_TYPE_DOUBLE:
+                 data.d[i + base_component] = c->get_double_component(i);
+                 break;
               case GLSL_TYPE_BOOL:
                  data.b[i + base_component] = c->get_bool_component(i);
                  break;
@@ -1056,6 +1268,14 @@ emit_inline_vector_constructor(const glsl_type *type,
            rhs_components = lhs_components - base_component;
         }
 
+        /* If we do not have any components left to copy, break out of the
+         * loop. This can happen when initializing a vec4 with a mat3 as the
+         * mat3 would have been broken into a series of column vectors.
+         */
+        if (rhs_components == 0) {
+           break;
+        }
+
         const ir_constant *const c = param->as_constant();
         if (c == NULL) {
            /* Mask of fields to be written in the assignment.
@@ -1156,7 +1376,7 @@ emit_inline_matrix_constructor(const glsl_type *type,
     *
     *  - Construct a matrix from an arbirary combination of vectors and
     *    scalars.  The components of the constructor parameters are assigned
-    *    to the matrix in colum-major order until the matrix is full.
+    *    to the matrix in column-major order until the matrix is full.
     *
     *  - Construct a matrix from a single matrix.  The source matrix is copied
     *    to the upper left portion of the constructed matrix, and the remaining
@@ -1167,16 +1387,21 @@ emit_inline_matrix_constructor(const glsl_type *type,
       /* Assign the scalar to the X component of a vec4, and fill the remaining
        * components with zero.
        */
+      glsl_base_type param_base_type = first_param->type->base_type;
+      assert(param_base_type == GLSL_TYPE_FLOAT ||
+             param_base_type == GLSL_TYPE_DOUBLE);
       ir_variable *rhs_var =
-        new(ctx) ir_variable(glsl_type::vec4_type, "mat_ctor_vec",
-                             ir_var_temporary);
+         new(ctx) ir_variable(glsl_type::get_instance(param_base_type, 4, 1),
+                              "mat_ctor_vec",
+                              ir_var_temporary);
       instructions->push_tail(rhs_var);
 
       ir_constant_data zero;
-      zero.f[0] = 0.0;
-      zero.f[1] = 0.0;
-      zero.f[2] = 0.0;
-      zero.f[3] = 0.0;
+      for (unsigned i = 0; i < 4; i++)
+         if (param_base_type == GLSL_TYPE_FLOAT)
+            zero.f[i] = 0.0;
+         else
+            zero.d[i] = 0.0;
 
       ir_instruction *inst =
         new(ctx) ir_assignment(new(ctx) ir_dereference_variable(rhs_var),
@@ -1330,71 +1555,59 @@ emit_inline_matrix_constructor(const glsl_type *type,
    } else {
       const unsigned cols = type->matrix_columns;
       const unsigned rows = type->vector_elements;
+      unsigned remaining_slots = rows * cols;
       unsigned col_idx = 0;
       unsigned row_idx = 0;
 
       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;
-
-        /* Since the parameter might be used in the RHS of two assignments,
-         * generate a temporary and copy the paramter there.
-         */
-        ir_variable *rhs_var =
-           new(ctx) ir_variable(rhs->type, "mat_ctor_vec", ir_var_temporary);
-        instructions->push_tail(rhs_var);
-
-        ir_dereference *rhs_var_ref =
-           new(ctx) ir_dereference_variable(rhs_var);
-        ir_instruction *inst = new(ctx) ir_assignment(rhs_var_ref, rhs, NULL);
-        instructions->push_tail(inst);
-
-        /* Assign the current parameter to as many components of the matrix
-         * as it will fill.
-         *
-         * NOTE: A single vector parameter can span two matrix columns.  A
-         * single vec4, for example, can completely fill a mat2.
-         */
-        if (rhs_components >= components_remaining_this_column) {
-           const unsigned count = MIN2(rhs_components,
-                                       components_remaining_this_column);
-
-           rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var);
-
-           ir_instruction *inst = assign_to_matrix_column(var, col_idx,
-                                                          row_idx,
-                                                          rhs_var_ref, 0,
-                                                          count, ctx);
-           instructions->push_tail(inst);
-
-           rhs_base = count;
-
-           col_idx++;
-           row_idx = 0;
-        }
-
-        /* If there is data left in the parameter and components left to be
-         * set in the destination, emit another assignment.  It is possible
-         * that the assignment could be of a vec4 to the last element of the
-         * matrix.  In this case col_idx==cols, but there is still data
-         * left in the source parameter.  Obviously, don't emit an assignment
-         * to data outside the destination matrix.
-         */
-        if ((col_idx < cols) && (rhs_base < rhs_components)) {
-           const unsigned count = rhs_components - rhs_base;
-
-           rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var);
-
-           ir_instruction *inst = assign_to_matrix_column(var, col_idx,
-                                                          row_idx,
-                                                          rhs_var_ref,
-                                                          rhs_base,
-                                                          count, ctx);
-           instructions->push_tail(inst);
-
-           row_idx += count;
-        }
+         unsigned rhs_components = rhs->type->components();
+         unsigned rhs_base = 0;
+
+         if (remaining_slots == 0)
+            break;
+
+         /* Since the parameter might be used in the RHS of two assignments,
+          * generate a temporary and copy the paramter there.
+          */
+         ir_variable *rhs_var =
+            new(ctx) ir_variable(rhs->type, "mat_ctor_vec", ir_var_temporary);
+         instructions->push_tail(rhs_var);
+
+         ir_dereference *rhs_var_ref =
+            new(ctx) ir_dereference_variable(rhs_var);
+         ir_instruction *inst = new(ctx) ir_assignment(rhs_var_ref, rhs, NULL);
+         instructions->push_tail(inst);
+
+         do {
+            /* Assign the current parameter to as many components of the matrix
+             * as it will fill.
+             *
+             * NOTE: A single vector parameter can span two matrix columns.  A
+             * single vec4, for example, can completely fill a mat2.
+             */
+            unsigned count = MIN2(rows - row_idx,
+                                  rhs_components - rhs_base);
+
+            rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var);
+            ir_instruction *inst = assign_to_matrix_column(var, col_idx,
+                                                         row_idx,
+                                                         rhs_var_ref,
+                                                         rhs_base,
+                                                         count, ctx);
+            instructions->push_tail(inst);
+            rhs_base += count;
+            row_idx += count;
+            remaining_slots -= count;
+
+            /* Sometimes, there is still data left in the parameters and
+             * components left to be set in the destination but in other
+             * column.
+             */
+            if (row_idx >= rows) {
+               row_idx = 0;
+               col_idx++;
+            }
+         } while(remaining_slots > 0 && rhs_base < rhs_components);
       }
    }
 
@@ -1491,6 +1704,70 @@ process_record_constructor(exec_list *instructions,
                                              &actual_parameters, state);
 }
 
+ir_rvalue *
+ast_function_expression::handle_method(exec_list *instructions,
+                                       struct _mesa_glsl_parse_state *state)
+{
+   const ast_expression *field = subexpressions[0];
+   ir_rvalue *op;
+   ir_rvalue *result;
+   void *ctx = state;
+   /* Handle "method calls" in GLSL 1.20 - namely, array.length() */
+   YYLTYPE loc = get_location();
+   state->check_version(120, 300, &loc, "methods not supported");
+
+   const char *method;
+   method = field->primary_expression.identifier;
+
+   op = field->subexpressions[0]->hir(instructions, state);
+   if (strcmp(method, "length") == 0) {
+      if (!this->expressions.is_empty()) {
+         _mesa_glsl_error(&loc, state, "length method takes no arguments");
+         goto fail;
+      }
+
+      if (op->type->is_array()) {
+         if (op->type->is_unsized_array()) {
+            if (!state->has_shader_storage_buffer_objects()) {
+               _mesa_glsl_error(&loc, state, "length called on unsized array"
+                                             " only available with "
+                                             "ARB_shader_storage_buffer_object");
+            }
+            /* Calculate length of an unsized array in run-time */
+            result = new(ctx) ir_expression(ir_unop_ssbo_unsized_array_length, op);
+         } else {
+            result = new(ctx) ir_constant(op->type->array_size());
+         }
+      } else if (op->type->is_vector()) {
+         if (state->has_420pack()) {
+            /* .length() returns int. */
+            result = new(ctx) ir_constant((int) op->type->vector_elements);
+         } else {
+            _mesa_glsl_error(&loc, state, "length method on matrix only available"
+                             "with ARB_shading_language_420pack");
+            goto fail;
+         }
+      } else if (op->type->is_matrix()) {
+         if (state->has_420pack()) {
+            /* .length() returns int. */
+            result = new(ctx) ir_constant((int) op->type->matrix_columns);
+         } else {
+            _mesa_glsl_error(&loc, state, "length method on matrix only available"
+                             "with ARB_shading_language_420pack");
+            goto fail;
+         }
+      } else {
+         _mesa_glsl_error(&loc, state, "length called on scalar.");
+         goto fail;
+      }
+   } else {
+         _mesa_glsl_error(&loc, state, "unknown method: `%s'", method);
+         goto fail;
+   }
+   return result;
+fail:
+   return ir_rvalue::error_value(ctx);
+}
 
 ir_rvalue *
 ast_function_expression::hir(exec_list *instructions,
@@ -1503,8 +1780,6 @@ ast_function_expression::hir(exec_list *instructions,
     * 2. methods - Only the .length() method of array types.
     * 3. functions - Calls to regular old functions.
     *
-    * Method calls are actually detected when the ast_field_selection
-    * expression is handled.
     */
    if (is_constructor()) {
       const ast_type_specifier *type = (ast_type_specifier *) subexpressions[0];
@@ -1524,10 +1799,10 @@ ast_function_expression::hir(exec_list *instructions,
       }
 
 
-      /* Constructors for samplers are illegal.
+      /* Constructors for opaque types are illegal.
        */
-      if (constructor_type->is_sampler()) {
-        _mesa_glsl_error(& loc, state, "cannot construct sampler type `%s'",
+      if (constructor_type->contains_opaque()) {
+        _mesa_glsl_error(& loc, state, "cannot construct opaque type `%s'",
                          constructor_type->name);
         return ir_rvalue::error_value(ctx);
       }
@@ -1653,11 +1928,11 @@ ast_function_expression::hir(exec_list *instructions,
         return ir_rvalue::error_value(ctx);
       }
 
-      /* Later, we cast each parameter to the same base type as the
-       * constructor.  Since there are no non-floating point matrices, we
-       * need to break them up into a series of column vectors.
+      /* Matrices can never be consumed as is by any constructor but matrix
+       * constructors. If the constructor type is not matrix, always break the
+       * matrix up into a series of column vectors.
        */
-      if (constructor_type->base_type != GLSL_TYPE_FLOAT) {
+      if (!constructor_type->is_matrix()) {
         foreach_in_list_safe(ir_rvalue, matrix, &actual_parameters) {
            if (!matrix->type->is_matrix())
               continue;
@@ -1725,19 +2000,36 @@ ast_function_expression::hir(exec_list *instructions,
                                               &actual_parameters,
                                               ctx);
       }
+   } else if (subexpressions[0]->oper == ast_field_selection) {
+      return handle_method(instructions, state);
    } else {
       const ast_expression *id = subexpressions[0];
-      const char *func_name = id->primary_expression.identifier;
+      const char *func_name;
       YYLTYPE loc = get_location();
       exec_list actual_parameters;
+      ir_variable *sub_var = NULL;
+      ir_rvalue *array_idx = NULL;
 
       process_parameters(instructions, &actual_parameters, &this->expressions,
                         state);
 
+      if (id->oper == ast_array_index) {
+         array_idx = generate_array_index(ctx, instructions, state, loc,
+                                          id->subexpressions[0],
+                                          id->subexpressions[1], &func_name,
+                                          &actual_parameters);
+      } else {
+         func_name = id->primary_expression.identifier;
+      }
+
       ir_function_signature *sig =
         match_function_by_name(func_name, &actual_parameters, state);
 
       ir_rvalue *value = NULL;
+      if (sig == NULL) {
+         sig = match_subroutine_by_name(func_name, &actual_parameters, state, &sub_var);
+      }
+
       if (sig == NULL) {
         no_matching_function_error(func_name, &loc, &actual_parameters, state);
         value = ir_rvalue::error_value(ctx);
@@ -1745,13 +2037,31 @@ 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, &actual_parameters, state);
+         value = generate_call(instructions, sig, &actual_parameters, sub_var, array_idx, state);
+         if (!value) {
+            ir_variable *const tmp = new(ctx) ir_variable(glsl_type::void_type,
+                                                          "void_var",
+                                                          ir_var_temporary);
+            instructions->push_tail(tmp);
+            value = new(ctx) ir_dereference_variable(tmp);
+         }
       }
 
       return value;
    }
 
-   return ir_rvalue::error_value(ctx);
+   unreachable("not reached");
+}
+
+bool
+ast_function_expression::has_sequence_subexpression() const
+{
+   foreach_list_typed(const ast_node, ast, link, &this->expressions) {
+      if (ast->has_sequence_subexpression())
+         return true;
+   }
+
+   return false;
 }
 
 ir_rvalue *
@@ -1767,7 +2077,7 @@ ast_aggregate_initializer::hir(exec_list *instructions,
    }
    const glsl_type *const constructor_type = this->constructor_type;
 
-   if (!state->ARB_shading_language_420pack_enable) {
+   if (!state->has_420pack()) {
       _mesa_glsl_error(&loc, state, "C-style initialization requires the "
                        "GL_ARB_shading_language_420pack extension");
       return ir_rvalue::error_value(ctx);