X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fast_to_hir.cpp;h=651fae808e623f7171828600c0b685fbbb7286df;hb=2b13e135942ea7ebe1426a1809bf0efb7891387d;hp=762f802c2b76ddeb08f56062e7d28fb44a533542;hpb=222d2f2ac2c7d93cbc0643082c78278ad2c8cfce;p=mesa.git diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 762f802c2b7..651fae808e6 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -60,7 +60,9 @@ void _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { _mesa_glsl_initialize_variables(instructions, state); - _mesa_glsl_initialize_functions(instructions, state); + _mesa_glsl_initialize_functions(state); + + state->symbols->language_version = state->language_version; state->current_function = NULL; @@ -362,12 +364,84 @@ unary_arithmetic_result_type(const struct glsl_type *type, return type; } +/** + * \brief Return the result type of a bit-logic operation. + * + * If the given types to the bit-logic operator are invalid, return + * glsl_type::error_type. + * + * \param type_a Type of LHS of bit-logic op + * \param type_b Type of RHS of bit-logic op + */ +static const struct glsl_type * +bit_logic_result_type(const struct glsl_type *type_a, + const struct glsl_type *type_b, + ast_operators op, + struct _mesa_glsl_parse_state *state, YYLTYPE *loc) +{ + if (state->language_version < 130) { + _mesa_glsl_error(loc, state, "bit operations require GLSL 1.30"); + return glsl_type::error_type; + } + + /* From page 50 (page 56 of PDF) of GLSL 1.30 spec: + * + * "The bitwise operators and (&), exclusive-or (^), and inclusive-or + * (|). The operands must be of type signed or unsigned integers or + * integer vectors." + */ + if (!type_a->is_integer()) { + _mesa_glsl_error(loc, state, "LHS of `%s' must be an integer", + ast_expression::operator_string(op)); + return glsl_type::error_type; + } + if (!type_b->is_integer()) { + _mesa_glsl_error(loc, state, "RHS of `%s' must be an integer", + ast_expression::operator_string(op)); + return glsl_type::error_type; + } + + /* "The fundamental types of the operands (signed or unsigned) must + * match," + */ + if (type_a->base_type != type_b->base_type) { + _mesa_glsl_error(loc, state, "operands of `%s' must have the same " + "base type", ast_expression::operator_string(op)); + return glsl_type::error_type; + } + + /* "The operands cannot be vectors of differing size." */ + if (type_a->is_vector() && + type_b->is_vector() && + type_a->vector_elements != type_b->vector_elements) { + _mesa_glsl_error(loc, state, "operands of `%s' cannot be vectors of " + "different sizes", ast_expression::operator_string(op)); + return glsl_type::error_type; + } + + /* "If one operand is a scalar and the other a vector, the scalar is + * applied component-wise to the vector, resulting in the same type as + * the vector. The fundamental types of the operands [...] will be the + * resulting fundamental type." + */ + if (type_a->is_scalar()) + return type_b; + else + return 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) { + if (state->language_version < 130) { + _mesa_glsl_error(loc, state, + "operator '%%' is reserved in %s", + state->version_string); + return glsl_type::error_type; + } + /* From GLSL 1.50 spec, page 56: * "The operator modulus (%) operates on signed or unsigned integers or * integer vectors. The operand types must both be signed or both be @@ -445,6 +519,71 @@ relational_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, return glsl_type::bool_type; } +/** + * \brief Return the result type of a bit-shift operation. + * + * If the given types to the bit-shift operator are invalid, return + * glsl_type::error_type. + * + * \param type_a Type of LHS of bit-shift op + * \param type_b Type of RHS of bit-shift op + */ +static const struct glsl_type * +shift_result_type(const struct glsl_type *type_a, + const struct glsl_type *type_b, + ast_operators op, + struct _mesa_glsl_parse_state *state, YYLTYPE *loc) +{ + if (state->language_version < 130) { + _mesa_glsl_error(loc, state, "bit operations require GLSL 1.30"); + return glsl_type::error_type; + } + + /* From page 50 (page 56 of the PDF) of the GLSL 1.30 spec: + * + * "The shift operators (<<) and (>>). For both operators, the operands + * must be signed or unsigned integers or integer vectors. One operand + * can be signed while the other is unsigned." + */ + 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)); + 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)); + return glsl_type::error_type; + } + + /* "If the first operand is a scalar, the second operand has to be + * 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)); + return glsl_type::error_type; + } + + /* If both operands are vectors, check that they have same number of + * elements. + */ + 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)); + return glsl_type::error_type; + } + + /* "In all cases, the resulting type will be the same type as the left + * operand." + */ + return type_a; +} /** * Validates that a value can be assigned to a location with a specified type @@ -466,17 +605,15 @@ ir_rvalue * validate_assignment(struct _mesa_glsl_parse_state *state, const glsl_type *lhs_type, ir_rvalue *rhs) { - const glsl_type *rhs_type = rhs->type; - /* 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. */ - if (rhs_type->is_error()) + if (rhs->type->is_error()) return rhs; /* If the types are identical, the assignment can trivially proceed. */ - if (rhs_type == lhs_type) + if (rhs->type == lhs_type) return rhs; /* If the array element types are the same and the size of the LHS is zero, @@ -493,8 +630,7 @@ validate_assignment(struct _mesa_glsl_parse_state *state, /* Check for implicit conversion in GLSL 1.20 */ if (apply_implicit_conversion(lhs_type, rhs, state)) { - rhs_type = rhs->type; - if (rhs_type == lhs_type) + if (rhs->type == lhs_type) return rhs; } @@ -510,10 +646,23 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, bool error_emitted = (lhs->type->is_error() || rhs->type->is_error()); if (!error_emitted) { - if (!lhs->is_lvalue()) { + if (lhs->variable_referenced() != NULL + && lhs->variable_referenced()->read_only) { + _mesa_glsl_error(&lhs_loc, state, + "assignment to read-only variable '%s'", + lhs->variable_referenced()->name); + error_emitted = true; + + } else if (!lhs->is_lvalue()) { _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment"); error_emitted = true; } + + if (state->es_shader && lhs->type->is_array()) { + _mesa_glsl_error(&lhs_loc, state, "whole array assignment is not " + "allowed in GLSL ES 1.00."); + error_emitted = true; + } } ir_rvalue *new_rhs = validate_assignment(state, lhs->type, rhs); @@ -577,7 +726,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, static ir_rvalue * get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue) { - void *ctx = talloc_parent(lvalue); + void *ctx = ralloc_parent(lvalue); ir_variable *var; var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp", @@ -607,6 +756,94 @@ ast_node::hir(exec_list *instructions, return NULL; } +static void +mark_whole_array_access(ir_rvalue *access) +{ + ir_dereference_variable *deref = access->as_dereference_variable(); + + if (deref) { + deref->var->max_array_access = deref->type->length - 1; + } +} + +static ir_rvalue * +do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1) +{ + int join_op; + ir_rvalue *cmp = NULL; + + if (operation == ir_binop_all_equal) + join_op = ir_binop_logic_and; + else + join_op = ir_binop_logic_or; + + switch (op0->type->base_type) { + case GLSL_TYPE_FLOAT: + case GLSL_TYPE_UINT: + case GLSL_TYPE_INT: + case GLSL_TYPE_BOOL: + return new(mem_ctx) ir_expression(operation, op0, 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; + } + } + + mark_whole_array_access(op0); + mark_whole_array_access(op1); + break; + } + + 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; + } + } + break; + } + + case GLSL_TYPE_ERROR: + case GLSL_TYPE_VOID: + case GLSL_TYPE_SAMPLER: + /* I assume a comparison of a struct containing a sampler just + * ignores the sampler present in the type. + */ + break; + + default: + assert(!"Should not get here."); + break; + } + + if (cmp == NULL) + cmp = new(mem_ctx) ir_constant(true); + + return cmp; +} ir_rvalue * ast_expression::hir(exec_list *instructions, @@ -628,8 +865,8 @@ ast_expression::hir(exec_list *instructions, ir_binop_greater, ir_binop_lequal, ir_binop_gequal, - ir_binop_equal, - ir_binop_nequal, + ir_binop_all_equal, + ir_binop_any_nequal, ir_binop_bit_and, ir_binop_bit_xor, ir_binop_bit_or, @@ -740,9 +977,20 @@ ast_expression::hir(exec_list *instructions, case ast_lshift: case ast_rshift: - _mesa_glsl_error(& loc, state, "FINISHME: implement bit-shift operators"); - error_emitted = true; - break; + if (state->language_version < 130) { + _mesa_glsl_error(&loc, state, "operator %s requires GLSL 1.30", + operator_string(this->oper)); + error_emitted = true; + } + + op[0] = this->subexpressions[0]->hir(instructions, state); + op[1] = this->subexpressions[1]->hir(instructions, state); + type = shift_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]); + error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); + break; case ast_less: case ast_greater: @@ -792,11 +1040,10 @@ ast_expression::hir(exec_list *instructions, error_emitted = true; } - result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type, - op[0], op[1]); + result = do_comparison(ctx, operations[this->oper], op[0], op[1]); type = glsl_type::bool_type; - assert(result->type == glsl_type::bool_type); + assert(error_emitted || (result->type == glsl_type::bool_type)); break; case ast_bit_and: @@ -804,38 +1051,8 @@ ast_expression::hir(exec_list *instructions, case ast_bit_or: op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); - - if (state->language_version < 130) { - _mesa_glsl_error(&loc, state, "bit-wise operations require GLSL 1.30"); - error_emitted = true; - } - - if (!op[0]->type->is_integer()) { - _mesa_glsl_error(&loc, state, "LHS of `%s' must be an integer", - operator_string(this->oper)); - error_emitted = true; - } - - if (!op[1]->type->is_integer()) { - _mesa_glsl_error(&loc, state, "RHS of `%s' must be an integer", - operator_string(this->oper)); - error_emitted = true; - } - - if (op[0]->type->base_type != op[1]->type->base_type) { - _mesa_glsl_error(&loc, state, "operands of `%s' must have the same " - "base type", operator_string(this->oper)); - error_emitted = true; - } - - if (op[0]->type->is_vector() && op[1]->type->is_vector() - && op[0]->type->vector_elements != op[1]->type->vector_elements) { - _mesa_glsl_error(&loc, state, "operands of `%s' cannot be vectors of " - "different sizes", operator_string(this->oper)); - error_emitted = true; - } - - type = op[0]->type->is_scalar() ? op[1]->type : op[0]->type; + 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]); error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); @@ -1062,19 +1279,35 @@ ast_expression::hir(exec_list *instructions, } case ast_ls_assign: - case ast_rs_assign: - _mesa_glsl_error(& loc, state, - "FINISHME: implement bit-shift assignment operators"); - error_emitted = true; + case ast_rs_assign: { + op[0] = this->subexpressions[0]->hir(instructions, state); + op[1] = this->subexpressions[1]->hir(instructions, state); + type = shift_result_type(op[0]->type, op[1]->type, this->oper, state, + &loc); + ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], + type, op[0], op[1]); + result = do_assignment(instructions, state, op[0]->clone(ctx, NULL), + temp_rhs, + this->subexpressions[0]->get_location()); + error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); break; + } case ast_and_assign: case ast_xor_assign: - case ast_or_assign: - _mesa_glsl_error(& loc, state, - "FINISHME: implement logic assignment operators"); - error_emitted = true; + case ast_or_assign: { + op[0] = this->subexpressions[0]->hir(instructions, state); + op[1] = this->subexpressions[1]->hir(instructions, state); + type = bit_logic_result_type(op[0]->type, op[1]->type, this->oper, + state, &loc); + ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], + type, op[0], op[1]); + result = do_assignment(instructions, state, op[0]->clone(ctx, NULL), + temp_rhs, + this->subexpressions[0]->get_location()); + error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); break; + } case ast_conditional: { op[0] = this->subexpressions[0]->hir(instructions, state); @@ -1125,6 +1358,17 @@ ast_expression::hir(exec_list *instructions, type = op[1]->type; } + /* From page 33 (page 39 of the PDF) of the GLSL 1.10 spec: + * + * "The second and third expressions must be the same type, but can + * be of any type other than an array." + */ + if ((state->language_version <= 110) && type->is_array()) { + _mesa_glsl_error(& loc, state, "Second and third operands of ?: " + "operator must not be arrays."); + error_emitted = true; + } + ir_constant *cond_val = op[0]->constant_expression_value(); ir_constant *then_val = op[1]->constant_expression_value(); ir_constant *else_val = op[2]->constant_expression_value(); @@ -1334,6 +1578,40 @@ ast_expression::hir(exec_list *instructions, } } + /* From page 23 (29 of the PDF) of the GLSL 1.30 spec: + * + * "Samplers aggregated into arrays within a shader (using square + * brackets [ ]) can only be indexed with integral constant + * expressions [...]." + * + * This restriction was added in GLSL 1.30. Shaders using earlier version + * of the language should not be rejected by the compiler front-end for + * using this construct. This allows useful things such as using a loop + * counter as the index to an array of samplers. If the loop in unrolled, + * the code should compile correctly. Instead, emit a warning. + */ + if (array->type->is_array() && + array->type->element_type()->is_sampler() && + const_index == NULL) { + + if (state->language_version == 100) { + _mesa_glsl_warning(&loc, state, + "sampler arrays indexed with non-constant " + "expressions is optional in GLSL ES 1.00"); + } else if (state->language_version < 130) { + _mesa_glsl_warning(&loc, state, + "sampler arrays indexed with non-constant " + "expressions is forbidden in GLSL 1.30 and " + "later"); + } else { + _mesa_glsl_error(&loc, state, + "sampler arrays indexed with non-constant " + "expressions is forbidden in GLSL 1.30 and " + "later"); + error_emitted = true; + } + } + if (error_emitted) result->type = glsl_type::error_type; @@ -1359,6 +1637,7 @@ ast_expression::hir(exec_list *instructions, result = new(ctx) ir_dereference_variable(var); if (var != NULL) { + var->used = true; type = result->type; } else { _mesa_glsl_error(& loc, state, "`%s' undeclared", @@ -1461,7 +1740,7 @@ ast_compound_statement::hir(exec_list *instructions, static const glsl_type * -process_array_type(const glsl_type *base, ast_node *array_size, +process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size, struct _mesa_glsl_parse_state *state) { unsigned length = 0; @@ -1497,6 +1776,12 @@ process_array_type(const glsl_type *base, ast_node *array_size, } } } + } else if (state->es_shader) { + /* Section 10.17 of the GLSL ES 1.00 specification states that unsized + * array declarations have been removed from the language. + */ + _mesa_glsl_error(loc, state, "unsized array declarations are not " + "allowed in GLSL ES 1.00."); } return glsl_type::get_array_instance(base, length); @@ -1509,16 +1794,12 @@ ast_type_specifier::glsl_type(const char **name, { const struct glsl_type *type; - if ((this->type_specifier == ast_struct) && (this->type_name == NULL)) { - /* FINISHME: Handle annonymous structures. */ - type = NULL; - } else { - type = state->symbols->get_type(this->type_name); - *name = this->type_name; + type = state->symbols->get_type(this->type_name); + *name = this->type_name; - if (this->is_array) { - type = process_array_type(type, this->array_size, state); - } + if (this->is_array) { + YYLTYPE loc = this->get_location(); + type = process_array_type(&loc, type, this->array_size, state); } return type; @@ -1531,18 +1812,26 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { - if (qual->invariant) - var->invariant = 1; + 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); + } else { + var->invariant = 1; + } + } - /* FINISHME: Mark 'in' variables at global scope as read-only. */ - if (qual->constant || qual->attribute || qual->uniform - || (qual->varying && (state->target == fragment_shader))) + 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; - if (qual->centroid) + if (qual->flags.q.centroid) var->centroid = 1; - if (qual->attribute && state->target != vertex_shader) { + if (qual->flags.q.attribute && state->target != vertex_shader) { var->type = glsl_type::error_type; _mesa_glsl_error(loc, state, "`attribute' variables may not be declared in the " @@ -1556,7 +1845,7 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, * float, vec2, vec3, vec4, mat2, mat3, and mat4, or arrays of * these." */ - if (qual->varying) { + if (qual->flags.q.varying) { const glsl_type *non_array_type; if (var->type && var->type->is_array()) @@ -1574,28 +1863,46 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, /* If there is no qualifier that changes the mode of the variable, leave * the setting alone. */ - if (qual->in && qual->out) + if (qual->flags.q.in && qual->flags.q.out) var->mode = ir_var_inout; - else if (qual->attribute || qual->in - || (qual->varying && (state->target == fragment_shader))) + else if (qual->flags.q.attribute || qual->flags.q.in + || (qual->flags.q.varying && (state->target == fragment_shader))) var->mode = ir_var_in; - else if (qual->out || (qual->varying && (state->target == vertex_shader))) + else if (qual->flags.q.out + || (qual->flags.q.varying && (state->target == vertex_shader))) var->mode = ir_var_out; - else if (qual->uniform) + else if (qual->flags.q.uniform) var->mode = ir_var_uniform; - if (qual->flat) + if (state->all_invariant && (state->current_function == NULL)) { + switch (state->target) { + case vertex_shader: + if (var->mode == ir_var_out) + var->invariant = true; + break; + case geometry_shader: + if ((var->mode == ir_var_in) || (var->mode == ir_var_out)) + var->invariant = true; + break; + case fragment_shader: + if (var->mode == ir_var_in) + var->invariant = true; + break; + } + } + + if (qual->flags.q.flat) var->interpolation = ir_var_flat; - else if (qual->noperspective) + else if (qual->flags.q.noperspective) var->interpolation = ir_var_noperspective; else var->interpolation = ir_var_smooth; - var->pixel_center_integer = qual->pixel_center_integer; - var->origin_upper_left = qual->origin_upper_left; - if ((qual->origin_upper_left || qual->pixel_center_integer) + var->pixel_center_integer = qual->flags.q.pixel_center_integer; + var->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->origin_upper_left) + const char *const qual_string = (qual->flags.q.origin_upper_left) ? "origin_upper_left" : "pixel_center_integer"; _mesa_glsl_error(loc, state, @@ -1604,11 +1911,404 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, qual_string); } - if (var->type->is_array() && (state->language_version >= 120)) { + if (qual->flags.q.explicit_location) { + const bool global_scope = (state->current_function == NULL); + bool fail = false; + const char *string = ""; + + /* In the vertex shader only shader inputs can be given explicit + * locations. + * + * In the fragment shader only shader outputs can be given explicit + * locations. + */ + switch (state->target) { + case vertex_shader: + if (!global_scope || (var->mode != ir_var_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_in)) { + 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; + } + } + } + + /* Does the declaration use the 'layout' keyword? + */ + const bool uses_layout = qual->flags.q.pixel_center_integer + || qual->flags.q.origin_upper_left + || qual->flags.q.explicit_location; + + /* Does the declaration use the deprecated 'attribute' or 'varying' + * keywords? + */ + const bool uses_deprecated_qualifier = qual->flags.q.attribute + || qual->flags.q.varying; + + /* Is the 'layout' keyword used with parameters that allow relaxed checking. + * Many implementations of GL_ARB_fragment_coord_conventions_enable and some + * implementations (only Mesa?) GL_ARB_explicit_attrib_location_enable + * allowed the layout qualifier to be used with 'varying' and 'attribute'. + * These extensions and all following extensions that add the 'layout' + * keyword have been modified to require the use of 'in' or 'out'. + * + * The following extension do not allow the deprecated keywords: + * + * GL_AMD_conservative_depth + * GL_ARB_gpu_shader5 + * GL_ARB_separate_shader_objects + * GL_ARB_tesselation_shader + * GL_ARB_transform_feedback3 + * GL_ARB_uniform_buffer_object + * + * It is unknown whether GL_EXT_shader_image_load_store or GL_NV_gpu_shader5 + * allow layout with the deprecated keywords. + */ + const bool relaxed_layout_qualifier_checking = + state->ARB_fragment_coord_conventions_enable; + + if (uses_layout && uses_deprecated_qualifier) { + if (relaxed_layout_qualifier_checking) { + _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'"); + } + } + + /* Layout qualifiers for gl_FragDepth, which are enabled by extension + * AMD_conservative_depth. + */ + int depth_layout_count = qual->flags.q.depth_any + + qual->flags.q.depth_greater + + qual->flags.q.depth_less + + qual->flags.q.depth_unchanged; + if (depth_layout_count > 0 + && !state->AMD_conservative_depth_enable) { + _mesa_glsl_error(loc, state, + "extension GL_AMD_conservative_depth must be enabled " + "to use depth layout qualifiers"); + } else if (depth_layout_count > 0 + && strcmp(var->name, "gl_FragDepth") != 0) { + _mesa_glsl_error(loc, state, + "depth layout qualifiers can be applied only to " + "gl_FragDepth"); + } else if (depth_layout_count > 1 + && strcmp(var->name, "gl_FragDepth") == 0) { + _mesa_glsl_error(loc, state, + "at most one depth layout qualifier can be applied to " + "gl_FragDepth"); + } + if (qual->flags.q.depth_any) + var->depth_layout = ir_depth_layout_any; + else if (qual->flags.q.depth_greater) + var->depth_layout = ir_depth_layout_greater; + else if (qual->flags.q.depth_less) + var->depth_layout = ir_depth_layout_less; + else if (qual->flags.q.depth_unchanged) + var->depth_layout = ir_depth_layout_unchanged; + else + var->depth_layout = ir_depth_layout_none; + + if (var->type->is_array() && state->language_version != 110) { var->array_lvalue = true; } } +/** + * Get the variable that is being redeclared by this declaration + * + * Semantic checks to verify the validity of the redeclaration are also + * performed. If semantic checks fail, compilation error will be emitted via + * \c _mesa_glsl_error, but a non-\c NULL pointer will still be returned. + * + * \returns + * 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) +{ + /* Check if this declaration is actually a re-declaration, either to + * resize an array or add qualifiers to an existing variable. + * + * 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); + if (earlier == NULL || + (state->current_function != NULL && + !state->symbols->name_declared_this_scope(decl->identifier))) { + 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() + && (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 + * FINISHME: required or not. + */ + + /* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec: + * + * "The size [of gl_TexCoord] can be at most + * gl_MaxTextureCoords." + */ + const unsigned size = unsigned(var->type->array_size()); + if ((strcmp("gl_TexCoord", var->name) == 0) + && (size > state->Const.MaxTextureCoords)) { + _mesa_glsl_error(& loc, state, "`gl_TexCoord' array size cannot " + "be larger than gl_MaxTextureCoords (%u)\n", + state->Const.MaxTextureCoords); + } else 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); + } + + 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) { + /* 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; + + /* According to section 4.3.7 of the GLSL 1.30 spec, + * the following built-in varaibles can be redeclared with an + * interpolation qualifier: + * * gl_FrontColor + * * gl_BackColor + * * gl_FrontSecondaryColor + * * gl_BackSecondaryColor + * * gl_Color + * * gl_SecondaryColor + */ + } else if (state->language_version >= 130 + && (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; + + /* Layout qualifiers for gl_FragDepth. */ + } else if (state->AMD_conservative_depth_enable + && strcmp(var->name, "gl_FragDepth") == 0 + && earlier->type == var->type + && earlier->mode == var->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"); + } + + /* 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)); + } + + earlier->depth_layout = var->depth_layout; + + } else { + _mesa_glsl_error(&loc, state, "`%s' redeclared", decl->identifier); + } + + return earlier; +} + +/** + * Generate the IR for an initializer in a variable declaration + */ +ir_rvalue * +process_initializer(ir_variable *var, ast_declaration *decl, + ast_fully_specified_type *type, + exec_list *initializer_instructions, + struct _mesa_glsl_parse_state *state) +{ + ir_rvalue *result = NULL; + + YYLTYPE initializer_loc = decl->initializer->get_location(); + + /* From page 24 (page 30 of the PDF) of the GLSL 1.10 spec: + * + * "All uniform variables are read-only and are initialized either + * directly by an application via API commands, or indirectly by + * OpenGL." + */ + if ((state->language_version <= 110) + && (var->mode == ir_var_uniform)) { + _mesa_glsl_error(& initializer_loc, state, + "cannot initialize uniforms in GLSL 1.10"); + } + + if (var->type->is_sampler()) { + _mesa_glsl_error(& initializer_loc, state, + "cannot initialize samplers"); + } + + if ((var->mode == ir_var_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) + ? "attribute" : "varying"); + } + + ir_dereference *const lhs = new(state) ir_dereference_variable(var); + 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); + if (new_rhs != NULL) { + rhs = new_rhs; + + ir_constant *constant_value = rhs->constant_expression_value(); + if (!constant_value) { + _mesa_glsl_error(& initializer_loc, state, + "initializer of %s variable `%s' must be a " + "constant expression", + (type->qualifier.flags.q.constant) + ? "const" : "uniform", + decl->identifier); + if (var->type->is_numeric()) { + /* Reduce cascading errors. */ + var->constant_value = ir_constant::zero(state, var->type); + } + } else { + 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 (rhs && !rhs->type->is_error()) { + bool temp = var->read_only; + if (type->qualifier.flags.q.constant) + var->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, + lhs, rhs, + type->get_location()); + initializer_type = result->type; + } else + initializer_type = rhs->type; + + /* If the declared variable is an unsized array, it must inherrit + * its full type from the initializer. A declaration such as + * + * uniform float a[] = float[](1.0, 2.0, 3.0, 3.0); + * + * becomes + * + * uniform float a[4] = float[](1.0, 2.0, 3.0, 3.0); + * + * The assignment generated in the if-statement (below) will also + * automatically handle this case for non-uniforms. + * + * If the declared variable is not an array, the types must + * already match exactly. As a result, the type assignment + * here can be done unconditionally. For non-uniforms the call + * to do_assignment can change the type of the initializer (via + * the implicit conversion rules). For uniforms the initializer + * must be a constant expression, and the type of that expression + * was validated above. + */ + var->type = initializer_type; + + var->read_only = temp; + } + + return result; +} ir_rvalue * ast_declarator_list::hir(exec_list *instructions, @@ -1661,6 +2361,11 @@ ast_declarator_list::hir(exec_list *instructions, _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; } @@ -1714,7 +2419,8 @@ ast_declarator_list::hir(exec_list *instructions, } if (decl->is_array) { - var_type = process_array_type(decl_type, decl->array_size, state); + var_type = process_array_type(&loc, decl_type, decl->array_size, + state); } else { var_type = decl_type; } @@ -1729,20 +2435,23 @@ ast_declarator_list::hir(exec_list *instructions, * * Local variables can only use the qualifier const." * - * This is relaxed in GLSL 1.30. + * This is relaxed in GLSL 1.30. It is also relaxed by any extension + * that adds the 'layout' keyword. */ - if (state->language_version < 120) { - if (this->type->qualifier.out) { + if ((state->language_version < 130) + && !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 GLSL 1.10.", - decl->identifier); + "only valid for function parameters in %s.", + decl->identifier, state->version_string); } - if (this->type->qualifier.in) { + if (this->type->qualifier.flags.q.in) { _mesa_glsl_error(& loc, state, "`in' qualifier in declaration of `%s' " - "only valid for function parameters in GLSL 1.10.", - decl->identifier); + "only valid for function parameters in %s.", + decl->identifier, state->version_string); } /* FINISHME: Test for other invalid qualifiers. */ } @@ -1750,7 +2459,7 @@ ast_declarator_list::hir(exec_list *instructions, apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc); - if (this->type->qualifier.invariant) { + if (this->type->qualifier.flags.q.invariant) { if ((state->target == vertex_shader) && !(var->mode == ir_var_out || var->mode == ir_var_inout)) { /* FINISHME: Note that this doesn't work for invariant on @@ -1777,16 +2486,16 @@ ast_declarator_list::hir(exec_list *instructions, /* There is no need to check for 'inout' here because the parser will * only allow that in function parameter lists. */ - if (this->type->qualifier.attribute) { + if (this->type->qualifier.flags.q.attribute) { mode = "attribute"; - } else if (this->type->qualifier.uniform) { + } else if (this->type->qualifier.flags.q.uniform) { mode = "uniform"; - } else if (this->type->qualifier.varying) { + } else if (this->type->qualifier.flags.q.varying) { mode = "varying"; - } else if (this->type->qualifier.in) { + } else if (this->type->qualifier.flags.q.in) { mode = "in"; extra = " or in function parameter list"; - } else if (this->type->qualifier.out) { + } else if (this->type->qualifier.flags.q.out) { mode = "out"; extra = " or in function parameter list"; } @@ -1798,6 +2507,8 @@ ast_declarator_list::hir(exec_list *instructions, mode, var->name, extra); } } else if (var->mode == ir_var_in) { + var->read_only = true; + if (state->target == vertex_shader) { bool error_emitted = false; @@ -1850,94 +2561,144 @@ ast_declarator_list::hir(exec_list *instructions, } } - /* Process the initializer and add its instructions to a temporary - * list. This list will be added to the instruction stream (below) after - * the declaration is added. This is done because in some cases (such as - * redeclarations) the declaration may not actually be added to the - * instruction stream. + /* Integer vertex outputs must be qualified with 'flat'. + * + * From section 4.3.6 of the GLSL 1.30 spec: + * "If a vertex output is a signed or unsigned integer or integer + * vector, then it must be qualified with the interpolation qualifier + * flat." */ - exec_list initializer_instructions; - if (decl->initializer != NULL) { - YYLTYPE initializer_loc = decl->initializer->get_location(); + if (state->language_version >= 130 + && state->target == vertex_shader + && state->current_function == NULL + && var->type->is_integer() + && var->mode == ir_var_out + && var->interpolation != ir_var_flat) { + + _mesa_glsl_error(&loc, state, "If a vertex output is an integer, " + "then it must be qualified with 'flat'"); + } - /* From page 24 (page 30 of the PDF) of the GLSL 1.10 spec: - * - * "All uniform variables are read-only and are initialized either - * directly by an application via API commands, or indirectly by - * OpenGL." - */ - if ((state->language_version <= 110) - && (var->mode == ir_var_uniform)) { - _mesa_glsl_error(& initializer_loc, state, - "cannot initialize uniforms in GLSL 1.10"); - } - if (var->type->is_sampler()) { - _mesa_glsl_error(& initializer_loc, state, - "cannot initialize samplers"); - } + /* Interpolation qualifiers cannot be applied to 'centroid' and + * 'centroid varying'. + * + * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec: + * "interpolation qualifiers may only precede the qualifiers in, + * centroid in, out, or centroid out in a declaration. They do not apply + * to the deprecated storage qualifiers varying or centroid varying." + */ + if (state->language_version >= 130 + && this->type->qualifier.has_interpolation() + && this->type->qualifier.flags.q.varying) { + + const char *i = this->type->qualifier.interpolation_string(); + assert(i != NULL); + const char *s; + if (this->type->qualifier.flags.q.centroid) + s = "centroid varying"; + else + s = "varying"; + + _mesa_glsl_error(&loc, state, + "qualifier '%s' cannot be applied to the " + "deprecated storage qualifier '%s'", i, s); + } - if ((var->mode == ir_var_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) - ? "attribute" : "varying"); - } - ir_dereference *const lhs = new(ctx) ir_dereference_variable(var); - ir_rvalue *rhs = decl->initializer->hir(&initializer_instructions, - state); + /* Interpolation qualifiers can only apply to vertex shader outputs and + * fragment shader inputs. + * + * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec: + * "Outputs from a vertex shader (out) and inputs to a fragment + * shader (in) can be further qualified with one or more of these + * interpolation qualifiers" + */ + if (state->language_version >= 130 + && this->type->qualifier.has_interpolation()) { + + const char *i = this->type->qualifier.interpolation_string(); + assert(i != NULL); + + switch (state->target) { + case vertex_shader: + 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: + if (this->type->qualifier.flags.q.out) { + _mesa_glsl_error(&loc, state, + "qualifier '%s' cannot be applied to fragment " + "shader outputs", i); + } + break; + default: + assert(0); + } + } - /* Calculate the constant value if this is a const or uniform - * declaration. - */ - if (this->type->qualifier.constant || this->type->qualifier.uniform) { - ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs); - if (new_rhs != NULL) { - rhs = new_rhs; - - ir_constant *constant_value = rhs->constant_expression_value(); - if (!constant_value) { - _mesa_glsl_error(& initializer_loc, state, - "initializer of %s variable `%s' must be a " - "constant expression", - (this->type->qualifier.constant) - ? "const" : "uniform", - decl->identifier); - if (var->type->is_numeric()) { - /* Reduce cascading errors. */ - var->constant_value = ir_constant::zero(ctx, var->type); - } - } else { - 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(ctx, var->type); - } - } - } - if (rhs && !rhs->type->is_error()) { - bool temp = var->read_only; - if (this->type->qualifier.constant) - var->read_only = false; + /* From section 4.3.4 of the GLSL 1.30 spec: + * "It is an error to use centroid in in a vertex shader." + */ + if (state->language_version >= 130 + && this->type->qualifier.flags.q.centroid + && this->type->qualifier.flags.q.in + && state->target == vertex_shader) { - /* Never emit code to initialize a uniform. - */ - if (!this->type->qualifier.uniform) - result = do_assignment(&initializer_instructions, state, - lhs, rhs, - this->get_location()); - var->read_only = temp; - } + _mesa_glsl_error(&loc, state, + "'centroid in' cannot be used in a vertex shader"); + } + + + /* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30. + */ + if (this->type->specifier->precision != ast_precision_none + && state->language_version != 100 + && state->language_version < 130) { + + _mesa_glsl_error(&loc, state, + "precision qualifiers are supported only in GLSL ES " + "1.00, and GLSL 1.30 and later"); + } + + + /* Precision qualifiers only apply to floating point and integer types. + * + * From section 4.5.2 of the GLSL 1.30 spec: + * "Any floating point or any integer declaration can have the type + * preceded by one of these precision qualifiers [...] Literal + * constants do not have precision qualifiers. Neither do Boolean + * variables. + */ + if (this->type->specifier->precision != ast_precision_none + && !var->type->is_float() + && !var->type->is_integer() + && !(var->type->is_array() + && (var->type->fields.array->is_float() + || var->type->fields.array->is_integer()))) { + + _mesa_glsl_error(&loc, state, + "precision qualifiers apply only to floating point " + "and integer types"); + } + + /* Process the initializer and add its instructions to a temporary + * list. This list will be added to the instruction stream (below) after + * the declaration is added. This is done because in some cases (such as + * redeclarations) the declaration may not actually be added to the + * instruction stream. + */ + exec_list initializer_instructions; + ir_variable *earlier = get_variable_being_redeclared(var, decl, state); + + if (decl->initializer != NULL) { + 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: @@ -1946,117 +2707,56 @@ ast_declarator_list::hir(exec_list *instructions, * its declaration, so they must be initialized when * declared." */ - if (this->type->qualifier.constant && decl->initializer == NULL) { + if (this->type->qualifier.flags.q.constant && decl->initializer == NULL) { _mesa_glsl_error(& loc, state, - "const declaration of `%s' must be initialized"); + "const declaration of `%s' must be initialized", + decl->identifier); } - /* Check if this declaration is actually a re-declaration, either to - * resize an array or add qualifiers to an existing variable. - * - * This is allowed for variables in the current scope, or when at - * global scope (for built-ins in the implicit outer scope). + /* If the declaration is not a redeclaration, there are a few additional + * semantic checks that must be applied. In addition, variable that was + * created for the declaration should be added to the IR stream. */ - ir_variable *earlier = state->symbols->get_variable(decl->identifier); - if (earlier != NULL && (state->current_function == NULL || - state->symbols->name_declared_this_scope(decl->identifier))) { - - /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec, + if (earlier == NULL) { + /* From page 15 (page 21 of the PDF) of the GLSL 1.10 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." + * "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 ((earlier->type->array_size() == 0) - && 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 - * FINISHME: required or not. - */ - - /* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec: - * - * "The size [of gl_TexCoord] can be at most - * gl_MaxTextureCoords." - */ - const unsigned size = unsigned(var->type->array_size()); - if ((strcmp("gl_TexCoord", var->name) == 0) - && (size > state->Const.MaxTextureCoords)) { - YYLTYPE loc = this->get_location(); - - _mesa_glsl_error(& loc, state, "`gl_TexCoord' array size cannot " - "be larger than gl_MaxTextureCoords (%u)\n", - state->Const.MaxTextureCoords); - } else if ((size > 0) && (size <= earlier->max_array_access)) { - YYLTYPE loc = this->get_location(); - - _mesa_glsl_error(& loc, state, "array size must be > %u due to " - "previous access", - earlier->max_array_access); - } + if (strncmp(decl->identifier, "gl_", 3) == 0) + _mesa_glsl_error(& loc, state, + "identifier `%s' uses reserved `gl_' prefix", + decl->identifier); - earlier->type = var->type; - delete var; - var = NULL; - } else if (state->extensions->ARB_fragment_coord_conventions - && strcmp(var->name, "gl_FragCoord") == 0 - && earlier->type == var->type - && earlier->mode == var->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; - } else { + /* 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, "`%s' redeclared", decl->identifier); + _mesa_glsl_error(&loc, state, "name `%s' already taken in the " + "current scope", decl->identifier); + continue; } - continue; - } - - /* By now, we know it's a new variable declaration (we didn't hit the - * above "continue"). - * - * 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); - - /* 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->name, 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); } - /* 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); } @@ -2129,7 +2829,7 @@ ast_parameter_declarator::hir(exec_list *instructions, * call already handled the "vec4[..] foo" case. */ if (this->is_array) { - type = process_array_type(type, this->array_size, state); + type = process_array_type(&loc, type, this->array_size, state); } if (type->array_size() == 0) { @@ -2182,6 +2882,27 @@ ast_parameter_declarator::parameters_to_hir(exec_list *ast_parameters, } +void +emit_function(_mesa_glsl_parse_state *state, exec_list *instructions, + ir_function *f) +{ + /* Emit the new function header */ + if (state->current_function == NULL) { + instructions->push_tail(f); + } else { + /* IR invariants disallow function declarations or definitions nested + * within other function definitions. Insert the new ir_function + * block in the instruction sequence before the ir_function block + * containing the current ir_function_signature. + */ + ir_function *const curr = + const_cast(state->current_function->function()); + + curr->insert_before(f); + } +} + + ir_rvalue * ast_function::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) @@ -2258,7 +2979,7 @@ ast_function::hir(exec_list *instructions, * that the previously seen signature does not have an associated definition. */ f = state->symbols->get_function(name); - if (f != NULL && !f->is_builtin) { + if (f != NULL && (state->es_shader || f->has_user_signature())) { sig = f->exact_matching_signature(&hir_parameters); if (sig != NULL) { const char *badvar = sig->qualifiers_match(&hir_parameters); @@ -2284,7 +3005,7 @@ ast_function::hir(exec_list *instructions, } } else { f = new(ctx) ir_function(name); - if (!state->symbols->add_function(f->name, f)) { + if (!state->symbols->add_function(f)) { /* This function name shadows a non-function use of the same name. */ YYLTYPE loc = this->get_location(); @@ -2293,24 +3014,7 @@ ast_function::hir(exec_list *instructions, return NULL; } - /* Emit the new function header */ - if (state->current_function == NULL) - instructions->push_tail(f); - else { - /* IR invariants disallow function declarations or definitions nested - * within other function definitions. Insert the new ir_function - * block in the instruction sequence before the ir_function block - * containing the current ir_function_signature. - * - * This can only happen in a GLSL 1.10 shader. In all other GLSL - * versions this nesting is disallowed. There is a check for this at - * the top of this function. - */ - ir_function *const curr = - const_cast(state->current_function->function()); - - curr->insert_before(f); - } + emit_function(state, instructions, f); } /* Verify the return type of main() */ @@ -2376,7 +3080,7 @@ ast_function_definition::hir(exec_list *instructions, _mesa_glsl_error(& loc, state, "parameter `%s' redeclared", var->name); } else { - state->symbols->add_variable(var->name, var); + state->symbols->add_variable(var); } } @@ -2415,28 +3119,26 @@ ast_jump_statement::hir(exec_list *instructions, assert(state->current_function); if (opt_return_value) { - if (state->current_function->return_type->base_type == - GLSL_TYPE_VOID) { - YYLTYPE loc = this->get_location(); + ir_rvalue *const ret = opt_return_value->hir(instructions, state); - _mesa_glsl_error(& loc, state, - "`return` with a value, in function `%s' " - "returning void", - state->current_function->function_name()); - } - - ir_expression *const ret = (ir_expression *) - opt_return_value->hir(instructions, state); - assert(ret != NULL); + /* 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. */ - if (state->current_function->return_type != ret->type) { + if (state->current_function->return_type != ret_type) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(& loc, state, "`return' with wrong type %s, in function `%s' " "returning %s", - ret->type->name, + ret_type->name, state->current_function->function_name(), state->current_function->return_type->name); } @@ -2653,6 +3355,58 @@ ir_rvalue * ast_type_specifier::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { + if (!this->is_precision_statement && this->structure == NULL) + return NULL; + + YYLTYPE loc = this->get_location(); + + if (this->precision != ast_precision_none + && state->language_version != 100 + && state->language_version < 130) { + _mesa_glsl_error(&loc, state, + "precision qualifiers exist only in " + "GLSL ES 1.00, and GLSL 1.30 and later"); + return NULL; + } + if (this->precision != ast_precision_none + && this->structure != NULL) { + _mesa_glsl_error(&loc, state, + "precision qualifiers do not apply to structures"); + return NULL; + } + + /* If this is a precision statement, check that the type to which it is + * applied is either float or int. + * + * From section 4.5.3 of the GLSL 1.30 spec: + * "The precision statement + * precision precision-qualifier type; + * can be used to establish a default precision qualifier. The type + * field can be either int or float [...]. Any other types or + * qualifiers will result in an error. + */ + if (this->is_precision_statement) { + assert(this->precision != ast_precision_none); + assert(this->structure == NULL); /* The check for structures was + * performed above. */ + if (this->is_array) { + _mesa_glsl_error(&loc, state, + "default precision statements do not apply to " + "arrays"); + return NULL; + } + if (this->type_specifier != ast_float + && this->type_specifier != ast_int) { + _mesa_glsl_error(&loc, state, + "default precision statements apply only to types " + "float and int"); + return NULL; + } + + /* FINISHME: Translate precision statements into IR. */ + return NULL; + } + if (this->structure != NULL) return this->structure->hir(instructions, state); @@ -2678,13 +3432,12 @@ ast_struct_specifier::hir(exec_list *instructions, } } - /* Allocate storage for the structure fields and process the field * declarations. As the declarations are processed, try to also convert * the types to HIR. This ensures that structure definitions embedded in * other structure definitions are processed. */ - glsl_struct_field *const fields = talloc_array(state, glsl_struct_field, + glsl_struct_field *const fields = ralloc_array(state, glsl_struct_field, decl_count); unsigned i = 0; @@ -2694,16 +3447,26 @@ ast_struct_specifier::hir(exec_list *instructions, decl_list->type->specifier->hir(instructions, state); + /* Section 10.9 of the GLSL ES 1.00 specification states that + * embedded structure definitions have been removed from the language. + */ + if (state->es_shader && decl_list->type->specifier->structure != NULL) { + YYLTYPE loc = this->get_location(); + _mesa_glsl_error(&loc, state, "Embedded structure definitions are " + "not allowed in GLSL ES 1.00."); + } + const glsl_type *decl_type = decl_list->type->specifier->glsl_type(& type_name, state); foreach_list_typed (ast_declaration, decl, link, &decl_list->declarations) { - const struct glsl_type *const field_type = - (decl->is_array) - ? process_array_type(decl_type, decl->array_size, state) - : decl_type; - + const struct glsl_type *field_type = decl_type; + if (decl->is_array) { + YYLTYPE loc = decl->get_location(); + field_type = process_array_type(&loc, decl_type, decl->array_size, + state); + } fields[i].type = (field_type != NULL) ? field_type : glsl_type::error_type; fields[i].name = decl->identifier; @@ -2713,31 +3476,16 @@ ast_struct_specifier::hir(exec_list *instructions, assert(i == decl_count); - const char *name; - if (this->name == NULL) { - static unsigned anon_count = 1; - char buf[32]; - - snprintf(buf, sizeof(buf), "#anon_struct_%04x", anon_count); - anon_count++; - - name = strdup(buf); - } else { - name = this->name; - } - const glsl_type *t = - glsl_type::get_record_instance(fields, decl_count, name); + glsl_type::get_record_instance(fields, decl_count, this->name); YYLTYPE loc = this->get_location(); if (!state->symbols->add_type(name, t)) { _mesa_glsl_error(& loc, state, "struct `%s' previously defined", name); } else { - - const glsl_type **s = (const glsl_type **) - realloc(state->user_structures, - sizeof(state->user_structures[0]) * - (state->num_user_structures + 1)); + const glsl_type **s = reralloc(state, state->user_structures, + const glsl_type *, + state->num_user_structures + 1); if (s != NULL) { s[state->num_user_structures] = t; state->user_structures = s;