101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2010 Intel Corporation
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2101e04c3fSmrg * DEALINGS IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg#include "ast.h"
2501e04c3fSmrg#include "compiler/glsl_types.h"
2601e04c3fSmrg#include "ir.h"
2701e04c3fSmrg
2801e04c3fSmrgvoid
2901e04c3fSmrgast_array_specifier::print(void) const
3001e04c3fSmrg{
3101e04c3fSmrg   foreach_list_typed (ast_node, array_dimension, link, &this->array_dimensions) {
3201e04c3fSmrg      printf("[ ");
3301e04c3fSmrg      if (((ast_expression*)array_dimension)->oper != ast_unsized_array_dim)
3401e04c3fSmrg         array_dimension->print();
3501e04c3fSmrg      printf("] ");
3601e04c3fSmrg   }
3701e04c3fSmrg}
3801e04c3fSmrg
3901e04c3fSmrg/**
4001e04c3fSmrg * If \c ir is a reference to an array for which we are tracking the max array
4101e04c3fSmrg * element accessed, track that the given element has been accessed.
4201e04c3fSmrg * Otherwise do nothing.
4301e04c3fSmrg *
4401e04c3fSmrg * This function also checks whether the array is a built-in array whose
4501e04c3fSmrg * maximum size is too small to accommodate the given index, and if so uses
4601e04c3fSmrg * loc and state to report the error.
4701e04c3fSmrg */
4801e04c3fSmrgstatic void
4901e04c3fSmrgupdate_max_array_access(ir_rvalue *ir, int idx, YYLTYPE *loc,
5001e04c3fSmrg                        struct _mesa_glsl_parse_state *state)
5101e04c3fSmrg{
5201e04c3fSmrg   if (ir_dereference_variable *deref_var = ir->as_dereference_variable()) {
5301e04c3fSmrg      ir_variable *var = deref_var->var;
5401e04c3fSmrg      if (idx > (int)var->data.max_array_access) {
5501e04c3fSmrg         var->data.max_array_access = idx;
5601e04c3fSmrg
5701e04c3fSmrg         /* Check whether this access will, as a side effect, implicitly cause
5801e04c3fSmrg          * the size of a built-in array to be too large.
5901e04c3fSmrg          */
6001e04c3fSmrg         check_builtin_array_max_size(var->name, idx+1, *loc, state);
6101e04c3fSmrg      }
6201e04c3fSmrg   } else if (ir_dereference_record *deref_record =
6301e04c3fSmrg              ir->as_dereference_record()) {
6401e04c3fSmrg      /* There are three possibilities we need to consider:
6501e04c3fSmrg       *
6601e04c3fSmrg       * - Accessing an element of an array that is a member of a named
6701e04c3fSmrg       *   interface block (e.g. ifc.foo[i])
6801e04c3fSmrg       *
6901e04c3fSmrg       * - Accessing an element of an array that is a member of a named
7001e04c3fSmrg       *   interface block array (e.g. ifc[j].foo[i]).
7101e04c3fSmrg       *
7201e04c3fSmrg       * - Accessing an element of an array that is a member of a named
7301e04c3fSmrg       *   interface block array of arrays (e.g. ifc[j][k].foo[i]).
7401e04c3fSmrg       */
7501e04c3fSmrg      ir_dereference_variable *deref_var =
7601e04c3fSmrg         deref_record->record->as_dereference_variable();
7701e04c3fSmrg      if (deref_var == NULL) {
7801e04c3fSmrg         ir_dereference_array *deref_array =
7901e04c3fSmrg            deref_record->record->as_dereference_array();
8001e04c3fSmrg         ir_dereference_array *deref_array_prev = NULL;
8101e04c3fSmrg         while (deref_array != NULL) {
8201e04c3fSmrg            deref_array_prev = deref_array;
8301e04c3fSmrg            deref_array = deref_array->array->as_dereference_array();
8401e04c3fSmrg         }
8501e04c3fSmrg         if (deref_array_prev != NULL)
8601e04c3fSmrg            deref_var = deref_array_prev->array->as_dereference_variable();
8701e04c3fSmrg      }
8801e04c3fSmrg
8901e04c3fSmrg      if (deref_var != NULL) {
9001e04c3fSmrg         if (deref_var->var->is_interface_instance()) {
9101e04c3fSmrg            unsigned field_idx = deref_record->field_idx;
9201e04c3fSmrg            assert(field_idx < deref_var->var->get_interface_type()->length);
9301e04c3fSmrg
9401e04c3fSmrg            int *const max_ifc_array_access =
9501e04c3fSmrg               deref_var->var->get_max_ifc_array_access();
9601e04c3fSmrg
9701e04c3fSmrg            assert(max_ifc_array_access != NULL);
9801e04c3fSmrg
9901e04c3fSmrg            if (idx > max_ifc_array_access[field_idx]) {
10001e04c3fSmrg               max_ifc_array_access[field_idx] = idx;
10101e04c3fSmrg
10201e04c3fSmrg               /* Check whether this access will, as a side effect, implicitly
10301e04c3fSmrg                * cause the size of a built-in array to be too large.
10401e04c3fSmrg                */
10501e04c3fSmrg               const char *field_name =
10601e04c3fSmrg                  deref_record->record->type->fields.structure[field_idx].name;
10701e04c3fSmrg               check_builtin_array_max_size(field_name, idx+1, *loc, state);
10801e04c3fSmrg            }
10901e04c3fSmrg         }
11001e04c3fSmrg      }
11101e04c3fSmrg   }
11201e04c3fSmrg}
11301e04c3fSmrg
11401e04c3fSmrg
11501e04c3fSmrgstatic int
11601e04c3fSmrgget_implicit_array_size(struct _mesa_glsl_parse_state *state,
11701e04c3fSmrg                        ir_rvalue *array)
11801e04c3fSmrg{
11901e04c3fSmrg   ir_variable *var = array->variable_referenced();
12001e04c3fSmrg
12101e04c3fSmrg   /* Inputs in control shader are implicitly sized
12201e04c3fSmrg    * to the maximum patch size.
12301e04c3fSmrg    */
12401e04c3fSmrg   if (state->stage == MESA_SHADER_TESS_CTRL &&
12501e04c3fSmrg       var->data.mode == ir_var_shader_in) {
12601e04c3fSmrg      return state->Const.MaxPatchVertices;
12701e04c3fSmrg   }
12801e04c3fSmrg
12901e04c3fSmrg   /* Non-patch inputs in evaluation shader are implicitly sized
13001e04c3fSmrg    * to the maximum patch size.
13101e04c3fSmrg    */
13201e04c3fSmrg   if (state->stage == MESA_SHADER_TESS_EVAL &&
13301e04c3fSmrg       var->data.mode == ir_var_shader_in &&
13401e04c3fSmrg       !var->data.patch) {
13501e04c3fSmrg      return state->Const.MaxPatchVertices;
13601e04c3fSmrg   }
13701e04c3fSmrg
13801e04c3fSmrg   return 0;
13901e04c3fSmrg}
14001e04c3fSmrg
14101e04c3fSmrg
14201e04c3fSmrgir_rvalue *
14301e04c3fSmrg_mesa_ast_array_index_to_hir(void *mem_ctx,
14401e04c3fSmrg                             struct _mesa_glsl_parse_state *state,
14501e04c3fSmrg                             ir_rvalue *array, ir_rvalue *idx,
14601e04c3fSmrg                             YYLTYPE &loc, YYLTYPE &idx_loc)
14701e04c3fSmrg{
14801e04c3fSmrg   if (!array->type->is_error()
14901e04c3fSmrg       && !array->type->is_array()
15001e04c3fSmrg       && !array->type->is_matrix()
15101e04c3fSmrg       && !array->type->is_vector()) {
15201e04c3fSmrg      _mesa_glsl_error(& idx_loc, state,
15301e04c3fSmrg                       "cannot dereference non-array / non-matrix / "
15401e04c3fSmrg                       "non-vector");
15501e04c3fSmrg   }
15601e04c3fSmrg
15701e04c3fSmrg   if (!idx->type->is_error()) {
1587ec681f3Smrg      if (!idx->type->is_integer_32()) {
15901e04c3fSmrg         _mesa_glsl_error(& idx_loc, state, "array index must be integer type");
16001e04c3fSmrg      } else if (!idx->type->is_scalar()) {
16101e04c3fSmrg         _mesa_glsl_error(& idx_loc, state, "array index must be scalar");
16201e04c3fSmrg      }
16301e04c3fSmrg   }
16401e04c3fSmrg
16501e04c3fSmrg   /* If the array index is a constant expression and the array has a
16601e04c3fSmrg    * declared size, ensure that the access is in-bounds.  If the array
16701e04c3fSmrg    * index is not a constant expression, ensure that the array has a
16801e04c3fSmrg    * declared size.
16901e04c3fSmrg    */
17001e04c3fSmrg   ir_constant *const const_index = idx->constant_expression_value(mem_ctx);
1717ec681f3Smrg   if (const_index != NULL && idx->type->is_integer_32()) {
17201e04c3fSmrg      const int idx = const_index->value.i[0];
17301e04c3fSmrg      const char *type_name = "error";
17401e04c3fSmrg      unsigned bound = 0;
17501e04c3fSmrg
17601e04c3fSmrg      /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec:
17701e04c3fSmrg       *
17801e04c3fSmrg       *    "It is illegal to declare an array with a size, and then
17901e04c3fSmrg       *    later (in the same shader) index the same array with an
18001e04c3fSmrg       *    integral constant expression greater than or equal to the
18101e04c3fSmrg       *    declared size. It is also illegal to index an array with a
18201e04c3fSmrg       *    negative constant expression."
18301e04c3fSmrg       */
18401e04c3fSmrg      if (array->type->is_matrix()) {
18501e04c3fSmrg         if (array->type->row_type()->vector_elements <= idx) {
18601e04c3fSmrg            type_name = "matrix";
18701e04c3fSmrg            bound = array->type->row_type()->vector_elements;
18801e04c3fSmrg         }
18901e04c3fSmrg      } else if (array->type->is_vector()) {
19001e04c3fSmrg         if (array->type->vector_elements <= idx) {
19101e04c3fSmrg            type_name = "vector";
19201e04c3fSmrg            bound = array->type->vector_elements;
19301e04c3fSmrg         }
19401e04c3fSmrg      } else {
19501e04c3fSmrg         /* glsl_type::array_size() returns -1 for non-array types.  This means
19601e04c3fSmrg          * that we don't need to verify that the type is an array before
19701e04c3fSmrg          * doing the bounds checking.
19801e04c3fSmrg          */
19901e04c3fSmrg         if ((array->type->array_size() > 0)
20001e04c3fSmrg             && (array->type->array_size() <= idx)) {
20101e04c3fSmrg            type_name = "array";
20201e04c3fSmrg            bound = array->type->array_size();
20301e04c3fSmrg         }
20401e04c3fSmrg      }
20501e04c3fSmrg
20601e04c3fSmrg      if (bound > 0) {
20701e04c3fSmrg         _mesa_glsl_error(& loc, state, "%s index must be < %u",
20801e04c3fSmrg                          type_name, bound);
20901e04c3fSmrg      } else if (idx < 0) {
21001e04c3fSmrg         _mesa_glsl_error(& loc, state, "%s index must be >= 0", type_name);
21101e04c3fSmrg      }
21201e04c3fSmrg
21301e04c3fSmrg      if (array->type->is_array())
21401e04c3fSmrg         update_max_array_access(array, idx, &loc, state);
21501e04c3fSmrg   } else if (const_index == NULL && array->type->is_array()) {
21601e04c3fSmrg      if (array->type->is_unsized_array()) {
21701e04c3fSmrg         int implicit_size = get_implicit_array_size(state, array);
21801e04c3fSmrg         if (implicit_size) {
21901e04c3fSmrg            ir_variable *v = array->whole_variable_referenced();
22001e04c3fSmrg            if (v != NULL)
22101e04c3fSmrg               v->data.max_array_access = implicit_size - 1;
22201e04c3fSmrg         }
22301e04c3fSmrg         else if (state->stage == MESA_SHADER_TESS_CTRL &&
22401e04c3fSmrg                  array->variable_referenced()->data.mode == ir_var_shader_out &&
22501e04c3fSmrg                  !array->variable_referenced()->data.patch) {
22601e04c3fSmrg            /* Tessellation control shader output non-patch arrays are
22701e04c3fSmrg             * initially unsized. Despite that, they are allowed to be
22801e04c3fSmrg             * indexed with a non-constant expression (typically
22901e04c3fSmrg             * "gl_InvocationID"). The array size will be determined
23001e04c3fSmrg             * by the linker.
23101e04c3fSmrg             */
23201e04c3fSmrg         }
23301e04c3fSmrg         else if (array->variable_referenced()->data.mode !=
23401e04c3fSmrg                  ir_var_shader_storage) {
23501e04c3fSmrg            _mesa_glsl_error(&loc, state, "unsized array index must be constant");
23601e04c3fSmrg         } else {
23701e04c3fSmrg            /* Unsized array non-constant indexing on SSBO is allowed only for
23801e04c3fSmrg             * the last member of the SSBO definition.
23901e04c3fSmrg             */
24001e04c3fSmrg            ir_variable *var = array->variable_referenced();
24101e04c3fSmrg            const glsl_type *iface_type = var->get_interface_type();
24201e04c3fSmrg            int field_index = iface_type->field_index(var->name);
24301e04c3fSmrg            /* Field index can be < 0 for instance arrays */
24401e04c3fSmrg            if (field_index >= 0 &&
24501e04c3fSmrg                field_index != (int) iface_type->length - 1) {
24601e04c3fSmrg               _mesa_glsl_error(&loc, state, "Indirect access on unsized "
24701e04c3fSmrg                                "array is limited to the last member of "
24801e04c3fSmrg                                "SSBO.");
24901e04c3fSmrg            }
25001e04c3fSmrg         }
25101e04c3fSmrg      } else if (array->type->without_array()->is_interface()
25201e04c3fSmrg                 && ((array->variable_referenced()->data.mode == ir_var_uniform
25301e04c3fSmrg                      && !state->is_version(400, 320)
25401e04c3fSmrg                      && !state->ARB_gpu_shader5_enable
25501e04c3fSmrg                      && !state->EXT_gpu_shader5_enable
25601e04c3fSmrg                      && !state->OES_gpu_shader5_enable) ||
25701e04c3fSmrg                     (array->variable_referenced()->data.mode == ir_var_shader_storage
25801e04c3fSmrg                      && !state->is_version(400, 0)
25901e04c3fSmrg                      && !state->ARB_gpu_shader5_enable))) {
26001e04c3fSmrg         /* Page 50 in section 4.3.9 of the OpenGL ES 3.10 spec says:
26101e04c3fSmrg          *
26201e04c3fSmrg          *     "All indices used to index a uniform or shader storage block
26301e04c3fSmrg          *     array must be constant integral expressions."
26401e04c3fSmrg          *
26501e04c3fSmrg          * But OES_gpu_shader5 (and ESSL 3.20) relax this to allow indexing
26601e04c3fSmrg          * on uniform blocks but not shader storage blocks.
26701e04c3fSmrg          *
26801e04c3fSmrg          */
26901e04c3fSmrg         _mesa_glsl_error(&loc, state, "%s block array index must be constant",
27001e04c3fSmrg                          array->variable_referenced()->data.mode
27101e04c3fSmrg                          == ir_var_uniform ? "uniform" : "shader storage");
27201e04c3fSmrg      } else {
27301e04c3fSmrg         /* whole_variable_referenced can return NULL if the array is a
27401e04c3fSmrg          * member of a structure.  In this case it is safe to not update
27501e04c3fSmrg          * the max_array_access field because it is never used for fields
27601e04c3fSmrg          * of structures.
27701e04c3fSmrg          */
27801e04c3fSmrg         ir_variable *v = array->whole_variable_referenced();
27901e04c3fSmrg         if (v != NULL)
28001e04c3fSmrg            v->data.max_array_access = array->type->array_size() - 1;
28101e04c3fSmrg      }
28201e04c3fSmrg
28301e04c3fSmrg      /* From page 23 (29 of the PDF) of the GLSL 1.30 spec:
28401e04c3fSmrg       *
28501e04c3fSmrg       *    "Samplers aggregated into arrays within a shader (using square
28601e04c3fSmrg       *    brackets [ ]) can only be indexed with integral constant
28701e04c3fSmrg       *    expressions [...]."
28801e04c3fSmrg       *
28901e04c3fSmrg       * This restriction was added in GLSL 1.30.  Shaders using earlier
29001e04c3fSmrg       * version of the language should not be rejected by the compiler
29101e04c3fSmrg       * front-end for using this construct.  This allows useful things such
29201e04c3fSmrg       * as using a loop counter as the index to an array of samplers.  If the
29301e04c3fSmrg       * loop in unrolled, the code should compile correctly.  Instead, emit a
29401e04c3fSmrg       * warning.
29501e04c3fSmrg       *
29601e04c3fSmrg       * In GLSL 4.00 / ARB_gpu_shader5, this requirement is relaxed again to allow
29701e04c3fSmrg       * indexing with dynamically uniform expressions. Note that these are not
29801e04c3fSmrg       * required to be uniforms or expressions based on them, but merely that the
29901e04c3fSmrg       * values must not diverge between shader invocations run together. If the
30001e04c3fSmrg       * values *do* diverge, then the behavior of the operation requiring a
30101e04c3fSmrg       * dynamically uniform expression is undefined.
30201e04c3fSmrg       *
30301e04c3fSmrg       * From section 4.1.7 of the ARB_bindless_texture spec:
30401e04c3fSmrg       *
30501e04c3fSmrg       *    "Samplers aggregated into arrays within a shader (using square
30601e04c3fSmrg       *    brackets []) can be indexed with arbitrary integer expressions."
30701e04c3fSmrg       */
30801e04c3fSmrg      if (array->type->without_array()->is_sampler()) {
30901e04c3fSmrg         if (!state->is_version(400, 320) &&
31001e04c3fSmrg             !state->ARB_gpu_shader5_enable &&
31101e04c3fSmrg             !state->EXT_gpu_shader5_enable &&
31201e04c3fSmrg             !state->OES_gpu_shader5_enable &&
31301e04c3fSmrg             !state->has_bindless()) {
31401e04c3fSmrg            if (state->is_version(130, 300))
31501e04c3fSmrg               _mesa_glsl_error(&loc, state,
31601e04c3fSmrg                                "sampler arrays indexed with non-constant "
31701e04c3fSmrg                                "expressions are forbidden in GLSL %s "
31801e04c3fSmrg                                "and later",
31901e04c3fSmrg                                state->es_shader ? "ES 3.00" : "1.30");
32001e04c3fSmrg            else if (state->es_shader)
32101e04c3fSmrg               _mesa_glsl_warning(&loc, state,
32201e04c3fSmrg                                  "sampler arrays indexed with non-constant "
32301e04c3fSmrg                                  "expressions will be forbidden in GLSL "
32401e04c3fSmrg                                  "3.00 and later");
32501e04c3fSmrg            else
32601e04c3fSmrg               _mesa_glsl_warning(&loc, state,
32701e04c3fSmrg                                  "sampler arrays indexed with non-constant "
32801e04c3fSmrg                                  "expressions will be forbidden in GLSL "
32901e04c3fSmrg                                  "1.30 and later");
33001e04c3fSmrg         }
33101e04c3fSmrg      }
33201e04c3fSmrg
33301e04c3fSmrg      /* From page 27 of the GLSL ES 3.1 specification:
33401e04c3fSmrg       *
33501e04c3fSmrg       * "When aggregated into arrays within a shader, images can only be
33601e04c3fSmrg       *  indexed with a constant integral expression."
33701e04c3fSmrg       *
33801e04c3fSmrg       * On the other hand the desktop GL specification extension allows
33901e04c3fSmrg       * non-constant indexing of image arrays, but behavior is left undefined
34001e04c3fSmrg       * in cases where the indexing expression is not dynamically uniform.
34101e04c3fSmrg       */
34201e04c3fSmrg      if (state->es_shader && array->type->without_array()->is_image()) {
34301e04c3fSmrg         _mesa_glsl_error(&loc, state,
34401e04c3fSmrg                          "image arrays indexed with non-constant "
34501e04c3fSmrg                          "expressions are forbidden in GLSL ES.");
34601e04c3fSmrg      }
34701e04c3fSmrg   }
34801e04c3fSmrg
34901e04c3fSmrg   /* After performing all of the error checking, generate the IR for the
35001e04c3fSmrg    * expression.
35101e04c3fSmrg    */
35201e04c3fSmrg   if (array->type->is_array()
35301e04c3fSmrg       || array->type->is_matrix()
35401e04c3fSmrg       || array->type->is_vector()) {
35501e04c3fSmrg      return new(mem_ctx) ir_dereference_array(array, idx);
35601e04c3fSmrg   } else if (array->type->is_error()) {
35701e04c3fSmrg      return array;
35801e04c3fSmrg   } else {
35901e04c3fSmrg      ir_rvalue *result = new(mem_ctx) ir_dereference_array(array, idx);
36001e04c3fSmrg      result->type = glsl_type::error_type;
36101e04c3fSmrg
36201e04c3fSmrg      return result;
36301e04c3fSmrg   }
36401e04c3fSmrg}
365