Begin processing ast_array_index nodes
authorIan Romanick <ian.d.romanick@intel.com>
Fri, 2 Apr 2010 01:03:59 +0000 (18:03 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 2 Apr 2010 01:34:56 +0000 (18:34 -0700)
This causes the following tests to pass:

    glslparsertest/shaders/parser3.frag
    glslparsertest/shaders/varying3.frag (also generates spurious error)

ast_to_hir.cpp

index 3c4b05e..ff9cbb0 100644 (file)
@@ -890,8 +890,74 @@ ast_expression::hir(exec_list *instructions,
       type = result->type;
       break;
 
-   case ast_array_index:
+   case ast_array_index: {
+      YYLTYPE index_loc = subexpressions[1]->get_location();
+
+      op[0] = subexpressions[0]->hir(instructions, state);
+      op[1] = subexpressions[1]->hir(instructions, state);
+
+      error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
+
+      result = new ir_dereference(op[0], op[1]);
+
+      if (error_emitted)
+        break;
+
+      /* FINISHME: Handle vectors and matrices accessed with []. */
+      if (!op[0]->type->is_array()) {
+        _mesa_glsl_error(& index_loc, state,
+                         "cannot dereference non-array");
+        error_emitted = true;
+      }
+
+      if (!op[1]->type->is_integer()) {
+        _mesa_glsl_error(& index_loc, state,
+                         "array index must be integer type");
+        error_emitted = true;
+      } else if (!op[1]->type->is_scalar()) {
+        _mesa_glsl_error(& index_loc, state,
+                         "array index must be scalar");
+        error_emitted = true;
+      }
+
+      /* If the array index is a constant expression and the array has a
+       * declared size, ensure that the access is in-bounds.  If the array
+       * index is not a constant expression, ensure that the array has a
+       * declared size.
+       */
+      ir_constant *const const_index = op[1]->constant_expression_value();
+      if (const_index != NULL) {
+        const int idx = const_index->value.i[0];
+
+        /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec:
+         *
+         *    "It is illegal to declare an array with a size, and then
+         *    later (in the same shader) index the same array with an
+         *    integral constant expression greater than or equal to the
+         *    declared size. It is also illegal to index an array with a
+         *    negative constant expression."
+         */
+        if ((op[0]->type->array_size() > 0)
+            && (op[0]->type->array_size() <= idx)) {
+           _mesa_glsl_error(& loc, state,
+                            "array index must be < %u",
+                            op[0]->type->array_size());
+           error_emitted = true;
+        }
+
+        if (idx < 0) {
+           _mesa_glsl_error(& loc, state,
+                            "array index must be >= 0");
+           error_emitted = true;
+        }
+      }
+
+      if (error_emitted)
+        result->type = glsl_type::error_type;
+
+      type = result->type;
       break;
+   }
 
    case ast_function_call:
       /* Should *NEVER* get here.  ast_function_call should always be handled