X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fast_to_hir.cpp;h=acb5c763c43c0cab7fb9aa0f7f24ed3bfe9f546f;hb=187ace73a93d87122a977e4afade237be159ab04;hp=43cf49745573a772d5d56d26ac6ac7b93fbf81a1;hpb=3c9f0096c75315ea73d44ec17bc90c4d4c0d8f77;p=mesa.git diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 43cf4974557..acb5c763c43 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -49,13 +49,15 @@ * parser (and lexer) sources. */ -#include "main/core.h" /* for struct gl_extensions */ #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" #include "ast.h" #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, @@ -77,6 +79,7 @@ _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 @@ -109,8 +112,8 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) * applications depend on this behavior, and it matches what nearly all * other drivers do. */ - foreach_list_safe(node, instructions) { - ir_variable *const var = ((ir_instruction *) node)->as_variable(); + foreach_in_list_safe(ir_instruction, node, instructions) { + ir_variable *const var = node->as_variable(); if (var == NULL) continue; @@ -119,6 +122,11 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) 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 @@ -155,6 +163,42 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) } +static ir_expression_operation +get_conversion_operation(const glsl_type *to, const glsl_type *from, + struct _mesa_glsl_parse_state *state) +{ + switch (to->base_type) { + case GLSL_TYPE_FLOAT: + switch (from->base_type) { + case GLSL_TYPE_INT: return ir_unop_i2f; + case GLSL_TYPE_UINT: return ir_unop_u2f; + case GLSL_TYPE_DOUBLE: return ir_unop_d2f; + default: return (ir_expression_operation)0; + } + + case GLSL_TYPE_UINT: + if (!state->is_version(400, 0) && !state->ARB_gpu_shader5_enable) + return (ir_expression_operation)0; + switch (from->base_type) { + case GLSL_TYPE_INT: return ir_unop_i2u; + default: return (ir_expression_operation)0; + } + + case GLSL_TYPE_DOUBLE: + if (!state->has_double()) + return (ir_expression_operation)0; + switch (from->base_type) { + case GLSL_TYPE_INT: return ir_unop_i2d; + case GLSL_TYPE_UINT: return ir_unop_u2d; + case GLSL_TYPE_FLOAT: return ir_unop_f2d; + default: return (ir_expression_operation)0; + } + + default: return (ir_expression_operation)0; + } +} + + /** * If a conversion is available, convert one operand to a different type * @@ -170,15 +214,13 @@ _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) return true; - /* This conversion was added in GLSL 1.20. If the compilation mode is - * GLSL 1.10, the conversion is skipped. - */ + /* Prior to GLSL 1.20, there are no implicit conversions */ if (!state->is_version(120, 0)) return false; @@ -186,43 +228,32 @@ apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from, * * "There are no implicit array or structure conversions. For * example, an array of int cannot be implicitly converted to an - * array of float. There are no implicit conversions between - * signed and unsigned integers." - */ - /* FINISHME: The above comment is partially a lie. There is int/uint - * FINISHME: conversion for immediate constants. + * array of float. */ - if (!to->is_float() || !from->type->is_numeric()) + if (!to->is_numeric() || !from->type->is_numeric()) return false; - /* Convert to a floating point type with the same number of components - * as the original type - i.e. int to float, not int to vec4. + /* We don't actually want the specific type `to`, we want a type + * with the same base type as `to`, but the same vector width as + * `from`. */ - to = glsl_type::get_instance(GLSL_TYPE_FLOAT, from->type->vector_elements, - from->type->matrix_columns); + to = glsl_type::get_instance(to->base_type, from->type->vector_elements, + from->type->matrix_columns); - switch (from->type->base_type) { - case GLSL_TYPE_INT: - from = new(ctx) ir_expression(ir_unop_i2f, to, from, NULL); - break; - case GLSL_TYPE_UINT: - from = new(ctx) ir_expression(ir_unop_u2f, to, from, NULL); - break; - case GLSL_TYPE_BOOL: - from = new(ctx) ir_expression(ir_unop_b2f, to, from, NULL); - break; - default: - assert(0); + ir_expression_operation op = get_conversion_operation(to, from->type, state); + if (op) { + from = new(ctx) ir_expression(op, to, from, NULL); + return true; + } else { + return false; } - - return true; } 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; @@ -235,7 +266,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; } @@ -247,8 +278,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; @@ -265,7 +296,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; } @@ -287,7 +318,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; } @@ -305,11 +336,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; } } @@ -320,8 +351,10 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, * type of both operands must be float. */ assert(type_a->is_matrix() || type_b->is_matrix()); - assert(type_a->base_type == GLSL_TYPE_FLOAT); - assert(type_b->base_type == GLSL_TYPE_FLOAT); + assert(type_a->base_type == GLSL_TYPE_FLOAT || + type_a->base_type == GLSL_TYPE_DOUBLE); + assert(type_b->base_type == GLSL_TYPE_FLOAT || + type_b->base_type == GLSL_TYPE_DOUBLE); /* "* The operator is add (+), subtract (-), or divide (/), and the * operands are matrices with the same number of rows and the same @@ -340,64 +373,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"); @@ -414,7 +447,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: * @@ -426,7 +459,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; } @@ -500,8 +533,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; @@ -522,7 +555,7 @@ modulus_result_type(const struct glsl_type *type_a, } 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; } @@ -533,8 +566,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; @@ -548,7 +581,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; @@ -563,8 +596,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; } @@ -575,8 +608,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; @@ -619,13 +652,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; } @@ -634,8 +667,8 @@ shift_result_type(const struct glsl_type *type_a, */ 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)); + "second must be scalar as well", + ast_expression::operator_string(op)); return glsl_type::error_type; } @@ -646,8 +679,8 @@ shift_result_type(const struct glsl_type *type_a, 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)); + "have same number of elements", + ast_expression::operator_string(op)); return glsl_type::error_type; } @@ -728,26 +761,29 @@ 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_loc, lhs->type, rhs, is_initializer); @@ -755,48 +791,58 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, if (new_rhs == NULL) { return lhs; } else { + /* This converts: + * - LHS: (expression float vector_extract ) + * - RHS: + * into: + * - LHS: + * - RHS: (expression vec2 vector_insert ) + * + * 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; - } else if (lhs->variable_referenced() != NULL - && lhs->variable_referenced()->read_only) { + non_lvalue_description); + error_emitted = true; + } else if (lhs_var != NULL && lhs_var->data.read_only) { _mesa_glsl_error(&lhs_loc, state, "assignment to read-only variable '%s'", - lhs->variable_referenced()->name); + lhs_var->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; } } @@ -811,27 +857,29 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, * is either not an l-value or not a whole array. */ if (lhs->type->is_unsized_array()) { - ir_dereference *const d = lhs->as_dereference(); + 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, @@ -839,22 +887,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) { + 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); - if (!error_emitted) - instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var)); + if (extract_channel) { + rvalue = new(ctx) ir_expression(ir_binop_vector_extract, + rvalue, + extract_channel->clone(ctx, NULL)); + } - return new(ctx) ir_dereference_variable(var); + *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 * @@ -866,7 +925,6 @@ 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; instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var), lvalue)); @@ -876,8 +934,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; @@ -885,6 +942,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) { @@ -901,23 +972,24 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1) case GLSL_TYPE_UINT: case GLSL_TYPE_INT: case GLSL_TYPE_BOOL: + case GLSL_TYPE_DOUBLE: 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; - } + 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); @@ -927,20 +999,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; } @@ -948,6 +1020,7 @@ 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 @@ -984,8 +1057,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; } @@ -1051,7 +1124,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] = { @@ -1119,18 +1207,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; } @@ -1152,7 +1240,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: @@ -1163,12 +1251,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: @@ -1180,7 +1268,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; @@ -1216,7 +1304,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; @@ -1235,15 +1323,15 @@ 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"); @@ -1251,10 +1339,10 @@ ast_expression::hir(exec_list *instructions, } 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; @@ -1266,7 +1354,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; @@ -1274,12 +1362,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; @@ -1289,35 +1377,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; } @@ -1325,35 +1413,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; } @@ -1366,20 +1454,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: @@ -1390,17 +1478,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 @@ -1420,13 +1509,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; } @@ -1438,11 +1528,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; } @@ -1455,11 +1546,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; } @@ -1471,7 +1563,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 @@ -1494,16 +1586,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: @@ -1515,40 +1607,38 @@ ast_expression::hir(exec_list *instructions, !state->check_version(120, 300, &loc, "second and third operands of ?: operator " "cannot be arrays")) { - error_emitted = true; + 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(); 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) { + result = cond_val->value.b[0] ? op[1] : op[2]; } 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; } @@ -1556,7 +1646,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); @@ -1565,20 +1655,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); @@ -1588,19 +1679,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; } @@ -1615,10 +1708,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; } @@ -1636,17 +1729,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; } @@ -1667,6 +1760,10 @@ ast_expression::hir(exec_list *instructions, result = new(ctx) ir_constant(bool(this->primary_expression.bool_constant)); break; + case ast_double_constant: + result = new(ctx) ir_constant(this->primary_expression.double_constant); + break; + case ast_sequence: { /* It should not be possible to generate a sequence in the AST without * any expressions in it. @@ -1682,37 +1779,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. @@ -1722,9 +1819,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; @@ -1733,7 +1830,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: @@ -1745,7 +1842,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. */ @@ -1755,7 +1852,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(); @@ -1771,80 +1868,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; } @@ -1860,7 +1997,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(); @@ -1882,15 +2019,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; } } @@ -1900,7 +2037,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) { @@ -1941,7 +2078,7 @@ 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"); return false; @@ -1983,18 +2120,7 @@ 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 = 0; - 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 " @@ -2049,8 +2175,8 @@ interpret_interpolation_qualifier(const struct ast_type_qualifier *qual, } - if ((state->target == vertex_shader && mode == ir_var_shader_in) || - (state->target == fragment_shader && mode == ir_var_shader_out)) { + 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", @@ -2070,32 +2196,91 @@ validate_explicit_location(const struct ast_type_qualifier *qual, { bool fail = false; - /* In the vertex shader only shader inputs can be given explicit - * locations. + /* Checks for GL_ARB_explicit_uniform_location. */ + if (qual->flags.q.uniform) { + if (!state->check_explicit_uniform_location_allowed(loc, var)) + return; + + const struct gl_context *const ctx = state->ctx; + unsigned max_loc = qual->location + var->type->uniform_locations() - 1; + + /* ARB_explicit_uniform_location specification states: + * + * "The explicitly defined locations and the generated locations + * must be in the range of 0 to MAX_UNIFORM_LOCATIONS minus one." + * + * "Valid locations for default-block uniform variable locations + * are in the range of 0 to the implementation-defined maximum + * number of uniform locations." + */ + if (qual->location < 0) { + _mesa_glsl_error(loc, state, + "explicit location < 0 for uniform %s", var->name); + return; + } + + if (max_loc >= ctx->Const.MaxUserAssignableUniformLocations) { + _mesa_glsl_error(loc, state, "location(s) consumed by uniform %s " + ">= MAX_UNIFORM_LOCATIONS (%u)", var->name, + ctx->Const.MaxUserAssignableUniformLocations); + return; + } + + var->data.explicit_location = true; + var->data.location = qual->location; + return; + } + + /* 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: * - * In the fragment shader only shader outputs can be given explicit - * locations. + * input output + * ----- ------ + * vertex explicit_loc sso + * geometry sso sso + * fragment sso explicit_loc */ - switch (state->target) { - case vertex_shader: - if (var->mode == ir_var_shader_in) { + 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 geometry_shader: - _mesa_glsl_error(loc, state, - "geometry shader variables cannot be given " - "explicit locations"); - return; + 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; + } - case fragment_shader: - if (var->mode == ir_var_shader_out) { + if (var->data.mode == ir_var_shader_out) { if (!state->check_explicit_attrib_location_allowed(loc, var)) return; @@ -2104,15 +2289,21 @@ validate_explicit_location(const struct ast_type_qualifier *qual, 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_glsl_shader_target_name(state->target)); + _mesa_shader_stage_to_string(state->stage)); } else { - var->explicit_location = true; + 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 @@ -2122,11 +2313,28 @@ validate_explicit_location(const struct ast_type_qualifier *qual, * 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); + 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->location = qual->location; + var->data.location = qual->location; } if (qual->flags.q.explicit_index) { @@ -2143,49 +2351,149 @@ validate_explicit_location(const struct ast_type_qualifier *qual, _mesa_glsl_error(loc, state, "explicit index may only be 0 or 1"); } else { - var->explicit_index = true; - var->index = qual->index; + 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 |= 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; + 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.precise) { + if (var->data.used) { + _mesa_glsl_error(loc, state, + "variable `%s' may not be redeclared " + "`precise' after being used", + var->name); + } else { + var->data.precise = 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 (state->stage == MESA_SHADER_GEOMETRY && + qual->flags.q.out && qual->flags.q.stream) { + var->data.stream = qual->stream; + } - 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)); + } + + /* Disallow layout qualifiers which may only appear on layout declarations. */ + if (qual->flags.q.prim_type) { + _mesa_glsl_error(loc, state, + "Primitive type may only be specified on GS input or output " + "layout declaration, not on variables."); } /* Section 6.1.1 (Function Calling Conventions) of the GLSL 1.10 spec says: @@ -2206,21 +2514,29 @@ 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. */ + assert(var->data.mode != ir_var_temporary); 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. @@ -2262,6 +2578,8 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, _mesa_glsl_error(loc, state, "varying variables may not be of type struct"); break; + case GLSL_TYPE_DOUBLE: + break; default: _mesa_glsl_error(loc, state, "illegal type for a varying variable"); break; @@ -2269,33 +2587,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; } } - var->interpolation = - interpret_interpolation_qualifier(qual, (ir_variable_mode) var->mode, + 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 " @@ -2303,36 +2624,83 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, qual_string); } - 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"); - } + if (var->name != NULL && strcmp(var->name, "gl_FragCoord") == 0) { - if (qual->flags.q.explicit_binding && + /* Section 4.3.8.1, page 39 of GLSL 1.50 spec says: + * + * "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. + */ + 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"); + } + + 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->mode == ir_var_uniform) { - if (var->explicit_binding) { - unsigned *offset = &state->atomic_counter_offsets[var->binding]; + 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->atomic.offset = *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->mode != ir_var_function_in) { + } 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"); @@ -2345,6 +2713,36 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, const bool uses_deprecated_qualifier = qual->flags.q.attribute || qual->flags.q.varying; + + /* Validate auxiliary storage qualifiers */ + + /* From section 4.3.4 of the GLSL 1.30 spec: + * "It is an error to use centroid in in a vertex shader." + * + * From section 4.3.4 of the GLSL ES 3.00 spec: + * "It is an error to use centroid in or interpolation qualifiers in + * a vertex shader input." + */ + + /* Section 4.3.6 of the GLSL 1.30 specification states: + * "It is an error to use centroid out in a fragment shader." + * + * The GL_ARB_shading_language_420pack extension specification states: + * "It is an error to use auxiliary storage qualifiers or interpolation + * qualifiers on an output in a fragment shader." + */ + if (qual->flags.q.sample && (!is_varying_var(var, state->stage) || uses_deprecated_qualifier)) { + _mesa_glsl_error(loc, state, + "sample qualifier may only be used on `in` or `out` " + "variables between shader stages"); + } + if (qual->flags.q.centroid && !is_varying_var(var, state->stage)) { + _mesa_glsl_error(loc, state, + "centroid qualifier may only be used with `in', " + "`out' or `varying' variables between shader stages"); + } + + /* 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 @@ -2370,13 +2768,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'"); } } @@ -2393,7 +2791,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, @@ -2406,28 +2804,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); } /** @@ -2455,7 +2856,7 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc, ir_variable *earlier = state->symbols->get_variable(var->name); if (earlier == NULL || (state->current_function != NULL && - !state->symbols->name_declared_this_scope(var->name))) { + !state->symbols->name_declared_this_scope(var->name))) { return NULL; } @@ -2475,25 +2876,25 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc, 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 || - state->is_version(150, 0)) - && strcmp(var->name, "gl_FragCoord") == 0 - && earlier->type == var->type - && earlier->mode == var->mode) { + 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 @@ -2506,48 +2907,48 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc, * * 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->mode != var->mode) { + if (earlier->data.mode != var->data.mode) { _mesa_glsl_error(&loc, state, "redeclaration of `%s' with incorrect qualifiers", var->name); @@ -2582,27 +2983,39 @@ 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. @@ -2612,10 +3025,10 @@ process_initializer(ir_variable *var, ast_declaration *decl, 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 @@ -2635,36 +3048,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 { - 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 @@ -2688,7 +3103,7 @@ process_initializer(ir_variable *var, ast_declaration *decl, */ var->type = initializer_type; - var->read_only = temp; + var->data.read_only = temp; } return result; @@ -2705,7 +3120,7 @@ handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state, { unsigned num_vertices = 0; if (state->gs_input_prim_type_specified) { - num_vertices = vertices_per_prim(state->gs_input_prim_type); + num_vertices = vertices_per_prim(state->in_qualifier->prim_type); } /* Geometry shader input variables must be arrays. Caller should have @@ -2780,7 +3195,7 @@ validate_identifier(const char *identifier, YYLTYPE loc, * OpenGL, and may not be declared in a shader as either a * variable or a function." */ - if (strncmp(identifier, "gl_", 3) == 0) { + if (is_gl_identifier(identifier)) { _mesa_glsl_error(&loc, state, "identifier `%s' uses reserved `gl_' prefix", identifier); @@ -2791,17 +3206,59 @@ validate_identifier(const char *identifier, YYLTYPE loc, * "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_error(&loc, state, - "identifier `%s' uses reserved `__' string", - identifier); + _mesa_glsl_warning(&loc, state, + "identifier `%s' uses reserved `__' string", + identifier); } } +static bool +precision_qualifier_allowed(const glsl_type *type) +{ + /* Precision qualifiers apply to floating point, integer and sampler + * types. + * + * Section 4.5.2 (Precision Qualifiers) of the GLSL 1.30 spec says: + * "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. + * + * Section 4.5 (Precision and Precision Qualifiers) of the GLSL 1.30 + * spec also says: + * + * "Precision qualifiers are added for code portability with OpenGL + * ES, not for functionality. They have the same syntax as in OpenGL + * ES." + * + * Section 8 (Built-In Functions) of the GLSL ES 1.00 spec says: + * + * "uniform lowp sampler2D sampler; + * highp vec2 coord; + * ... + * lowp vec4 col = texture2D (sampler, coord); + * // texture2D returns lowp" + * + * From this, we infer that GLSL 1.30 (and later) should allow precision + * qualifiers on sampler types just like float and integer types. + */ + return type->is_float() + || type->is_integer() + || type->is_record() + || type->is_sampler(); +} 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; @@ -2824,40 +3281,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"); + _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", 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", 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", 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. @@ -2865,8 +3315,45 @@ ast_declarator_list::hir(exec_list *instructions, return NULL; } + if (this->precise) { + assert(this->type == NULL); + + foreach_list_typed (ast_declaration, decl, link, &this->declarations) { + 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 " + "precise", decl->identifier); + } else if (state->current_function != NULL && + !state->symbols->name_declared_this_scope(decl->identifier)) { + /* Note: we have to check if we're in a function, since + * builtins are treated as having come from another scope. + */ + _mesa_glsl_error(& loc, state, + "variable `%s' from an outer scope may not be " + "redeclared `precise' in this scope", + earlier->name); + } else if (earlier->data.used) { + _mesa_glsl_error(& loc, state, + "variable `%s' may not be redeclared " + "`precise' after being used", + earlier->name); + } else { + earlier->data.precise = true; + } + } + + /* Precise redeclarations do not have r-values either. */ + return NULL; + } + assert(this->type != NULL); assert(!this->invariant); + assert(!this->precise); /* The type specifier may contain a structure definition. Process that * before any of the variable declarations. @@ -2940,7 +3427,7 @@ ast_declarator_list::hir(exec_list *instructions, precision_names[this->type->qualifier.precision], type_name); } - } else { + } else if (this->type->specifier->structure == NULL) { _mesa_glsl_warning(&loc, state, "empty declaration"); } } @@ -2954,26 +3441,20 @@ 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); @@ -3000,7 +3481,7 @@ ast_declarator_list::hir(exec_list *instructions, /* 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." @@ -3009,94 +3490,86 @@ ast_declarator_list::hir(exec_list *instructions, * any extension that adds the 'layout' keyword. */ if (!state->is_version(130, 300) - && !state->has_explicit_attrib_location() - && !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", 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", 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: * @@ -3104,34 +3577,35 @@ 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; - } - } else if (state->target == geometry_shader) { + 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 @@ -3147,6 +3621,51 @@ ast_declarator_list::hir(exec_list *instructions, handle_geometry_shader_input_decl(state, loc, var); } + } else if (var->data.mode == ir_var_shader_out) { + const glsl_type *check_type = var->type->without_array(); + + /* From section 4.3.6 (Output variables) of the GLSL 4.40 spec: + * + * It is a compile-time error to declare a vertex, tessellation + * evaluation, tessellation control, or geometry shader output + * that contains any of the following: + * + * * A Boolean type (bool, bvec2 ...) + * * An opaque type + */ + if (check_type->is_boolean() || check_type->contains_opaque()) + _mesa_glsl_error(&loc, state, + "%s shader output cannot have type %s", + _mesa_shader_stage_to_string(state->stage), + check_type->name); + + /* From section 4.3.6 (Output variables) of the GLSL 4.40 spec: + * + * It is a compile-time error to declare a fragment shader output + * that contains any of the following: + * + * * A Boolean type (bool, bvec2 ...) + * * A double-precision scalar or vector (double, dvec2 ...) + * * An opaque type + * * Any matrix type + * * A structure + */ + if (state->stage == MESA_SHADER_FRAGMENT) { + if (check_type->is_record() || check_type->is_matrix()) + _mesa_glsl_error(&loc, state, + "fragment shader output " + "cannot have struct or array type"); + switch (check_type->base_type) { + case GLSL_TYPE_UINT: + case GLSL_TYPE_INT: + case GLSL_TYPE_FLOAT: + break; + default: + _mesa_glsl_error(&loc, state, + "fragment shader output cannot have " + "type %s", check_type->name); + } + } } /* Integer fragment inputs must be qualified with 'flat'. In GLSL ES, @@ -3180,17 +3699,26 @@ 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) " "an integer, then it must be qualified with 'flat'", var_type); } + /* Double fragment inputs must be qualified with 'flat'. */ + if (var->type->contains_double() && + var->data.interpolation != INTERP_QUALIFIER_FLAT && + state->stage == MESA_SHADER_FRAGMENT && + var->data.mode == ir_var_shader_in) { + _mesa_glsl_error(&loc, state, "if a fragment input is (or contains) " + "a double, then it must be qualified with 'flat'", + var_type); + } /* Interpolation qualifiers cannot be applied to 'centroid' and * 'centroid varying'. @@ -3240,15 +3768,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 " @@ -3261,37 +3789,6 @@ ast_declarator_list::hir(exec_list *instructions, } - /* From section 4.3.4 of the GLSL 1.30 spec: - * "It is an error to use centroid in in a vertex shader." - * - * From section 4.3.4 of the GLSL ES 3.00 spec: - * "It is an error to use centroid in or interpolation qualifiers in - * a vertex shader input." - */ - if (state->is_version(130, 300) - && this->type->qualifier.flags.q.centroid - && this->type->qualifier.flags.q.in - && state->target == vertex_shader) { - - _mesa_glsl_error(&loc, state, - "'centroid 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." - * - * The GL_ARB_shading_language_420pack extension specification states: - * "It is an error to use auxiliary storage qualifiers or interpolation - * qualifiers on an output in a fragment shader." - */ - if (state->target == fragment_shader && - this->type->qualifier.flags.q.out && - this->type->qualifier.has_auxiliary_storage()) { - _mesa_glsl_error(&loc, state, - "auxiliary storage qualifiers cannot be used on " - "fragment shader outputs"); - } - /* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30. */ if (this->type->qualifier.precision != ast_precision_none) { @@ -3299,56 +3796,28 @@ ast_declarator_list::hir(exec_list *instructions, } - /* Precision qualifiers apply to floating point, integer and sampler - * types. - * - * Section 4.5.2 (Precision Qualifiers) of the GLSL 1.30 spec says: - * "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. - * - * Section 4.5 (Precision and Precision Qualifiers) of the GLSL 1.30 - * spec also says: - * - * "Precision qualifiers are added for code portability with OpenGL - * ES, not for functionality. They have the same syntax as in OpenGL - * ES." - * - * Section 8 (Built-In Functions) of the GLSL ES 1.00 spec says: - * - * "uniform lowp sampler2D sampler; - * highp vec2 coord; - * ... - * lowp vec4 col = texture2D (sampler, coord); - * // texture2D returns lowp" - * - * From this, we infer that GLSL 1.30 (and later) should allow precision - * qualifiers on sampler types just like float and integer types. + /* If a precision qualifier is allowed on a type, it is allowed on + * an array of that type. */ - if (this->type->qualifier.precision != ast_precision_none - && !var->type->is_float() - && !var->type->is_integer() - && !var->type->is_record() - && !var->type->is_sampler() - && !(var->type->is_array() - && (var->type->fields.array->is_float() - || var->type->fields.array->is_integer()))) { + if (!(this->type->qualifier.precision == ast_precision_none + || precision_qualifier_allowed(var->type) + || (var->type->is_array() + && precision_qualifier_allowed(var->type->fields.array)))) { _mesa_glsl_error(&loc, state, "precision qualifiers apply only to floating point" ", 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 @@ -3358,23 +3827,27 @@ ast_declarator_list::hir(exec_list *instructions, * instruction stream. */ exec_list initializer_instructions; + + /* Examine var name here since var may get deleted in the next call */ + bool var_is_gl_id = is_gl_identifier(var->name); + ir_variable *earlier = get_variable_being_redeclared(var, decl->get_location(), state, false /* allow_all_redeclarations */); if (earlier != NULL) { - if (strncmp(var->name, "gl_", 3) == 0 && - earlier->how_declared == ir_var_declared_in_block) { + 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); + "gl_PerVertex", earlier->name); } - earlier->how_declared = ir_var_declared_normally; + 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: @@ -3384,14 +3857,14 @@ 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_unsized_array()) /* Section 10.17 of the GLSL ES 1.00 specification states that @@ -3423,32 +3896,32 @@ ast_declarator_list::hir(exec_list *instructions, if (earlier == NULL) { 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); + /* 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); @@ -3470,7 +3943,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; @@ -3481,13 +3954,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; @@ -3507,8 +3980,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; @@ -3522,13 +3995,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->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; } @@ -3540,17 +4011,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; } @@ -3568,7 +4040,7 @@ 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")) { @@ -3585,9 +4057,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; @@ -3597,7 +4069,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++; } @@ -3606,7 +4078,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"); } } @@ -3627,7 +4099,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; @@ -3669,8 +4141,8 @@ ast_function::hir(exec_list *instructions, * 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 = @@ -3679,8 +4151,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; } @@ -3690,7 +4162,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: @@ -3701,44 +4173,80 @@ ast_function::hir(exec_list *instructions, 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); } + /* Create an ir_function if one doesn't already exist. */ + f = state->symbols->get_function(name); + if (f == NULL) { + 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(); + + _mesa_glsl_error(&loc, state, "function name `%s' conflicts with " + "non-function", name); + return NULL; + } + + emit_function(state, f); + } + + /* From GLSL ES 3.0 spec, chapter 6.1 "Function Definitions", page 71: + * + * "A shader cannot redefine or overload built-in functions." + * + * While in GLSL ES 1.0 specification, chapter 8 "Built-in Functions": + * + * "User code can overload the built-in functions but cannot redefine + * them." + */ + if (state->es_shader && state->language_version >= 300) { + /* Local shader has no exact candidates; check the built-ins. */ + _mesa_glsl_initialize_builtin_functions(); + if (_mesa_glsl_find_builtin_function_by_name(state, name)) { + YYLTYPE loc = this->get_location(); + _mesa_glsl_error(& loc, state, + "A shader cannot redefine or overload built-in " + "function `%s' in GLSL ES 3.00", name); + return NULL; + } + } + /* Verify that this function's signature either doesn't match a previously * seen signature for a function with the same name, or, if a match is found, * that the previously seen signature does not have an associated definition. */ - f = state->symbols->get_function(name); - if (f != NULL && (state->es_shader || f->has_user_signature())) { + if (state->es_shader || f->has_user_signature()) { 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) { @@ -3751,34 +4259,22 @@ 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(); - - _mesa_glsl_error(&loc, state, "function name `%s' conflicts with " - "non-function", name); - return NULL; + } } - - emit_function(state, f); } /* 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"); } } @@ -3800,7 +4296,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); @@ -3817,20 +4313,18 @@ 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(); - - assert(var != NULL); + foreach_in_list(ir_variable, var, &signature->parameters) { + assert(var->as_variable() != NULL); /* The only way a parameter would "exist" is if two parameters have * 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); } } @@ -3846,9 +4340,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. @@ -3859,7 +4353,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; @@ -3869,23 +4363,23 @@ 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, @@ -3922,18 +4416,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; @@ -3942,11 +4436,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; @@ -3954,51 +4448,63 @@ 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); - - 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); - } + /* 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 && !state->switch_state.is_switch_innermost) { + 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_continue) { + /* Set 'continue_inside' to true. */ + ir_rvalue *const true_val = new (ctx) ir_constant(true); + ir_dereference_variable *deref_continue_inside_var = + new(ctx) ir_dereference_variable(state->switch_state.continue_inside); + instructions->push_tail(new(ctx) ir_assignment(deref_continue_inside_var, + true_val)); + + /* Break out from the switch, continue for the loop will + * be called right after switch. */ + ir_loop_jump *const jump = + new(ctx) ir_loop_jump(ir_loop_jump::jump_break); + instructions->push_tail(jump); + + } else if (state->switch_state.is_switch_innermost && + mode == ast_break) { + /* Force break out of switch by inserting a break. */ + ir_loop_jump *const jump = + new(ctx) ir_loop_jump(ir_loop_jump::jump_break); + instructions->push_tail(jump); + } 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; @@ -4012,7 +4518,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; @@ -4031,7 +4537,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); @@ -4058,7 +4564,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; @@ -4075,9 +4581,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. @@ -4095,35 +4601,71 @@ 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. + /* Initialize continue_inside 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); - instructions->push_tail(state->switch_state.is_break_var); + state->switch_state.continue_inside = + new(ctx) ir_variable(glsl_type::bool_type, + "continue_inside_tmp", + ir_var_temporary); + instructions->push_tail(state->switch_state.continue_inside); - 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)); + ir_rvalue *const false_val = new (ctx) ir_constant(false); + ir_dereference_variable *deref_continue_inside_var = + new(ctx) ir_dereference_variable(state->switch_state.continue_inside); + instructions->push_tail(new(ctx) ir_assignment(deref_continue_inside_var, + false_val)); + + state->switch_state.run_default = + new(ctx) ir_variable(glsl_type::bool_type, + "run_default_tmp", + ir_var_temporary); + instructions->push_tail(state->switch_state.run_default); + + /* Loop around the switch is used for flow control. */ + ir_loop * loop = new(ctx) ir_loop(); + instructions->push_tail(loop); /* Cache test expression. */ - test_to_hir(instructions, state); + test_to_hir(&loop->body_instructions, state); /* Emit code for body of switch stmt. */ - body->hir(instructions, state); + body->hir(&loop->body_instructions, state); + + /* Insert a break at the end to exit loop. */ + ir_loop_jump *jump = new(ctx) ir_loop_jump(ir_loop_jump::jump_break); + loop->body_instructions.push_tail(jump); + + /* If we are inside loop, check if continue got called inside switch. */ + if (state->loop_nesting_ast != NULL) { + ir_dereference_variable *deref_continue_inside = + new(ctx) ir_dereference_variable(state->switch_state.continue_inside); + ir_if *irif = new(ctx) ir_if(deref_continue_inside); + ir_loop_jump *jump = new(ctx) ir_loop_jump(ir_loop_jump::jump_continue); + + if (state->loop_nesting_ast != NULL) { + if (state->loop_nesting_ast->rest_expression) { + state->loop_nesting_ast->rest_expression->hir(&irif->then_instructions, + state); + } + if (state->loop_nesting_ast->mode == + ast_iteration_statement::ast_do_while) { + state->loop_nesting_ast->condition_to_hir(&irif->then_instructions, state); + } + } + irif->then_instructions.push_tail(jump); + instructions->push_tail(irif); + } hash_table_dtor(state->switch_state.labels_ht); @@ -4136,7 +4678,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; @@ -4146,8 +4688,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); @@ -4158,7 +4700,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); @@ -4169,10 +4711,73 @@ 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); + exec_list default_case, after_default, tmp; + + foreach_list_typed (ast_case_statement, case_stmt, link, & this->cases) { + case_stmt->hir(&tmp, state); + + /* Default case. */ + if (state->switch_state.previous_default && default_case.is_empty()) { + default_case.append_list(&tmp); + continue; + } + + /* If default case found, append 'after_default' list. */ + if (!default_case.is_empty()) + after_default.append_list(&tmp); + else + instructions->append_list(&tmp); + } + + /* Handle the default case. This is done here because default might not be + * the last case. We need to add checks against following cases first to see + * if default should be chosen or not. + */ + if (!default_case.is_empty()) { + + ir_rvalue *const true_val = new (state) ir_constant(true); + ir_dereference_variable *deref_run_default_var = + new(state) ir_dereference_variable(state->switch_state.run_default); + + /* Choose to run default case initially, following conditional + * assignments might change this. + */ + ir_assignment *const init_var = + new(state) ir_assignment(deref_run_default_var, true_val); + instructions->push_tail(init_var); + + /* Default case was the last one, no checks required. */ + if (after_default.is_empty()) { + instructions->append_list(&default_case); + return NULL; + } + + foreach_in_list(ir_instruction, ir, &after_default) { + ir_assignment *assign = ir->as_assignment(); + + if (!assign) + continue; + + /* Clone the check between case label and init expression. */ + ir_expression *exp = (ir_expression*) assign->condition; + ir_expression *clone = exp->clone(state, NULL); + + ir_dereference_variable *deref_var = + new(state) ir_dereference_variable(state->switch_state.run_default); + ir_rvalue *const false_val = new (state) ir_constant(false); + + ir_assignment *const set_false = + new(state) ir_assignment(deref_var, false_val, clone); + + instructions->push_tail(set_false); + } + + /* Append default case and all cases after it. */ + instructions->append_list(&default_case); + instructions->append_list(&after_default); + } /* Case statements do not have r-values. */ return NULL; @@ -4180,22 +4785,10 @@ 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); - /* Conditionally set fallthru state based on break state. */ - ir_constant *const false_val = new(state) ir_constant(false); - ir_dereference_variable *const deref_is_fallthru_var = - new(state) ir_dereference_variable(state->switch_state.is_fallthru_var); - ir_dereference_variable *const deref_is_break_var = - 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); - instructions->push_tail(reset_fallthru_on_break); - /* Guard case statements depending on fallthru state. */ ir_dereference_variable *const deref_fallthru_guard = new(state) ir_dereference_variable(state->switch_state.is_fallthru_var); @@ -4213,7 +4806,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); @@ -4224,7 +4817,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; @@ -4242,62 +4835,107 @@ 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); + ir_expression *test_cond = new(ctx) ir_expression(ir_binop_all_equal, + label_const, + deref_test_var); + + /* + * From GLSL 4.40 specification section 6.2 ("Selection"): + * + * "The type of the init-expression value in a switch statement must + * be a scalar int or uint. The type of the constant-expression value + * in a case label also must be a scalar int or uint. When any pair + * of these values is tested for "equal value" and the types do not + * match, an implicit conversion will be done to convert the int to a + * uint (see section 4.1.10 “Implicit Conversions”) before the compare + * is done." + */ + if (label_const->type != state->switch_state.test_var->type) { + YYLTYPE loc = this->test_value->get_location(); + + const glsl_type *type_a = label_const->type; + const glsl_type *type_b = state->switch_state.test_var->type; + + /* Check if int->uint implicit conversion is supported. */ + bool integer_conversion_supported = + glsl_type::int_type->can_implicitly_convert_to(glsl_type::uint_type, + state); + + if ((!type_a->is_integer() || !type_b->is_integer()) || + !integer_conversion_supported) { + _mesa_glsl_error(&loc, state, "type mismatch with switch " + "init-expression and case label (%s != %s)", + type_a->name, type_b->name); + } else { + /* Conversion of the case label. */ + if (type_a->base_type == GLSL_TYPE_INT) { + if (!apply_implicit_conversion(glsl_type::uint_type, + test_cond->operands[0], state)) + _mesa_glsl_error(&loc, state, "implicit type conversion error"); + } else { + /* Conversion of the init-expression value. */ + if (!apply_implicit_conversion(glsl_type::uint_type, + test_cond->operands[1], state)) + _mesa_glsl_error(&loc, state, "implicit type conversion error"); + } + } + } 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 fallthru condition on 'run_default' bool. */ + ir_dereference_variable *deref_run_default = + new(ctx) ir_dereference_variable(state->switch_state.run_default); + ir_rvalue *const cond_true = new(ctx) ir_constant(true); + ir_expression *test_cond = new(ctx) ir_expression(ir_binop_all_equal, + cond_true, + deref_run_default); + /* 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, test_cond); instructions->push_tail(set_fallthru); } @@ -4307,35 +4945,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); } } } @@ -4343,7 +4981,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; @@ -4370,7 +5008,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); @@ -4379,7 +5017,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(); @@ -4435,7 +5073,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; @@ -4462,7 +5100,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"); @@ -4480,7 +5118,7 @@ ast_type_specifier::hir(exec_list *instructions, 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: * @@ -4511,7 +5149,7 @@ ast_type_specifier::hir(exec_list *instructions, */ ir_variable *const junk = new(state) ir_variable(type, "#default precision", - ir_var_temporary); + ir_var_auto); state->symbols->add_variable(junk); } @@ -4557,12 +5195,12 @@ ast_type_specifier::hir(exec_list *instructions, */ 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, + enum glsl_matrix_layout matrix_layout, bool allow_reserved_names, ir_variable_mode var_mode) { @@ -4574,9 +5212,7 @@ ast_process_structure_or_interface_block(exec_list *instructions, * 'declarations' list in each of the elements. */ foreach_list_typed (ast_declarator_list, decl_list, link, declarations) { - foreach_list_const (decl_ptr, & decl_list->declarations) { - decl_count++; - } + decl_count += decl_list->declarations.length(); } /* Allocate storage for the fields and process the field @@ -4585,7 +5221,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) { @@ -4597,24 +5233,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) { + &decl_list->declarations) { if (!allow_reserved_names) validate_identifier(decl->identifier, loc, state); - /* From the GL_ARB_uniform_buffer_object spec: + /* 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 @@ -4624,10 +5257,11 @@ 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 sampler"); + "uniform in non-default uniform block contains " + "opaque variable"); } if (field_type->contains_atomic()) { @@ -4641,6 +5275,16 @@ ast_process_structure_or_interface_block(exec_list *instructions, "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, + "image in structure or uniform block"); + } + const struct ast_type_qualifier *const qual = & decl_list->type->qualifier; if (qual->flags.q.std140 || @@ -4652,16 +5296,25 @@ 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); - } + if (qual->flags.q.constant) { + YYLTYPE loc = decl_list->get_location(); + _mesa_glsl_error(&loc, state, + "const storage qualifier cannot be applied " + "to struct or interface block members"); + } + + 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; + + /* Only save explicitly defined streams in block's field */ + fields[i].stream = qual->flags.q.explicit_stream ? qual->stream : -1; if (qual->flags.q.row_major || qual->flags.q.column_major) { if (!qual->flags.q.uniform) { @@ -4678,16 +5331,39 @@ ast_process_structure_or_interface_block(exec_list *instructions, "with uniform interface blocks"); } - if (field_type->is_matrix() || - (field_type->is_array() && field_type->fields.array->is_matrix())) { - fields[i].row_major = block_row_major; + if ((qual->flags.q.uniform || !is_interface) && + qual->has_auxiliary_storage()) { + _mesa_glsl_error(&loc, state, + "auxiliary storage qualifiers cannot be used " + "in uniform blocks or structures."); + } + + /* Propogate row- / column-major information down the fields of the + * structure or interface block. Structures need this data because + * the structure may contain a structure that contains ... a matrix + * that need the proper layout. + */ + if (field_type->without_array()->is_matrix() + || field_type->without_array()->is_record()) { + /* If no layout is specified for the field, inherit the layout + * from the block. + */ + fields[i].matrix_layout = matrix_layout; + if (qual->flags.q.row_major) - fields[i].row_major = true; + fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_ROW_MAJOR; else if (qual->flags.q.column_major) - fields[i].row_major = false; + fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR; + + /* If we're processing an interface block, the matrix layout must + * be decided by this point. + */ + assert(!is_interface + || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR + || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR); } - i++; + i++; } } @@ -4700,7 +5376,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(); @@ -4727,19 +5403,19 @@ ast_struct_specifier::hir(exec_list *instructions, */ if (state->language_version != 110 && state->struct_specifier_depth != 0) _mesa_glsl_error(&loc, state, - "embedded structure declartions are not allowed"); + "embedded structure declarations are not allowed"); state->struct_specifier_depth++; glsl_struct_field *fields; unsigned decl_count = ast_process_structure_or_interface_block(instructions, - state, - &this->declarations, - loc, - &fields, - false, + state, + &this->declarations, + loc, + &fields, false, + GLSL_MATRIX_LAYOUT_INHERITED, false /* allow_reserved_names */, ir_var_auto); @@ -4752,12 +5428,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++; } } @@ -4782,7 +5458,7 @@ public: virtual ir_visitor_status visit(ir_dereference_variable *ir) { - if (ir->var->mode == mode && ir->var->get_interface_type() == block) { + if (ir->var->data.mode == mode && ir->var->get_interface_type() == block) { found = true; return visit_stop; } @@ -4803,10 +5479,18 @@ private: 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(); + /* Interface blocks must be declared at global scope */ + if (state->current_function != NULL) { + _mesa_glsl_error(&loc, state, + "Interface block `%s' must be declared " + "at global scope", + this->block_name); + } + /* The ast_interface_block has a list of ast_declarator_lists. We * need to turn those into ir_variables with an association * with this uniform block. @@ -4839,10 +5523,21 @@ ast_interface_block::hir(exec_list *instructions, assert(!"interface block layout qualifier not found!"); } + enum glsl_matrix_layout matrix_layout = GLSL_MATRIX_LAYOUT_INHERITED; + if (this->layout.flags.q.row_major) + matrix_layout = GLSL_MATRIX_LAYOUT_ROW_MAJOR; + else if (this->layout.flags.q.column_major) + matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR; + 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; + + /* Treat an interface block as one level of nesting, so that embedded struct + * specifiers will be disallowed. + */ + state->struct_specifier_depth++; + unsigned int num_variables = ast_process_structure_or_interface_block(&declared_variables, state, @@ -4850,13 +5545,29 @@ ast_interface_block::hir(exec_list *instructions, loc, &fields, true, - block_row_major, + matrix_layout, redeclaring_per_vertex, var_mode); - if (!redeclaring_per_vertex) + state->struct_specifier_depth--; + + if (!redeclaring_per_vertex) { validate_identifier(this->block_name, loc, state); + /* From section 4.3.9 ("Interface Blocks") of the GLSL 4.50 spec: + * + * "Block names have no other use within a shader beyond interface + * matching; it is a compile-time error to use a block name at global + * scope for anything other than as a block name." + */ + ir_variable *var = state->symbols->get_variable(this->block_name); + if (var && !var->type->is_interface()) { + _mesa_glsl_error(&loc, state, "Block name `%s' is " + "already used in the scope.", + this->block_name); + } + } + const glsl_type *earlier_per_vertex = NULL; if (redeclaring_per_vertex) { /* Find the previous declaration of gl_PerVertex. If we're redeclaring @@ -4877,10 +5588,10 @@ ast_interface_block::hir(exec_list *instructions, _mesa_glsl_error(&loc, state, "redeclaration of gl_PerVertex input not allowed " "in the %s shader", - _mesa_glsl_shader_target_name(state->target)); + _mesa_shader_stage_to_string(state->stage)); } if (this->instance_name == NULL || - strcmp(this->instance_name, "gl_in") != 0 || !this->is_array) { + 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[]"); @@ -4894,11 +5605,11 @@ ast_interface_block::hir(exec_list *instructions, _mesa_glsl_error(&loc, state, "redeclaration of gl_PerVertex output not " "allowed in the %s shader", - _mesa_glsl_shader_target_name(state->target)); + _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 " + "gl_PerVertex output may not be redeclared with " "an instance name"); } break; @@ -4930,6 +5641,8 @@ ast_interface_block::hir(exec_list *instructions, 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; } } @@ -4980,7 +5693,7 @@ ast_interface_block::hir(exec_list *instructions, * variable (or input block, see interface blocks below) needs to be * declared as an array. */ - if (state->target == geometry_shader && !this->is_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"); } @@ -5014,7 +5727,7 @@ ast_interface_block::hir(exec_list *instructions, ir_variable *var; - if (this->is_array) { + 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 @@ -5034,8 +5747,8 @@ ast_interface_block::hir(exec_list *instructions, * interface array size *doesn't* need to be specified is on a * geometry shader input. */ - if (this->array_size == NULL && - (state->target != geometry_shader || !this->layout.flags.q.in)) { + 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"); @@ -5043,7 +5756,7 @@ ast_interface_block::hir(exec_list *instructions, } 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, @@ -5054,7 +5767,10 @@ ast_interface_block::hir(exec_list *instructions, var_mode); } - if (state->target == geometry_shader && var_mode == ir_var_shader_in) + var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED + ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout; + + if (state->stage == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in) handle_geometry_shader_input_decl(state, loc, var); if (ir_variable *earlier = @@ -5063,42 +5779,72 @@ ast_interface_block::hir(exec_list *instructions, _mesa_glsl_error(&loc, state, "`%s' redeclared", this->instance_name); } - earlier->how_declared = ir_var_declared_normally; + 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->is_array); + 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->interpolation = fields[i].interpolation; - var->centroid = fields[i].centroid; + 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 (fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED) { + var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED + ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout; + } else { + var->data.matrix_layout = fields[i].matrix_layout; + } + + if (fields[i].stream != -1 && + ((unsigned)fields[i].stream) != this->layout.stream) { + _mesa_glsl_error(&loc, state, + "stream layout qualifier on " + "interface block member `%s' does not match " + "the interface block (%d vs %d)", + var->name, fields[i].stream, this->layout.stream); + } + + var->data.stream = this->layout.stream; + + /* Examine var name here since var may get deleted in the next call */ + bool var_is_gl_id = is_gl_identifier(var->name); + 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) { + if (!var_is_gl_id || earlier == NULL) { _mesa_glsl_error(&loc, state, "redeclaration of gl_PerVertex can only " "include built-in variables"); - } else if (earlier->how_declared == ir_var_declared_normally) { + } else if (earlier->data.how_declared == ir_var_declared_normally) { _mesa_glsl_error(&loc, state, - "`%s' has already been redeclared", var->name); + "`%s' has already been redeclared", + earlier->name); } else { - earlier->how_declared = ir_var_declared_in_block; + earlier->data.how_declared = ir_var_declared_in_block; earlier->reinit_interface_type(block_type); } continue; @@ -5111,8 +5857,8 @@ ast_interface_block::hir(exec_list *instructions, * 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); @@ -5140,12 +5886,12 @@ ast_interface_block::hir(exec_list *instructions, * 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(); + foreach_in_list_safe(ir_instruction, node, instructions) { + ir_variable *const var = node->as_variable(); if (var != NULL && var->get_interface_type() == earlier_per_vertex && - var->mode == var_mode) { - if (var->how_declared == ir_var_declared_normally) { + 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'", @@ -5172,7 +5918,7 @@ ast_gs_input_layout::hir(exec_list *instructions, * was consistent with this one. */ if (state->gs_input_prim_type_specified && - state->gs_input_prim_type != this->prim_type) { + state->in_qualifier->prim_type != this->prim_type) { _mesa_glsl_error(&loc, state, "geometry shader input layout does not match" " previous declaration"); @@ -5193,14 +5939,13 @@ ast_gs_input_layout::hir(exec_list *instructions, } state->gs_input_prim_type_specified = true; - state->gs_input_prim_type = this->prim_type; /* 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->mode != ir_var_shader_in) + foreach_in_list(ir_instruction, node, instructions) { + ir_variable *var = 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 @@ -5208,12 +5953,12 @@ ast_gs_input_layout::hir(exec_list *instructions, */ if (var->type->is_unsized_array()) { - if (var->max_array_access >= num_vertices) { + 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->max_array_access, var->name); + var->data.max_array_access, var->name); } else { var->type = glsl_type::get_array_instance(var->type->fields.array, num_vertices); @@ -5225,9 +5970,87 @@ ast_gs_input_layout::hir(exec_list *instructions, } +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::uvec3_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.u[i] = this->local_size[i]; + var->constant_value = new(var) ir_constant(glsl_type::uvec3_type, &data); + var->constant_initializer = + new(var) ir_constant(glsl_type::uvec3_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; @@ -5238,22 +6061,22 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, YYLTYPE loc; memset(&loc, 0, sizeof(loc)); - foreach_list(node, instructions) { - ir_variable *var = ((ir_instruction *)node)->as_variable(); + foreach_in_list(ir_instruction, node, instructions) { + ir_variable *var = 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; - 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; - } + gl_FragData_assigned = true; + else if (!is_gl_identifier(var->name)) { + if (state->stage == MESA_SHADER_FRAGMENT && + var->data.mode == ir_var_shader_out) { + user_defined_fs_output_assigned = true; + user_defined_fs_output = var; + } } } @@ -5274,15 +6097,15 @@ 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'"); + "`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'", - 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'", - user_defined_fs_output->name); + "`gl_FragData' and `%s'", + user_defined_fs_output->name); } } @@ -5328,10 +6151,10 @@ remove_per_vertex_blocks(exec_list *instructions, /* 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(); + foreach_in_list_safe(ir_instruction, node, instructions) { + ir_variable *const var = node->as_variable(); if (var != NULL && var->get_interface_type() == per_vertex && - var->mode == mode) { + var->data.mode == mode) { state->symbols->disable_variable(var->name); var->remove(); }