diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2014-07-09 21:09:02 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2014-07-09 21:09:02 +0000 |
commit | 473dc96b5bfcd9b8163bba1931980c767d4e8a86 (patch) | |
tree | 792db8214c0e02c8c286cc22b67ad99ff928095f /dist/Mesa/src/glsl/ast_to_hir.cpp | |
parent | 90414e9e8766ee4a4f0ba93d8206de27cf984ce6 (diff) |
Merge Mesa 10.2.3
tested by matthieu@ kettenis@ mpi@ brett@ and myself across a
diverse range of hardware
Diffstat (limited to 'dist/Mesa/src/glsl/ast_to_hir.cpp')
-rw-r--r-- | dist/Mesa/src/glsl/ast_to_hir.cpp | 3563 |
1 files changed, 2321 insertions, 1242 deletions
diff --git a/dist/Mesa/src/glsl/ast_to_hir.cpp b/dist/Mesa/src/glsl/ast_to_hir.cpp index b06a0816e..332f934ff 100644 --- a/dist/Mesa/src/glsl/ast_to_hir.cpp +++ b/dist/Mesa/src/glsl/ast_to_hir.cpp @@ -56,10 +56,17 @@ #include "glsl_types.h" #include "program/hash_table.h" #include "ir.h" +#include "ir_builder.h" + +using namespace ir_builder; static void detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, exec_list *instructions); +static void +remove_per_vertex_blocks(exec_list *instructions, + _mesa_glsl_parse_state *state, ir_variable_mode mode); + void _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) @@ -72,6 +79,9 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) state->toplevel_ir = instructions; + state->gs_input_prim_type_specified = false; + state->cs_input_local_size_specified = false; + /* Section 4.2 of the GLSL 1.20 specification states: * "The built-in functions are scoped in a scope outside the global scope * users declare global variables in. That is, a shader's global scope, @@ -112,6 +122,45 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) var->remove(); instructions->push_head(var); } + + /* Figure out if gl_FragCoord is actually used in fragment shader */ + ir_variable *const var = state->symbols->get_variable("gl_FragCoord"); + if (var != NULL) + state->fs_uses_gl_fragcoord = var->data.used; + + /* From section 7.1 (Built-In Language Variables) of the GLSL 4.10 spec: + * + * If multiple shaders using members of a built-in block belonging to + * the same interface are linked together in the same program, they + * must all redeclare the built-in block in the same way, as described + * in section 4.3.7 "Interface Blocks" for interface block matching, or + * a link error will result. + * + * The phrase "using members of a built-in block" implies that if two + * shaders are linked together and one of them *does not use* any members + * of the built-in block, then that shader does not need to have a matching + * redeclaration of the built-in block. + * + * This appears to be a clarification to the behaviour established for + * gl_PerVertex by GLSL 1.50, therefore implement it regardless of GLSL + * version. + * + * The definition of "interface" in section 4.3.7 that applies here is as + * follows: + * + * The boundary between adjacent programmable pipeline stages: This + * spans all the outputs in all compilation units of the first stage + * and all the inputs in all compilation units of the second stage. + * + * Therefore this rule applies to both inter- and intra-stage linking. + * + * The easiest way to implement this is to check whether the shader uses + * gl_PerVertex right after ast-to-ir conversion, and if it doesn't, simply + * remove all the relevant variable declaration from the IR, so that the + * linker won't see them and complain about mismatches. + */ + remove_per_vertex_blocks(instructions, state, ir_var_shader_in); + remove_per_vertex_blocks(instructions, state, ir_var_shader_out); } @@ -130,7 +179,7 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) */ bool apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { void *ctx = state; if (to->base_type == from->type->base_type) @@ -181,8 +230,8 @@ apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from, static const struct glsl_type * arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, - bool multiply, - struct _mesa_glsl_parse_state *state, YYLTYPE *loc) + bool multiply, + struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { const glsl_type *type_a = value_a->type; const glsl_type *type_b = value_b->type; @@ -195,7 +244,7 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, */ if (!type_a->is_numeric() || !type_b->is_numeric()) { _mesa_glsl_error(loc, state, - "Operands to arithmetic operators must be numeric"); + "operands to arithmetic operators must be numeric"); return glsl_type::error_type; } @@ -207,8 +256,8 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, if (!apply_implicit_conversion(type_a, value_b, state) && !apply_implicit_conversion(type_b, value_a, state)) { _mesa_glsl_error(loc, state, - "Could not implicitly convert operands to " - "arithmetic operator"); + "could not implicitly convert operands to " + "arithmetic operator"); return glsl_type::error_type; } type_a = value_a->type; @@ -225,7 +274,7 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, */ if (type_a->base_type != type_b->base_type) { _mesa_glsl_error(loc, state, - "base type mismatch for arithmetic operator"); + "base type mismatch for arithmetic operator"); return glsl_type::error_type; } @@ -247,7 +296,7 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, */ if (type_a->is_scalar()) { if (!type_b->is_scalar()) - return type_b; + return type_b; } else if (type_b->is_scalar()) { return type_a; } @@ -265,11 +314,11 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, */ if (type_a->is_vector() && type_b->is_vector()) { if (type_a == type_b) { - return type_a; + return type_a; } else { - _mesa_glsl_error(loc, state, - "vector size mismatch for arithmetic operator"); - return glsl_type::error_type; + _mesa_glsl_error(loc, state, + "vector size mismatch for arithmetic operator"); + return glsl_type::error_type; } } @@ -300,64 +349,64 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, */ if (! multiply) { if (type_a == type_b) - return type_a; + return type_a; } else { if (type_a->is_matrix() && type_b->is_matrix()) { - /* Matrix multiply. The columns of A must match the rows of B. Given - * the other previously tested constraints, this means the vector type - * of a row from A must be the same as the vector type of a column from - * B. - */ - if (type_a->row_type() == type_b->column_type()) { - /* The resulting matrix has the number of columns of matrix B and - * the number of rows of matrix A. We get the row count of A by - * looking at the size of a vector that makes up a column. The - * transpose (size of a row) is done for B. - */ - const glsl_type *const type = - glsl_type::get_instance(type_a->base_type, - type_a->column_type()->vector_elements, - type_b->row_type()->vector_elements); - assert(type != glsl_type::error_type); - - return type; - } + /* Matrix multiply. The columns of A must match the rows of B. Given + * the other previously tested constraints, this means the vector type + * of a row from A must be the same as the vector type of a column from + * B. + */ + if (type_a->row_type() == type_b->column_type()) { + /* The resulting matrix has the number of columns of matrix B and + * the number of rows of matrix A. We get the row count of A by + * looking at the size of a vector that makes up a column. The + * transpose (size of a row) is done for B. + */ + const glsl_type *const type = + glsl_type::get_instance(type_a->base_type, + type_a->column_type()->vector_elements, + type_b->row_type()->vector_elements); + assert(type != glsl_type::error_type); + + return type; + } } else if (type_a->is_matrix()) { - /* A is a matrix and B is a column vector. Columns of A must match - * rows of B. Given the other previously tested constraints, this - * means the vector type of a row from A must be the same as the - * vector the type of B. - */ - if (type_a->row_type() == type_b) { - /* The resulting vector has a number of elements equal to - * the number of rows of matrix A. */ - const glsl_type *const type = - glsl_type::get_instance(type_a->base_type, - type_a->column_type()->vector_elements, - 1); - assert(type != glsl_type::error_type); - - return type; - } + /* A is a matrix and B is a column vector. Columns of A must match + * rows of B. Given the other previously tested constraints, this + * means the vector type of a row from A must be the same as the + * vector the type of B. + */ + if (type_a->row_type() == type_b) { + /* The resulting vector has a number of elements equal to + * the number of rows of matrix A. */ + const glsl_type *const type = + glsl_type::get_instance(type_a->base_type, + type_a->column_type()->vector_elements, + 1); + assert(type != glsl_type::error_type); + + return type; + } } else { - assert(type_b->is_matrix()); - - /* A is a row vector and B is a matrix. Columns of A must match rows - * of B. Given the other previously tested constraints, this means - * the type of A must be the same as the vector type of a column from - * B. - */ - if (type_a == type_b->column_type()) { - /* The resulting vector has a number of elements equal to - * the number of columns of matrix B. */ - const glsl_type *const type = - glsl_type::get_instance(type_a->base_type, - type_b->row_type()->vector_elements, - 1); - assert(type != glsl_type::error_type); - - return type; - } + assert(type_b->is_matrix()); + + /* A is a row vector and B is a matrix. Columns of A must match rows + * of B. Given the other previously tested constraints, this means + * the type of A must be the same as the vector type of a column from + * B. + */ + if (type_a == type_b->column_type()) { + /* The resulting vector has a number of elements equal to + * the number of columns of matrix B. */ + const glsl_type *const type = + glsl_type::get_instance(type_a->base_type, + type_b->row_type()->vector_elements, + 1); + assert(type != glsl_type::error_type); + + return type; + } } _mesa_glsl_error(loc, state, "size mismatch for matrix multiplication"); @@ -374,7 +423,7 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, static const struct glsl_type * unary_arithmetic_result_type(const struct glsl_type *type, - struct _mesa_glsl_parse_state *state, YYLTYPE *loc) + struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { /* From GLSL 1.50 spec, page 57: * @@ -386,7 +435,7 @@ unary_arithmetic_result_type(const struct glsl_type *type, */ if (!type->is_numeric()) { _mesa_glsl_error(loc, state, - "Operands to arithmetic operators must be numeric"); + "operands to arithmetic operators must be numeric"); return glsl_type::error_type; } @@ -460,8 +509,8 @@ bit_logic_result_type(const struct glsl_type *type_a, static const struct glsl_type * modulus_result_type(const struct glsl_type *type_a, - const struct glsl_type *type_b, - struct _mesa_glsl_parse_state *state, YYLTYPE *loc) + const struct glsl_type *type_b, + struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { if (!state->check_version(130, 300, loc, "operator '%%' is reserved")) { return glsl_type::error_type; @@ -473,16 +522,16 @@ modulus_result_type(const struct glsl_type *type_a, * unsigned." */ if (!type_a->is_integer()) { - _mesa_glsl_error(loc, state, "LHS of operator %% must be an integer."); + _mesa_glsl_error(loc, state, "LHS of operator %% must be an integer"); return glsl_type::error_type; } if (!type_b->is_integer()) { - _mesa_glsl_error(loc, state, "RHS of operator %% must be an integer."); + _mesa_glsl_error(loc, state, "RHS of operator %% must be an integer"); return glsl_type::error_type; } if (type_a->base_type != type_b->base_type) { _mesa_glsl_error(loc, state, - "operands of %% must have the same base type"); + "operands of %% must have the same base type"); return glsl_type::error_type; } @@ -493,8 +542,8 @@ modulus_result_type(const struct glsl_type *type_a, */ if (type_a->is_vector()) { if (!type_b->is_vector() - || (type_a->vector_elements == type_b->vector_elements)) - return type_a; + || (type_a->vector_elements == type_b->vector_elements)) + return type_a; } else return type_b; @@ -508,7 +557,7 @@ modulus_result_type(const struct glsl_type *type_a, static const struct glsl_type * relational_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, - struct _mesa_glsl_parse_state *state, YYLTYPE *loc) + struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { const glsl_type *type_a = value_a->type; const glsl_type *type_b = value_b->type; @@ -523,8 +572,8 @@ relational_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, || !type_a->is_scalar() || !type_b->is_scalar()) { _mesa_glsl_error(loc, state, - "Operands to relational operators must be scalar and " - "numeric"); + "operands to relational operators must be scalar and " + "numeric"); return glsl_type::error_type; } @@ -535,8 +584,8 @@ relational_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, if (!apply_implicit_conversion(type_a, value_b, state) && !apply_implicit_conversion(type_b, value_a, state)) { _mesa_glsl_error(loc, state, - "Could not implicitly convert operands to " - "relational operator"); + "could not implicitly convert operands to " + "relational operator"); return glsl_type::error_type; } type_a = value_a->type; @@ -579,13 +628,13 @@ shift_result_type(const struct glsl_type *type_a, */ if (!type_a->is_integer()) { _mesa_glsl_error(loc, state, "LHS of operator %s must be an integer or " - "integer vector", ast_expression::operator_string(op)); + "integer vector", ast_expression::operator_string(op)); return glsl_type::error_type; } if (!type_b->is_integer()) { _mesa_glsl_error(loc, state, "RHS of operator %s must be an integer or " - "integer vector", ast_expression::operator_string(op)); + "integer vector", ast_expression::operator_string(op)); return glsl_type::error_type; } @@ -593,9 +642,9 @@ shift_result_type(const struct glsl_type *type_a, * a scalar as well." */ if (type_a->is_scalar() && !type_b->is_scalar()) { - _mesa_glsl_error(loc, state, "If the first operand of %s is scalar, the " - "second must be scalar as well", - ast_expression::operator_string(op)); + _mesa_glsl_error(loc, state, "if the first operand of %s is scalar, the " + "second must be scalar as well", + ast_expression::operator_string(op)); return glsl_type::error_type; } @@ -605,9 +654,9 @@ shift_result_type(const struct glsl_type *type_a, if (type_a->is_vector() && type_b->is_vector() && type_a->vector_elements != type_b->vector_elements) { - _mesa_glsl_error(loc, state, "Vector operands to operator %s must " - "have same number of elements", - ast_expression::operator_string(op)); + _mesa_glsl_error(loc, state, "vector operands to operator %s must " + "have same number of elements", + ast_expression::operator_string(op)); return glsl_type::error_type; } @@ -635,8 +684,8 @@ shift_result_type(const struct glsl_type *type_a, */ ir_rvalue * validate_assignment(struct _mesa_glsl_parse_state *state, - const glsl_type *lhs_type, ir_rvalue *rhs, - bool is_initializer) + YYLTYPE loc, const glsl_type *lhs_type, + ir_rvalue *rhs, bool is_initializer) { /* If there is already some error in the RHS, just return it. Anything * else will lead to an avalanche of error message back to the user. @@ -649,17 +698,22 @@ validate_assignment(struct _mesa_glsl_parse_state *state, if (rhs->type == lhs_type) return rhs; - /* If the array element types are the same and the size of the LHS is zero, + /* If the array element types are the same and the LHS is unsized, * the assignment is okay for initializers embedded in variable * declarations. * * Note: Whole-array assignments are not permitted in GLSL 1.10, but this * is handled by ir_dereference::is_lvalue. */ - if (is_initializer && lhs_type->is_array() && rhs->type->is_array() - && (lhs_type->element_type() == rhs->type->element_type()) - && (lhs_type->array_size() == 0)) { - return rhs; + if (lhs_type->is_unsized_array() && rhs->type->is_array() + && (lhs_type->element_type() == rhs->type->element_type())) { + if (is_initializer) { + return rhs; + } else { + _mesa_glsl_error(&loc, state, + "implicitly sized arrays cannot be assigned"); + return NULL; + } } /* Check for implicit conversion in GLSL 1.20 */ @@ -668,6 +722,12 @@ validate_assignment(struct _mesa_glsl_parse_state *state, return rhs; } + _mesa_glsl_error(&loc, state, + "%s of type %s cannot be assigned to " + "variable of type %s", + is_initializer ? "initializer" : "value", + rhs->type->name, lhs_type->name); + return NULL; } @@ -677,83 +737,95 @@ mark_whole_array_access(ir_rvalue *access) ir_dereference_variable *deref = access->as_dereference_variable(); if (deref && deref->var) { - deref->var->max_array_access = deref->type->length - 1; + deref->var->data.max_array_access = deref->type->length - 1; } } -ir_rvalue * +static bool do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, - const char *non_lvalue_description, - ir_rvalue *lhs, ir_rvalue *rhs, bool is_initializer, - YYLTYPE lhs_loc) + const char *non_lvalue_description, + ir_rvalue *lhs, ir_rvalue *rhs, + ir_rvalue **out_rvalue, bool needs_rvalue, + bool is_initializer, + YYLTYPE lhs_loc) { void *ctx = state; bool error_emitted = (lhs->type->is_error() || rhs->type->is_error()); + ir_rvalue *extract_channel = NULL; /* If the assignment LHS comes back as an ir_binop_vector_extract * expression, move it to the RHS as an ir_triop_vector_insert. */ if (lhs->ir_type == ir_type_expression) { - ir_expression *const expr = lhs->as_expression(); + ir_expression *const lhs_expr = lhs->as_expression(); - if (unlikely(expr->operation == ir_binop_vector_extract)) { + if (unlikely(lhs_expr->operation == ir_binop_vector_extract)) { ir_rvalue *new_rhs = - validate_assignment(state, lhs->type, rhs, is_initializer); + validate_assignment(state, lhs_loc, lhs->type, + rhs, is_initializer); if (new_rhs == NULL) { - _mesa_glsl_error(& lhs_loc, state, "type mismatch"); return lhs; } else { + /* This converts: + * - LHS: (expression float vector_extract <vec> <channel>) + * - RHS: <scalar> + * into: + * - LHS: <vec> + * - RHS: (expression vec2 vector_insert <vec> <channel> <scalar>) + * + * The LHS type is now a vector instead of a scalar. Since GLSL + * allows assignments to be used as rvalues, we need to re-extract + * the channel from assignment_temp when returning the rvalue. + */ + extract_channel = lhs_expr->operands[1]; rhs = new(ctx) ir_expression(ir_triop_vector_insert, - expr->operands[0]->type, - expr->operands[0], + lhs_expr->operands[0]->type, + lhs_expr->operands[0], new_rhs, - expr->operands[1]); - lhs = expr->operands[0]->clone(ctx, NULL); + extract_channel); + lhs = lhs_expr->operands[0]->clone(ctx, NULL); } } } ir_variable *lhs_var = lhs->variable_referenced(); if (lhs_var) - lhs_var->assigned = true; + lhs_var->data.assigned = true; if (!error_emitted) { if (non_lvalue_description != NULL) { _mesa_glsl_error(&lhs_loc, state, "assignment to %s", - non_lvalue_description); - error_emitted = true; + non_lvalue_description); + error_emitted = true; } else if (lhs->variable_referenced() != NULL - && lhs->variable_referenced()->read_only) { + && lhs->variable_referenced()->data.read_only) { _mesa_glsl_error(&lhs_loc, state, "assignment to read-only variable '%s'", lhs->variable_referenced()->name); error_emitted = true; - } else if (lhs->type->is_array() && !state->check_version(120, 300, &lhs_loc, "whole array assignment forbidden")) { - /* From page 32 (page 38 of the PDF) of the GLSL 1.10 spec: - * - * "Other binary or unary expressions, non-dereferenced - * arrays, function names, swizzles with repeated fields, - * and constants cannot be l-values." + /* From page 32 (page 38 of the PDF) of the GLSL 1.10 spec: + * + * "Other binary or unary expressions, non-dereferenced + * arrays, function names, swizzles with repeated fields, + * and constants cannot be l-values." * * The restriction on arrays is lifted in GLSL 1.20 and GLSL ES 3.00. - */ - error_emitted = true; + */ + error_emitted = true; } else if (!lhs->is_lvalue()) { - _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment"); - error_emitted = true; + _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment"); + error_emitted = true; } } ir_rvalue *new_rhs = - validate_assignment(state, lhs->type, rhs, is_initializer); - if (new_rhs == NULL) { - _mesa_glsl_error(& lhs_loc, state, "type mismatch"); - } else { + validate_assignment(state, lhs_loc, lhs->type, rhs, is_initializer); + if (new_rhs != NULL) { rhs = new_rhs; /* If the LHS array was not declared with a size, it takes it size from @@ -761,28 +833,30 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, * dereference of a variable. Any other case would require that the LHS * is either not an l-value or not a whole array. */ - if (lhs->type->array_size() == 0) { - ir_dereference *const d = lhs->as_dereference(); + if (lhs->type->is_unsized_array()) { + ir_dereference *const d = lhs->as_dereference(); - assert(d != NULL); + assert(d != NULL); - ir_variable *const var = d->variable_referenced(); + ir_variable *const var = d->variable_referenced(); - assert(var != NULL); + assert(var != NULL); - if (var->max_array_access >= unsigned(rhs->type->array_size())) { - /* FINISHME: This should actually log the location of the RHS. */ - _mesa_glsl_error(& lhs_loc, state, "array size must be > %u due to " - "previous access", - var->max_array_access); - } + if (var->data.max_array_access >= unsigned(rhs->type->array_size())) { + /* FINISHME: This should actually log the location of the RHS. */ + _mesa_glsl_error(& lhs_loc, state, "array size must be > %u due to " + "previous access", + var->data.max_array_access); + } - var->type = glsl_type::get_array_instance(lhs->type->element_type(), - rhs->type->array_size()); - d->type = var->type; + var->type = glsl_type::get_array_instance(lhs->type->element_type(), + rhs->type->array_size()); + d->type = var->type; + } + if (lhs->type->is_array()) { + mark_whole_array_access(rhs); + mark_whole_array_access(lhs); } - mark_whole_array_access(rhs); - mark_whole_array_access(lhs); } /* Most callers of do_assignment (assign, add_assign, pre_inc/dec, @@ -790,22 +864,33 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, * to handle things like: * * i = j += 1; - * - * So we always just store the computed value being assigned to a - * temporary and return a deref of that temporary. If the rvalue - * ends up not being used, the temp will get copy-propagated out. */ - ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp", - ir_var_temporary); - ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var); - instructions->push_tail(var); - instructions->push_tail(new(ctx) ir_assignment(deref_var, rhs)); - deref_var = new(ctx) ir_dereference_variable(var); + if (needs_rvalue) { + ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp", + ir_var_temporary); + instructions->push_tail(var); + instructions->push_tail(assign(var, rhs)); - if (!error_emitted) - instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var)); + if (!error_emitted) { + ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var); + instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var)); + } + ir_rvalue *rvalue = new(ctx) ir_dereference_variable(var); - return new(ctx) ir_dereference_variable(var); + if (extract_channel) { + rvalue = new(ctx) ir_expression(ir_binop_vector_extract, + rvalue, + extract_channel->clone(ctx, NULL)); + } + + *out_rvalue = rvalue; + } else { + if (!error_emitted) + instructions->push_tail(new(ctx) ir_assignment(lhs, rhs)); + *out_rvalue = NULL; + } + + return error_emitted; } static ir_rvalue * @@ -817,7 +902,7 @@ get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue) var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp", ir_var_temporary); instructions->push_tail(var); - var->mode = ir_var_auto; + var->data.mode = ir_var_auto; instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var), lvalue)); @@ -827,8 +912,7 @@ get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue) ir_rvalue * -ast_node::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) +ast_node::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { (void) instructions; (void) state; @@ -836,6 +920,20 @@ ast_node::hir(exec_list *instructions, return NULL; } +void +ast_function_expression::hir_no_rvalue(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + (void)hir(instructions, state); +} + +void +ast_aggregate_initializer::hir_no_rvalue(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + (void)hir(instructions, state); +} + static ir_rvalue * do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1) { @@ -856,19 +954,19 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1) case GLSL_TYPE_ARRAY: { for (unsigned int i = 0; i < op0->type->length; i++) { - ir_rvalue *e0, *e1, *result; - - e0 = new(mem_ctx) ir_dereference_array(op0->clone(mem_ctx, NULL), - new(mem_ctx) ir_constant(i)); - e1 = new(mem_ctx) ir_dereference_array(op1->clone(mem_ctx, NULL), - new(mem_ctx) ir_constant(i)); - result = do_comparison(mem_ctx, operation, e0, e1); - - if (cmp) { - cmp = new(mem_ctx) ir_expression(join_op, cmp, result); - } else { - cmp = result; - } + ir_rvalue *e0, *e1, *result; + + e0 = new(mem_ctx) ir_dereference_array(op0->clone(mem_ctx, NULL), + new(mem_ctx) ir_constant(i)); + e1 = new(mem_ctx) ir_dereference_array(op1->clone(mem_ctx, NULL), + new(mem_ctx) ir_constant(i)); + result = do_comparison(mem_ctx, operation, e0, e1); + + if (cmp) { + cmp = new(mem_ctx) ir_expression(join_op, cmp, result); + } else { + cmp = result; + } } mark_whole_array_access(op0); @@ -878,20 +976,20 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1) case GLSL_TYPE_STRUCT: { for (unsigned int i = 0; i < op0->type->length; i++) { - ir_rvalue *e0, *e1, *result; - const char *field_name = op0->type->fields.structure[i].name; - - e0 = new(mem_ctx) ir_dereference_record(op0->clone(mem_ctx, NULL), - field_name); - e1 = new(mem_ctx) ir_dereference_record(op1->clone(mem_ctx, NULL), - field_name); - result = do_comparison(mem_ctx, operation, e0, e1); - - if (cmp) { - cmp = new(mem_ctx) ir_expression(join_op, cmp, result); - } else { - cmp = result; - } + ir_rvalue *e0, *e1, *result; + const char *field_name = op0->type->fields.structure[i].name; + + e0 = new(mem_ctx) ir_dereference_record(op0->clone(mem_ctx, NULL), + field_name); + e1 = new(mem_ctx) ir_dereference_record(op1->clone(mem_ctx, NULL), + field_name); + result = do_comparison(mem_ctx, operation, e0, e1); + + if (cmp) { + cmp = new(mem_ctx) ir_expression(join_op, cmp, result); + } else { + cmp = result; + } } break; } @@ -899,7 +997,9 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1) case GLSL_TYPE_ERROR: case GLSL_TYPE_VOID: case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: case GLSL_TYPE_INTERFACE: + case GLSL_TYPE_ATOMIC_UINT: /* I assume a comparison of a struct containing a sampler just * ignores the sampler present in the type. */ @@ -934,8 +1034,8 @@ get_scalar_boolean_operand(exec_list *instructions, if (!*error_emitted) { YYLTYPE loc = expr->get_location(); _mesa_glsl_error(&loc, state, "%s of `%s' must be scalar boolean", - operand_name, - parent_expr->operator_string(parent_expr->oper)); + operand_name, + parent_expr->operator_string(parent_expr->oper)); *error_emitted = true; } @@ -958,7 +1058,7 @@ check_builtin_array_max_size(const char *name, unsigned size, * gl_MaxTextureCoords." */ _mesa_glsl_error(&loc, state, "`gl_TexCoord' array size cannot " - "be larger than gl_MaxTextureCoords (%u)\n", + "be larger than gl_MaxTextureCoords (%u)", state->Const.MaxTextureCoords); } else if (strcmp("gl_ClipDistance", name) == 0 && size > state->Const.MaxClipPlanes) { @@ -972,7 +1072,7 @@ check_builtin_array_max_size(const char *name, unsigned size, * gl_MaxClipDistances." */ _mesa_glsl_error(&loc, state, "`gl_ClipDistance' array size cannot " - "be larger than gl_MaxClipDistances (%u)\n", + "be larger than gl_MaxClipDistances (%u)", state->Const.MaxClipPlanes); } } @@ -1001,7 +1101,22 @@ constant_one_for_inc_dec(void *ctx, const glsl_type *type) ir_rvalue * ast_expression::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) +{ + return do_hir(instructions, state, true); +} + +void +ast_expression::hir_no_rvalue(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + do_hir(instructions, state, false); +} + +ir_rvalue * +ast_expression::do_hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state, + bool needs_rvalue) { void *ctx = state; static const int operations[AST_NUM_OPERATORS] = { @@ -1069,18 +1184,18 @@ ast_expression::hir(exec_list *instructions, switch (this->oper) { case ast_aggregate: - assert(!"ast_aggregate: Should never get here."); - break; + assert(!"ast_aggregate: Should never get here."); + break; case ast_assign: { op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); - result = do_assignment(instructions, state, - this->subexpressions[0]->non_lvalue_description, - op[0], op[1], false, - this->subexpressions[0]->get_location()); - error_emitted = result->type->is_error(); + error_emitted = + do_assignment(instructions, state, + this->subexpressions[0]->non_lvalue_description, + op[0], op[1], &result, needs_rvalue, false, + this->subexpressions[0]->get_location()); break; } @@ -1102,7 +1217,7 @@ ast_expression::hir(exec_list *instructions, error_emitted = type->is_error(); result = new(ctx) ir_expression(operations[this->oper], type, - op[0], NULL); + op[0], NULL); break; case ast_add: @@ -1113,12 +1228,12 @@ ast_expression::hir(exec_list *instructions, op[1] = this->subexpressions[1]->hir(instructions, state); type = arithmetic_result_type(op[0], op[1], - (this->oper == ast_mul), - state, & loc); + (this->oper == ast_mul), + state, & loc); error_emitted = type->is_error(); result = new(ctx) ir_expression(operations[this->oper], type, - op[0], op[1]); + op[0], op[1]); break; case ast_mod: @@ -1130,7 +1245,7 @@ ast_expression::hir(exec_list *instructions, assert(operations[this->oper] == ir_binop_mod); result = new(ctx) ir_expression(operations[this->oper], type, - op[0], op[1]); + op[0], op[1]); error_emitted = type->is_error(); break; @@ -1166,7 +1281,7 @@ ast_expression::hir(exec_list *instructions, && type->is_scalar())); result = new(ctx) ir_expression(operations[this->oper], type, - op[0], op[1]); + op[0], op[1]); error_emitted = type->is_error(); break; @@ -1185,22 +1300,26 @@ ast_expression::hir(exec_list *instructions, * case this conversion is done." */ if ((!apply_implicit_conversion(op[0]->type, op[1], state) - && !apply_implicit_conversion(op[1]->type, op[0], state)) - || (op[0]->type != op[1]->type)) { - _mesa_glsl_error(& loc, state, "operands of `%s' must have the same " - "type", (this->oper == ast_equal) ? "==" : "!="); - error_emitted = true; + && !apply_implicit_conversion(op[1]->type, op[0], state)) + || (op[0]->type != op[1]->type)) { + _mesa_glsl_error(& loc, state, "operands of `%s' must have the same " + "type", (this->oper == ast_equal) ? "==" : "!="); + error_emitted = true; } else if ((op[0]->type->is_array() || op[1]->type->is_array()) && !state->check_version(120, 300, &loc, "array comparisons forbidden")) { - error_emitted = true; + error_emitted = true; + } else if ((op[0]->type->contains_opaque() || + op[1]->type->contains_opaque())) { + _mesa_glsl_error(&loc, state, "opaque type comparisons forbidden"); + error_emitted = true; } if (error_emitted) { - result = new(ctx) ir_constant(false); + result = new(ctx) ir_constant(false); } else { - result = do_comparison(ctx, operations[this->oper], op[0], op[1]); - assert(result->type == glsl_type::bool_type); + result = do_comparison(ctx, operations[this->oper], op[0], op[1]); + assert(result->type == glsl_type::bool_type); } break; @@ -1212,7 +1331,7 @@ ast_expression::hir(exec_list *instructions, type = bit_logic_result_type(op[0]->type, op[1]->type, this->oper, state, &loc); result = new(ctx) ir_expression(operations[this->oper], type, - op[0], op[1]); + op[0], op[1]); error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); break; @@ -1220,12 +1339,12 @@ ast_expression::hir(exec_list *instructions, op[0] = this->subexpressions[0]->hir(instructions, state); if (!state->check_bitwise_operations_allowed(&loc)) { - error_emitted = true; + error_emitted = true; } if (!op[0]->type->is_integer()) { - _mesa_glsl_error(&loc, state, "operand of `~' must be an integer"); - error_emitted = true; + _mesa_glsl_error(&loc, state, "operand of `~' must be an integer"); + error_emitted = true; } type = error_emitted ? glsl_type::error_type : op[0]->type; @@ -1235,35 +1354,35 @@ ast_expression::hir(exec_list *instructions, case ast_logic_and: { exec_list rhs_instructions; op[0] = get_scalar_boolean_operand(instructions, state, this, 0, - "LHS", &error_emitted); + "LHS", &error_emitted); op[1] = get_scalar_boolean_operand(&rhs_instructions, state, this, 1, - "RHS", &error_emitted); + "RHS", &error_emitted); if (rhs_instructions.is_empty()) { - result = new(ctx) ir_expression(ir_binop_logic_and, op[0], op[1]); - type = result->type; + result = new(ctx) ir_expression(ir_binop_logic_and, op[0], op[1]); + type = result->type; } else { - ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type, - "and_tmp", - ir_var_temporary); - instructions->push_tail(tmp); - - ir_if *const stmt = new(ctx) ir_if(op[0]); - instructions->push_tail(stmt); - - stmt->then_instructions.append_list(&rhs_instructions); - ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp); - ir_assignment *const then_assign = - new(ctx) ir_assignment(then_deref, op[1]); - stmt->then_instructions.push_tail(then_assign); - - ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp); - ir_assignment *const else_assign = - new(ctx) ir_assignment(else_deref, new(ctx) ir_constant(false)); - stmt->else_instructions.push_tail(else_assign); - - result = new(ctx) ir_dereference_variable(tmp); - type = tmp->type; + ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type, + "and_tmp", + ir_var_temporary); + instructions->push_tail(tmp); + + ir_if *const stmt = new(ctx) ir_if(op[0]); + instructions->push_tail(stmt); + + stmt->then_instructions.append_list(&rhs_instructions); + ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp); + ir_assignment *const then_assign = + new(ctx) ir_assignment(then_deref, op[1]); + stmt->then_instructions.push_tail(then_assign); + + ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp); + ir_assignment *const else_assign = + new(ctx) ir_assignment(else_deref, new(ctx) ir_constant(false)); + stmt->else_instructions.push_tail(else_assign); + + result = new(ctx) ir_dereference_variable(tmp); + type = tmp->type; } break; } @@ -1271,35 +1390,35 @@ ast_expression::hir(exec_list *instructions, case ast_logic_or: { exec_list rhs_instructions; op[0] = get_scalar_boolean_operand(instructions, state, this, 0, - "LHS", &error_emitted); + "LHS", &error_emitted); op[1] = get_scalar_boolean_operand(&rhs_instructions, state, this, 1, - "RHS", &error_emitted); + "RHS", &error_emitted); if (rhs_instructions.is_empty()) { - result = new(ctx) ir_expression(ir_binop_logic_or, op[0], op[1]); - type = result->type; + result = new(ctx) ir_expression(ir_binop_logic_or, op[0], op[1]); + type = result->type; } else { - ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type, - "or_tmp", - ir_var_temporary); - instructions->push_tail(tmp); - - ir_if *const stmt = new(ctx) ir_if(op[0]); - instructions->push_tail(stmt); - - ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp); - ir_assignment *const then_assign = - new(ctx) ir_assignment(then_deref, new(ctx) ir_constant(true)); - stmt->then_instructions.push_tail(then_assign); - - stmt->else_instructions.append_list(&rhs_instructions); - ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp); - ir_assignment *const else_assign = - new(ctx) ir_assignment(else_deref, op[1]); - stmt->else_instructions.push_tail(else_assign); - - result = new(ctx) ir_dereference_variable(tmp); - type = tmp->type; + ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type, + "or_tmp", + ir_var_temporary); + instructions->push_tail(tmp); + + ir_if *const stmt = new(ctx) ir_if(op[0]); + instructions->push_tail(stmt); + + ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp); + ir_assignment *const then_assign = + new(ctx) ir_assignment(then_deref, new(ctx) ir_constant(true)); + stmt->then_instructions.push_tail(then_assign); + + stmt->else_instructions.append_list(&rhs_instructions); + ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp); + ir_assignment *const else_assign = + new(ctx) ir_assignment(else_deref, op[1]); + stmt->else_instructions.push_tail(else_assign); + + result = new(ctx) ir_dereference_variable(tmp); + type = tmp->type; } break; } @@ -1312,20 +1431,20 @@ ast_expression::hir(exec_list *instructions, * expressions and result in a Boolean expression." */ op[0] = get_scalar_boolean_operand(instructions, state, this, 0, "LHS", - &error_emitted); + &error_emitted); op[1] = get_scalar_boolean_operand(instructions, state, this, 1, "RHS", - &error_emitted); + &error_emitted); result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type, - op[0], op[1]); + op[0], op[1]); break; case ast_logic_not: op[0] = get_scalar_boolean_operand(instructions, state, this, 0, - "operand", &error_emitted); + "operand", &error_emitted); result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type, - op[0], NULL); + op[0], NULL); break; case ast_mul_assign: @@ -1336,17 +1455,18 @@ ast_expression::hir(exec_list *instructions, op[1] = this->subexpressions[1]->hir(instructions, state); type = arithmetic_result_type(op[0], op[1], - (this->oper == ast_mul_assign), - state, & loc); + (this->oper == ast_mul_assign), + state, & loc); ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], type, - op[0], op[1]); + op[0], op[1]); - result = do_assignment(instructions, state, - this->subexpressions[0]->non_lvalue_description, - op[0]->clone(ctx, NULL), temp_rhs, false, - this->subexpressions[0]->get_location()); - error_emitted = (op[0]->type->is_error()); + error_emitted = + do_assignment(instructions, state, + this->subexpressions[0]->non_lvalue_description, + op[0]->clone(ctx, NULL), temp_rhs, + &result, needs_rvalue, false, + this->subexpressions[0]->get_location()); /* GLSL 1.10 does not allow array assignment. However, we don't have to * explicitly test for this because none of the binary expression @@ -1366,13 +1486,14 @@ ast_expression::hir(exec_list *instructions, ir_rvalue *temp_rhs; temp_rhs = new(ctx) ir_expression(operations[this->oper], type, - op[0], op[1]); - - result = do_assignment(instructions, state, - this->subexpressions[0]->non_lvalue_description, - op[0]->clone(ctx, NULL), temp_rhs, false, - this->subexpressions[0]->get_location()); - error_emitted = type->is_error(); + op[0], op[1]); + + error_emitted = + do_assignment(instructions, state, + this->subexpressions[0]->non_lvalue_description, + op[0]->clone(ctx, NULL), temp_rhs, + &result, needs_rvalue, false, + this->subexpressions[0]->get_location()); break; } @@ -1384,11 +1505,12 @@ ast_expression::hir(exec_list *instructions, &loc); ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], type, op[0], op[1]); - result = do_assignment(instructions, state, - this->subexpressions[0]->non_lvalue_description, - op[0]->clone(ctx, NULL), temp_rhs, false, - this->subexpressions[0]->get_location()); - error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); + error_emitted = + do_assignment(instructions, state, + this->subexpressions[0]->non_lvalue_description, + op[0]->clone(ctx, NULL), temp_rhs, + &result, needs_rvalue, false, + this->subexpressions[0]->get_location()); break; } @@ -1401,11 +1523,12 @@ ast_expression::hir(exec_list *instructions, state, &loc); ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], type, op[0], op[1]); - result = do_assignment(instructions, state, - this->subexpressions[0]->non_lvalue_description, - op[0]->clone(ctx, NULL), temp_rhs, false, - this->subexpressions[0]->get_location()); - error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); + error_emitted = + do_assignment(instructions, state, + this->subexpressions[0]->non_lvalue_description, + op[0]->clone(ctx, NULL), temp_rhs, + &result, needs_rvalue, false, + this->subexpressions[0]->get_location()); break; } @@ -1417,7 +1540,7 @@ ast_expression::hir(exec_list *instructions, * first expression, which must result in a scalar Boolean." */ op[0] = get_scalar_boolean_operand(instructions, state, this, 0, - "condition", &error_emitted); + "condition", &error_emitted); /* The :? operator is implemented by generating an anonymous temporary * followed by an if-statement. The last instruction in each branch of @@ -1440,16 +1563,16 @@ ast_expression::hir(exec_list *instructions, * expression." */ if ((!apply_implicit_conversion(op[1]->type, op[2], state) - && !apply_implicit_conversion(op[2]->type, op[1], state)) - || (op[1]->type != op[2]->type)) { - YYLTYPE loc = this->subexpressions[1]->get_location(); - - _mesa_glsl_error(& loc, state, "Second and third operands of ?: " - "operator must have matching types."); - error_emitted = true; - type = glsl_type::error_type; + && !apply_implicit_conversion(op[2]->type, op[1], state)) + || (op[1]->type != op[2]->type)) { + YYLTYPE loc = this->subexpressions[1]->get_location(); + + _mesa_glsl_error(& loc, state, "second and third operands of ?: " + "operator must have matching types"); + error_emitted = true; + type = glsl_type::error_type; } else { - type = op[1]->type; + type = op[1]->type; } /* From page 33 (page 39 of the PDF) of the GLSL 1.10 spec: @@ -1459,9 +1582,9 @@ ast_expression::hir(exec_list *instructions, */ if (type->is_array() && !state->check_version(120, 300, &loc, - "Second and third operands of ?: operator " + "second and third operands of ?: operator " "cannot be arrays")) { - error_emitted = true; + error_emitted = true; } ir_constant *cond_val = op[0]->constant_expression_value(); @@ -1469,32 +1592,32 @@ ast_expression::hir(exec_list *instructions, ir_constant *else_val = op[2]->constant_expression_value(); if (then_instructions.is_empty() - && else_instructions.is_empty() - && (cond_val != NULL) && (then_val != NULL) && (else_val != NULL)) { - result = (cond_val->value.b[0]) ? then_val : else_val; + && else_instructions.is_empty() + && (cond_val != NULL) && (then_val != NULL) && (else_val != NULL)) { + result = (cond_val->value.b[0]) ? then_val : else_val; } else { - ir_variable *const tmp = - new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary); - instructions->push_tail(tmp); - - ir_if *const stmt = new(ctx) ir_if(op[0]); - instructions->push_tail(stmt); - - then_instructions.move_nodes_to(& stmt->then_instructions); - ir_dereference *const then_deref = - new(ctx) ir_dereference_variable(tmp); - ir_assignment *const then_assign = - new(ctx) ir_assignment(then_deref, op[1]); - stmt->then_instructions.push_tail(then_assign); - - else_instructions.move_nodes_to(& stmt->else_instructions); - ir_dereference *const else_deref = - new(ctx) ir_dereference_variable(tmp); - ir_assignment *const else_assign = - new(ctx) ir_assignment(else_deref, op[2]); - stmt->else_instructions.push_tail(else_assign); - - result = new(ctx) ir_dereference_variable(tmp); + ir_variable *const tmp = + new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary); + instructions->push_tail(tmp); + + ir_if *const stmt = new(ctx) ir_if(op[0]); + instructions->push_tail(stmt); + + then_instructions.move_nodes_to(& stmt->then_instructions); + ir_dereference *const then_deref = + new(ctx) ir_dereference_variable(tmp); + ir_assignment *const then_assign = + new(ctx) ir_assignment(then_deref, op[1]); + stmt->then_instructions.push_tail(then_assign); + + else_instructions.move_nodes_to(& stmt->else_instructions); + ir_dereference *const else_deref = + new(ctx) ir_dereference_variable(tmp); + ir_assignment *const else_assign = + new(ctx) ir_assignment(else_deref, op[2]); + stmt->else_instructions.push_tail(else_assign); + + result = new(ctx) ir_dereference_variable(tmp); } break; } @@ -1502,7 +1625,7 @@ ast_expression::hir(exec_list *instructions, case ast_pre_inc: case ast_pre_dec: { this->non_lvalue_description = (this->oper == ast_pre_inc) - ? "pre-increment operation" : "pre-decrement operation"; + ? "pre-increment operation" : "pre-decrement operation"; op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = constant_one_for_inc_dec(ctx, op[0]->type); @@ -1511,20 +1634,21 @@ ast_expression::hir(exec_list *instructions, ir_rvalue *temp_rhs; temp_rhs = new(ctx) ir_expression(operations[this->oper], type, - op[0], op[1]); - - result = do_assignment(instructions, state, - this->subexpressions[0]->non_lvalue_description, - op[0]->clone(ctx, NULL), temp_rhs, false, - this->subexpressions[0]->get_location()); - error_emitted = op[0]->type->is_error(); + op[0], op[1]); + + error_emitted = + do_assignment(instructions, state, + this->subexpressions[0]->non_lvalue_description, + op[0]->clone(ctx, NULL), temp_rhs, + &result, needs_rvalue, false, + this->subexpressions[0]->get_location()); break; } case ast_post_inc: case ast_post_dec: { this->non_lvalue_description = (this->oper == ast_post_inc) - ? "post-increment operation" : "post-decrement operation"; + ? "post-increment operation" : "post-decrement operation"; op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = constant_one_for_inc_dec(ctx, op[0]->type); @@ -1534,19 +1658,21 @@ ast_expression::hir(exec_list *instructions, ir_rvalue *temp_rhs; temp_rhs = new(ctx) ir_expression(operations[this->oper], type, - op[0], op[1]); + op[0], op[1]); /* Get a temporary of a copy of the lvalue before it's modified. * This may get thrown away later. */ result = get_lvalue_copy(instructions, op[0]->clone(ctx, NULL)); - (void)do_assignment(instructions, state, - this->subexpressions[0]->non_lvalue_description, - op[0]->clone(ctx, NULL), temp_rhs, false, - this->subexpressions[0]->get_location()); + ir_rvalue *junk_rvalue; + error_emitted = + do_assignment(instructions, state, + this->subexpressions[0]->non_lvalue_description, + op[0]->clone(ctx, NULL), temp_rhs, + &junk_rvalue, false, false, + this->subexpressions[0]->get_location()); - error_emitted = op[0]->type->is_error(); break; } @@ -1561,10 +1687,10 @@ ast_expression::hir(exec_list *instructions, op[1] = subexpressions[1]->hir(instructions, state); result = _mesa_ast_array_index_to_hir(ctx, state, op[0], op[1], - loc, index_loc); + loc, index_loc); if (result->type->is_error()) - error_emitted = true; + error_emitted = true; break; } @@ -1582,17 +1708,17 @@ ast_expression::hir(exec_list *instructions, * as 'variable_identifier'. */ ir_variable *var = - state->symbols->get_variable(this->primary_expression.identifier); + state->symbols->get_variable(this->primary_expression.identifier); if (var != NULL) { - var->used = true; - result = new(ctx) ir_dereference_variable(var); + var->data.used = true; + result = new(ctx) ir_dereference_variable(var); } else { - _mesa_glsl_error(& loc, state, "`%s' undeclared", - this->primary_expression.identifier); + _mesa_glsl_error(& loc, state, "`%s' undeclared", + this->primary_expression.identifier); - result = ir_rvalue::error_value(ctx); - error_emitted = true; + result = ir_rvalue::error_value(ctx); + error_emitted = true; } break; } @@ -1628,37 +1754,37 @@ ast_expression::hir(exec_list *instructions, YYLTYPE previous_operand_loc = loc; foreach_list_typed (ast_node, ast, link, &this->expressions) { - /* If one of the operands of comma operator does not generate any - * code, we want to emit a warning. At each pass through the loop - * previous_tail_pred will point to the last instruction in the - * stream *before* processing the previous operand. Naturally, - * instructions->tail_pred will point to the last instruction in the - * stream *after* processing the previous operand. If the two - * pointers match, then the previous operand had no effect. - * - * The warning behavior here differs slightly from GCC. GCC will - * only emit a warning if none of the left-hand operands have an - * effect. However, it will emit a warning for each. I believe that - * there are some cases in C (especially with GCC extensions) where - * it is useful to have an intermediate step in a sequence have no - * effect, but I don't think these cases exist in GLSL. Either way, - * it would be a giant hassle to replicate that behavior. - */ - if (previous_tail_pred == instructions->tail_pred) { - _mesa_glsl_warning(&previous_operand_loc, state, - "left-hand operand of comma expression has " - "no effect"); - } - - /* tail_pred is directly accessed instead of using the get_tail() - * method for performance reasons. get_tail() has extra code to - * return NULL when the list is empty. We don't care about that - * here, so using tail_pred directly is fine. - */ - previous_tail_pred = instructions->tail_pred; - previous_operand_loc = ast->get_location(); - - result = ast->hir(instructions, state); + /* If one of the operands of comma operator does not generate any + * code, we want to emit a warning. At each pass through the loop + * previous_tail_pred will point to the last instruction in the + * stream *before* processing the previous operand. Naturally, + * instructions->tail_pred will point to the last instruction in the + * stream *after* processing the previous operand. If the two + * pointers match, then the previous operand had no effect. + * + * The warning behavior here differs slightly from GCC. GCC will + * only emit a warning if none of the left-hand operands have an + * effect. However, it will emit a warning for each. I believe that + * there are some cases in C (especially with GCC extensions) where + * it is useful to have an intermediate step in a sequence have no + * effect, but I don't think these cases exist in GLSL. Either way, + * it would be a giant hassle to replicate that behavior. + */ + if (previous_tail_pred == instructions->tail_pred) { + _mesa_glsl_warning(&previous_operand_loc, state, + "left-hand operand of comma expression has " + "no effect"); + } + + /* tail_pred is directly accessed instead of using the get_tail() + * method for performance reasons. get_tail() has extra code to + * return NULL when the list is empty. We don't care about that + * here, so using tail_pred directly is fine. + */ + previous_tail_pred = instructions->tail_pred; + previous_operand_loc = ast->get_location(); + + result = ast->hir(instructions, state); } /* Any errors should have already been emitted in the loop above. @@ -1668,9 +1794,9 @@ ast_expression::hir(exec_list *instructions, } } type = NULL; /* use result->type, not type. */ - assert(result != NULL); + assert(result != NULL || !needs_rvalue); - if (result->type->is_error() && !error_emitted) + if (result && result->type->is_error() && !error_emitted) _mesa_glsl_error(& loc, state, "type mismatch"); return result; @@ -1679,7 +1805,7 @@ ast_expression::hir(exec_list *instructions, ir_rvalue * ast_expression_statement::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { /* It is possible to have expression statements that don't have an * expression. This is the solitary semicolon: @@ -1691,7 +1817,7 @@ ast_expression_statement::hir(exec_list *instructions, * anything in that case. */ if (expression != NULL) - expression->hir(instructions, state); + expression->hir_no_rvalue(instructions, state); /* Statements do not have r-values. */ @@ -1701,7 +1827,7 @@ ast_expression_statement::hir(exec_list *instructions, ir_rvalue * ast_compound_statement::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { if (new_scope) state->symbols->push_scope(); @@ -1717,80 +1843,120 @@ ast_compound_statement::hir(exec_list *instructions, return NULL; } +/** + * Evaluate the given exec_node (which should be an ast_node representing + * a single array dimension) and return its integer value. + */ +static unsigned +process_array_size(exec_node *node, + struct _mesa_glsl_parse_state *state) +{ + exec_list dummy_instructions; + + ast_node *array_size = exec_node_data(ast_node, node, link); + ir_rvalue *const ir = array_size->hir(& dummy_instructions, state); + YYLTYPE loc = array_size->get_location(); + + if (ir == NULL) { + _mesa_glsl_error(& loc, state, + "array size could not be resolved"); + return 0; + } + + if (!ir->type->is_integer()) { + _mesa_glsl_error(& loc, state, + "array size must be integer type"); + return 0; + } + + if (!ir->type->is_scalar()) { + _mesa_glsl_error(& loc, state, + "array size must be scalar type"); + return 0; + } + + ir_constant *const size = ir->constant_expression_value(); + if (size == NULL) { + _mesa_glsl_error(& loc, state, "array size must be a " + "constant valued expression"); + return 0; + } + + if (size->value.i[0] <= 0) { + _mesa_glsl_error(& loc, state, "array size must be > 0"); + return 0; + } + + assert(size->type == ir->type); + + /* If the array size is const (and we've verified that + * it is) then no instructions should have been emitted + * when we converted it to HIR. If they were emitted, + * then either the array size isn't const after all, or + * we are emitting unnecessary instructions. + */ + assert(dummy_instructions.is_empty()); + + return size->value.u[0]; +} static const glsl_type * -process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size, - struct _mesa_glsl_parse_state *state) +process_array_type(YYLTYPE *loc, const glsl_type *base, + ast_array_specifier *array_specifier, + struct _mesa_glsl_parse_state *state) { - unsigned length = 0; + const glsl_type *array_type = base; - if (base == NULL) - return glsl_type::error_type; + if (array_specifier != NULL) { + if (base->is_array()) { - /* From page 19 (page 25) of the GLSL 1.20 spec: - * - * "Only one-dimensional arrays may be declared." - */ - if (base->is_array()) { - _mesa_glsl_error(loc, state, - "invalid array of `%s' (only one-dimensional arrays " - "may be declared)", - base->name); - return glsl_type::error_type; - } + /* From page 19 (page 25) of the GLSL 1.20 spec: + * + * "Only one-dimensional arrays may be declared." + */ + if (!state->ARB_arrays_of_arrays_enable) { + _mesa_glsl_error(loc, state, + "invalid array of `%s'" + "GL_ARB_arrays_of_arrays " + "required for defining arrays of arrays", + base->name); + return glsl_type::error_type; + } - if (array_size != NULL) { - exec_list dummy_instructions; - ir_rvalue *const ir = array_size->hir(& dummy_instructions, state); - YYLTYPE loc = array_size->get_location(); - - if (ir != NULL) { - if (!ir->type->is_integer()) { - _mesa_glsl_error(& loc, state, "array size must be integer type"); - } else if (!ir->type->is_scalar()) { - _mesa_glsl_error(& loc, state, "array size must be scalar type"); - } else { - ir_constant *const size = ir->constant_expression_value(); - - if (size == NULL) { - _mesa_glsl_error(& loc, state, "array size must be a " - "constant valued expression"); - } else if (size->value.i[0] <= 0) { - _mesa_glsl_error(& loc, state, "array size must be > 0"); - } else { - assert(size->type == ir->type); - length = size->value.u[0]; - - /* If the array size is const (and we've verified that - * it is) then no instructions should have been emitted - * when we converted it to HIR. If they were emitted, - * then either the array size isn't const after all, or - * we are emitting unnecessary instructions. - */ - assert(dummy_instructions.is_empty()); - } - } + if (base->length == 0) { + _mesa_glsl_error(loc, state, + "only the outermost array dimension can " + "be unsized", + base->name); + return glsl_type::error_type; + } } + + for (exec_node *node = array_specifier->array_dimensions.tail_pred; + !node->is_head_sentinel(); node = node->prev) { + unsigned array_size = process_array_size(node, state); + array_type = glsl_type::get_array_instance(array_type, array_size); + } + + if (array_specifier->is_unsized_array) + array_type = glsl_type::get_array_instance(array_type, 0); } - const glsl_type *array_type = glsl_type::get_array_instance(base, length); - return array_type != NULL ? array_type : glsl_type::error_type; + return array_type; } const glsl_type * ast_type_specifier::glsl_type(const char **name, - struct _mesa_glsl_parse_state *state) const + struct _mesa_glsl_parse_state *state) const { const struct glsl_type *type; type = state->symbols->get_type(this->type_name); *name = this->type_name; - if (this->is_array) { - YYLTYPE loc = this->get_location(); - type = process_array_type(&loc, type, this->array_size, state); - } + YYLTYPE loc = this->get_location(); + type = process_array_type(&loc, type, this->array_specifier, state); return type; } @@ -1806,7 +1972,7 @@ ast_fully_specified_type::glsl_type(const char **name, if (type->base_type == GLSL_TYPE_FLOAT && state->es_shader - && state->target == fragment_shader + && state->stage == MESA_SHADER_FRAGMENT && this->qualifier.precision == ast_precision_none && state->symbols->get_variable("#default precision") == NULL) { YYLTYPE loc = this->get_location(); @@ -1828,15 +1994,15 @@ ast_fully_specified_type::glsl_type(const char **name, * this function will produce undefined results. */ static bool -is_varying_var(ir_variable *var, _mesa_glsl_parser_targets target) +is_varying_var(ir_variable *var, gl_shader_stage target) { switch (target) { - case vertex_shader: - return var->mode == ir_var_shader_out; - case fragment_shader: - return var->mode == ir_var_shader_in; + case MESA_SHADER_VERTEX: + return var->data.mode == ir_var_shader_out; + case MESA_SHADER_FRAGMENT: + return var->data.mode == ir_var_shader_in; default: - return var->mode == ir_var_shader_out || var->mode == ir_var_shader_in; + return var->data.mode == ir_var_shader_out || var->data.mode == ir_var_shader_in; } } @@ -1846,7 +2012,7 @@ is_varying_var(ir_variable *var, _mesa_glsl_parser_targets target) */ static void validate_matrix_layout_for_type(struct _mesa_glsl_parse_state *state, - YYLTYPE *loc, + YYLTYPE *loc, const glsl_type *type, ir_variable *var) { @@ -1887,14 +2053,14 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state, ir_variable *var, const ast_type_qualifier *qual) { - if (var->mode != ir_var_uniform) { + if (var->data.mode != ir_var_uniform) { _mesa_glsl_error(loc, state, - "the \"binding\" qualifier only applies to uniforms.\n"); + "the \"binding\" qualifier only applies to uniforms"); return false; } if (qual->binding < 0) { - _mesa_glsl_error(loc, state, "binding values must be >= 0.\n"); + _mesa_glsl_error(loc, state, "binding values must be >= 0"); return false; } @@ -1915,7 +2081,7 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state, */ if (max_index >= ctx->Const.MaxUniformBufferBindings) { _mesa_glsl_error(loc, state, "layout(binding = %d) for %d UBOs exceeds " - "the maximum number of UBO binding points (%d).\n", + "the maximum number of UBO binding points (%d)", qual->binding, elements, ctx->Const.MaxUniformBufferBindings); return false; @@ -1929,68 +2095,322 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state, * with an array of size N, all elements of the array from binding * through binding + N - 1 must be within this range." */ - unsigned limit; - switch (state->target) { - case vertex_shader: - limit = ctx->Const.VertexProgram.MaxTextureImageUnits; - break; - case geometry_shader: - limit = ctx->Const.GeometryProgram.MaxTextureImageUnits; - break; - case fragment_shader: - limit = ctx->Const.FragmentProgram.MaxTextureImageUnits; - break; - } + unsigned limit = ctx->Const.Program[state->stage].MaxTextureImageUnits; if (max_index >= limit) { _mesa_glsl_error(loc, state, "layout(binding = %d) for %d samplers " "exceeds the maximum number of texture image units " - "(%d).\n", qual->binding, elements, limit); + "(%d)", qual->binding, elements, limit); + + return false; + } + } else if (var->type->contains_atomic()) { + assert(ctx->Const.MaxAtomicBufferBindings <= MAX_COMBINED_ATOMIC_BUFFERS); + if (unsigned(qual->binding) >= ctx->Const.MaxAtomicBufferBindings) { + _mesa_glsl_error(loc, state, "layout(binding = %d) exceeds the " + " maximum number of atomic counter buffer bindings" + "(%d)", qual->binding, + ctx->Const.MaxAtomicBufferBindings); return false; } } else { _mesa_glsl_error(loc, state, "the \"binding\" qualifier only applies to uniform " - "blocks, samplers, or arrays of samplers.\n"); + "blocks, samplers, atomic counters, or arrays thereof"); return false; } return true; } + +static glsl_interp_qualifier +interpret_interpolation_qualifier(const struct ast_type_qualifier *qual, + ir_variable_mode mode, + struct _mesa_glsl_parse_state *state, + YYLTYPE *loc) +{ + glsl_interp_qualifier interpolation; + if (qual->flags.q.flat) + interpolation = INTERP_QUALIFIER_FLAT; + else if (qual->flags.q.noperspective) + interpolation = INTERP_QUALIFIER_NOPERSPECTIVE; + else if (qual->flags.q.smooth) + interpolation = INTERP_QUALIFIER_SMOOTH; + else + interpolation = INTERP_QUALIFIER_NONE; + + if (interpolation != INTERP_QUALIFIER_NONE) { + if (mode != ir_var_shader_in && mode != ir_var_shader_out) { + _mesa_glsl_error(loc, state, + "interpolation qualifier `%s' can only be applied to " + "shader inputs or outputs.", + interpolation_string(interpolation)); + + } + + if ((state->stage == MESA_SHADER_VERTEX && mode == ir_var_shader_in) || + (state->stage == MESA_SHADER_FRAGMENT && mode == ir_var_shader_out)) { + _mesa_glsl_error(loc, state, + "interpolation qualifier `%s' cannot be applied to " + "vertex shader inputs or fragment shader outputs", + interpolation_string(interpolation)); + } + } + + return interpolation; +} + + +static void +validate_explicit_location(const struct ast_type_qualifier *qual, + ir_variable *var, + struct _mesa_glsl_parse_state *state, + YYLTYPE *loc) +{ + bool fail = false; + + /* Between GL_ARB_explicit_attrib_location an + * GL_ARB_separate_shader_objects, the inputs and outputs of any shader + * stage can be assigned explicit locations. The checking here associates + * the correct extension with the correct stage's input / output: + * + * input output + * ----- ------ + * vertex explicit_loc sso + * geometry sso sso + * fragment sso explicit_loc + */ + switch (state->stage) { + case MESA_SHADER_VERTEX: + if (var->data.mode == ir_var_shader_in) { + if (!state->check_explicit_attrib_location_allowed(loc, var)) + return; + + break; + } + + if (var->data.mode == ir_var_shader_out) { + if (!state->check_separate_shader_objects_allowed(loc, var)) + return; + + break; + } + + fail = true; + break; + + case MESA_SHADER_GEOMETRY: + if (var->data.mode == ir_var_shader_in || var->data.mode == ir_var_shader_out) { + if (!state->check_separate_shader_objects_allowed(loc, var)) + return; + + break; + } + + fail = true; + break; + + case MESA_SHADER_FRAGMENT: + if (var->data.mode == ir_var_shader_in) { + if (!state->check_separate_shader_objects_allowed(loc, var)) + return; + + break; + } + + if (var->data.mode == ir_var_shader_out) { + if (!state->check_explicit_attrib_location_allowed(loc, var)) + return; + + break; + } + + fail = true; + break; + + case MESA_SHADER_COMPUTE: + _mesa_glsl_error(loc, state, + "compute shader variables cannot be given " + "explicit locations"); + return; + }; + + if (fail) { + _mesa_glsl_error(loc, state, + "%s cannot be given an explicit location in %s shader", + mode_string(var), + _mesa_shader_stage_to_string(state->stage)); + } else { + var->data.explicit_location = true; + + /* This bit of silliness is needed because invalid explicit locations + * are supposed to be flagged during linking. Small negative values + * biased by VERT_ATTRIB_GENERIC0 or FRAG_RESULT_DATA0 could alias + * built-in values (e.g., -16+VERT_ATTRIB_GENERIC0 = VERT_ATTRIB_POS). + * The linker needs to be able to differentiate these cases. This + * ensures that negative values stay negative. + */ + if (qual->location >= 0) { + switch (state->stage) { + case MESA_SHADER_VERTEX: + var->data.location = (var->data.mode == ir_var_shader_in) + ? (qual->location + VERT_ATTRIB_GENERIC0) + : (qual->location + VARYING_SLOT_VAR0); + break; + + case MESA_SHADER_GEOMETRY: + var->data.location = qual->location + VARYING_SLOT_VAR0; + break; + + case MESA_SHADER_FRAGMENT: + var->data.location = (var->data.mode == ir_var_shader_out) + ? (qual->location + FRAG_RESULT_DATA0) + : (qual->location + VARYING_SLOT_VAR0); + break; + case MESA_SHADER_COMPUTE: + assert(!"Unexpected shader type"); + break; + } + } else { + var->data.location = qual->location; + } + + if (qual->flags.q.explicit_index) { + /* From the GLSL 4.30 specification, section 4.4.2 (Output + * Layout Qualifiers): + * + * "It is also a compile-time error if a fragment shader + * sets a layout index to less than 0 or greater than 1." + * + * Older specifications don't mandate a behavior; we take + * this as a clarification and always generate the error. + */ + if (qual->index < 0 || qual->index > 1) { + _mesa_glsl_error(loc, state, + "explicit index may only be 0 or 1"); + } else { + var->data.explicit_index = true; + var->data.index = qual->index; + } + } + } +} + +static void +apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual, + ir_variable *var, + struct _mesa_glsl_parse_state *state, + YYLTYPE *loc) +{ + const glsl_type *base_type = + (var->type->is_array() ? var->type->element_type() : var->type); + + if (base_type->is_image()) { + if (var->data.mode != ir_var_uniform && + var->data.mode != ir_var_function_in) { + _mesa_glsl_error(loc, state, "image variables may only be declared as " + "function parameters or uniform-qualified " + "global variables"); + } + + var->data.image.read_only |= qual->flags.q.read_only; + var->data.image.write_only |= qual->flags.q.write_only; + var->data.image.coherent |= qual->flags.q.coherent; + var->data.image._volatile |= qual->flags.q._volatile; + var->data.image.restrict_flag |= qual->flags.q.restrict_flag; + var->data.read_only = true; + + if (qual->flags.q.explicit_image_format) { + if (var->data.mode == ir_var_function_in) { + _mesa_glsl_error(loc, state, "format qualifiers cannot be " + "used on image function parameters"); + } + + if (qual->image_base_type != base_type->sampler_type) { + _mesa_glsl_error(loc, state, "format qualifier doesn't match the " + "base data type of the image"); + } + + var->data.image.format = qual->image_format; + } else { + if (var->data.mode == ir_var_uniform && !qual->flags.q.write_only) { + _mesa_glsl_error(loc, state, "uniforms not qualified with " + "`writeonly' must have a format layout " + "qualifier"); + } + + var->data.image.format = GL_NONE; + } + } +} + +static inline const char* +get_layout_qualifier_string(bool origin_upper_left, bool pixel_center_integer) +{ + if (origin_upper_left && pixel_center_integer) + return "origin_upper_left, pixel_center_integer"; + else if (origin_upper_left) + return "origin_upper_left"; + else if (pixel_center_integer) + return "pixel_center_integer"; + else + return " "; +} + +static inline bool +is_conflicting_fragcoord_redeclaration(struct _mesa_glsl_parse_state *state, + const struct ast_type_qualifier *qual) +{ + /* If gl_FragCoord was previously declared, and the qualifiers were + * different in any way, return true. + */ + if (state->fs_redeclares_gl_fragcoord) { + return (state->fs_pixel_center_integer != qual->flags.q.pixel_center_integer + || state->fs_origin_upper_left != qual->flags.q.origin_upper_left); + } + + return false; +} + static void apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, - ir_variable *var, - struct _mesa_glsl_parse_state *state, - YYLTYPE *loc, + ir_variable *var, + struct _mesa_glsl_parse_state *state, + YYLTYPE *loc, bool is_parameter) { + STATIC_ASSERT(sizeof(qual->flags.q) <= sizeof(qual->flags.i)); + if (qual->flags.q.invariant) { - if (var->used) { - _mesa_glsl_error(loc, state, - "variable `%s' may not be redeclared " - "`invariant' after being used", - var->name); + if (var->data.used) { + _mesa_glsl_error(loc, state, + "variable `%s' may not be redeclared " + "`invariant' after being used", + var->name); } else { - var->invariant = 1; + var->data.invariant = 1; } } if (qual->flags.q.constant || qual->flags.q.attribute || qual->flags.q.uniform - || (qual->flags.q.varying && (state->target == fragment_shader))) - var->read_only = 1; + || (qual->flags.q.varying && (state->stage == MESA_SHADER_FRAGMENT))) + var->data.read_only = 1; if (qual->flags.q.centroid) - var->centroid = 1; + var->data.centroid = 1; + + if (qual->flags.q.sample) + var->data.sample = 1; - if (qual->flags.q.attribute && state->target != vertex_shader) { + if (qual->flags.q.attribute && state->stage != MESA_SHADER_VERTEX) { var->type = glsl_type::error_type; _mesa_glsl_error(loc, state, - "`attribute' variables may not be declared in the " - "%s shader", - _mesa_glsl_shader_target_name(state->target)); + "`attribute' variables may not be declared in the " + "%s shader", + _mesa_shader_stage_to_string(state->stage)); } /* Section 6.1.1 (Function Calling Conventions) of the GLSL 1.10 spec says: @@ -2012,20 +2432,27 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, * the setting alone. */ if (qual->flags.q.in && qual->flags.q.out) - var->mode = ir_var_function_inout; + var->data.mode = ir_var_function_inout; else if (qual->flags.q.in) - var->mode = is_parameter ? ir_var_function_in : ir_var_shader_in; + var->data.mode = is_parameter ? ir_var_function_in : ir_var_shader_in; else if (qual->flags.q.attribute - || (qual->flags.q.varying && (state->target == fragment_shader))) - var->mode = ir_var_shader_in; + || (qual->flags.q.varying && (state->stage == MESA_SHADER_FRAGMENT))) + var->data.mode = ir_var_shader_in; else if (qual->flags.q.out) - var->mode = is_parameter ? ir_var_function_out : ir_var_shader_out; - else if (qual->flags.q.varying && (state->target == vertex_shader)) - var->mode = ir_var_shader_out; + var->data.mode = is_parameter ? ir_var_function_out : ir_var_shader_out; + else if (qual->flags.q.varying && (state->stage == MESA_SHADER_VERTEX)) + var->data.mode = ir_var_shader_out; else if (qual->flags.q.uniform) - var->mode = ir_var_uniform; + var->data.mode = ir_var_uniform; + + if (!is_parameter && is_varying_var(var, state->stage)) { + /* User-defined ins/outs are not permitted in compute shaders. */ + if (state->stage == MESA_SHADER_COMPUTE) { + _mesa_glsl_error(loc, state, + "user-defined input and output variables are not " + "permitted in compute shaders"); + } - if (!is_parameter && is_varying_var(var, state->target)) { /* This variable is being used to link data between shader stages (in * pre-glsl-1.30 parlance, it's a "varying"). Check that it has a type * that is allowed for such purposes. @@ -2074,47 +2501,36 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, } if (state->all_invariant && (state->current_function == NULL)) { - switch (state->target) { - case vertex_shader: - if (var->mode == ir_var_shader_out) - var->invariant = true; - break; - case geometry_shader: - if ((var->mode == ir_var_shader_in) - || (var->mode == ir_var_shader_out)) - var->invariant = true; - break; - case fragment_shader: - if (var->mode == ir_var_shader_in) - var->invariant = true; - break; + switch (state->stage) { + case MESA_SHADER_VERTEX: + if (var->data.mode == ir_var_shader_out) + var->data.invariant = true; + break; + case MESA_SHADER_GEOMETRY: + if ((var->data.mode == ir_var_shader_in) + || (var->data.mode == ir_var_shader_out)) + var->data.invariant = true; + break; + case MESA_SHADER_FRAGMENT: + if (var->data.mode == ir_var_shader_in) + var->data.invariant = true; + break; + case MESA_SHADER_COMPUTE: + /* Invariance isn't meaningful in compute shaders. */ + break; } } - if (qual->flags.q.flat) - var->interpolation = INTERP_QUALIFIER_FLAT; - else if (qual->flags.q.noperspective) - var->interpolation = INTERP_QUALIFIER_NOPERSPECTIVE; - else if (qual->flags.q.smooth) - var->interpolation = INTERP_QUALIFIER_SMOOTH; - else - var->interpolation = INTERP_QUALIFIER_NONE; - - if (var->interpolation != INTERP_QUALIFIER_NONE && - !(state->target == vertex_shader && var->mode == ir_var_shader_out) && - !(state->target == fragment_shader && var->mode == ir_var_shader_in)) { - _mesa_glsl_error(loc, state, - "interpolation qualifier `%s' can only be applied to " - "vertex shader outputs and fragment shader inputs.", - var->interpolation_string()); - } + var->data.interpolation = + interpret_interpolation_qualifier(qual, (ir_variable_mode) var->data.mode, + state, loc); - var->pixel_center_integer = qual->flags.q.pixel_center_integer; - var->origin_upper_left = qual->flags.q.origin_upper_left; + var->data.pixel_center_integer = qual->flags.q.pixel_center_integer; + var->data.origin_upper_left = qual->flags.q.origin_upper_left; if ((qual->flags.q.origin_upper_left || qual->flags.q.pixel_center_integer) && (strcmp(var->name, "gl_FragCoord") != 0)) { const char *const qual_string = (qual->flags.q.origin_upper_left) - ? "origin_upper_left" : "pixel_center_integer"; + ? "origin_upper_left" : "pixel_center_integer"; _mesa_glsl_error(loc, state, "layout qualifier `%s' can only be applied to " @@ -2122,91 +2538,87 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, qual_string); } - if (qual->flags.q.explicit_location) { - const bool global_scope = (state->current_function == NULL); - bool fail = false; - const char *string = ""; + if (var->name != NULL && strcmp(var->name, "gl_FragCoord") == 0) { - /* In the vertex shader only shader inputs can be given explicit - * locations. + /* Section 4.3.8.1, page 39 of GLSL 1.50 spec says: * - * In the fragment shader only shader outputs can be given explicit - * locations. + * "Within any shader, the first redeclarations of gl_FragCoord + * must appear before any use of gl_FragCoord." + * + * Generate a compiler error if above condition is not met by the + * fragment shader. */ - switch (state->target) { - case vertex_shader: - if (!global_scope || (var->mode != ir_var_shader_in)) { - fail = true; - string = "input"; - } - break; - - case geometry_shader: - _mesa_glsl_error(loc, state, - "geometry shader variables cannot be given " - "explicit locations\n"); - break; - - case fragment_shader: - if (!global_scope || (var->mode != ir_var_shader_out)) { - fail = true; - string = "output"; - } - break; - }; - - if (fail) { - _mesa_glsl_error(loc, state, - "only %s shader %s variables can be given an " - "explicit location\n", - _mesa_glsl_shader_target_name(state->target), - string); - } else { - var->explicit_location = true; - - /* This bit of silliness is needed because invalid explicit locations - * are supposed to be flagged during linking. Small negative values - * biased by VERT_ATTRIB_GENERIC0 or FRAG_RESULT_DATA0 could alias - * built-in values (e.g., -16+VERT_ATTRIB_GENERIC0 = VERT_ATTRIB_POS). - * The linker needs to be able to differentiate these cases. This - * ensures that negative values stay negative. - */ - if (qual->location >= 0) { - var->location = (state->target == vertex_shader) - ? (qual->location + VERT_ATTRIB_GENERIC0) - : (qual->location + FRAG_RESULT_DATA0); - } else { - var->location = qual->location; - } - - if (qual->flags.q.explicit_index) { - /* From the GLSL 4.30 specification, section 4.4.2 (Output - * Layout Qualifiers): - * - * "It is also a compile-time error if a fragment shader - * sets a layout index to less than 0 or greater than 1." - * - * Older specifications don't mandate a behavior; we take - * this as a clarification and always generate the error. - */ - if (qual->index < 0 || qual->index > 1) { - _mesa_glsl_error(loc, state, - "explicit index may only be 0 or 1\n"); - } else { - var->explicit_index = true; - var->index = qual->index; - } - } + ir_variable *earlier = state->symbols->get_variable("gl_FragCoord"); + if (earlier != NULL && + earlier->data.used && + !state->fs_redeclares_gl_fragcoord) { + _mesa_glsl_error(loc, state, + "gl_FragCoord used before its first redeclaration " + "in fragment shader"); + } + + /* Make sure all gl_FragCoord redeclarations specify the same layout + * qualifiers. + */ + if (is_conflicting_fragcoord_redeclaration(state, qual)) { + const char *const qual_string = + get_layout_qualifier_string(qual->flags.q.origin_upper_left, + qual->flags.q.pixel_center_integer); + + const char *const state_string = + get_layout_qualifier_string(state->fs_origin_upper_left, + state->fs_pixel_center_integer); + + _mesa_glsl_error(loc, state, + "gl_FragCoord redeclared with different layout " + "qualifiers (%s) and (%s) ", + state_string, + qual_string); } + state->fs_origin_upper_left = qual->flags.q.origin_upper_left; + state->fs_pixel_center_integer = qual->flags.q.pixel_center_integer; + state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers = + !qual->flags.q.origin_upper_left && !qual->flags.q.pixel_center_integer; + state->fs_redeclares_gl_fragcoord = + state->fs_origin_upper_left || + state->fs_pixel_center_integer || + state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers; + } + + if (qual->flags.q.explicit_location) { + validate_explicit_location(qual, var, state, loc); } else if (qual->flags.q.explicit_index) { - _mesa_glsl_error(loc, state, - "explicit index requires explicit location\n"); + _mesa_glsl_error(loc, state, "explicit index requires explicit location"); } if (qual->flags.q.explicit_binding && validate_binding_qualifier(state, loc, var, qual)) { - var->explicit_binding = true; - var->binding = qual->binding; + var->data.explicit_binding = true; + var->data.binding = qual->binding; + } + + if (var->type->contains_atomic()) { + if (var->data.mode == ir_var_uniform) { + if (var->data.explicit_binding) { + unsigned *offset = + &state->atomic_counter_offsets[var->data.binding]; + + if (*offset % ATOMIC_COUNTER_SIZE) + _mesa_glsl_error(loc, state, + "misaligned atomic counter offset"); + + var->data.atomic.offset = *offset; + *offset += var->type->atomic_size(); + + } else { + _mesa_glsl_error(loc, state, + "atomic counters require explicit binding point"); + } + } else if (var->data.mode != ir_var_function_in) { + _mesa_glsl_error(loc, state, "atomic counters may only be declared as " + "function parameters or uniform-qualified " + "global variables"); + } } /* Does the declaration use the deprecated 'attribute' or 'varying' @@ -2240,13 +2652,13 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, if (qual->has_layout() && uses_deprecated_qualifier) { if (relaxed_layout_qualifier_checking) { - _mesa_glsl_warning(loc, state, - "`layout' qualifier may not be used with " - "`attribute' or `varying'"); + _mesa_glsl_warning(loc, state, + "`layout' qualifier may not be used with " + "`attribute' or `varying'"); } else { - _mesa_glsl_error(loc, state, - "`layout' qualifier may not be used with " - "`attribute' or `varying'"); + _mesa_glsl_error(loc, state, + "`layout' qualifier may not be used with " + "`attribute' or `varying'"); } } @@ -2263,7 +2675,7 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, _mesa_glsl_error(loc, state, "extension GL_AMD_conservative_depth or " "GL_ARB_conservative_depth must be enabled " - "to use depth layout qualifiers"); + "to use depth layout qualifiers"); } else if (depth_layout_count > 0 && strcmp(var->name, "gl_FragDepth") != 0) { _mesa_glsl_error(loc, state, @@ -2276,28 +2688,31 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, "gl_FragDepth"); } if (qual->flags.q.depth_any) - var->depth_layout = ir_depth_layout_any; + var->data.depth_layout = ir_depth_layout_any; else if (qual->flags.q.depth_greater) - var->depth_layout = ir_depth_layout_greater; + var->data.depth_layout = ir_depth_layout_greater; else if (qual->flags.q.depth_less) - var->depth_layout = ir_depth_layout_less; + var->data.depth_layout = ir_depth_layout_less; else if (qual->flags.q.depth_unchanged) - var->depth_layout = ir_depth_layout_unchanged; + var->data.depth_layout = ir_depth_layout_unchanged; else - var->depth_layout = ir_depth_layout_none; + var->data.depth_layout = ir_depth_layout_none; if (qual->flags.q.std140 || qual->flags.q.packed || qual->flags.q.shared) { _mesa_glsl_error(loc, state, "uniform block layout qualifiers std140, packed, and " - "shared can only be applied to uniform blocks, not " - "members"); + "shared can only be applied to uniform blocks, not " + "members"); } if (qual->flags.q.row_major || qual->flags.q.column_major) { validate_matrix_layout_for_type(state, loc, var->type, var); } + + if (var->type->contains_image()) + apply_image_qualifier_to_variable(qual, var, state, loc); } /** @@ -2311,9 +2726,10 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, * A pointer to an existing variable in the current scope if the declaration * is a redeclaration, \c NULL otherwise. */ -ir_variable * -get_variable_being_redeclared(ir_variable *var, ast_declaration *decl, - struct _mesa_glsl_parse_state *state) +static ir_variable * +get_variable_being_redeclared(ir_variable *var, YYLTYPE loc, + struct _mesa_glsl_parse_state *state, + bool allow_all_redeclarations) { /* Check if this declaration is actually a re-declaration, either to * resize an array or add qualifiers to an existing variable. @@ -2321,24 +2737,21 @@ get_variable_being_redeclared(ir_variable *var, ast_declaration *decl, * This is allowed for variables in the current scope, or when at * global scope (for built-ins in the implicit outer scope). */ - ir_variable *earlier = state->symbols->get_variable(decl->identifier); + ir_variable *earlier = state->symbols->get_variable(var->name); if (earlier == NULL || (state->current_function != NULL && - !state->symbols->name_declared_this_scope(decl->identifier))) { + !state->symbols->name_declared_this_scope(var->name))) { return NULL; } - YYLTYPE loc = decl->get_location(); - /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec, * * "It is legal to declare an array without a size and then * later re-declare the same name as an array of the same * type and specify a size." */ - if ((earlier->type->array_size() == 0) - && var->type->is_array() + if (earlier->type->is_unsized_array() && var->type->is_array() && (var->type->element_type() == earlier->type->element_type())) { /* FINISHME: This doesn't match the qualifiers on the two * FINISHME: declarations. It's not 100% clear whether this is @@ -2347,24 +2760,25 @@ get_variable_being_redeclared(ir_variable *var, ast_declaration *decl, const unsigned size = unsigned(var->type->array_size()); check_builtin_array_max_size(var->name, size, loc, state); - if ((size > 0) && (size <= earlier->max_array_access)) { - _mesa_glsl_error(& loc, state, "array size must be > %u due to " - "previous access", - earlier->max_array_access); + if ((size > 0) && (size <= earlier->data.max_array_access)) { + _mesa_glsl_error(& loc, state, "array size must be > %u due to " + "previous access", + earlier->data.max_array_access); } earlier->type = var->type; delete var; var = NULL; - } else if (state->ARB_fragment_coord_conventions_enable - && strcmp(var->name, "gl_FragCoord") == 0 - && earlier->type == var->type - && earlier->mode == var->mode) { + } else if ((state->ARB_fragment_coord_conventions_enable || + state->is_version(150, 0)) + && strcmp(var->name, "gl_FragCoord") == 0 + && earlier->type == var->type + && earlier->data.mode == var->data.mode) { /* Allow redeclaration of gl_FragCoord for ARB_fcc layout * qualifiers. */ - earlier->origin_upper_left = var->origin_upper_left; - earlier->pixel_center_integer = var->pixel_center_integer; + earlier->data.origin_upper_left = var->data.origin_upper_left; + earlier->data.pixel_center_integer = var->data.pixel_center_integer; /* According to section 4.3.7 of the GLSL 1.30 spec, * the following built-in varaibles can be redeclared with an @@ -2377,48 +2791,58 @@ get_variable_being_redeclared(ir_variable *var, ast_declaration *decl, * * gl_SecondaryColor */ } else if (state->is_version(130, 0) - && (strcmp(var->name, "gl_FrontColor") == 0 - || strcmp(var->name, "gl_BackColor") == 0 - || strcmp(var->name, "gl_FrontSecondaryColor") == 0 - || strcmp(var->name, "gl_BackSecondaryColor") == 0 - || strcmp(var->name, "gl_Color") == 0 - || strcmp(var->name, "gl_SecondaryColor") == 0) - && earlier->type == var->type - && earlier->mode == var->mode) { - earlier->interpolation = var->interpolation; + && (strcmp(var->name, "gl_FrontColor") == 0 + || strcmp(var->name, "gl_BackColor") == 0 + || strcmp(var->name, "gl_FrontSecondaryColor") == 0 + || strcmp(var->name, "gl_BackSecondaryColor") == 0 + || strcmp(var->name, "gl_Color") == 0 + || strcmp(var->name, "gl_SecondaryColor") == 0) + && earlier->type == var->type + && earlier->data.mode == var->data.mode) { + earlier->data.interpolation = var->data.interpolation; /* Layout qualifiers for gl_FragDepth. */ } else if ((state->AMD_conservative_depth_enable || state->ARB_conservative_depth_enable) - && strcmp(var->name, "gl_FragDepth") == 0 - && earlier->type == var->type - && earlier->mode == var->mode) { + && strcmp(var->name, "gl_FragDepth") == 0 + && earlier->type == var->type + && earlier->data.mode == var->data.mode) { /** From the AMD_conservative_depth spec: * Within any shader, the first redeclarations of gl_FragDepth * must appear before any use of gl_FragDepth. */ - if (earlier->used) { - _mesa_glsl_error(&loc, state, - "the first redeclaration of gl_FragDepth " - "must appear before any use of gl_FragDepth"); + if (earlier->data.used) { + _mesa_glsl_error(&loc, state, + "the first redeclaration of gl_FragDepth " + "must appear before any use of gl_FragDepth"); } /* Prevent inconsistent redeclaration of depth layout qualifier. */ - if (earlier->depth_layout != ir_depth_layout_none - && earlier->depth_layout != var->depth_layout) { - _mesa_glsl_error(&loc, state, - "gl_FragDepth: depth layout is declared here " - "as '%s, but it was previously declared as " - "'%s'", - depth_layout_string(var->depth_layout), - depth_layout_string(earlier->depth_layout)); + if (earlier->data.depth_layout != ir_depth_layout_none + && earlier->data.depth_layout != var->data.depth_layout) { + _mesa_glsl_error(&loc, state, + "gl_FragDepth: depth layout is declared here " + "as '%s, but it was previously declared as " + "'%s'", + depth_layout_string(var->data.depth_layout), + depth_layout_string(earlier->data.depth_layout)); } - earlier->depth_layout = var->depth_layout; + earlier->data.depth_layout = var->data.depth_layout; + } else if (allow_all_redeclarations) { + if (earlier->data.mode != var->data.mode) { + _mesa_glsl_error(&loc, state, + "redeclaration of `%s' with incorrect qualifiers", + var->name); + } else if (earlier->type != var->type) { + _mesa_glsl_error(&loc, state, + "redeclaration of `%s' has incorrect type", + var->name); + } } else { - _mesa_glsl_error(&loc, state, "`%s' redeclared", decl->identifier); + _mesa_glsl_error(&loc, state, "`%s' redeclared", var->name); } return earlier; @@ -2443,39 +2867,52 @@ process_initializer(ir_variable *var, ast_declaration *decl, * directly by an application via API commands, or indirectly by * OpenGL." */ - if (var->mode == ir_var_uniform) { + if (var->data.mode == ir_var_uniform) { state->check_version(120, 0, &initializer_loc, "cannot initialize uniforms"); } - if (var->type->is_sampler()) { + /* From section 4.1.7 of the GLSL 4.40 spec: + * + * "Opaque variables [...] are initialized only through the + * OpenGL API; they cannot be declared with an initializer in a + * shader." + */ + if (var->type->contains_opaque()) { _mesa_glsl_error(& initializer_loc, state, - "cannot initialize samplers"); + "cannot initialize opaque variable"); } - if ((var->mode == ir_var_shader_in) && (state->current_function == NULL)) { + if ((var->data.mode == ir_var_shader_in) && (state->current_function == NULL)) { _mesa_glsl_error(& initializer_loc, state, "cannot initialize %s shader input / %s", - _mesa_glsl_shader_target_name(state->target), - (state->target == vertex_shader) + _mesa_shader_stage_to_string(state->stage), + (state->stage == MESA_SHADER_VERTEX) ? "attribute" : "varying"); } + /* If the initializer is an ast_aggregate_initializer, recursively store + * type information from the LHS into it, so that its hir() function can do + * type checking. + */ + if (decl->initializer->oper == ast_aggregate) + _mesa_ast_set_aggregate_type(var->type, decl->initializer); + ir_dereference *const lhs = new(state) ir_dereference_variable(var); - ir_rvalue *rhs = decl->initializer->hir(initializer_instructions, - state); + ir_rvalue *rhs = decl->initializer->hir(initializer_instructions, state); /* Calculate the constant value if this is a const or uniform * declaration. */ if (type->qualifier.flags.q.constant || type->qualifier.flags.q.uniform) { - ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs, true); + ir_rvalue *new_rhs = validate_assignment(state, initializer_loc, + var->type, rhs, true); if (new_rhs != NULL) { - rhs = new_rhs; + rhs = new_rhs; - ir_constant *constant_value = rhs->constant_expression_value(); - if (!constant_value) { + ir_constant *constant_value = rhs->constant_expression_value(); + if (!constant_value) { /* If ARB_shading_language_420pack is enabled, initializers of * const-qualified local variables do not have to be constant * expressions. Const-qualified global variables must still be @@ -2495,40 +2932,38 @@ process_initializer(ir_variable *var, ast_declaration *decl, } } } else { - rhs = constant_value; - var->constant_value = constant_value; - } + rhs = constant_value; + var->constant_value = constant_value; + } } else { - _mesa_glsl_error(&initializer_loc, state, - "initializer of type %s cannot be assigned to " - "variable of type %s", - rhs->type->name, var->type->name); - if (var->type->is_numeric()) { - /* Reduce cascading errors. */ - var->constant_value = ir_constant::zero(state, var->type); - } + if (var->type->is_numeric()) { + /* Reduce cascading errors. */ + var->constant_value = ir_constant::zero(state, var->type); + } } } if (rhs && !rhs->type->is_error()) { - bool temp = var->read_only; + bool temp = var->data.read_only; if (type->qualifier.flags.q.constant) - var->read_only = false; + var->data.read_only = false; /* Never emit code to initialize a uniform. */ const glsl_type *initializer_type; if (!type->qualifier.flags.q.uniform) { - result = do_assignment(initializer_instructions, state, - NULL, - lhs, rhs, true, - type->get_location()); - initializer_type = result->type; + do_assignment(initializer_instructions, state, + NULL, + lhs, rhs, + &result, true, + true, + type->get_location()); + initializer_type = result->type; } else - initializer_type = rhs->type; + initializer_type = rhs->type; var->constant_initializer = rhs->constant_expression_value(); - var->has_initializer = true; + var->data.has_initializer = true; /* If the declared variable is an unsized array, it must inherrit * its full type from the initializer. A declaration such as @@ -2552,15 +2987,127 @@ process_initializer(ir_variable *var, ast_declaration *decl, */ var->type = initializer_type; - var->read_only = temp; + var->data.read_only = temp; } return result; } + +/** + * Do additional processing necessary for geometry shader input declarations + * (this covers both interface blocks arrays and bare input variables). + */ +static void +handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state, + YYLTYPE loc, ir_variable *var) +{ + unsigned num_vertices = 0; + if (state->gs_input_prim_type_specified) { + num_vertices = vertices_per_prim(state->in_qualifier->prim_type); + } + + /* Geometry shader input variables must be arrays. Caller should have + * reported an error for this. + */ + if (!var->type->is_array()) { + assert(state->error); + + /* To avoid cascading failures, short circuit the checks below. */ + return; + } + + if (var->type->is_unsized_array()) { + /* Section 4.3.8.1 (Input Layout Qualifiers) of the GLSL 1.50 spec says: + * + * All geometry shader input unsized array declarations will be + * sized by an earlier input layout qualifier, when present, as per + * the following table. + * + * Followed by a table mapping each allowed input layout qualifier to + * the corresponding input length. + */ + if (num_vertices != 0) + var->type = glsl_type::get_array_instance(var->type->fields.array, + num_vertices); + } else { + /* Section 4.3.8.1 (Input Layout Qualifiers) of the GLSL 1.50 spec + * includes the following examples of compile-time errors: + * + * // code sequence within one shader... + * in vec4 Color1[]; // size unknown + * ...Color1.length()...// illegal, length() unknown + * in vec4 Color2[2]; // size is 2 + * ...Color1.length()...// illegal, Color1 still has no size + * in vec4 Color3[3]; // illegal, input sizes are inconsistent + * layout(lines) in; // legal, input size is 2, matching + * in vec4 Color4[3]; // illegal, contradicts layout + * ... + * + * To detect the case illustrated by Color3, we verify that the size of + * an explicitly-sized array matches the size of any previously declared + * explicitly-sized array. To detect the case illustrated by Color4, we + * verify that the size of an explicitly-sized array is consistent with + * any previously declared input layout. + */ + if (num_vertices != 0 && var->type->length != num_vertices) { + _mesa_glsl_error(&loc, state, + "geometry shader input size contradicts previously" + " declared layout (size is %u, but layout requires a" + " size of %u)", var->type->length, num_vertices); + } else if (state->gs_input_size != 0 && + var->type->length != state->gs_input_size) { + _mesa_glsl_error(&loc, state, + "geometry shader input sizes are " + "inconsistent (size is %u, but a previous " + "declaration has size %u)", + var->type->length, state->gs_input_size); + } else { + state->gs_input_size = var->type->length; + } + } +} + + +void +validate_identifier(const char *identifier, YYLTYPE loc, + struct _mesa_glsl_parse_state *state) +{ + /* From page 15 (page 21 of the PDF) of the GLSL 1.10 spec, + * + * "Identifiers starting with "gl_" are reserved for use by + * OpenGL, and may not be declared in a shader as either a + * variable or a function." + */ + if (strncmp(identifier, "gl_", 3) == 0) { + _mesa_glsl_error(&loc, state, + "identifier `%s' uses reserved `gl_' prefix", + identifier); + } else if (strstr(identifier, "__")) { + /* From page 14 (page 20 of the PDF) of the GLSL 1.10 + * spec: + * + * "In addition, all identifiers containing two + * consecutive underscores (__) are reserved as + * possible future keywords." + * + * The intention is that names containing __ are reserved for internal + * use by the implementation, and names prefixed with GL_ are reserved + * for use by Khronos. Names simply containing __ are dangerous to use, + * but should be allowed. + * + * A future version of the GLSL specification will clarify this. + */ + _mesa_glsl_warning(&loc, state, + "identifier `%s' uses reserved `__' string", + identifier); + } +} + + ir_rvalue * ast_declarator_list::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { void *ctx = state; const struct glsl_type *decl_type; @@ -2583,40 +3130,33 @@ ast_declarator_list::hir(exec_list *instructions, assert(this->type == NULL); if (state->current_function != NULL) { - _mesa_glsl_error(& loc, state, - "All uses of `invariant' keyword must be at global " - "scope\n"); + _mesa_glsl_error(& loc, state, + "all uses of `invariant' keyword must be at global " + "scope"); } foreach_list_typed (ast_declaration, decl, link, &this->declarations) { - assert(!decl->is_array); - assert(decl->array_size == NULL); - assert(decl->initializer == NULL); - - ir_variable *const earlier = - state->symbols->get_variable(decl->identifier); - if (earlier == NULL) { - _mesa_glsl_error(& loc, state, - "Undeclared variable `%s' cannot be marked " - "invariant\n", decl->identifier); - } else if ((state->target == vertex_shader) - && (earlier->mode != ir_var_shader_out)) { - _mesa_glsl_error(& loc, state, - "`%s' cannot be marked invariant, vertex shader " - "outputs only\n", decl->identifier); - } else if ((state->target == fragment_shader) - && (earlier->mode != ir_var_shader_in)) { - _mesa_glsl_error(& loc, state, - "`%s' cannot be marked invariant, fragment shader " - "inputs only\n", decl->identifier); - } else if (earlier->used) { - _mesa_glsl_error(& loc, state, - "variable `%s' may not be redeclared " - "`invariant' after being used", - earlier->name); - } else { - earlier->invariant = true; - } + assert(decl->array_specifier == NULL); + assert(decl->initializer == NULL); + + ir_variable *const earlier = + state->symbols->get_variable(decl->identifier); + if (earlier == NULL) { + _mesa_glsl_error(& loc, state, + "undeclared variable `%s' cannot be marked " + "invariant", decl->identifier); + } else if (!is_varying_var(earlier, state->stage)) { + _mesa_glsl_error(&loc, state, + "`%s' cannot be marked invariant; interfaces between " + "shader stages only.", decl->identifier); + } else if (earlier->data.used) { + _mesa_glsl_error(& loc, state, + "variable `%s' may not be redeclared " + "`invariant' after being used", + earlier->name); + } else { + earlier->data.invariant = true; + } } /* Invariant redeclarations do not have r-values. @@ -2633,6 +3173,18 @@ ast_declarator_list::hir(exec_list *instructions, (void) this->type->specifier->hir(instructions, state); decl_type = this->type->glsl_type(& type_name, state); + + /* An offset-qualified atomic counter declaration sets the default + * offset for the next declaration within the same atomic counter + * buffer. + */ + if (decl_type && decl_type->contains_atomic()) { + if (type->qualifier.flags.q.explicit_binding && + type->qualifier.flags.q.explicit_offset) + state->atomic_counter_offsets[type->qualifier.binding] = + type->qualifier.offset; + } + if (this->declarations.is_empty()) { /* If there is no structure involved in the program text, there are two * possible scenarios: @@ -2662,6 +3214,11 @@ ast_declarator_list::hir(exec_list *instructions, _mesa_glsl_error(&loc, state, "invalid type `%s' in empty declaration", type_name); + } else if (decl_type->base_type == GLSL_TYPE_ATOMIC_UINT) { + /* Empty atomic counter declarations are allowed and useful + * to set the default offset qualifier. + */ + return NULL; } else if (this->type->qualifier.precision != ast_precision_none) { if (this->type->specifier->structure != NULL) { _mesa_glsl_error(&loc, state, @@ -2696,33 +3253,47 @@ ast_declarator_list::hir(exec_list *instructions, */ if ((decl_type == NULL) || decl_type->is_void()) { - if (type_name != NULL) { - _mesa_glsl_error(& loc, state, - "invalid type `%s' in declaration of `%s'", - type_name, decl->identifier); - } else { - _mesa_glsl_error(& loc, state, - "invalid type in declaration of `%s'", - decl->identifier); - } - continue; + if (type_name != NULL) { + _mesa_glsl_error(& loc, state, + "invalid type `%s' in declaration of `%s'", + type_name, decl->identifier); + } else { + _mesa_glsl_error(& loc, state, + "invalid type in declaration of `%s'", + decl->identifier); + } + continue; } - if (decl->is_array) { - var_type = process_array_type(&loc, decl_type, decl->array_size, - state); - if (var_type->is_error()) - continue; - } else { - var_type = decl_type; - } + var_type = process_array_type(&loc, decl_type, decl->array_specifier, + state); var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto); + /* The 'varying in' and 'varying out' qualifiers can only be used with + * ARB_geometry_shader4 and EXT_geometry_shader4, which we don't support + * yet. + */ + if (this->type->qualifier.flags.q.varying) { + if (this->type->qualifier.flags.q.in) { + _mesa_glsl_error(& loc, state, + "`varying in' qualifier in declaration of " + "`%s' only valid for geometry shaders using " + "ARB_geometry_shader4 or EXT_geometry_shader4", + decl->identifier); + } else if (this->type->qualifier.flags.q.out) { + _mesa_glsl_error(& loc, state, + "`varying out' qualifier in declaration of " + "`%s' only valid for geometry shaders using " + "ARB_geometry_shader4 or EXT_geometry_shader4", + decl->identifier); + } + } + /* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification; * * "Global variables can only use the qualifiers const, - * attribute, uni form, or varying. Only one may be + * attribute, uniform, or varying. Only one may be * specified. * * Local variables can only use the qualifier const." @@ -2731,94 +3302,86 @@ ast_declarator_list::hir(exec_list *instructions, * any extension that adds the 'layout' keyword. */ if (!state->is_version(130, 300) - && !state->ARB_explicit_attrib_location_enable - && !state->ARB_fragment_coord_conventions_enable) { - if (this->type->qualifier.flags.q.out) { - _mesa_glsl_error(& loc, state, - "`out' qualifier in declaration of `%s' " - "only valid for function parameters in %s.", - decl->identifier, state->get_version_string()); - } - if (this->type->qualifier.flags.q.in) { - _mesa_glsl_error(& loc, state, - "`in' qualifier in declaration of `%s' " - "only valid for function parameters in %s.", - decl->identifier, state->get_version_string()); - } - /* FINISHME: Test for other invalid qualifiers. */ + && !state->has_explicit_attrib_location() + && !state->has_separate_shader_objects() + && !state->ARB_fragment_coord_conventions_enable) { + if (this->type->qualifier.flags.q.out) { + _mesa_glsl_error(& loc, state, + "`out' qualifier in declaration of `%s' " + "only valid for function parameters in %s", + decl->identifier, state->get_version_string()); + } + if (this->type->qualifier.flags.q.in) { + _mesa_glsl_error(& loc, state, + "`in' qualifier in declaration of `%s' " + "only valid for function parameters in %s", + decl->identifier, state->get_version_string()); + } + /* FINISHME: Test for other invalid qualifiers. */ } apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc, false); if (this->type->qualifier.flags.q.invariant) { - if ((state->target == vertex_shader) && - var->mode != ir_var_shader_out) { - _mesa_glsl_error(& loc, state, - "`%s' cannot be marked invariant, vertex shader " - "outputs only\n", var->name); - } else if ((state->target == fragment_shader) && - var->mode != ir_var_shader_in) { - /* FINISHME: Note that this doesn't work for invariant on - * a function signature inval - */ - _mesa_glsl_error(& loc, state, - "`%s' cannot be marked invariant, fragment shader " - "inputs only\n", var->name); - } + if (!is_varying_var(var, state->stage)) { + _mesa_glsl_error(&loc, state, + "`%s' cannot be marked invariant; interfaces between " + "shader stages only", var->name); + } } if (state->current_function != NULL) { - const char *mode = NULL; - const char *extra = ""; - - /* There is no need to check for 'inout' here because the parser will - * only allow that in function parameter lists. - */ - if (this->type->qualifier.flags.q.attribute) { - mode = "attribute"; - } else if (this->type->qualifier.flags.q.uniform) { - mode = "uniform"; - } else if (this->type->qualifier.flags.q.varying) { - mode = "varying"; - } else if (this->type->qualifier.flags.q.in) { - mode = "in"; - extra = " or in function parameter list"; - } else if (this->type->qualifier.flags.q.out) { - mode = "out"; - extra = " or in function parameter list"; - } - - if (mode) { - _mesa_glsl_error(& loc, state, - "%s variable `%s' must be declared at " - "global scope%s", - mode, var->name, extra); - } - } else if (var->mode == ir_var_shader_in) { - var->read_only = true; - - if (state->target == vertex_shader) { - bool error_emitted = false; - - /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec: - * - * "Vertex shader inputs can only be float, floating-point - * vectors, matrices, signed and unsigned integers and integer - * vectors. Vertex shader inputs can also form arrays of these - * types, but not structures." - * - * From page 31 (page 27 of the PDF) of the GLSL 1.30 spec: - * - * "Vertex shader inputs can only be float, floating-point - * vectors, matrices, signed and unsigned integers and integer - * vectors. They cannot be arrays or structures." - * - * From page 23 (page 29 of the PDF) of the GLSL 1.20 spec: - * - * "The attribute qualifier can be used only with float, - * floating-point vectors, and matrices. Attribute variables - * cannot be declared as arrays or structures." + const char *mode = NULL; + const char *extra = ""; + + /* There is no need to check for 'inout' here because the parser will + * only allow that in function parameter lists. + */ + if (this->type->qualifier.flags.q.attribute) { + mode = "attribute"; + } else if (this->type->qualifier.flags.q.uniform) { + mode = "uniform"; + } else if (this->type->qualifier.flags.q.varying) { + mode = "varying"; + } else if (this->type->qualifier.flags.q.in) { + mode = "in"; + extra = " or in function parameter list"; + } else if (this->type->qualifier.flags.q.out) { + mode = "out"; + extra = " or in function parameter list"; + } + + if (mode) { + _mesa_glsl_error(& loc, state, + "%s variable `%s' must be declared at " + "global scope%s", + mode, var->name, extra); + } + } else if (var->data.mode == ir_var_shader_in) { + var->data.read_only = true; + + if (state->stage == MESA_SHADER_VERTEX) { + bool error_emitted = false; + + /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec: + * + * "Vertex shader inputs can only be float, floating-point + * vectors, matrices, signed and unsigned integers and integer + * vectors. Vertex shader inputs can also form arrays of these + * types, but not structures." + * + * From page 31 (page 27 of the PDF) of the GLSL 1.30 spec: + * + * "Vertex shader inputs can only be float, floating-point + * vectors, matrices, signed and unsigned integers and integer + * vectors. They cannot be arrays or structures." + * + * From page 23 (page 29 of the PDF) of the GLSL 1.20 spec: + * + * "The attribute qualifier can be used only with float, + * floating-point vectors, and matrices. Attribute variables + * cannot be declared as arrays or structures." * * From page 33 (page 39 of the PDF) of the GLSL ES 3.00 spec: * @@ -2826,34 +3389,50 @@ ast_declarator_list::hir(exec_list *instructions, * vectors, matrices, signed and unsigned integers and integer * vectors. Vertex shader inputs cannot be arrays or * structures." - */ - const glsl_type *check_type = var->type->is_array() - ? var->type->fields.array : var->type; - - switch (check_type->base_type) { - case GLSL_TYPE_FLOAT: - break; - case GLSL_TYPE_UINT: - case GLSL_TYPE_INT: - if (state->is_version(120, 300)) - break; - /* FALLTHROUGH */ - default: - _mesa_glsl_error(& loc, state, - "vertex shader input / attribute cannot have " - "type %s`%s'", - var->type->is_array() ? "array of " : "", - check_type->name); - error_emitted = true; - } - - if (!error_emitted && var->type->is_array() && + */ + const glsl_type *check_type = var->type; + while (check_type->is_array()) + check_type = check_type->element_type(); + + switch (check_type->base_type) { + case GLSL_TYPE_FLOAT: + break; + case GLSL_TYPE_UINT: + case GLSL_TYPE_INT: + if (state->is_version(120, 300)) + break; + /* FALLTHROUGH */ + default: + _mesa_glsl_error(& loc, state, + "vertex shader input / attribute cannot have " + "type %s`%s'", + var->type->is_array() ? "array of " : "", + check_type->name); + error_emitted = true; + } + + if (!error_emitted && var->type->is_array() && !state->check_version(150, 0, &loc, "vertex shader input / attribute " "cannot have array type")) { - error_emitted = true; - } - } + error_emitted = true; + } + } else if (state->stage == MESA_SHADER_GEOMETRY) { + /* From section 4.3.4 (Inputs) of the GLSL 1.50 spec: + * + * Geometry shader input variables get the per-vertex values + * written out by vertex shader output variables of the same + * names. Since a geometry shader operates on a set of + * vertices, each input varying variable (or input block, see + * interface blocks below) needs to be declared as an array. + */ + if (!var->type->is_array()) { + _mesa_glsl_error(&loc, state, + "geometry shader inputs must be arrays"); + } + + handle_geometry_shader_input_decl(state, loc, var); + } } /* Integer fragment inputs must be qualified with 'flat'. In GLSL ES, @@ -2887,13 +3466,13 @@ ast_declarator_list::hir(exec_list *instructions, */ if (state->is_version(130, 300) && var->type->contains_integer() && - var->interpolation != INTERP_QUALIFIER_FLAT && - ((state->target == fragment_shader && var->mode == ir_var_shader_in) - || (state->target == vertex_shader && var->mode == ir_var_shader_out + var->data.interpolation != INTERP_QUALIFIER_FLAT && + ((state->stage == MESA_SHADER_FRAGMENT && var->data.mode == ir_var_shader_in) + || (state->stage == MESA_SHADER_VERTEX && var->data.mode == ir_var_shader_out && state->es_shader))) { - const char *var_type = (state->target == vertex_shader) ? + const char *var_type = (state->stage == MESA_SHADER_VERTEX) ? "vertex output" : "fragment input"; - _mesa_glsl_error(&loc, state, "If a %s is (or contains) " + _mesa_glsl_error(&loc, state, "if a %s is (or contains) " "an integer, then it must be qualified with 'flat'", var_type); } @@ -2947,15 +3526,15 @@ ast_declarator_list::hir(exec_list *instructions, const char *i = this->type->qualifier.interpolation_string(); assert(i != NULL); - switch (state->target) { - case vertex_shader: + switch (state->stage) { + case MESA_SHADER_VERTEX: if (this->type->qualifier.flags.q.in) { _mesa_glsl_error(&loc, state, "qualifier '%s' cannot be applied to vertex " "shader inputs", i); } break; - case fragment_shader: + case MESA_SHADER_FRAGMENT: if (this->type->qualifier.flags.q.out) { _mesa_glsl_error(&loc, state, "qualifier '%s' cannot be applied to fragment " @@ -2963,7 +3542,7 @@ ast_declarator_list::hir(exec_list *instructions, } break; default: - assert(0); + break; } } @@ -2978,12 +3557,20 @@ ast_declarator_list::hir(exec_list *instructions, if (state->is_version(130, 300) && this->type->qualifier.flags.q.centroid && this->type->qualifier.flags.q.in - && state->target == vertex_shader) { + && state->stage == MESA_SHADER_VERTEX) { _mesa_glsl_error(&loc, state, "'centroid in' cannot be used in a vertex shader"); } + if (state->stage == MESA_SHADER_VERTEX + && this->type->qualifier.flags.q.sample + && this->type->qualifier.flags.q.in) { + + _mesa_glsl_error(&loc, state, + "'sample in' cannot be used in a vertex shader"); + } + /* Section 4.3.6 of the GLSL 1.30 specification states: * "It is an error to use centroid out in a fragment shader." * @@ -2991,7 +3578,7 @@ ast_declarator_list::hir(exec_list *instructions, * "It is an error to use auxiliary storage qualifiers or interpolation * qualifiers on an output in a fragment shader." */ - if (state->target == fragment_shader && + if (state->stage == MESA_SHADER_FRAGMENT && this->type->qualifier.flags.q.out && this->type->qualifier.has_auxiliary_storage()) { _mesa_glsl_error(&loc, state, @@ -3047,15 +3634,15 @@ ast_declarator_list::hir(exec_list *instructions, ", integer and sampler types"); } - /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + /* From section 4.1.7 of the GLSL 4.40 spec: * - * "[Sampler types] can only be declared as function - * parameters or uniform variables (see Section 4.3.5 - * "Uniform")". + * "[Opaque types] can only be declared as function + * parameters or uniform-qualified variables." */ - if (var_type->contains_sampler() && + if (var_type->contains_opaque() && !this->type->qualifier.flags.q.uniform) { - _mesa_glsl_error(&loc, state, "samplers must be declared uniform"); + _mesa_glsl_error(&loc, state, + "opaque variables must be declared uniform"); } /* Process the initializer and add its instructions to a temporary @@ -3065,12 +3652,27 @@ ast_declarator_list::hir(exec_list *instructions, * instruction stream. */ exec_list initializer_instructions; - ir_variable *earlier = get_variable_being_redeclared(var, decl, state); + + /* Examine var name here since var may get deleted in the next call */ + bool var_is_gl_id = (strncmp(var->name, "gl_", 3) == 0); + + ir_variable *earlier = + get_variable_being_redeclared(var, decl->get_location(), state, + false /* allow_all_redeclarations */); + if (earlier != NULL) { + if (var_is_gl_id && + earlier->data.how_declared == ir_var_declared_in_block) { + _mesa_glsl_error(&loc, state, + "`%s' has already been redeclared using " + "gl_PerVertex", var->name); + } + earlier->data.how_declared = ir_var_declared_normally; + } if (decl->initializer != NULL) { - result = process_initializer((earlier == NULL) ? var : earlier, - decl, this->type, - &initializer_instructions, state); + result = process_initializer((earlier == NULL) ? var : earlier, + decl, this->type, + &initializer_instructions, state); } /* From page 23 (page 29 of the PDF) of the GLSL 1.10 spec: @@ -3080,16 +3682,16 @@ ast_declarator_list::hir(exec_list *instructions, * declared." */ if (this->type->qualifier.flags.q.constant && decl->initializer == NULL) { - _mesa_glsl_error(& loc, state, - "const declaration of `%s' must be initialized", - decl->identifier); + _mesa_glsl_error(& loc, state, + "const declaration of `%s' must be initialized", + decl->identifier); } if (state->es_shader) { - const glsl_type *const t = (earlier == NULL) - ? var->type : earlier->type; + const glsl_type *const t = (earlier == NULL) + ? var->type : earlier->type; - if (t->is_array() && t->length == 0) + if (t->is_unsized_array()) /* Section 10.17 of the GLSL ES 1.00 specification states that * unsized array declarations have been removed from the language. * Arrays that are sized using an initializer are still explicitly @@ -3117,55 +3719,34 @@ ast_declarator_list::hir(exec_list *instructions, * created for the declaration should be added to the IR stream. */ if (earlier == NULL) { - /* From page 15 (page 21 of the PDF) of the GLSL 1.10 spec, - * - * "Identifiers starting with "gl_" are reserved for use by - * OpenGL, and may not be declared in a shader as either a - * variable or a function." - */ - if (strncmp(decl->identifier, "gl_", 3) == 0) - _mesa_glsl_error(& loc, state, - "identifier `%s' uses reserved `gl_' prefix", - decl->identifier); - else if (strstr(decl->identifier, "__")) { - /* From page 14 (page 20 of the PDF) of the GLSL 1.10 - * spec: - * - * "In addition, all identifiers containing two - * consecutive underscores (__) are reserved as - * possible future keywords." - */ - _mesa_glsl_error(& loc, state, - "identifier `%s' uses reserved `__' string", - decl->identifier); - } - - /* Add the variable to the symbol table. Note that the initializer's - * IR was already processed earlier (though it hasn't been emitted - * yet), without the variable in scope. - * - * This differs from most C-like languages, but it follows the GLSL - * specification. From page 28 (page 34 of the PDF) of the GLSL 1.50 - * spec: - * - * "Within a declaration, the scope of a name starts immediately - * after the initializer if present or immediately after the name - * being declared if not." - */ - if (!state->symbols->add_variable(var)) { - YYLTYPE loc = this->get_location(); - _mesa_glsl_error(&loc, state, "name `%s' already taken in the " - "current scope", decl->identifier); - continue; - } - - /* Push the variable declaration to the top. It means that all the - * variable declarations will appear in a funny last-to-first order, - * but otherwise we run into trouble if a function is prototyped, a - * global var is decled, then the function is defined with usage of - * the global var. See glslparsertest's CorrectModule.frag. - */ - instructions->push_head(var); + validate_identifier(decl->identifier, loc, state); + + /* Add the variable to the symbol table. Note that the initializer's + * IR was already processed earlier (though it hasn't been emitted + * yet), without the variable in scope. + * + * This differs from most C-like languages, but it follows the GLSL + * specification. From page 28 (page 34 of the PDF) of the GLSL 1.50 + * spec: + * + * "Within a declaration, the scope of a name starts immediately + * after the initializer if present or immediately after the name + * being declared if not." + */ + if (!state->symbols->add_variable(var)) { + YYLTYPE loc = this->get_location(); + _mesa_glsl_error(&loc, state, "name `%s' already taken in the " + "current scope", decl->identifier); + continue; + } + + /* Push the variable declaration to the top. It means that all the + * variable declarations will appear in a funny last-to-first order, + * but otherwise we run into trouble if a function is prototyped, a + * global var is decled, then the function is defined with usage of + * the global var. See glslparsertest's CorrectModule.frag. + */ + instructions->push_head(var); } instructions->append_list(&initializer_instructions); @@ -3187,7 +3768,7 @@ ast_declarator_list::hir(exec_list *instructions, ir_rvalue * ast_parameter_declarator::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { void *ctx = state; const struct glsl_type *type; @@ -3198,13 +3779,13 @@ ast_parameter_declarator::hir(exec_list *instructions, if (type == NULL) { if (name != NULL) { - _mesa_glsl_error(& loc, state, - "invalid type `%s' in declaration of `%s'", - name, this->identifier); + _mesa_glsl_error(& loc, state, + "invalid type `%s' in declaration of `%s'", + name, this->identifier); } else { - _mesa_glsl_error(& loc, state, - "invalid type in declaration of `%s'", - this->identifier); + _mesa_glsl_error(& loc, state, + "invalid type in declaration of `%s'", + this->identifier); } type = glsl_type::error_type; @@ -3224,8 +3805,8 @@ ast_parameter_declarator::hir(exec_list *instructions, */ if (type->is_void()) { if (this->identifier != NULL) - _mesa_glsl_error(& loc, state, - "named parameter cannot have type `void'"); + _mesa_glsl_error(& loc, state, + "named parameter cannot have type `void'"); is_void = true; return NULL; @@ -3239,13 +3820,11 @@ ast_parameter_declarator::hir(exec_list *instructions, /* This only handles "vec4 foo[..]". The earlier specifier->glsl_type(...) * call already handled the "vec4[..] foo" case. */ - if (this->is_array) { - type = process_array_type(&loc, type, this->array_size, state); - } + type = process_array_type(&loc, type, this->array_specifier, state); - if (!type->is_error() && type->array_size() == 0) { + if (!type->is_error() && type->is_unsized_array()) { _mesa_glsl_error(&loc, state, "arrays passed as parameters must have " - "a declared size."); + "a declared size"); type = glsl_type::error_type; } @@ -3257,17 +3836,18 @@ ast_parameter_declarator::hir(exec_list *instructions, * for function parameters the default mode is 'in'. */ apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc, - true); + true); - /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + /* From section 4.1.7 of the GLSL 4.40 spec: * - * "Samplers cannot be treated as l-values; hence cannot be used - * as out or inout function parameters, nor can they be assigned - * into." + * "Opaque variables cannot be treated as l-values; hence cannot + * be used as out or inout function parameters, nor can they be + * assigned into." */ - if ((var->mode == ir_var_function_inout || var->mode == ir_var_function_out) - && type->contains_sampler()) { - _mesa_glsl_error(&loc, state, "out and inout parameters cannot contain samplers"); + if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out) + && type->contains_opaque()) { + _mesa_glsl_error(&loc, state, "out and inout parameters cannot " + "contain opaque variables"); type = glsl_type::error_type; } @@ -3285,10 +3865,10 @@ ast_parameter_declarator::hir(exec_list *instructions, * So for GLSL 1.10, passing an array as an out or inout parameter is not * allowed. This restriction is removed in GLSL 1.20, and in GLSL ES. */ - if ((var->mode == ir_var_function_inout || var->mode == ir_var_function_out) + if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out) && type->is_array() && !state->check_version(120, 100, &loc, - "Arrays cannot be out or inout parameters")) { + "arrays cannot be out or inout parameters")) { type = glsl_type::error_type; } @@ -3302,9 +3882,9 @@ ast_parameter_declarator::hir(exec_list *instructions, void ast_parameter_declarator::parameters_to_hir(exec_list *ast_parameters, - bool formal, - exec_list *ir_parameters, - _mesa_glsl_parse_state *state) + bool formal, + exec_list *ir_parameters, + _mesa_glsl_parse_state *state) { ast_parameter_declarator *void_param = NULL; unsigned count = 0; @@ -3314,7 +3894,7 @@ ast_parameter_declarator::parameters_to_hir(exec_list *ast_parameters, param->hir(ir_parameters, state); if (param->is_void) - void_param = param; + void_param = param; count++; } @@ -3323,7 +3903,7 @@ ast_parameter_declarator::parameters_to_hir(exec_list *ast_parameters, YYLTYPE loc = void_param->get_location(); _mesa_glsl_error(& loc, state, - "`void' parameter must be only parameter"); + "`void' parameter must be only parameter"); } } @@ -3344,7 +3924,7 @@ emit_function(_mesa_glsl_parse_state *state, ir_function *f) ir_rvalue * ast_function::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { void *ctx = state; ir_function *f = NULL; @@ -3379,25 +3959,15 @@ ast_function::hir(exec_list *instructions, "function body", name); } - /* From page 15 (page 21 of the PDF) of the GLSL 1.10 spec, - * - * "Identifiers starting with "gl_" are reserved for use by - * OpenGL, and may not be declared in a shader as either a - * variable or a function." - */ - if (strncmp(name, "gl_", 3) == 0) { - YYLTYPE loc = this->get_location(); - _mesa_glsl_error(&loc, state, - "identifier `%s' uses reserved `gl_' prefix", name); - } + validate_identifier(name, this->get_location(), state); /* Convert the list of function parameters to HIR now so that they can be * used below to compare this function's signature with previously seen * signatures for functions with the same name. */ ast_parameter_declarator::parameters_to_hir(& this->parameters, - is_definition, - & hir_parameters, state); + is_definition, + & hir_parameters, state); const char *return_type_name; const glsl_type *return_type = @@ -3406,8 +3976,8 @@ ast_function::hir(exec_list *instructions, if (!return_type) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(&loc, state, - "function `%s' has undeclared return type `%s'", - name, return_type_name); + "function `%s' has undeclared return type `%s'", + name, return_type_name); return_type = glsl_type::error_type; } @@ -3417,7 +3987,7 @@ ast_function::hir(exec_list *instructions, if (this->return_type->has_qualifiers()) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(& loc, state, - "function `%s' return type has qualifiers", name); + "function `%s' return type has qualifiers", name); } /* Section 6.1 (Function Definitions) of the GLSL 1.20 spec says: @@ -3425,22 +3995,22 @@ ast_function::hir(exec_list *instructions, * "Arrays are allowed as arguments and as the return type. In both * cases, the array must be explicitly sized." */ - if (return_type->is_array() && return_type->length == 0) { + if (return_type->is_unsized_array()) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(& loc, state, - "function `%s' return type array must be explicitly " - "sized", name); + "function `%s' return type array must be explicitly " + "sized", name); } - /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + /* From section 4.1.7 of the GLSL 4.40 spec: * - * "[Sampler types] can only be declared as function parameters - * or uniform variables (see Section 4.3.5 "Uniform")". + * "[Opaque types] can only be declared as function parameters + * or uniform-qualified variables." */ - if (return_type->contains_sampler()) { + if (return_type->contains_opaque()) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(&loc, state, - "function `%s' return type can't contain a sampler", + "function `%s' return type can't contain an opaque type", name); } @@ -3450,22 +4020,22 @@ ast_function::hir(exec_list *instructions, */ f = state->symbols->get_function(name); if (f != NULL && (state->es_shader || f->has_user_signature())) { - sig = f->exact_matching_signature(&hir_parameters); + sig = f->exact_matching_signature(state, &hir_parameters); if (sig != NULL) { - const char *badvar = sig->qualifiers_match(&hir_parameters); - if (badvar != NULL) { - YYLTYPE loc = this->get_location(); + const char *badvar = sig->qualifiers_match(&hir_parameters); + if (badvar != NULL) { + YYLTYPE loc = this->get_location(); - _mesa_glsl_error(&loc, state, "function `%s' parameter `%s' " - "qualifiers don't match prototype", name, badvar); - } + _mesa_glsl_error(&loc, state, "function `%s' parameter `%s' " + "qualifiers don't match prototype", name, badvar); + } - if (sig->return_type != return_type) { - YYLTYPE loc = this->get_location(); + if (sig->return_type != return_type) { + YYLTYPE loc = this->get_location(); - _mesa_glsl_error(&loc, state, "function `%s' return type doesn't " - "match prototype", name); - } + _mesa_glsl_error(&loc, state, "function `%s' return type doesn't " + "match prototype", name); + } if (sig->is_defined) { if (is_definition) { @@ -3478,17 +4048,17 @@ ast_function::hir(exec_list *instructions, */ return NULL; } - } + } } } else { f = new(ctx) ir_function(name); if (!state->symbols->add_function(f)) { - /* This function name shadows a non-function use of the same name. */ - YYLTYPE loc = this->get_location(); + /* This function name shadows a non-function use of the same name. */ + YYLTYPE loc = this->get_location(); - _mesa_glsl_error(&loc, state, "function name `%s' conflicts with " - "non-function", name); - return NULL; + _mesa_glsl_error(&loc, state, "function name `%s' conflicts with " + "non-function", name); + return NULL; } emit_function(state, f); @@ -3497,15 +4067,15 @@ ast_function::hir(exec_list *instructions, /* Verify the return type of main() */ if (strcmp(name, "main") == 0) { if (! return_type->is_void()) { - YYLTYPE loc = this->get_location(); + YYLTYPE loc = this->get_location(); - _mesa_glsl_error(& loc, state, "main() must return void"); + _mesa_glsl_error(& loc, state, "main() must return void"); } if (!hir_parameters.is_empty()) { - YYLTYPE loc = this->get_location(); + YYLTYPE loc = this->get_location(); - _mesa_glsl_error(& loc, state, "main() must not take any parameters"); + _mesa_glsl_error(& loc, state, "main() must not take any parameters"); } } @@ -3527,7 +4097,7 @@ ast_function::hir(exec_list *instructions, ir_rvalue * ast_function_definition::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { prototype->is_definition = true; prototype->hir(instructions, state); @@ -3544,8 +4114,8 @@ ast_function_definition::hir(exec_list *instructions, * Add these to the symbol table. */ state->symbols->push_scope(); - foreach_iter(exec_list_iterator, iter, signature->parameters) { - ir_variable *const var = ((ir_instruction *) iter.get())->as_variable(); + foreach_list(n, &signature->parameters) { + ir_variable *const var = ((ir_instruction *) n)->as_variable(); assert(var != NULL); @@ -3553,11 +4123,11 @@ ast_function_definition::hir(exec_list *instructions, * the same name. */ if (state->symbols->name_declared_this_scope(var->name)) { - YYLTYPE loc = this->get_location(); + YYLTYPE loc = this->get_location(); - _mesa_glsl_error(& loc, state, "parameter `%s' redeclared", var->name); + _mesa_glsl_error(& loc, state, "parameter `%s' redeclared", var->name); } else { - state->symbols->add_variable(var); + state->symbols->add_variable(var); } } @@ -3573,9 +4143,9 @@ ast_function_definition::hir(exec_list *instructions, if (!signature->return_type->is_void() && !state->found_return) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(& loc, state, "function `%s' has non-void return type " - "%s, but no return statement", - signature->function_name(), - signature->return_type->name); + "%s, but no return statement", + signature->function_name(), + signature->return_type->name); } /* Function definitions do not have r-values. @@ -3586,7 +4156,7 @@ ast_function_definition::hir(exec_list *instructions, ir_rvalue * ast_jump_statement::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { void *ctx = state; @@ -3596,29 +4166,29 @@ ast_jump_statement::hir(exec_list *instructions, assert(state->current_function); if (opt_return_value) { - ir_rvalue *ret = opt_return_value->hir(instructions, state); - - /* The value of the return type can be NULL if the shader says - * 'return foo();' and foo() is a function that returns void. - * - * NOTE: The GLSL spec doesn't say that this is an error. The type - * of the return value is void. If the return type of the function is - * also void, then this should compile without error. Seriously. - */ - const glsl_type *const ret_type = - (ret == NULL) ? glsl_type::void_type : ret->type; + ir_rvalue *ret = opt_return_value->hir(instructions, state); + + /* The value of the return type can be NULL if the shader says + * 'return foo();' and foo() is a function that returns void. + * + * NOTE: The GLSL spec doesn't say that this is an error. The type + * of the return value is void. If the return type of the function is + * also void, then this should compile without error. Seriously. + */ + const glsl_type *const ret_type = + (ret == NULL) ? glsl_type::void_type : ret->type; /* Implicit conversions are not allowed for return values prior to * ARB_shading_language_420pack. */ if (state->current_function->return_type != ret_type) { - YYLTYPE loc = this->get_location(); + YYLTYPE loc = this->get_location(); if (state->ARB_shading_language_420pack_enable) { if (!apply_implicit_conversion(state->current_function->return_type, ret, state)) { _mesa_glsl_error(& loc, state, - "Could not implicitly convert return value " + "could not implicitly convert return value " "to %s, in function `%s'", state->current_function->return_type->name, state->current_function->function_name()); @@ -3649,18 +4219,18 @@ ast_jump_statement::hir(exec_list *instructions, "return argument"); } - inst = new(ctx) ir_return(ret); + inst = new(ctx) ir_return(ret); } else { - if (state->current_function->return_type->base_type != - GLSL_TYPE_VOID) { - YYLTYPE loc = this->get_location(); - - _mesa_glsl_error(& loc, state, - "`return' with no value, in function %s returning " - "non-void", - state->current_function->function_name()); - } - inst = new(ctx) ir_return; + if (state->current_function->return_type->base_type != + GLSL_TYPE_VOID) { + YYLTYPE loc = this->get_location(); + + _mesa_glsl_error(& loc, state, + "`return' with no value, in function %s returning " + "non-void", + state->current_function->function_name()); + } + inst = new(ctx) ir_return; } state->found_return = true; @@ -3669,11 +4239,11 @@ ast_jump_statement::hir(exec_list *instructions, } case ast_discard: - if (state->target != fragment_shader) { - YYLTYPE loc = this->get_location(); + if (state->stage != MESA_SHADER_FRAGMENT) { + YYLTYPE loc = this->get_location(); - _mesa_glsl_error(& loc, state, - "`discard' may only appear in a fragment shader"); + _mesa_glsl_error(& loc, state, + "`discard' may only appear in a fragment shader"); } instructions->push_tail(new(ctx) ir_discard); break; @@ -3681,51 +4251,55 @@ ast_jump_statement::hir(exec_list *instructions, case ast_break: case ast_continue: if (mode == ast_continue && - state->loop_nesting_ast == NULL) { - YYLTYPE loc = this->get_location(); + state->loop_nesting_ast == NULL) { + YYLTYPE loc = this->get_location(); - _mesa_glsl_error(& loc, state, - "continue may only appear in a loop"); + _mesa_glsl_error(& loc, state, "continue may only appear in a loop"); } else if (mode == ast_break && - state->loop_nesting_ast == NULL && - state->switch_state.switch_nesting_ast == NULL) { - YYLTYPE loc = this->get_location(); + state->loop_nesting_ast == NULL && + state->switch_state.switch_nesting_ast == NULL) { + YYLTYPE loc = this->get_location(); - _mesa_glsl_error(& loc, state, - "break may only appear in a loop or a switch"); + _mesa_glsl_error(& loc, state, + "break may only appear in a loop or a switch"); } else { - /* For a loop, inline the for loop expression again, - * since we don't know where near the end of - * the loop body the normal copy of it - * is going to be placed. - */ - if (state->loop_nesting_ast != NULL && - mode == ast_continue && - state->loop_nesting_ast->rest_expression) { - state->loop_nesting_ast->rest_expression->hir(instructions, - state); - } - - if (state->switch_state.is_switch_innermost && - mode == ast_break) { - /* Force break out of switch by setting is_break switch state. - */ - ir_variable *const is_break_var = state->switch_state.is_break_var; - ir_dereference_variable *const deref_is_break_var = - new(ctx) ir_dereference_variable(is_break_var); - ir_constant *const true_val = new(ctx) ir_constant(true); - ir_assignment *const set_break_var = - new(ctx) ir_assignment(deref_is_break_var, true_val); + /* For a loop, inline the for loop expression again, since we don't + * know where near the end of the loop body the normal copy of it is + * going to be placed. Same goes for the condition for a do-while + * loop. + */ + if (state->loop_nesting_ast != NULL && + mode == ast_continue) { + if (state->loop_nesting_ast->rest_expression) { + state->loop_nesting_ast->rest_expression->hir(instructions, + state); + } + if (state->loop_nesting_ast->mode == + ast_iteration_statement::ast_do_while) { + state->loop_nesting_ast->condition_to_hir(instructions, state); + } + } + + if (state->switch_state.is_switch_innermost && + mode == ast_break) { + /* Force break out of switch by setting is_break switch state. + */ + ir_variable *const is_break_var = state->switch_state.is_break_var; + ir_dereference_variable *const deref_is_break_var = + new(ctx) ir_dereference_variable(is_break_var); + ir_constant *const true_val = new(ctx) ir_constant(true); + ir_assignment *const set_break_var = + new(ctx) ir_assignment(deref_is_break_var, true_val); - instructions->push_tail(set_break_var); - } - else { - ir_loop_jump *const jump = - new(ctx) ir_loop_jump((mode == ast_break) - ? ir_loop_jump::jump_break - : ir_loop_jump::jump_continue); - instructions->push_tail(jump); - } + instructions->push_tail(set_break_var); + } + else { + ir_loop_jump *const jump = + new(ctx) ir_loop_jump((mode == ast_break) + ? ir_loop_jump::jump_break + : ir_loop_jump::jump_continue); + instructions->push_tail(jump); + } } break; @@ -3739,7 +4313,7 @@ ast_jump_statement::hir(exec_list *instructions, ir_rvalue * ast_selection_statement::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { void *ctx = state; @@ -3758,7 +4332,7 @@ ast_selection_statement::hir(exec_list *instructions, YYLTYPE loc = this->condition->get_location(); _mesa_glsl_error(& loc, state, "if-statement condition must be scalar " - "boolean"); + "boolean"); } ir_if *const stmt = new(ctx) ir_if(condition); @@ -3785,7 +4359,7 @@ ast_selection_statement::hir(exec_list *instructions, ir_rvalue * ast_switch_statement::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { void *ctx = state; @@ -3802,9 +4376,9 @@ ast_switch_statement::hir(exec_list *instructions, YYLTYPE loc = this->test_expression->get_location(); _mesa_glsl_error(& loc, - state, - "switch-statement expression must be scalar " - "integer"); + state, + "switch-statement expression must be scalar " + "integer"); } /* Track the switch-statement nesting in a stack-like manner. @@ -3822,27 +4396,28 @@ ast_switch_statement::hir(exec_list *instructions, ir_rvalue *const is_fallthru_val = new (ctx) ir_constant(false); state->switch_state.is_fallthru_var = new(ctx) ir_variable(glsl_type::bool_type, - "switch_is_fallthru_tmp", - ir_var_temporary); + "switch_is_fallthru_tmp", + ir_var_temporary); instructions->push_tail(state->switch_state.is_fallthru_var); ir_dereference_variable *deref_is_fallthru_var = new(ctx) ir_dereference_variable(state->switch_state.is_fallthru_var); instructions->push_tail(new(ctx) ir_assignment(deref_is_fallthru_var, - is_fallthru_val)); + is_fallthru_val)); /* Initalize is_break state to false. */ ir_rvalue *const is_break_val = new (ctx) ir_constant(false); - state->switch_state.is_break_var = new(ctx) ir_variable(glsl_type::bool_type, - "switch_is_break_tmp", - ir_var_temporary); + state->switch_state.is_break_var = + new(ctx) ir_variable(glsl_type::bool_type, + "switch_is_break_tmp", + ir_var_temporary); instructions->push_tail(state->switch_state.is_break_var); ir_dereference_variable *deref_is_break_var = new(ctx) ir_dereference_variable(state->switch_state.is_break_var); instructions->push_tail(new(ctx) ir_assignment(deref_is_break_var, - is_break_val)); + is_break_val)); /* Cache test expression. */ @@ -3863,7 +4438,7 @@ ast_switch_statement::hir(exec_list *instructions, void ast_switch_statement::test_to_hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { void *ctx = state; @@ -3873,8 +4448,8 @@ ast_switch_statement::test_to_hir(exec_list *instructions, state); state->switch_state.test_var = new(ctx) ir_variable(test_val->type, - "switch_test_tmp", - ir_var_temporary); + "switch_test_tmp", + ir_var_temporary); ir_dereference_variable *deref_test_var = new(ctx) ir_dereference_variable(state->switch_state.test_var); @@ -3885,7 +4460,7 @@ ast_switch_statement::test_to_hir(exec_list *instructions, ir_rvalue * ast_switch_body::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { if (stmts != NULL) stmts->hir(instructions, state); @@ -3896,7 +4471,7 @@ ast_switch_body::hir(exec_list *instructions, ir_rvalue * ast_case_statement_list::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { foreach_list_typed (ast_case_statement, case_stmt, link, & this->cases) case_stmt->hir(instructions, state); @@ -3907,7 +4482,7 @@ ast_case_statement_list::hir(exec_list *instructions, ir_rvalue * ast_case_statement::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { labels->hir(instructions, state); @@ -3919,8 +4494,8 @@ ast_case_statement::hir(exec_list *instructions, new(state) ir_dereference_variable(state->switch_state.is_break_var); ir_assignment *const reset_fallthru_on_break = new(state) ir_assignment(deref_is_fallthru_var, - false_val, - deref_is_break_var); + false_val, + deref_is_break_var); instructions->push_tail(reset_fallthru_on_break); /* Guard case statements depending on fallthru state. */ @@ -3940,7 +4515,7 @@ ast_case_statement::hir(exec_list *instructions, ir_rvalue * ast_case_label_list::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { foreach_list_typed (ast_case_label, label, link, & this->labels) label->hir(instructions, state); @@ -3951,7 +4526,7 @@ ast_case_label_list::hir(exec_list *instructions, ir_rvalue * ast_case_label::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { void *ctx = state; @@ -3969,62 +4544,57 @@ ast_case_label::hir(exec_list *instructions, ir_constant *label_const = label_rval->constant_expression_value(); if (!label_const) { - YYLTYPE loc = this->test_value->get_location(); + YYLTYPE loc = this->test_value->get_location(); - _mesa_glsl_error(& loc, state, - "switch statement case label must be a " - "constant expression"); + _mesa_glsl_error(& loc, state, + "switch statement case label must be a " + "constant expression"); - /* Stuff a dummy value in to allow processing to continue. */ - label_const = new(ctx) ir_constant(0); + /* Stuff a dummy value in to allow processing to continue. */ + label_const = new(ctx) ir_constant(0); } else { - ast_expression *previous_label = (ast_expression *) - hash_table_find(state->switch_state.labels_ht, - (void *)(uintptr_t)label_const->value.u[0]); - - if (previous_label) { - YYLTYPE loc = this->test_value->get_location(); - _mesa_glsl_error(& loc, state, - "duplicate case value"); - - loc = previous_label->get_location(); - _mesa_glsl_error(& loc, state, - "this is the previous case label"); - } else { - hash_table_insert(state->switch_state.labels_ht, - this->test_value, - (void *)(uintptr_t)label_const->value.u[0]); - } + ast_expression *previous_label = (ast_expression *) + hash_table_find(state->switch_state.labels_ht, + (void *)(uintptr_t)label_const->value.u[0]); + + if (previous_label) { + YYLTYPE loc = this->test_value->get_location(); + _mesa_glsl_error(& loc, state, "duplicate case value"); + + loc = previous_label->get_location(); + _mesa_glsl_error(& loc, state, "this is the previous case label"); + } else { + hash_table_insert(state->switch_state.labels_ht, + this->test_value, + (void *)(uintptr_t)label_const->value.u[0]); + } } ir_dereference_variable *deref_test_var = - new(ctx) ir_dereference_variable(state->switch_state.test_var); + new(ctx) ir_dereference_variable(state->switch_state.test_var); ir_rvalue *const test_cond = new(ctx) ir_expression(ir_binop_all_equal, - label_const, - deref_test_var); + label_const, + deref_test_var); ir_assignment *set_fallthru_on_test = - new(ctx) ir_assignment(deref_fallthru_var, - true_val, - test_cond); + new(ctx) ir_assignment(deref_fallthru_var, true_val, test_cond); instructions->push_tail(set_fallthru_on_test); } else { /* default case */ if (state->switch_state.previous_default) { - YYLTYPE loc = this->get_location(); - _mesa_glsl_error(& loc, state, - "multiple default labels in one switch"); + YYLTYPE loc = this->get_location(); + _mesa_glsl_error(& loc, state, + "multiple default labels in one switch"); - loc = state->switch_state.previous_default->get_location(); - _mesa_glsl_error(& loc, state, - "this is the first default label"); + loc = state->switch_state.previous_default->get_location(); + _mesa_glsl_error(& loc, state, "this is the first default label"); } state->switch_state.previous_default = this; /* Set falltrhu state. */ ir_assignment *set_fallthru = - new(ctx) ir_assignment(deref_fallthru_var, true_val); + new(ctx) ir_assignment(deref_fallthru_var, true_val); instructions->push_tail(set_fallthru); } @@ -4034,35 +4604,35 @@ ast_case_label::hir(exec_list *instructions, } void -ast_iteration_statement::condition_to_hir(ir_loop *stmt, - struct _mesa_glsl_parse_state *state) +ast_iteration_statement::condition_to_hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) { void *ctx = state; if (condition != NULL) { ir_rvalue *const cond = - condition->hir(& stmt->body_instructions, state); + condition->hir(instructions, state); if ((cond == NULL) - || !cond->type->is_boolean() || !cond->type->is_scalar()) { - YYLTYPE loc = condition->get_location(); + || !cond->type->is_boolean() || !cond->type->is_scalar()) { + YYLTYPE loc = condition->get_location(); - _mesa_glsl_error(& loc, state, - "loop condition must be scalar boolean"); + _mesa_glsl_error(& loc, state, + "loop condition must be scalar boolean"); } else { - /* As the first code in the loop body, generate a block that looks - * like 'if (!condition) break;' as the loop termination condition. - */ - ir_rvalue *const not_cond = - new(ctx) ir_expression(ir_unop_logic_not, cond); + /* As the first code in the loop body, generate a block that looks + * like 'if (!condition) break;' as the loop termination condition. + */ + ir_rvalue *const not_cond = + new(ctx) ir_expression(ir_unop_logic_not, cond); - ir_if *const if_stmt = new(ctx) ir_if(not_cond); + ir_if *const if_stmt = new(ctx) ir_if(not_cond); - ir_jump *const break_stmt = - new(ctx) ir_loop_jump(ir_loop_jump::jump_break); + ir_jump *const break_stmt = + new(ctx) ir_loop_jump(ir_loop_jump::jump_break); - if_stmt->then_instructions.push_tail(break_stmt); - stmt->body_instructions.push_tail(if_stmt); + if_stmt->then_instructions.push_tail(break_stmt); + instructions->push_tail(if_stmt); } } } @@ -4070,7 +4640,7 @@ ast_iteration_statement::condition_to_hir(ir_loop *stmt, ir_rvalue * ast_iteration_statement::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { void *ctx = state; @@ -4097,7 +4667,7 @@ ast_iteration_statement::hir(exec_list *instructions, state->switch_state.is_switch_innermost = false; if (mode != ast_do_while) - condition_to_hir(stmt, state); + condition_to_hir(&stmt->body_instructions, state); if (body != NULL) body->hir(& stmt->body_instructions, state); @@ -4106,7 +4676,7 @@ ast_iteration_statement::hir(exec_list *instructions, rest_expression->hir(& stmt->body_instructions, state); if (mode == ast_do_while) - condition_to_hir(stmt, state); + condition_to_hir(&stmt->body_instructions, state); if (mode != ast_do_while) state->symbols->pop_scope(); @@ -4162,7 +4732,7 @@ is_valid_default_precision_type(const struct glsl_type *const type) ir_rvalue * ast_type_specifier::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { if (this->default_precision == ast_precision_none && this->structure == NULL) return NULL; @@ -4189,7 +4759,7 @@ ast_type_specifier::hir(exec_list *instructions, return NULL; } - if (this->is_array) { + if (this->array_specifier != NULL) { _mesa_glsl_error(&loc, state, "default precision statements do not apply to " "arrays"); @@ -4200,14 +4770,14 @@ ast_type_specifier::hir(exec_list *instructions, state->symbols->get_type(this->type_name); if (!is_valid_default_precision_type(type)) { _mesa_glsl_error(&loc, state, - "default precision statements apply only to types " + "default precision statements apply only to " "float, int, and sampler types"); return NULL; } if (type->base_type == GLSL_TYPE_FLOAT && state->es_shader - && state->target == fragment_shader) { + && state->stage == MESA_SHADER_FRAGMENT) { /* Section 4.5.3 (Default Precision Qualifiers) of the GLSL ES 1.00 * spec says: * @@ -4274,18 +4844,24 @@ ast_type_specifier::hir(exec_list *instructions, * AST for each can be processed the same way into a set of * \c glsl_struct_field to describe the members. * + * If we're processing an interface block, var_mode should be the type of the + * interface block (ir_var_shader_in, ir_var_shader_out, or ir_var_uniform). + * If we're processing a structure, var_mode should be ir_var_auto. + * * \return * The number of fields processed. A pointer to the array structure fields is * stored in \c *fields_ret. */ unsigned ast_process_structure_or_interface_block(exec_list *instructions, - struct _mesa_glsl_parse_state *state, - exec_list *declarations, - YYLTYPE &loc, - glsl_struct_field **fields_ret, + struct _mesa_glsl_parse_state *state, + exec_list *declarations, + YYLTYPE &loc, + glsl_struct_field **fields_ret, bool is_interface, - bool block_row_major) + bool block_row_major, + bool allow_reserved_names, + ir_variable_mode var_mode) { unsigned decl_count = 0; @@ -4296,7 +4872,7 @@ ast_process_structure_or_interface_block(exec_list *instructions, */ foreach_list_typed (ast_declarator_list, decl_list, link, declarations) { foreach_list_const (decl_ptr, & decl_list->declarations) { - decl_count++; + decl_count++; } } @@ -4306,7 +4882,7 @@ ast_process_structure_or_interface_block(exec_list *instructions, * other structure definitions or in interface blocks are processed. */ glsl_struct_field *const fields = ralloc_array(state, glsl_struct_field, - decl_count); + decl_count); unsigned i = 0; foreach_list_typed (ast_declarator_list, decl_list, link, declarations) { @@ -4318,21 +4894,21 @@ ast_process_structure_or_interface_block(exec_list *instructions, * embedded structure definitions have been removed from the language. */ if (state->es_shader && decl_list->type->specifier->structure != NULL) { - _mesa_glsl_error(&loc, state, "Embedded structure definitions are " - "not allowed in GLSL ES 1.00."); + _mesa_glsl_error(&loc, state, "embedded structure definitions are " + "not allowed in GLSL ES 1.00"); } const glsl_type *decl_type = decl_list->type->glsl_type(& type_name, state); foreach_list_typed (ast_declaration, decl, link, - &decl_list->declarations) { - /* From the GL_ARB_uniform_buffer_object spec: + &decl_list->declarations) { + if (!allow_reserved_names) + validate_identifier(decl->identifier, loc, state); + + /* From section 4.3.9 of the GLSL 4.40 spec: * - * "Sampler types are not allowed inside of uniform - * blocks. All other types, arrays, and structures - * allowed for uniforms are allowed within a uniform - * block." + * "[In interface blocks] opaque types are not allowed." * * It should be impossible for decl_type to be NULL here. Cases that * might naturally lead to decl_type being NULL, especially for the @@ -4342,10 +4918,32 @@ ast_process_structure_or_interface_block(exec_list *instructions, const struct glsl_type *field_type = decl_type != NULL ? decl_type : glsl_type::error_type; - if (is_interface && field_type->contains_sampler()) { + if (is_interface && field_type->contains_opaque()) { + YYLTYPE loc = decl_list->get_location(); + _mesa_glsl_error(&loc, state, + "uniform in non-default uniform block contains " + "opaque variable"); + } + + if (field_type->contains_atomic()) { + /* FINISHME: Add a spec quotation here once updated spec + * FINISHME: language is available. See Khronos bug #10903 + * FINISHME: on whether atomic counters are allowed in + * FINISHME: structures. + */ + YYLTYPE loc = decl_list->get_location(); + _mesa_glsl_error(&loc, state, "atomic counter in structure or " + "uniform block"); + } + + if (field_type->contains_image()) { + /* FINISHME: Same problem as with atomic counters. + * FINISHME: Request clarification from Khronos and add + * FINISHME: spec quotation here. + */ YYLTYPE loc = decl_list->get_location(); _mesa_glsl_error(&loc, state, - "Uniform in non-default uniform block contains sampler\n"); + "image in structure or uniform block"); } const struct ast_type_qualifier *const qual = @@ -4359,12 +4957,15 @@ ast_process_structure_or_interface_block(exec_list *instructions, "members"); } - if (decl->is_array) { - field_type = process_array_type(&loc, decl_type, decl->array_size, - state); - } + field_type = process_array_type(&loc, decl_type, + decl->array_specifier, state); fields[i].type = field_type; - fields[i].name = decl->identifier; + fields[i].name = decl->identifier; + fields[i].location = -1; + fields[i].interpolation = + interpret_interpolation_qualifier(qual, var_mode, state, &loc); + fields[i].centroid = qual->flags.q.centroid ? 1 : 0; + fields[i].sample = qual->flags.q.sample ? 1 : 0; if (qual->flags.q.row_major || qual->flags.q.column_major) { if (!qual->flags.q.uniform) { @@ -4390,7 +4991,7 @@ ast_process_structure_or_interface_block(exec_list *instructions, fields[i].row_major = false; } - i++; + i++; } } @@ -4403,7 +5004,7 @@ ast_process_structure_or_interface_block(exec_list *instructions, ir_rvalue * ast_struct_specifier::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { YYLTYPE loc = this->get_location(); @@ -4437,12 +5038,16 @@ ast_struct_specifier::hir(exec_list *instructions, glsl_struct_field *fields; unsigned decl_count = ast_process_structure_or_interface_block(instructions, - state, - &this->declarations, - loc, - &fields, + state, + &this->declarations, + loc, + &fields, false, - false); + false, + false /* allow_reserved_names */, + ir_var_auto); + + validate_identifier(this->name, loc, state); const glsl_type *t = glsl_type::get_record_instance(fields, decl_count, this->name); @@ -4451,12 +5056,12 @@ ast_struct_specifier::hir(exec_list *instructions, _mesa_glsl_error(& loc, state, "struct `%s' previously defined", name); } else { const glsl_type **s = reralloc(state, state->user_structures, - const glsl_type *, - state->num_user_structures + 1); + const glsl_type *, + state->num_user_structures + 1); if (s != NULL) { - s[state->num_user_structures] = t; - state->user_structures = s; - state->num_user_structures++; + s[state->num_user_structures] = t; + state->user_structures = s; + state->num_user_structures++; } } @@ -4467,9 +5072,42 @@ ast_struct_specifier::hir(exec_list *instructions, return NULL; } + +/** + * Visitor class which detects whether a given interface block has been used. + */ +class interface_block_usage_visitor : public ir_hierarchical_visitor +{ +public: + interface_block_usage_visitor(ir_variable_mode mode, const glsl_type *block) + : mode(mode), block(block), found(false) + { + } + + virtual ir_visitor_status visit(ir_dereference_variable *ir) + { + if (ir->var->data.mode == mode && ir->var->get_interface_type() == block) { + found = true; + return visit_stop; + } + return visit_continue; + } + + bool usage_found() const + { + return this->found; + } + +private: + ir_variable_mode mode; + const glsl_type *block; + bool found; +}; + + ir_rvalue * ast_interface_block::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) + struct _mesa_glsl_parse_state *state) { YYLTYPE loc = this->get_location(); @@ -4488,18 +5126,6 @@ ast_interface_block::hir(exec_list *instructions, packing = GLSL_INTERFACE_PACKING_STD140; } - bool block_row_major = this->layout.flags.q.row_major; - exec_list declared_variables; - glsl_struct_field *fields; - unsigned int num_variables = - ast_process_structure_or_interface_block(&declared_variables, - state, - &this->declarations, - loc, - &fields, - true, - block_row_major); - ir_variable_mode var_mode; const char *iface_type_name; if (this->layout.flags.q.in) { @@ -4517,6 +5143,123 @@ ast_interface_block::hir(exec_list *instructions, assert(!"interface block layout qualifier not found!"); } + bool redeclaring_per_vertex = strcmp(this->block_name, "gl_PerVertex") == 0; + bool block_row_major = this->layout.flags.q.row_major; + exec_list declared_variables; + glsl_struct_field *fields; + unsigned int num_variables = + ast_process_structure_or_interface_block(&declared_variables, + state, + &this->declarations, + loc, + &fields, + true, + block_row_major, + redeclaring_per_vertex, + var_mode); + + if (!redeclaring_per_vertex) + validate_identifier(this->block_name, loc, state); + + const glsl_type *earlier_per_vertex = NULL; + if (redeclaring_per_vertex) { + /* Find the previous declaration of gl_PerVertex. If we're redeclaring + * the named interface block gl_in, we can find it by looking at the + * previous declaration of gl_in. Otherwise we can find it by looking + * at the previous decalartion of any of the built-in outputs, + * e.g. gl_Position. + * + * Also check that the instance name and array-ness of the redeclaration + * are correct. + */ + switch (var_mode) { + case ir_var_shader_in: + if (ir_variable *earlier_gl_in = + state->symbols->get_variable("gl_in")) { + earlier_per_vertex = earlier_gl_in->get_interface_type(); + } else { + _mesa_glsl_error(&loc, state, + "redeclaration of gl_PerVertex input not allowed " + "in the %s shader", + _mesa_shader_stage_to_string(state->stage)); + } + if (this->instance_name == NULL || + strcmp(this->instance_name, "gl_in") != 0 || this->array_specifier == NULL) { + _mesa_glsl_error(&loc, state, + "gl_PerVertex input must be redeclared as " + "gl_in[]"); + } + break; + case ir_var_shader_out: + if (ir_variable *earlier_gl_Position = + state->symbols->get_variable("gl_Position")) { + earlier_per_vertex = earlier_gl_Position->get_interface_type(); + } else { + _mesa_glsl_error(&loc, state, + "redeclaration of gl_PerVertex output not " + "allowed in the %s shader", + _mesa_shader_stage_to_string(state->stage)); + } + if (this->instance_name != NULL) { + _mesa_glsl_error(&loc, state, + "gl_PerVertex input may not be redeclared with " + "an instance name"); + } + break; + default: + _mesa_glsl_error(&loc, state, + "gl_PerVertex must be declared as an input or an " + "output"); + break; + } + + if (earlier_per_vertex == NULL) { + /* An error has already been reported. Bail out to avoid null + * dereferences later in this function. + */ + return NULL; + } + + /* Copy locations from the old gl_PerVertex interface block. */ + for (unsigned i = 0; i < num_variables; i++) { + int j = earlier_per_vertex->field_index(fields[i].name); + if (j == -1) { + _mesa_glsl_error(&loc, state, + "redeclaration of gl_PerVertex must be a subset " + "of the built-in members of gl_PerVertex"); + } else { + fields[i].location = + earlier_per_vertex->fields.structure[j].location; + fields[i].interpolation = + earlier_per_vertex->fields.structure[j].interpolation; + fields[i].centroid = + earlier_per_vertex->fields.structure[j].centroid; + fields[i].sample = + earlier_per_vertex->fields.structure[j].sample; + } + } + + /* From section 7.1 ("Built-in Language Variables") of the GLSL 4.10 + * spec: + * + * If a built-in interface block is redeclared, it must appear in + * the shader before any use of any member included in the built-in + * declaration, or a compilation error will result. + * + * This appears to be a clarification to the behaviour established for + * gl_PerVertex by GLSL 1.50, therefore we implement this behaviour + * regardless of GLSL version. + */ + interface_block_usage_visitor v(var_mode, earlier_per_vertex); + v.run(instructions); + if (v.usage_found()) { + _mesa_glsl_error(&loc, state, + "redeclaration of a built-in interface block must " + "appear before any use of any member of the " + "interface block"); + } + } + const glsl_type *block_type = glsl_type::get_interface_instance(fields, num_variables, @@ -4525,8 +5268,8 @@ ast_interface_block::hir(exec_list *instructions, if (!state->symbols->add_interface(block_type->name, block_type, var_mode)) { YYLTYPE loc = this->get_location(); - _mesa_glsl_error(&loc, state, "Interface block `%s' with type `%s' " - "already taken in the current scope.\n", + _mesa_glsl_error(&loc, state, "interface block `%s' with type `%s' " + "already taken in the current scope", this->block_name, iface_type_name); } @@ -4535,6 +5278,19 @@ ast_interface_block::hir(exec_list *instructions, */ assert(declared_variables.is_empty()); + /* From section 4.3.4 (Inputs) of the GLSL 1.50 spec: + * + * Geometry shader input variables get the per-vertex values written + * out by vertex shader output variables of the same names. Since a + * geometry shader operates on a set of vertices, each input varying + * variable (or input block, see interface blocks below) needs to be + * declared as an array. + */ + if (state->stage == MESA_SHADER_GEOMETRY && this->array_specifier == NULL && + var_mode == ir_var_shader_in) { + _mesa_glsl_error(&loc, state, "geometry shader inputs must be arrays"); + } + /* Page 39 (page 45 of the PDF) of section 4.3.7 in the GLSL ES 3.00 spec * says: * @@ -4543,11 +5299,57 @@ ast_interface_block::hir(exec_list *instructions, * field selector ( . ) operator (analogously to structures)." */ if (this->instance_name) { + if (redeclaring_per_vertex) { + /* When a built-in in an unnamed interface block is redeclared, + * get_variable_being_redeclared() calls + * check_builtin_array_max_size() to make sure that built-in array + * variables aren't redeclared to illegal sizes. But we're looking + * at a redeclaration of a named built-in interface block. So we + * have to manually call check_builtin_array_max_size() for all parts + * of the interface that are arrays. + */ + for (unsigned i = 0; i < num_variables; i++) { + if (fields[i].type->is_array()) { + const unsigned size = fields[i].type->array_size(); + check_builtin_array_max_size(fields[i].name, size, loc, state); + } + } + } else { + validate_identifier(this->instance_name, loc, state); + } + ir_variable *var; - if (this->array_size != NULL) { + if (this->array_specifier != NULL) { + /* Section 4.3.7 (Interface Blocks) of the GLSL 1.50 spec says: + * + * For uniform blocks declared an array, each individual array + * element corresponds to a separate buffer object backing one + * instance of the block. As the array size indicates the number + * of buffer objects needed, uniform block array declarations + * must specify an array size. + * + * And a few paragraphs later: + * + * Geometry shader input blocks must be declared as arrays and + * follow the array declaration and linking rules for all + * geometry shader inputs. All other input and output block + * arrays must specify an array size. + * + * The upshot of this is that the only circumstance where an + * interface array size *doesn't* need to be specified is on a + * geometry shader input. + */ + if (this->array_specifier->is_unsized_array && + (state->stage != MESA_SHADER_GEOMETRY || !this->layout.flags.q.in)) { + _mesa_glsl_error(&loc, state, + "only geometry shader inputs may be unsized " + "instance block arrays"); + + } + const glsl_type *block_array_type = - process_array_type(&loc, block_type, this->array_size, state); + process_array_type(&loc, block_type, this->array_specifier, state); var = new(state) ir_variable(block_array_type, this->instance_name, @@ -4558,40 +5360,265 @@ ast_interface_block::hir(exec_list *instructions, var_mode); } - var->interface_type = block_type; - state->symbols->add_variable(var); - instructions->push_tail(var); + if (state->stage == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in) + handle_geometry_shader_input_decl(state, loc, var); + + if (ir_variable *earlier = + state->symbols->get_variable(this->instance_name)) { + if (!redeclaring_per_vertex) { + _mesa_glsl_error(&loc, state, "`%s' redeclared", + this->instance_name); + } + earlier->data.how_declared = ir_var_declared_normally; + earlier->type = var->type; + earlier->reinit_interface_type(block_type); + delete var; + } else { + /* Propagate the "binding" keyword into this UBO's fields; + * the UBO declaration itself doesn't get an ir_variable unless it + * has an instance name. This is ugly. + */ + var->data.explicit_binding = this->layout.flags.q.explicit_binding; + var->data.binding = this->layout.binding; + + state->symbols->add_variable(var); + instructions->push_tail(var); + } } else { /* In order to have an array size, the block must also be declared with - * an instane name. + * an instance name. */ - assert(this->array_size == NULL); + assert(this->array_specifier == NULL); for (unsigned i = 0; i < num_variables; i++) { ir_variable *var = new(state) ir_variable(fields[i].type, ralloc_strdup(state, fields[i].name), var_mode); - var->interface_type = block_type; + var->data.interpolation = fields[i].interpolation; + var->data.centroid = fields[i].centroid; + var->data.sample = fields[i].sample; + var->init_interface_type(block_type); + + if (redeclaring_per_vertex) { + ir_variable *earlier = + get_variable_being_redeclared(var, loc, state, + true /* allow_all_redeclarations */); + if (strncmp(var->name, "gl_", 3) != 0 || earlier == NULL) { + _mesa_glsl_error(&loc, state, + "redeclaration of gl_PerVertex can only " + "include built-in variables"); + } else if (earlier->data.how_declared == ir_var_declared_normally) { + _mesa_glsl_error(&loc, state, + "`%s' has already been redeclared", var->name); + } else { + earlier->data.how_declared = ir_var_declared_in_block; + earlier->reinit_interface_type(block_type); + } + continue; + } + + if (state->symbols->get_variable(var->name) != NULL) + _mesa_glsl_error(&loc, state, "`%s' redeclared", var->name); /* Propagate the "binding" keyword into this UBO's fields; * the UBO declaration itself doesn't get an ir_variable unless it * has an instance name. This is ugly. */ - var->explicit_binding = this->layout.flags.q.explicit_binding; - var->binding = this->layout.binding; + var->data.explicit_binding = this->layout.flags.q.explicit_binding; + var->data.binding = this->layout.binding; state->symbols->add_variable(var); instructions->push_tail(var); } + + if (redeclaring_per_vertex && block_type != earlier_per_vertex) { + /* From section 7.1 ("Built-in Language Variables") of the GLSL 4.10 spec: + * + * It is also a compilation error ... to redeclare a built-in + * block and then use a member from that built-in block that was + * not included in the redeclaration. + * + * This appears to be a clarification to the behaviour established + * for gl_PerVertex by GLSL 1.50, therefore we implement this + * behaviour regardless of GLSL version. + * + * To prevent the shader from using a member that was not included in + * the redeclaration, we disable any ir_variables that are still + * associated with the old declaration of gl_PerVertex (since we've + * already updated all of the variables contained in the new + * gl_PerVertex to point to it). + * + * As a side effect this will prevent + * validate_intrastage_interface_blocks() from getting confused and + * thinking there are conflicting definitions of gl_PerVertex in the + * shader. + */ + foreach_list_safe(node, instructions) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + if (var != NULL && + var->get_interface_type() == earlier_per_vertex && + var->data.mode == var_mode) { + if (var->data.how_declared == ir_var_declared_normally) { + _mesa_glsl_error(&loc, state, + "redeclaration of gl_PerVertex cannot " + "follow a redeclaration of `%s'", + var->name); + } + state->symbols->disable_variable(var->name); + var->remove(); + } + } + } + } + + return NULL; +} + + +ir_rvalue * +ast_gs_input_layout::hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + YYLTYPE loc = this->get_location(); + + /* If any geometry input layout declaration preceded this one, make sure it + * was consistent with this one. + */ + if (state->gs_input_prim_type_specified && + state->in_qualifier->prim_type != this->prim_type) { + _mesa_glsl_error(&loc, state, + "geometry shader input layout does not match" + " previous declaration"); + return NULL; + } + + /* If any shader inputs occurred before this declaration and specified an + * array size, make sure the size they specified is consistent with the + * primitive type. + */ + unsigned num_vertices = vertices_per_prim(this->prim_type); + if (state->gs_input_size != 0 && state->gs_input_size != num_vertices) { + _mesa_glsl_error(&loc, state, + "this geometry shader input layout implies %u vertices" + " per primitive, but a previous input is declared" + " with size %u", num_vertices, state->gs_input_size); + return NULL; + } + + state->gs_input_prim_type_specified = true; + + /* If any shader inputs occurred before this declaration and did not + * specify an array size, their size is determined now. + */ + foreach_list (node, instructions) { + ir_variable *var = ((ir_instruction *) node)->as_variable(); + if (var == NULL || var->data.mode != ir_var_shader_in) + continue; + + /* Note: gl_PrimitiveIDIn has mode ir_var_shader_in, but it's not an + * array; skip it. + */ + + if (var->type->is_unsized_array()) { + if (var->data.max_array_access >= num_vertices) { + _mesa_glsl_error(&loc, state, + "this geometry shader input layout implies %u" + " vertices, but an access to element %u of input" + " `%s' already exists", num_vertices, + var->data.max_array_access, var->name); + } else { + var->type = glsl_type::get_array_instance(var->type->fields.array, + num_vertices); + } + } + } + + return NULL; +} + + +ir_rvalue * +ast_cs_input_layout::hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + YYLTYPE loc = this->get_location(); + + /* If any compute input layout declaration preceded this one, make sure it + * was consistent with this one. + */ + if (state->cs_input_local_size_specified) { + for (int i = 0; i < 3; i++) { + if (state->cs_input_local_size[i] != this->local_size[i]) { + _mesa_glsl_error(&loc, state, + "compute shader input layout does not match" + " previous declaration"); + return NULL; + } + } + } + + /* From the ARB_compute_shader specification: + * + * If the local size of the shader in any dimension is greater + * than the maximum size supported by the implementation for that + * dimension, a compile-time error results. + * + * It is not clear from the spec how the error should be reported if + * the total size of the work group exceeds + * MAX_COMPUTE_WORK_GROUP_INVOCATIONS, but it seems reasonable to + * report it at compile time as well. + */ + GLuint64 total_invocations = 1; + for (int i = 0; i < 3; i++) { + if (this->local_size[i] > state->ctx->Const.MaxComputeWorkGroupSize[i]) { + _mesa_glsl_error(&loc, state, + "local_size_%c exceeds MAX_COMPUTE_WORK_GROUP_SIZE" + " (%d)", 'x' + i, + state->ctx->Const.MaxComputeWorkGroupSize[i]); + break; + } + total_invocations *= this->local_size[i]; + if (total_invocations > + state->ctx->Const.MaxComputeWorkGroupInvocations) { + _mesa_glsl_error(&loc, state, + "product of local_sizes exceeds " + "MAX_COMPUTE_WORK_GROUP_INVOCATIONS (%d)", + state->ctx->Const.MaxComputeWorkGroupInvocations); + break; + } } + state->cs_input_local_size_specified = true; + for (int i = 0; i < 3; i++) + state->cs_input_local_size[i] = this->local_size[i]; + + /* We may now declare the built-in constant gl_WorkGroupSize (see + * builtin_variable_generator::generate_constants() for why we didn't + * declare it earlier). + */ + ir_variable *var = new(state->symbols) + ir_variable(glsl_type::ivec3_type, "gl_WorkGroupSize", ir_var_auto); + var->data.how_declared = ir_var_declared_implicitly; + var->data.read_only = true; + instructions->push_tail(var); + state->symbols->add_variable(var); + ir_constant_data data; + memset(&data, 0, sizeof(data)); + for (int i = 0; i < 3; i++) + data.i[i] = this->local_size[i]; + var->constant_value = new(var) ir_constant(glsl_type::ivec3_type, &data); + var->constant_initializer = + new(var) ir_constant(glsl_type::ivec3_type, &data); + var->data.has_initializer = true; + return NULL; } + static void detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, - exec_list *instructions) + exec_list *instructions) { bool gl_FragColor_assigned = false; bool gl_FragData_assigned = false; @@ -4605,19 +5632,19 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, foreach_list(node, instructions) { ir_variable *var = ((ir_instruction *)node)->as_variable(); - if (!var || !var->assigned) - continue; + if (!var || !var->data.assigned) + continue; if (strcmp(var->name, "gl_FragColor") == 0) - gl_FragColor_assigned = true; + gl_FragColor_assigned = true; else if (strcmp(var->name, "gl_FragData") == 0) - gl_FragData_assigned = true; + gl_FragData_assigned = true; else if (strncmp(var->name, "gl_", 3) != 0) { - if (state->target == fragment_shader && - var->mode == ir_var_shader_out) { - user_defined_fs_output_assigned = true; - user_defined_fs_output = var; - } + if (state->stage == MESA_SHADER_FRAGMENT && + var->data.mode == ir_var_shader_out) { + user_defined_fs_output_assigned = true; + user_defined_fs_output = var; + } } } @@ -4638,14 +5665,66 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, */ if (gl_FragColor_assigned && gl_FragData_assigned) { _mesa_glsl_error(&loc, state, "fragment shader writes to both " - "`gl_FragColor' and `gl_FragData'\n"); + "`gl_FragColor' and `gl_FragData'"); } else if (gl_FragColor_assigned && user_defined_fs_output_assigned) { _mesa_glsl_error(&loc, state, "fragment shader writes to both " - "`gl_FragColor' and `%s'\n", - user_defined_fs_output->name); + "`gl_FragColor' and `%s'", + user_defined_fs_output->name); } else if (gl_FragData_assigned && user_defined_fs_output_assigned) { _mesa_glsl_error(&loc, state, "fragment shader writes to both " - "`gl_FragData' and `%s'\n", - user_defined_fs_output->name); + "`gl_FragData' and `%s'", + user_defined_fs_output->name); + } +} + + +static void +remove_per_vertex_blocks(exec_list *instructions, + _mesa_glsl_parse_state *state, ir_variable_mode mode) +{ + /* Find the gl_PerVertex interface block of the appropriate (in/out) mode, + * if it exists in this shader type. + */ + const glsl_type *per_vertex = NULL; + switch (mode) { + case ir_var_shader_in: + if (ir_variable *gl_in = state->symbols->get_variable("gl_in")) + per_vertex = gl_in->get_interface_type(); + break; + case ir_var_shader_out: + if (ir_variable *gl_Position = + state->symbols->get_variable("gl_Position")) { + per_vertex = gl_Position->get_interface_type(); + } + break; + default: + assert(!"Unexpected mode"); + break; + } + + /* If we didn't find a built-in gl_PerVertex interface block, then we don't + * need to do anything. + */ + if (per_vertex == NULL) + return; + + /* If the interface block is used by the shader, then we don't need to do + * anything. + */ + interface_block_usage_visitor v(mode, per_vertex); + v.run(instructions); + if (v.usage_found()) + return; + + /* Remove any ir_variable declarations that refer to the interface block + * we're removing. + */ + foreach_list_safe(node, instructions) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + if (var != NULL && var->get_interface_type() == per_vertex && + var->data.mode == mode) { + state->symbols->disable_variable(var->name); + var->remove(); + } } } |