/* * Copyright © 2010 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /** * \file ast_to_hir.c * Convert abstract syntax to to high-level intermediate reprensentation (HIR). * * During the conversion to HIR, the majority of the symantic checking is * preformed on the program. This includes: * * * Symbol table management * * Type checking * * Function binding * * The majority of this work could be done during parsing, and the parser could * probably generate HIR directly. However, this results in frequent changes * to the parser code. Since we do not assume that every system this complier * is built on will have Flex and Bison installed, we have to store the code * generated by these tools in our version control system. In other parts of * the system we've seen problems where a parser was changed but the generated * code was not committed, merge conflicts where created because two developers * had slightly different versions of Bison installed, etc. * * I have also noticed that running Bison generated parsers in GDB is very * irritating. When you get a segfault on '$$ = $1->foo', you can't very * well 'print $1' in GDB. * * As a result, my preference is to put as little C code as possible in the * 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" static void detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, exec_list *instructions); void _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { _mesa_glsl_initialize_variables(instructions, state); state->symbols->language_version = state->language_version; state->current_function = NULL; state->toplevel_ir = instructions; /* Section 4.2 of the GLSL 1.20 specification states: * "The built-in functions are scoped in a scope outside the global scope * users declare global variables in. That is, a shader's global scope, * available for user-defined functions and global variables, is nested * inside the scope containing the built-in functions." * * Since built-in functions like ftransform() access built-in variables, * it follows that those must be in the outer scope as well. * * We push scope here to create this nesting effect...but don't pop. * This way, a shader's globals are still in the symbol table for use * by the linker. */ state->symbols->push_scope(); foreach_list_typed (ast_node, ast, link, & state->translation_unit) ast->hir(instructions, state); detect_recursion_unlinked(state, instructions); detect_conflicting_assignments(state, instructions); state->toplevel_ir = NULL; } /** * If a conversion is available, convert one operand to a different type * * The \c from \c ir_rvalue is converted "in place". * * \param to Type that the operand it to be converted to * \param from Operand that is being converted * \param state GLSL compiler state * * \return * If a conversion is possible (or unnecessary), \c true is returned. * Otherwise \c false is returned. */ bool apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from, 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. */ if (state->language_version < 120) return false; /* From page 27 (page 33 of the PDF) of the GLSL 1.50 spec: * * "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. */ if (!to->is_float() || !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. */ to = glsl_type::get_instance(GLSL_TYPE_FLOAT, 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); } 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) { const glsl_type *type_a = value_a->type; const glsl_type *type_b = value_b->type; /* From GLSL 1.50 spec, page 56: * * "The arithmetic binary operators add (+), subtract (-), * multiply (*), and divide (/) operate on integer and * floating-point scalars, vectors, and matrices." */ if (!type_a->is_numeric() || !type_b->is_numeric()) { _mesa_glsl_error(loc, state, "Operands to arithmetic operators must be numeric"); return glsl_type::error_type; } /* "If one operand is floating-point based and the other is * not, then the conversions from Section 4.1.10 "Implicit * Conversions" are applied to the non-floating-point-based operand." */ 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"); return glsl_type::error_type; } type_a = value_a->type; type_b = value_b->type; /* "If the operands are integer types, they must both be signed or * both be unsigned." * * From this rule and the preceeding conversion it can be inferred that * both types must be GLSL_TYPE_FLOAT, or GLSL_TYPE_UINT, or GLSL_TYPE_INT. * The is_numeric check above already filtered out the case where either * type is not one of these, so now the base types need only be tested for * equality. */ if (type_a->base_type != type_b->base_type) { _mesa_glsl_error(loc, state, "base type mismatch for arithmetic operator"); return glsl_type::error_type; } /* "All arithmetic binary operators result in the same fundamental type * (signed integer, unsigned integer, or floating-point) as the * operands they operate on, after operand type conversion. After * conversion, the following cases are valid * * * The two operands are scalars. In this case the operation is * applied, resulting in a scalar." */ if (type_a->is_scalar() && type_b->is_scalar()) return type_a; /* "* One operand is a scalar, and the other is a vector or matrix. * In this case, the scalar operation is applied independently to each * component of the vector or matrix, resulting in the same size * vector or matrix." */ if (type_a->is_scalar()) { if (!type_b->is_scalar()) return type_b; } else if (type_b->is_scalar()) { return type_a; } /* All of the combinations of <scalar, scalar>, <vector, scalar>, * <scalar, vector>, <scalar, matrix>, and <matrix, scalar> have been * handled. */ assert(!type_a->is_scalar()); assert(!type_b->is_scalar()); /* "* The two operands are vectors of the same size. In this case, the * operation is done component-wise resulting in the same size * vector." */ if (type_a->is_vector() && type_b->is_vector()) { if (type_a == type_b) { return type_a; } else { _mesa_glsl_error(loc, state, "vector size mismatch for arithmetic operator"); return glsl_type::error_type; } } /* All of the combinations of <scalar, scalar>, <vector, scalar>, * <scalar, vector>, <scalar, matrix>, <matrix, scalar>, and * <vector, vector> have been handled. At least one of the operands must * be matrix. Further, since there are no integer matrix types, the base * 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); /* "* The operator is add (+), subtract (-), or divide (/), and the * operands are matrices with the same number of rows and the same * number of columns. In this case, the operation is done component- * wise resulting in the same size matrix." * * The operator is multiply (*), where both operands are matrices or * one operand is a vector and the other a matrix. A right vector * operand is treated as a column vector and a left vector operand as a * row vector. In all these cases, it is required that the number of * columns of the left operand is equal to the number of rows of the * right operand. Then, the multiply (*) operation does a linear * algebraic multiply, yielding an object that has the same number of * rows as the left operand and the same number of columns as the right * operand. Section 5.10 "Vector and Matrix Operations" explains in * more detail how vectors and matrices are operated on." */ if (! multiply) { if (type_a == type_b) 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; } } 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; } } 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; } } _mesa_glsl_error(loc, state, "size mismatch for matrix multiplication"); return glsl_type::error_type; } /* "All other cases are illegal." */ _mesa_glsl_error(loc, state, "type mismatch"); return glsl_type::error_type; } static const struct glsl_type * unary_arithmetic_result_type(const struct glsl_type *type, struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { /* From GLSL 1.50 spec, page 57: * * "The arithmetic unary operators negate (-), post- and pre-increment * and decrement (-- and ++) operate on integer or floating-point * values (including vectors and matrices). All unary operators work * component-wise on their operands. These result with the same type * they operated on." */ if (!type->is_numeric()) { _mesa_glsl_error(loc, state, "Operands to arithmetic operators must be numeric"); return glsl_type::error_type; } return type; } /** * \brief Return the result type of a bit-logic operation. * * If the given types to the bit-logic operator are invalid, return * glsl_type::error_type. * * \param type_a Type of LHS of bit-logic op * \param type_b Type of RHS of bit-logic op */ static const struct glsl_type * bit_logic_result_type(const struct glsl_type *type_a, const struct glsl_type *type_b, ast_operators op, struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { if (state->language_version < 130) { _mesa_glsl_error(loc, state, "bit operations require GLSL 1.30"); return glsl_type::error_type; } /* From page 50 (page 56 of PDF) of GLSL 1.30 spec: * * "The bitwise operators and (&), exclusive-or (^), and inclusive-or * (|). The operands must be of type signed or unsigned integers or * integer vectors." */ if (!type_a->is_integer()) { _mesa_glsl_error(loc, state, "LHS of `%s' must be an integer", ast_expression::operator_string(op)); return glsl_type::error_type; } if (!type_b->is_integer()) { _mesa_glsl_error(loc, state, "RHS of `%s' must be an integer", ast_expression::operator_string(op)); return glsl_type::error_type; } /* "The fundamental types of the operands (signed or unsigned) must * match," */ if (type_a->base_type != type_b->base_type) { _mesa_glsl_error(loc, state, "operands of `%s' must have the same " "base type", ast_expression::operator_string(op)); return glsl_type::error_type; } /* "The operands cannot be vectors of differing size." */ if (type_a->is_vector() && type_b->is_vector() && type_a->vector_elements != type_b->vector_elements) { _mesa_glsl_error(loc, state, "operands of `%s' cannot be vectors of " "different sizes", ast_expression::operator_string(op)); return glsl_type::error_type; } /* "If one operand is a scalar and the other a vector, the scalar is * applied component-wise to the vector, resulting in the same type as * the vector. The fundamental types of the operands [...] will be the * resulting fundamental type." */ if (type_a->is_scalar()) return type_b; else return type_a; } static const struct glsl_type * modulus_result_type(const struct glsl_type *type_a, const struct glsl_type *type_b, struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { if (state->language_version < 130) { _mesa_glsl_error(loc, state, "operator '%%' is reserved in %s", state->version_string); return glsl_type::error_type; } /* From GLSL 1.50 spec, page 56: * "The operator modulus (%) operates on signed or unsigned integers or * integer vectors. The operand types must both be signed or both be * unsigned." */ if (!type_a->is_integer()) { _mesa_glsl_error(loc, state, "LHS of operator %% must be an integer."); return glsl_type::error_type; } if (!type_b->is_integer()) { _mesa_glsl_error(loc, state, "RHS of operator %% must be an integer."); return glsl_type::error_type; } if (type_a->base_type != type_b->base_type) { _mesa_glsl_error(loc, state, "operands of %% must have the same base type"); return glsl_type::error_type; } /* "The operands cannot be vectors of differing size. If one operand is * a scalar and the other vector, then the scalar is applied component- * wise to the vector, resulting in the same type as the vector. If both * are vectors of the same size, the result is computed component-wise." */ if (type_a->is_vector()) { if (!type_b->is_vector() || (type_a->vector_elements == type_b->vector_elements)) return type_a; } else return type_b; /* "The operator modulus (%) is not defined for any other data types * (non-integer types)." */ _mesa_glsl_error(loc, state, "type mismatch"); return glsl_type::error_type; } static const struct glsl_type * relational_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { const glsl_type *type_a = value_a->type; const glsl_type *type_b = value_b->type; /* From GLSL 1.50 spec, page 56: * "The relational operators greater than (>), less than (<), greater * than or equal (>=), and less than or equal (<=) operate only on * scalar integer and scalar floating-point expressions." */ if (!type_a->is_numeric() || !type_b->is_numeric() || !type_a->is_scalar() || !type_b->is_scalar()) { _mesa_glsl_error(loc, state, "Operands to relational operators must be scalar and " "numeric"); return glsl_type::error_type; } /* "Either the operands' types must match, or the conversions from * Section 4.1.10 "Implicit Conversions" will be applied to the integer * operand, after which the types must match." */ 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"); return glsl_type::error_type; } type_a = value_a->type; type_b = value_b->type; if (type_a->base_type != type_b->base_type) { _mesa_glsl_error(loc, state, "base type mismatch"); return glsl_type::error_type; } /* "The result is scalar Boolean." */ return glsl_type::bool_type; } /** * \brief Return the result type of a bit-shift operation. * * If the given types to the bit-shift operator are invalid, return * glsl_type::error_type. * * \param type_a Type of LHS of bit-shift op * \param type_b Type of RHS of bit-shift op */ static const struct glsl_type * shift_result_type(const struct glsl_type *type_a, const struct glsl_type *type_b, ast_operators op, struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { if (state->language_version < 130) { _mesa_glsl_error(loc, state, "bit operations require GLSL 1.30"); return glsl_type::error_type; } /* From page 50 (page 56 of the PDF) of the GLSL 1.30 spec: * * "The shift operators (<<) and (>>). For both operators, the operands * must be signed or unsigned integers or integer vectors. One operand * can be signed while the other is unsigned." */ if (!type_a->is_integer()) { _mesa_glsl_error(loc, state, "LHS of operator %s must be an integer or " "integer vector", ast_expression::operator_string(op)); return glsl_type::error_type; } if (!type_b->is_integer()) { _mesa_glsl_error(loc, state, "RHS of operator %s must be an integer or " "integer vector", ast_expression::operator_string(op)); return glsl_type::error_type; } /* "If the first operand is a scalar, the second operand has to be * a scalar as well." */ if (type_a->is_scalar() && !type_b->is_scalar()) { _mesa_glsl_error(loc, state, "If the first operand of %s is scalar, the " "second must be scalar as well", ast_expression::operator_string(op)); return glsl_type::error_type; } /* If both operands are vectors, check that they have same number of * elements. */ if (type_a->is_vector() && type_b->is_vector() && type_a->vector_elements != type_b->vector_elements) { _mesa_glsl_error(loc, state, "Vector operands to operator %s must " "have same number of elements", ast_expression::operator_string(op)); return glsl_type::error_type; } /* "In all cases, the resulting type will be the same type as the left * operand." */ return type_a; } /** * Validates that a value can be assigned to a location with a specified type * * Validates that \c rhs can be assigned to some location. If the types are * not an exact match but an automatic conversion is possible, \c rhs will be * converted. * * \return * \c NULL if \c rhs cannot be assigned to a location with type \c lhs_type. * Otherwise the actual RHS to be assigned will be returned. This may be * \c rhs, or it may be \c rhs after some type conversion. * * \note * In addition to being used for assignments, this function is used to * type-check return values. */ ir_rvalue * validate_assignment(struct _mesa_glsl_parse_state *state, const glsl_type *lhs_type, ir_rvalue *rhs, bool is_initializer) { /* If there is already some error in the RHS, just return it. Anything * else will lead to an avalanche of error message back to the user. */ if (rhs->type->is_error()) return rhs; /* If the types are identical, the assignment can trivially proceed. */ if (rhs->type == lhs_type) return rhs; /* If the array element types are the same and the size of the LHS is zero, * the assignment is okay for initializers embedded in variable * declarations. * * Note: Whole-array assignments are not permitted in GLSL 1.10, but this * is handled by ir_dereference::is_lvalue. */ if (is_initializer && lhs_type->is_array() && rhs->type->is_array() && (lhs_type->element_type() == rhs->type->element_type()) && (lhs_type->array_size() == 0)) { return rhs; } /* Check for implicit conversion in GLSL 1.20 */ if (apply_implicit_conversion(lhs_type, rhs, state)) { if (rhs->type == lhs_type) return rhs; } return NULL; } static void 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; } } ir_rvalue * 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) { void *ctx = state; bool error_emitted = (lhs->type->is_error() || rhs->type->is_error()); ir_variable *lhs_var = lhs->variable_referenced(); if (lhs_var) lhs_var->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) { _mesa_glsl_error(&lhs_loc, state, "assignment to read-only variable '%s'", lhs->variable_referenced()->name); error_emitted = true; } else if (state->language_version <= 110 && lhs->type->is_array()) { /* 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." */ _mesa_glsl_error(&lhs_loc, state, "whole array assignment is not " "allowed in GLSL 1.10 or GLSL ES 1.00."); error_emitted = true; } else if (!lhs->is_lvalue()) { _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment"); error_emitted = true; } } ir_rvalue *new_rhs = validate_assignment(state, lhs->type, rhs, is_initializer); if (new_rhs == NULL) { _mesa_glsl_error(& lhs_loc, state, "type mismatch"); } else { rhs = new_rhs; /* If the LHS array was not declared with a size, it takes it size from * the RHS. If the LHS is an l-value and a whole array, it must be a * dereference of a variable. Any other case would require that the LHS * is either not an l-value or not a whole array. */ if (lhs->type->array_size() == 0) { ir_dereference *const d = lhs->as_dereference(); assert(d != NULL); ir_variable *const var = d->variable_referenced(); 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); } var->type = glsl_type::get_array_instance(lhs->type->element_type(), rhs->type->array_size()); d->type = var->type; } mark_whole_array_access(rhs); mark_whole_array_access(lhs); } /* Most callers of do_assignment (assign, add_assign, pre_inc/dec, * but not post_inc) need the converted assigned value as an rvalue * 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 (!error_emitted) instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var)); return new(ctx) ir_dereference_variable(var); } static ir_rvalue * get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue) { void *ctx = ralloc_parent(lvalue); ir_variable *var; 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)); return new(ctx) ir_dereference_variable(var); } ir_rvalue * ast_node::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { (void) instructions; (void) state; return NULL; } static ir_rvalue * do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1) { int join_op; ir_rvalue *cmp = NULL; if (operation == ir_binop_all_equal) join_op = ir_binop_logic_and; else join_op = ir_binop_logic_or; switch (op0->type->base_type) { case GLSL_TYPE_FLOAT: case GLSL_TYPE_UINT: case GLSL_TYPE_INT: case GLSL_TYPE_BOOL: return new(mem_ctx) ir_expression(operation, op0, op1); case GLSL_TYPE_ARRAY: { for (unsigned int i = 0; i < op0->type->length; i++) { ir_rvalue *e0, *e1, *result; e0 = new(mem_ctx) ir_dereference_array(op0->clone(mem_ctx, NULL), new(mem_ctx) ir_constant(i)); e1 = new(mem_ctx) ir_dereference_array(op1->clone(mem_ctx, NULL), new(mem_ctx) ir_constant(i)); result = do_comparison(mem_ctx, operation, e0, e1); if (cmp) { cmp = new(mem_ctx) ir_expression(join_op, cmp, result); } else { cmp = result; } } mark_whole_array_access(op0); mark_whole_array_access(op1); break; } case GLSL_TYPE_STRUCT: { for (unsigned int i = 0; i < op0->type->length; i++) { ir_rvalue *e0, *e1, *result; const char *field_name = op0->type->fields.structure[i].name; e0 = new(mem_ctx) ir_dereference_record(op0->clone(mem_ctx, NULL), field_name); e1 = new(mem_ctx) ir_dereference_record(op1->clone(mem_ctx, NULL), field_name); result = do_comparison(mem_ctx, operation, e0, e1); if (cmp) { cmp = new(mem_ctx) ir_expression(join_op, cmp, result); } else { cmp = result; } } break; } case GLSL_TYPE_ERROR: case GLSL_TYPE_VOID: case GLSL_TYPE_SAMPLER: /* I assume a comparison of a struct containing a sampler just * ignores the sampler present in the type. */ break; default: assert(!"Should not get here."); break; } if (cmp == NULL) cmp = new(mem_ctx) ir_constant(true); return cmp; } /* For logical operations, we want to ensure that the operands are * scalar booleans. If it isn't, emit an error and return a constant * boolean to avoid triggering cascading error messages. */ ir_rvalue * get_scalar_boolean_operand(exec_list *instructions, struct _mesa_glsl_parse_state *state, ast_expression *parent_expr, int operand, const char *operand_name, bool *error_emitted) { ast_expression *expr = parent_expr->subexpressions[operand]; void *ctx = state; ir_rvalue *val = expr->hir(instructions, state); if (val->type->is_boolean() && val->type->is_scalar()) return val; 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)); *error_emitted = true; } return new(ctx) ir_constant(true); } /** * If name refers to a builtin array whose maximum allowed size is less than * size, report an error and return true. Otherwise return false. */ static bool check_builtin_array_max_size(const char *name, unsigned size, YYLTYPE loc, struct _mesa_glsl_parse_state *state) { if ((strcmp("gl_TexCoord", name) == 0) && (size > state->Const.MaxTextureCoords)) { /* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec: * * "The size [of gl_TexCoord] can be at most * gl_MaxTextureCoords." */ _mesa_glsl_error(&loc, state, "`gl_TexCoord' array size cannot " "be larger than gl_MaxTextureCoords (%u)\n", state->Const.MaxTextureCoords); return true; } else if (strcmp("gl_ClipDistance", name) == 0 && size > state->Const.MaxClipPlanes) { /* From section 7.1 (Vertex Shader Special Variables) of the * GLSL 1.30 spec: * * "The gl_ClipDistance array is predeclared as unsized and * must be sized by the shader either redeclaring it with a * size or indexing it only with integral constant * expressions. ... The size can be at most * gl_MaxClipDistances." */ _mesa_glsl_error(&loc, state, "`gl_ClipDistance' array size cannot " "be larger than gl_MaxClipDistances (%u)\n", state->Const.MaxClipPlanes); return true; } return false; } /** * Create the constant 1, of a which is appropriate for incrementing and * decrementing values of the given GLSL type. For example, if type is vec4, * this creates a constant value of 1.0 having type float. * * If the given type is invalid for increment and decrement operators, return * a floating point 1--the error will be detected later. */ static ir_rvalue * constant_one_for_inc_dec(void *ctx, const glsl_type *type) { switch (type->base_type) { case GLSL_TYPE_UINT: return new(ctx) ir_constant((unsigned) 1); case GLSL_TYPE_INT: return new(ctx) ir_constant(1); default: case GLSL_TYPE_FLOAT: return new(ctx) ir_constant(1.0f); } } ir_rvalue * ast_expression::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { void *ctx = state; static const int operations[AST_NUM_OPERATORS] = { -1, /* ast_assign doesn't convert to ir_expression. */ -1, /* ast_plus doesn't convert to ir_expression. */ ir_unop_neg, ir_binop_add, ir_binop_sub, ir_binop_mul, ir_binop_div, ir_binop_mod, ir_binop_lshift, ir_binop_rshift, ir_binop_less, ir_binop_greater, ir_binop_lequal, ir_binop_gequal, ir_binop_all_equal, ir_binop_any_nequal, ir_binop_bit_and, ir_binop_bit_xor, ir_binop_bit_or, ir_unop_bit_not, ir_binop_logic_and, ir_binop_logic_xor, ir_binop_logic_or, ir_unop_logic_not, /* Note: The following block of expression types actually convert * to multiple IR instructions. */ ir_binop_mul, /* ast_mul_assign */ ir_binop_div, /* ast_div_assign */ ir_binop_mod, /* ast_mod_assign */ ir_binop_add, /* ast_add_assign */ ir_binop_sub, /* ast_sub_assign */ ir_binop_lshift, /* ast_ls_assign */ ir_binop_rshift, /* ast_rs_assign */ ir_binop_bit_and, /* ast_and_assign */ ir_binop_bit_xor, /* ast_xor_assign */ ir_binop_bit_or, /* ast_or_assign */ -1, /* ast_conditional doesn't convert to ir_expression. */ ir_binop_add, /* ast_pre_inc. */ ir_binop_sub, /* ast_pre_dec. */ ir_binop_add, /* ast_post_inc. */ ir_binop_sub, /* ast_post_dec. */ -1, /* ast_field_selection doesn't conv to ir_expression. */ -1, /* ast_array_index doesn't convert to ir_expression. */ -1, /* ast_function_call doesn't conv to ir_expression. */ -1, /* ast_identifier doesn't convert to ir_expression. */ -1, /* ast_int_constant doesn't convert to ir_expression. */ -1, /* ast_uint_constant doesn't conv to ir_expression. */ -1, /* ast_float_constant doesn't conv to ir_expression. */ -1, /* ast_bool_constant doesn't conv to ir_expression. */ -1, /* ast_sequence doesn't convert to ir_expression. */ }; ir_rvalue *result = NULL; ir_rvalue *op[3]; const struct glsl_type *type; /* a temporary variable for switch cases */ bool error_emitted = false; YYLTYPE loc; loc = this->get_location(); switch (this->oper) { 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(); break; } case ast_plus: op[0] = this->subexpressions[0]->hir(instructions, state); type = unary_arithmetic_result_type(op[0]->type, state, & loc); error_emitted = type->is_error(); result = op[0]; break; case ast_neg: op[0] = this->subexpressions[0]->hir(instructions, state); type = unary_arithmetic_result_type(op[0]->type, state, & loc); error_emitted = type->is_error(); result = new(ctx) ir_expression(operations[this->oper], type, op[0], NULL); break; case ast_add: case ast_sub: case ast_mul: case ast_div: op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); type = arithmetic_result_type(op[0], op[1], (this->oper == ast_mul), state, & loc); error_emitted = type->is_error(); result = new(ctx) ir_expression(operations[this->oper], type, op[0], op[1]); break; case ast_mod: op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); type = modulus_result_type(op[0]->type, op[1]->type, state, & loc); assert(operations[this->oper] == ir_binop_mod); result = new(ctx) ir_expression(operations[this->oper], type, op[0], op[1]); error_emitted = type->is_error(); break; case ast_lshift: case ast_rshift: if (state->language_version < 130) { _mesa_glsl_error(&loc, state, "operator %s requires GLSL 1.30", operator_string(this->oper)); error_emitted = true; } op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); type = shift_result_type(op[0]->type, op[1]->type, this->oper, state, &loc); result = new(ctx) ir_expression(operations[this->oper], type, op[0], op[1]); error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); break; case ast_less: case ast_greater: case ast_lequal: case ast_gequal: op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); type = relational_result_type(op[0], op[1], state, & loc); /* The relational operators must either generate an error or result * in a scalar boolean. See page 57 of the GLSL 1.50 spec. */ assert(type->is_error() || ((type->base_type == GLSL_TYPE_BOOL) && type->is_scalar())); result = new(ctx) ir_expression(operations[this->oper], type, op[0], op[1]); error_emitted = type->is_error(); break; case ast_nequal: case ast_equal: op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); /* From page 58 (page 64 of the PDF) of the GLSL 1.50 spec: * * "The equality operators equal (==), and not equal (!=) * operate on all types. They result in a scalar Boolean. If * the operand types do not match, then there must be a * conversion from Section 4.1.10 "Implicit Conversions" * applied to one operand that can make them match, in which * 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; } else if ((state->language_version <= 110) && (op[0]->type->is_array() || op[1]->type->is_array())) { _mesa_glsl_error(& loc, state, "array comparisons forbidden in " "GLSL 1.10"); error_emitted = true; } if (error_emitted) { 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); } break; case ast_bit_and: case ast_bit_xor: case ast_bit_or: op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); type = bit_logic_result_type(op[0]->type, op[1]->type, this->oper, state, &loc); result = new(ctx) ir_expression(operations[this->oper], type, op[0], op[1]); error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); break; case ast_bit_not: op[0] = this->subexpressions[0]->hir(instructions, state); if (state->language_version < 130) { _mesa_glsl_error(&loc, state, "bit-wise operations require GLSL 1.30"); error_emitted = true; } if (!op[0]->type->is_integer()) { _mesa_glsl_error(&loc, state, "operand of `~' must be an integer"); error_emitted = true; } type = error_emitted ? glsl_type::error_type : op[0]->type; result = new(ctx) ir_expression(ir_unop_bit_not, type, op[0], NULL); break; case ast_logic_and: { exec_list rhs_instructions; op[0] = get_scalar_boolean_operand(instructions, state, this, 0, "LHS", &error_emitted); op[1] = get_scalar_boolean_operand(&rhs_instructions, state, this, 1, "RHS", &error_emitted); if (rhs_instructions.is_empty()) { 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; } break; } case ast_logic_or: { exec_list rhs_instructions; op[0] = get_scalar_boolean_operand(instructions, state, this, 0, "LHS", &error_emitted); op[1] = get_scalar_boolean_operand(&rhs_instructions, state, this, 1, "RHS", &error_emitted); if (rhs_instructions.is_empty()) { 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; } break; } case ast_logic_xor: /* From page 33 (page 39 of the PDF) of the GLSL 1.10 spec: * * "The logical binary operators and (&&), or ( | | ), and * exclusive or (^^). They operate only on two Boolean * expressions and result in a Boolean expression." */ op[0] = get_scalar_boolean_operand(instructions, state, this, 0, "LHS", &error_emitted); op[1] = get_scalar_boolean_operand(instructions, state, this, 1, "RHS", &error_emitted); result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type, op[0], op[1]); break; case ast_logic_not: op[0] = get_scalar_boolean_operand(instructions, state, this, 0, "operand", &error_emitted); result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type, op[0], NULL); break; case ast_mul_assign: case ast_div_assign: case ast_add_assign: case ast_sub_assign: { op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); type = arithmetic_result_type(op[0], op[1], (this->oper == ast_mul_assign), 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()); /* GLSL 1.10 does not allow array assignment. However, we don't have to * explicitly test for this because none of the binary expression * operators allow array operands either. */ break; } case ast_mod_assign: { op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); type = modulus_result_type(op[0]->type, op[1]->type, state, & loc); assert(operations[this->oper] == ir_binop_mod); 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(); break; } case ast_ls_assign: case ast_rs_assign: { op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); type = shift_result_type(op[0]->type, op[1]->type, this->oper, state, &loc); ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], type, op[0], op[1]); result = do_assignment(instructions, state, 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(); break; } case ast_and_assign: case ast_xor_assign: case ast_or_assign: { op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); type = bit_logic_result_type(op[0]->type, op[1]->type, this->oper, state, &loc); ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], type, op[0], op[1]); result = do_assignment(instructions, state, 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(); break; } case ast_conditional: { /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec: * * "The ternary selection operator (?:). It operates on three * expressions (exp1 ? exp2 : exp3). This operator evaluates the * first expression, which must result in a scalar Boolean." */ op[0] = get_scalar_boolean_operand(instructions, state, this, 0, "condition", &error_emitted); /* The :? operator is implemented by generating an anonymous temporary * followed by an if-statement. The last instruction in each branch of * the if-statement assigns a value to the anonymous temporary. This * temporary is the r-value of the expression. */ exec_list then_instructions; exec_list else_instructions; op[1] = this->subexpressions[1]->hir(&then_instructions, state); op[2] = this->subexpressions[2]->hir(&else_instructions, state); /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec: * * "The second and third expressions can be any type, as * long their types match, or there is a conversion in * Section 4.1.10 "Implicit Conversions" that can be applied * to one of the expressions to make their types match. This * resulting matching type is the type of the entire * 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; } else { type = op[1]->type; } /* From page 33 (page 39 of the PDF) of the GLSL 1.10 spec: * * "The second and third expressions must be the same type, but can * be of any type other than an array." */ if ((state->language_version <= 110) && type->is_array()) { _mesa_glsl_error(& loc, state, "Second and third operands of ?: " "operator must not be arrays."); error_emitted = true; } ir_constant *cond_val = op[0]->constant_expression_value(); ir_constant *then_val = op[1]->constant_expression_value(); ir_constant *else_val = op[2]->constant_expression_value(); 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 { 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; } case ast_pre_inc: case ast_pre_dec: { this->non_lvalue_description = (this->oper == ast_pre_inc) ? "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); type = arithmetic_result_type(op[0], op[1], false, state, & loc); 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(); break; } case ast_post_inc: case ast_post_dec: { this->non_lvalue_description = (this->oper == ast_post_inc) ? "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); error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); type = arithmetic_result_type(op[0], op[1], false, state, & loc); ir_rvalue *temp_rhs; temp_rhs = new(ctx) ir_expression(operations[this->oper], type, 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()); error_emitted = op[0]->type->is_error(); break; } case ast_field_selection: result = _mesa_ast_field_selection_to_hir(this, instructions, state); break; case ast_array_index: { YYLTYPE index_loc = subexpressions[1]->get_location(); op[0] = subexpressions[0]->hir(instructions, state); op[1] = subexpressions[1]->hir(instructions, state); error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); ir_rvalue *const array = op[0]; result = new(ctx) ir_dereference_array(op[0], op[1]); /* Do not use op[0] after this point. Use array. */ op[0] = NULL; if (error_emitted) break; if (!array->type->is_array() && !array->type->is_matrix() && !array->type->is_vector()) { _mesa_glsl_error(& index_loc, state, "cannot dereference non-array / non-matrix / " "non-vector"); error_emitted = true; } if (!op[1]->type->is_integer()) { _mesa_glsl_error(& index_loc, state, "array index must be integer type"); error_emitted = true; } else if (!op[1]->type->is_scalar()) { _mesa_glsl_error(& index_loc, state, "array index must be scalar"); error_emitted = true; } /* If the array index is a constant expression and the array has a * declared size, ensure that the access is in-bounds. If the array * index is not a constant expression, ensure that the array has a * declared size. */ ir_constant *const const_index = op[1]->constant_expression_value(); if (const_index != NULL) { const int idx = const_index->value.i[0]; const char *type_name; unsigned bound = 0; if (array->type->is_matrix()) { type_name = "matrix"; } else if (array->type->is_vector()) { type_name = "vector"; } else { type_name = "array"; } /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec: * * "It is illegal to declare an array with a size, and then * later (in the same shader) index the same array with an * integral constant expression greater than or equal to the * declared size. It is also illegal to index an array with a * negative constant expression." */ if (array->type->is_matrix()) { if (array->type->row_type()->vector_elements <= idx) { bound = array->type->row_type()->vector_elements; } } else if (array->type->is_vector()) { if (array->type->vector_elements <= idx) { bound = array->type->vector_elements; } } else { if ((array->type->array_size() > 0) && (array->type->array_size() <= idx)) { bound = array->type->array_size(); } } if (bound > 0) { _mesa_glsl_error(& loc, state, "%s index must be < %u", type_name, bound); error_emitted = true; } else if (idx < 0) { _mesa_glsl_error(& loc, state, "%s index must be >= 0", type_name); error_emitted = true; } if (array->type->is_array()) { /* If the array is a variable dereference, it dereferences the * whole array, by definition. Use this to get the variable. * * FINISHME: Should some methods for getting / setting / testing * FINISHME: array access limits be added to ir_dereference? */ ir_variable *const v = array->whole_variable_referenced(); if ((v != NULL) && (unsigned(idx) > v->max_array_access)) { v->max_array_access = idx; /* Check whether this access will, as a side effect, implicitly * cause the size of a built-in array to be too large. */ if (check_builtin_array_max_size(v->name, idx+1, loc, state)) error_emitted = true; } } } else if (array->type->array_size() == 0) { _mesa_glsl_error(&loc, state, "unsized array index must be constant"); } else { if (array->type->is_array()) { /* whole_variable_referenced can return NULL if the array is a * member of a structure. In this case it is safe to not update * the max_array_access field because it is never used for fields * of structures. */ ir_variable *v = array->whole_variable_referenced(); if (v != NULL) v->max_array_access = array->type->array_size() - 1; } } /* From page 23 (29 of the PDF) of the GLSL 1.30 spec: * * "Samplers aggregated into arrays within a shader (using square * brackets [ ]) can only be indexed with integral constant * expressions [...]." * * This restriction was added in GLSL 1.30. Shaders using earlier version * of the language should not be rejected by the compiler front-end for * using this construct. This allows useful things such as using a loop * counter as the index to an array of samplers. If the loop in unrolled, * the code should compile correctly. Instead, emit a warning. */ if (array->type->is_array() && array->type->element_type()->is_sampler() && const_index == NULL) { if (state->language_version == 100) { _mesa_glsl_warning(&loc, state, "sampler arrays indexed with non-constant " "expressions is optional in GLSL ES 1.00"); } else if (state->language_version < 130) { _mesa_glsl_warning(&loc, state, "sampler arrays indexed with non-constant " "expressions is forbidden in GLSL 1.30 and " "later"); } else { _mesa_glsl_error(&loc, state, "sampler arrays indexed with non-constant " "expressions is forbidden in GLSL 1.30 and " "later"); error_emitted = true; } } if (error_emitted) result->type = glsl_type::error_type; break; } case ast_function_call: /* Should *NEVER* get here. ast_function_call should always be handled * by ast_function_expression::hir. */ assert(0); break; case ast_identifier: { /* ast_identifier can appear several places in a full abstract syntax * tree. This particular use must be at location specified in the grammar * as 'variable_identifier'. */ ir_variable *var = state->symbols->get_variable(this->primary_expression.identifier); if (var != NULL) { var->used = true; result = new(ctx) ir_dereference_variable(var); } else { _mesa_glsl_error(& loc, state, "`%s' undeclared", this->primary_expression.identifier); result = ir_rvalue::error_value(ctx); error_emitted = true; } break; } case ast_int_constant: result = new(ctx) ir_constant(this->primary_expression.int_constant); break; case ast_uint_constant: result = new(ctx) ir_constant(this->primary_expression.uint_constant); break; case ast_float_constant: result = new(ctx) ir_constant(this->primary_expression.float_constant); break; case ast_bool_constant: result = new(ctx) ir_constant(bool(this->primary_expression.bool_constant)); break; case ast_sequence: { /* It should not be possible to generate a sequence in the AST without * any expressions in it. */ assert(!this->expressions.is_empty()); /* The r-value of a sequence is the last expression in the sequence. If * the other expressions in the sequence do not have side-effects (and * therefore add instructions to the instruction list), they get dropped * on the floor. */ exec_node *previous_tail_pred = NULL; 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); } /* Any errors should have already been emitted in the loop above. */ error_emitted = true; break; } } type = NULL; /* use result->type, not type. */ assert(result != NULL); if (result->type->is_error() && !error_emitted) _mesa_glsl_error(& loc, state, "type mismatch"); return result; } ir_rvalue * ast_expression_statement::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { /* It is possible to have expression statements that don't have an * expression. This is the solitary semicolon: * * for (i = 0; i < 5; i++) * ; * * In this case the expression will be NULL. Test for NULL and don't do * anything in that case. */ if (expression != NULL) expression->hir(instructions, state); /* Statements do not have r-values. */ return NULL; } ir_rvalue * ast_compound_statement::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { if (new_scope) state->symbols->push_scope(); foreach_list_typed (ast_node, ast, link, &this->statements) ast->hir(instructions, state); if (new_scope) state->symbols->pop_scope(); /* Compound statements do not have r-values. */ return NULL; } static const glsl_type * process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size, struct _mesa_glsl_parse_state *state) { unsigned length = 0; /* 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; } 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()); } } } } else if (state->es_shader) { /* Section 10.17 of the GLSL ES 1.00 specification states that unsized * array declarations have been removed from the language. */ _mesa_glsl_error(loc, state, "unsized array declarations are not " "allowed in GLSL ES 1.00."); } return glsl_type::get_array_instance(base, length); } const glsl_type * ast_type_specifier::glsl_type(const char **name, 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); } return type; } static void apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, ir_variable *var, struct _mesa_glsl_parse_state *state, YYLTYPE *loc, bool ubo_qualifiers_valid) { if (qual->flags.q.invariant) { if (var->used) { _mesa_glsl_error(loc, state, "variable `%s' may not be redeclared " "`invariant' after being used", var->name); } else { var->invariant = 1; } } if (qual->flags.q.constant || qual->flags.q.attribute || qual->flags.q.uniform || (qual->flags.q.varying && (state->target == fragment_shader))) var->read_only = 1; if (qual->flags.q.centroid) var->centroid = 1; if (qual->flags.q.attribute && state->target != vertex_shader) { var->type = glsl_type::error_type; _mesa_glsl_error(loc, state, "`attribute' variables may not be declared in the " "%s shader", _mesa_glsl_shader_target_name(state->target)); } /* From page 25 (page 31 of the PDF) of the GLSL 1.10 spec: * * "The varying qualifier can be used only with the data types * float, vec2, vec3, vec4, mat2, mat3, and mat4, or arrays of * these." */ if (qual->flags.q.varying) { const glsl_type *non_array_type; if (var->type && var->type->is_array()) non_array_type = var->type->fields.array; else non_array_type = var->type; if (non_array_type && non_array_type->base_type != GLSL_TYPE_FLOAT) { var->type = glsl_type::error_type; _mesa_glsl_error(loc, state, "varying variables must be of base type float"); } } /* If there is no qualifier that changes the mode of the variable, leave * the setting alone. */ if (qual->flags.q.in && qual->flags.q.out) var->mode = ir_var_inout; else if (qual->flags.q.attribute || qual->flags.q.in || (qual->flags.q.varying && (state->target == fragment_shader))) var->mode = ir_var_in; else if (qual->flags.q.out || (qual->flags.q.varying && (state->target == vertex_shader))) var->mode = ir_var_out; else if (qual->flags.q.uniform) var->mode = ir_var_uniform; if (state->all_invariant && (state->current_function == NULL)) { switch (state->target) { case vertex_shader: if (var->mode == ir_var_out) var->invariant = true; break; case geometry_shader: if ((var->mode == ir_var_in) || (var->mode == ir_var_out)) var->invariant = true; break; case fragment_shader: if (var->mode == ir_var_in) var->invariant = true; break; } } if (qual->flags.q.flat) var->interpolation = INTERP_QUALIFIER_FLAT; else if (qual->flags.q.noperspective) var->interpolation = INTERP_QUALIFIER_NOPERSPECTIVE; else if (qual->flags.q.smooth) var->interpolation = INTERP_QUALIFIER_SMOOTH; else var->interpolation = INTERP_QUALIFIER_NONE; if (var->interpolation != INTERP_QUALIFIER_NONE && !(state->target == vertex_shader && var->mode == ir_var_out) && !(state->target == fragment_shader && var->mode == ir_var_in)) { _mesa_glsl_error(loc, state, "interpolation qualifier `%s' can only be applied to " "vertex shader outputs and fragment shader inputs.", var->interpolation_string()); } var->pixel_center_integer = qual->flags.q.pixel_center_integer; var->origin_upper_left = qual->flags.q.origin_upper_left; if ((qual->flags.q.origin_upper_left || qual->flags.q.pixel_center_integer) && (strcmp(var->name, "gl_FragCoord") != 0)) { const char *const qual_string = (qual->flags.q.origin_upper_left) ? "origin_upper_left" : "pixel_center_integer"; _mesa_glsl_error(loc, state, "layout qualifier `%s' can only be applied to " "fragment shader input `gl_FragCoord'", qual_string); } if (qual->flags.q.explicit_location) { const bool global_scope = (state->current_function == NULL); bool fail = false; const char *string = ""; /* In the vertex shader only shader inputs can be given explicit * locations. * * In the fragment shader only shader outputs can be given explicit * locations. */ switch (state->target) { case vertex_shader: if (!global_scope || (var->mode != ir_var_in)) { fail = true; string = "input"; } break; case geometry_shader: _mesa_glsl_error(loc, state, "geometry shader variables cannot be given " "explicit locations\n"); break; case fragment_shader: if (!global_scope || (var->mode != ir_var_out)) { fail = true; string = "output"; } break; }; if (fail) { _mesa_glsl_error(loc, state, "only %s shader %s variables can be given an " "explicit location\n", _mesa_glsl_shader_target_name(state->target), string); } else { var->explicit_location = true; /* This bit of silliness is needed because invalid explicit locations * are supposed to be flagged during linking. Small negative values * biased by VERT_ATTRIB_GENERIC0 or FRAG_RESULT_DATA0 could alias * built-in values (e.g., -16+VERT_ATTRIB_GENERIC0 = VERT_ATTRIB_POS). * The linker needs to be able to differentiate these cases. This * ensures that negative values stay negative. */ if (qual->location >= 0) { var->location = (state->target == vertex_shader) ? (qual->location + VERT_ATTRIB_GENERIC0) : (qual->location + FRAG_RESULT_DATA0); } else { var->location = qual->location; } if (qual->flags.q.explicit_index) { /* From the GLSL 4.30 specification, section 4.4.2 (Output * Layout Qualifiers): * * "It is also a compile-time error if a fragment shader * sets a layout index to less than 0 or greater than 1." * * Older specifications don't mandate a behavior; we take * this as a clarification and always generate the error. */ if (qual->index < 0 || qual->index > 1) { _mesa_glsl_error(loc, state, "explicit index may only be 0 or 1\n"); } else { var->explicit_index = true; var->index = qual->index; } } } } else if (qual->flags.q.explicit_index) { _mesa_glsl_error(loc, state, "explicit index requires explicit location\n"); } /* Does the declaration use the 'layout' keyword? */ const bool uses_layout = qual->flags.q.pixel_center_integer || qual->flags.q.origin_upper_left || qual->flags.q.explicit_location; /* no need for index since it relies on location */ /* Does the declaration use the deprecated 'attribute' or 'varying' * keywords? */ const bool uses_deprecated_qualifier = qual->flags.q.attribute || qual->flags.q.varying; /* Is the 'layout' keyword used with parameters that allow relaxed checking. * Many implementations of GL_ARB_fragment_coord_conventions_enable and some * implementations (only Mesa?) GL_ARB_explicit_attrib_location_enable * allowed the layout qualifier to be used with 'varying' and 'attribute'. * These extensions and all following extensions that add the 'layout' * keyword have been modified to require the use of 'in' or 'out'. * * The following extension do not allow the deprecated keywords: * * GL_AMD_conservative_depth * GL_ARB_conservative_depth * GL_ARB_gpu_shader5 * GL_ARB_separate_shader_objects * GL_ARB_tesselation_shader * GL_ARB_transform_feedback3 * GL_ARB_uniform_buffer_object * * It is unknown whether GL_EXT_shader_image_load_store or GL_NV_gpu_shader5 * allow layout with the deprecated keywords. */ const bool relaxed_layout_qualifier_checking = state->ARB_fragment_coord_conventions_enable; if (uses_layout && uses_deprecated_qualifier) { if (relaxed_layout_qualifier_checking) { _mesa_glsl_warning(loc, state, "`layout' qualifier may not be used with " "`attribute' or `varying'"); } else { _mesa_glsl_error(loc, state, "`layout' qualifier may not be used with " "`attribute' or `varying'"); } } /* Layout qualifiers for gl_FragDepth, which are enabled by extension * AMD_conservative_depth. */ int depth_layout_count = qual->flags.q.depth_any + qual->flags.q.depth_greater + qual->flags.q.depth_less + qual->flags.q.depth_unchanged; if (depth_layout_count > 0 && !state->AMD_conservative_depth_enable && !state->ARB_conservative_depth_enable) { _mesa_glsl_error(loc, state, "extension GL_AMD_conservative_depth or " "GL_ARB_conservative_depth must be enabled " "to use depth layout qualifiers"); } else if (depth_layout_count > 0 && strcmp(var->name, "gl_FragDepth") != 0) { _mesa_glsl_error(loc, state, "depth layout qualifiers can be applied only to " "gl_FragDepth"); } else if (depth_layout_count > 1 && strcmp(var->name, "gl_FragDepth") == 0) { _mesa_glsl_error(loc, state, "at most one depth layout qualifier can be applied to " "gl_FragDepth"); } if (qual->flags.q.depth_any) var->depth_layout = ir_depth_layout_any; else if (qual->flags.q.depth_greater) var->depth_layout = ir_depth_layout_greater; else if (qual->flags.q.depth_less) var->depth_layout = ir_depth_layout_less; else if (qual->flags.q.depth_unchanged) var->depth_layout = ir_depth_layout_unchanged; else var->depth_layout = ir_depth_layout_none; if (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"); } if (!ubo_qualifiers_valid && (qual->flags.q.row_major || qual->flags.q.column_major)) { _mesa_glsl_error(loc, state, "uniform block layout qualifiers row_major and " "column_major can only be applied to uniform block " "members"); } } /** * Get the variable that is being redeclared by this declaration * * Semantic checks to verify the validity of the redeclaration are also * performed. If semantic checks fail, compilation error will be emitted via * \c _mesa_glsl_error, but a non-\c NULL pointer will still be returned. * * \returns * A pointer to an existing variable in the current scope if the declaration * is a redeclaration, \c NULL otherwise. */ ir_variable * get_variable_being_redeclared(ir_variable *var, ast_declaration *decl, struct _mesa_glsl_parse_state *state) { /* Check if this declaration is actually a re-declaration, either to * resize an array or add qualifiers to an existing variable. * * This is allowed for variables in the current scope, or when at * global scope (for built-ins in the implicit outer scope). */ ir_variable *earlier = state->symbols->get_variable(decl->identifier); if (earlier == NULL || (state->current_function != NULL && !state->symbols->name_declared_this_scope(decl->identifier))) { return NULL; } YYLTYPE loc = decl->get_location(); /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec, * * "It is legal to declare an array without a size and then * later re-declare the same name as an array of the same * type and specify a size." */ if ((earlier->type->array_size() == 0) && var->type->is_array() && (var->type->element_type() == earlier->type->element_type())) { /* FINISHME: This doesn't match the qualifiers on the two * FINISHME: declarations. It's not 100% clear whether this is * FINISHME: required or not. */ 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); } earlier->type = var->type; delete var; var = NULL; } else if (state->ARB_fragment_coord_conventions_enable && strcmp(var->name, "gl_FragCoord") == 0 && earlier->type == var->type && earlier->mode == var->mode) { /* Allow redeclaration of gl_FragCoord for ARB_fcc layout * qualifiers. */ earlier->origin_upper_left = var->origin_upper_left; earlier->pixel_center_integer = var->pixel_center_integer; /* According to section 4.3.7 of the GLSL 1.30 spec, * the following built-in varaibles can be redeclared with an * interpolation qualifier: * * gl_FrontColor * * gl_BackColor * * gl_FrontSecondaryColor * * gl_BackSecondaryColor * * gl_Color * * gl_SecondaryColor */ } else if (state->language_version >= 130 && (strcmp(var->name, "gl_FrontColor") == 0 || strcmp(var->name, "gl_BackColor") == 0 || strcmp(var->name, "gl_FrontSecondaryColor") == 0 || strcmp(var->name, "gl_BackSecondaryColor") == 0 || strcmp(var->name, "gl_Color") == 0 || strcmp(var->name, "gl_SecondaryColor") == 0) && earlier->type == var->type && earlier->mode == var->mode) { earlier->interpolation = var->interpolation; /* Layout qualifiers for gl_FragDepth. */ } else if ((state->AMD_conservative_depth_enable || state->ARB_conservative_depth_enable) && strcmp(var->name, "gl_FragDepth") == 0 && earlier->type == var->type && earlier->mode == var->mode) { /** From the AMD_conservative_depth spec: * Within any shader, the first redeclarations of gl_FragDepth * must appear before any use of gl_FragDepth. */ if (earlier->used) { _mesa_glsl_error(&loc, state, "the first redeclaration of gl_FragDepth " "must appear before any use of gl_FragDepth"); } /* Prevent inconsistent redeclaration of depth layout qualifier. */ if (earlier->depth_layout != ir_depth_layout_none && earlier->depth_layout != var->depth_layout) { _mesa_glsl_error(&loc, state, "gl_FragDepth: depth layout is declared here " "as '%s, but it was previously declared as " "'%s'", depth_layout_string(var->depth_layout), depth_layout_string(earlier->depth_layout)); } earlier->depth_layout = var->depth_layout; } else { _mesa_glsl_error(&loc, state, "`%s' redeclared", decl->identifier); } return earlier; } /** * Generate the IR for an initializer in a variable declaration */ ir_rvalue * process_initializer(ir_variable *var, ast_declaration *decl, ast_fully_specified_type *type, exec_list *initializer_instructions, struct _mesa_glsl_parse_state *state) { ir_rvalue *result = NULL; YYLTYPE initializer_loc = decl->initializer->get_location(); /* From page 24 (page 30 of the PDF) of the GLSL 1.10 spec: * * "All uniform variables are read-only and are initialized either * directly by an application via API commands, or indirectly by * OpenGL." */ if ((state->language_version <= 110) && (var->mode == ir_var_uniform)) { _mesa_glsl_error(& initializer_loc, state, "cannot initialize uniforms in GLSL 1.10"); } if (var->type->is_sampler()) { _mesa_glsl_error(& initializer_loc, state, "cannot initialize samplers"); } if ((var->mode == ir_var_in) && (state->current_function == NULL)) { _mesa_glsl_error(& initializer_loc, state, "cannot initialize %s shader input / %s", _mesa_glsl_shader_target_name(state->target), (state->target == vertex_shader) ? "attribute" : "varying"); } ir_dereference *const lhs = new(state) ir_dereference_variable(var); ir_rvalue *rhs = decl->initializer->hir(initializer_instructions, state); /* Calculate the constant value if this is a const or uniform * declaration. */ if (type->qualifier.flags.q.constant || type->qualifier.flags.q.uniform) { ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs, true); if (new_rhs != NULL) { rhs = new_rhs; ir_constant *constant_value = rhs->constant_expression_value(); if (!constant_value) { _mesa_glsl_error(& initializer_loc, state, "initializer of %s variable `%s' must be a " "constant expression", (type->qualifier.flags.q.constant) ? "const" : "uniform", decl->identifier); if (var->type->is_numeric()) { /* Reduce cascading errors. */ var->constant_value = ir_constant::zero(state, var->type); } } else { rhs = constant_value; var->constant_value = constant_value; } } else { _mesa_glsl_error(&initializer_loc, state, "initializer of type %s cannot be assigned to " "variable of type %s", rhs->type->name, var->type->name); if (var->type->is_numeric()) { /* Reduce cascading errors. */ var->constant_value = ir_constant::zero(state, var->type); } } } if (rhs && !rhs->type->is_error()) { bool temp = var->read_only; if (type->qualifier.flags.q.constant) var->read_only = false; /* Never emit code to initialize a uniform. */ const glsl_type *initializer_type; if (!type->qualifier.flags.q.uniform) { result = do_assignment(initializer_instructions, state, NULL, lhs, rhs, true, type->get_location()); initializer_type = result->type; } else initializer_type = rhs->type; var->constant_initializer = rhs->constant_expression_value(); var->has_initializer = true; /* If the declared variable is an unsized array, it must inherrit * its full type from the initializer. A declaration such as * * uniform float a[] = float[](1.0, 2.0, 3.0, 3.0); * * becomes * * uniform float a[4] = float[](1.0, 2.0, 3.0, 3.0); * * The assignment generated in the if-statement (below) will also * automatically handle this case for non-uniforms. * * If the declared variable is not an array, the types must * already match exactly. As a result, the type assignment * here can be done unconditionally. For non-uniforms the call * to do_assignment can change the type of the initializer (via * the implicit conversion rules). For uniforms the initializer * must be a constant expression, and the type of that expression * was validated above. */ var->type = initializer_type; var->read_only = temp; } return result; } ir_rvalue * ast_declarator_list::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { void *ctx = state; const struct glsl_type *decl_type; const char *type_name = NULL; ir_rvalue *result = NULL; YYLTYPE loc = this->get_location(); /* From page 46 (page 52 of the PDF) of the GLSL 1.50 spec: * * "To ensure that a particular output variable is invariant, it is * necessary to use the invariant qualifier. It can either be used to * qualify a previously declared variable as being invariant * * invariant gl_Position; // make existing gl_Position be invariant" * * In these cases the parser will set the 'invariant' flag in the declarator * list, and the type will be NULL. */ if (this->invariant) { assert(this->type == NULL); if (state->current_function != NULL) { _mesa_glsl_error(& loc, state, "All uses of `invariant' keyword must be at global " "scope\n"); } foreach_list_typed (ast_declaration, decl, link, &this->declarations) { assert(!decl->is_array); assert(decl->array_size == NULL); assert(decl->initializer == NULL); ir_variable *const earlier = state->symbols->get_variable(decl->identifier); if (earlier == NULL) { _mesa_glsl_error(& loc, state, "Undeclared variable `%s' cannot be marked " "invariant\n", decl->identifier); } else if ((state->target == vertex_shader) && (earlier->mode != ir_var_out)) { _mesa_glsl_error(& loc, state, "`%s' cannot be marked invariant, vertex shader " "outputs only\n", decl->identifier); } else if ((state->target == fragment_shader) && (earlier->mode != ir_var_in)) { _mesa_glsl_error(& loc, state, "`%s' cannot be marked invariant, fragment shader " "inputs only\n", decl->identifier); } else if (earlier->used) { _mesa_glsl_error(& loc, state, "variable `%s' may not be redeclared " "`invariant' after being used", earlier->name); } else { earlier->invariant = true; } } /* Invariant redeclarations do not have r-values. */ return NULL; } assert(this->type != NULL); assert(!this->invariant); /* The type specifier may contain a structure definition. Process that * before any of the variable declarations. */ (void) this->type->specifier->hir(instructions, state); decl_type = this->type->specifier->glsl_type(& type_name, state); if (this->declarations.is_empty()) { /* If there is no structure involved in the program text, there are two * possible scenarios: * * - The program text contained something like 'vec4;'. This is an * empty declaration. It is valid but weird. Emit a warning. * * - The program text contained something like 'S;' and 'S' is not the * name of a known structure type. This is both invalid and weird. * Emit an error. * * Note that if decl_type is NULL and there is a structure involved, * there must have been some sort of error with the structure. In this * case we assume that an error was already generated on this line of * code for the structure. There is no need to generate an additional, * confusing error. */ assert(this->type->specifier->structure == NULL || decl_type != NULL || state->error); if (this->type->specifier->structure == NULL) { if (decl_type != NULL) { _mesa_glsl_warning(&loc, state, "empty declaration"); } else { _mesa_glsl_error(&loc, state, "invalid type `%s' in empty declaration", type_name); } } } foreach_list_typed (ast_declaration, decl, link, &this->declarations) { const struct glsl_type *var_type; ir_variable *var; /* FINISHME: Emit a warning if a variable declaration shadows a * FINISHME: declaration at a higher scope. */ 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 (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 = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto); /* 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 * specified. * * Local variables can only use the qualifier const." * * This is relaxed in GLSL 1.30. It is also relaxed by any extension * that adds the 'layout' keyword. */ if ((state->language_version < 130) && !state->ARB_explicit_attrib_location_enable && !state->ARB_fragment_coord_conventions_enable) { if (this->type->qualifier.flags.q.out) { _mesa_glsl_error(& loc, state, "`out' qualifier in declaration of `%s' " "only valid for function parameters in %s.", decl->identifier, state->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->version_string); } /* FINISHME: Test for other invalid qualifiers. */ } apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc, this->ubo_qualifiers_valid); if (this->type->qualifier.flags.q.invariant) { if ((state->target == vertex_shader) && !(var->mode == ir_var_out || var->mode == ir_var_inout)) { /* FINISHME: Note that this doesn't work for invariant on * a function signature outval */ _mesa_glsl_error(& loc, state, "`%s' cannot be marked invariant, vertex shader " "outputs only\n", var->name); } else if ((state->target == fragment_shader) && !(var->mode == ir_var_in || var->mode == ir_var_inout)) { /* FINISHME: Note that this doesn't work for invariant on * a function signature inval */ _mesa_glsl_error(& loc, state, "`%s' cannot be marked invariant, fragment shader " "inputs only\n", var->name); } } if (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_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 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->language_version > 120) 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 && (state->language_version <= 130) && var->type->is_array()) { _mesa_glsl_error(& loc, state, "vertex shader input / attribute cannot have " "array type"); error_emitted = true; } } } /* Integer vertex outputs must be qualified with 'flat'. * * From section 4.3.6 of the GLSL 1.30 spec: * "If a vertex output is a signed or unsigned integer or integer * vector, then it must be qualified with the interpolation qualifier * flat." */ if (state->language_version >= 130 && state->target == vertex_shader && state->current_function == NULL && var->type->is_integer() && var->mode == ir_var_out && var->interpolation != INTERP_QUALIFIER_FLAT) { _mesa_glsl_error(&loc, state, "If a vertex output is an integer, " "then it must be qualified with 'flat'"); } /* Interpolation qualifiers cannot be applied to 'centroid' and * 'centroid varying'. * * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec: * "interpolation qualifiers may only precede the qualifiers in, * centroid in, out, or centroid out in a declaration. They do not apply * to the deprecated storage qualifiers varying or centroid varying." */ if (state->language_version >= 130 && this->type->qualifier.has_interpolation() && this->type->qualifier.flags.q.varying) { const char *i = this->type->qualifier.interpolation_string(); assert(i != NULL); const char *s; if (this->type->qualifier.flags.q.centroid) s = "centroid varying"; else s = "varying"; _mesa_glsl_error(&loc, state, "qualifier '%s' cannot be applied to the " "deprecated storage qualifier '%s'", i, s); } /* Interpolation qualifiers can only apply to vertex shader outputs and * fragment shader inputs. * * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec: * "Outputs from a vertex shader (out) and inputs to a fragment * shader (in) can be further qualified with one or more of these * interpolation qualifiers" */ if (state->language_version >= 130 && this->type->qualifier.has_interpolation()) { const char *i = this->type->qualifier.interpolation_string(); assert(i != NULL); switch (state->target) { case vertex_shader: if (this->type->qualifier.flags.q.in) { _mesa_glsl_error(&loc, state, "qualifier '%s' cannot be applied to vertex " "shader inputs", i); } break; case fragment_shader: if (this->type->qualifier.flags.q.out) { _mesa_glsl_error(&loc, state, "qualifier '%s' cannot be applied to fragment " "shader outputs", i); } break; default: assert(0); } } /* From section 4.3.4 of the GLSL 1.30 spec: * "It is an error to use centroid in in a vertex shader." */ if (state->language_version >= 130 && this->type->qualifier.flags.q.centroid && this->type->qualifier.flags.q.in && state->target == vertex_shader) { _mesa_glsl_error(&loc, state, "'centroid in' cannot be used in a vertex shader"); } /* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30. */ if (this->type->specifier->precision != ast_precision_none && state->language_version != 100 && state->language_version < 130) { _mesa_glsl_error(&loc, state, "precision qualifiers are supported only in GLSL ES " "1.00, and GLSL 1.30 and later"); } /* Precision qualifiers only apply to floating point and integer types. * * From section 4.5.2 of the GLSL 1.30 spec: * "Any floating point or any integer declaration can have the type * preceded by one of these precision qualifiers [...] Literal * constants do not have precision qualifiers. Neither do Boolean * variables. * * In GLSL ES, sampler types are also allowed. * * From page 87 of the GLSL ES spec: * "RESOLUTION: Allow sampler types to take a precision qualifier." */ if (this->type->specifier->precision != ast_precision_none && !var->type->is_float() && !var->type->is_integer() && !(var->type->is_sampler() && state->es_shader) && !(var->type->is_array() && (var->type->fields.array->is_float() || var->type->fields.array->is_integer()))) { _mesa_glsl_error(&loc, state, "precision qualifiers apply only to floating point" "%s types", state->es_shader ? ", integer, and sampler" : "and integer"); } /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: * * "[Sampler types] can only be declared as function * parameters or uniform variables (see Section 4.3.5 * "Uniform")". */ if (var_type->contains_sampler() && !this->type->qualifier.flags.q.uniform) { _mesa_glsl_error(&loc, state, "samplers must be declared uniform"); } /* Process the initializer and add its instructions to a temporary * list. This list will be added to the instruction stream (below) after * the declaration is added. This is done because in some cases (such as * redeclarations) the declaration may not actually be added to the * instruction stream. */ exec_list initializer_instructions; ir_variable *earlier = get_variable_being_redeclared(var, decl, state); if (decl->initializer != NULL) { result = process_initializer((earlier == NULL) ? var : earlier, decl, this->type, &initializer_instructions, state); } /* From page 23 (page 29 of the PDF) of the GLSL 1.10 spec: * * "It is an error to write to a const variable outside of * its declaration, so they must be initialized when * 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); } /* If the declaration is not a redeclaration, there are a few additional * semantic checks that must be applied. In addition, variable that was * created for the declaration should be added to the IR stream. */ if (earlier == NULL) { /* From page 15 (page 21 of the PDF) of the GLSL 1.10 spec, * * "Identifiers starting with "gl_" are reserved for use by * OpenGL, and may not be declared in a shader as either a * variable or a function." */ if (strncmp(decl->identifier, "gl_", 3) == 0) _mesa_glsl_error(& loc, state, "identifier `%s' uses reserved `gl_' prefix", decl->identifier); else if (strstr(decl->identifier, "__")) { /* From page 14 (page 20 of the PDF) of the GLSL 1.10 * spec: * * "In addition, all identifiers containing two * consecutive underscores (__) are reserved as * possible future keywords." */ _mesa_glsl_error(& loc, state, "identifier `%s' uses reserved `__' string", decl->identifier); } /* Add the variable to the symbol table. Note that the initializer's * IR was already processed earlier (though it hasn't been emitted * yet), without the variable in scope. * * This differs from most C-like languages, but it follows the GLSL * specification. From page 28 (page 34 of the PDF) of the GLSL 1.50 * spec: * * "Within a declaration, the scope of a name starts immediately * after the initializer if present or immediately after the name * being declared if not." */ if (!state->symbols->add_variable(var)) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(&loc, state, "name `%s' already taken in the " "current scope", decl->identifier); continue; } /* Push the variable declaration to the top. It means that all the * variable declarations will appear in a funny last-to-first order, * but otherwise we run into trouble if a function is prototyped, a * global var is decled, then the function is defined with usage of * the global var. See glslparsertest's CorrectModule.frag. */ instructions->push_head(var); } instructions->append_list(&initializer_instructions); } /* Generally, variable declarations do not have r-values. However, * one is used for the declaration in * * while (bool b = some_condition()) { * ... * } * * so we return the rvalue from the last seen declaration here. */ return result; } ir_rvalue * ast_parameter_declarator::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { void *ctx = state; const struct glsl_type *type; const char *name = NULL; YYLTYPE loc = this->get_location(); type = this->type->specifier->glsl_type(& name, state); if (type == NULL) { if (name != NULL) { _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); } type = glsl_type::error_type; } /* From page 62 (page 68 of the PDF) of the GLSL 1.50 spec: * * "Functions that accept no input arguments need not use void in the * argument list because prototypes (or definitions) are required and * therefore there is no ambiguity when an empty argument list "( )" is * declared. The idiom "(void)" as a parameter list is provided for * convenience." * * Placing this check here prevents a void parameter being set up * for a function, which avoids tripping up checks for main taking * parameters and lookups of an unnamed symbol. */ if (type->is_void()) { if (this->identifier != NULL) _mesa_glsl_error(& loc, state, "named parameter cannot have type `void'"); is_void = true; return NULL; } if (formal_parameter && (this->identifier == NULL)) { _mesa_glsl_error(& loc, state, "formal parameter lacks a name"); return NULL; } /* 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); } if (!type->is_error() && type->array_size() == 0) { _mesa_glsl_error(&loc, state, "arrays passed as parameters must have " "a declared size."); type = glsl_type::error_type; } is_void = false; ir_variable *var = new(ctx) ir_variable(type, this->identifier, ir_var_in); /* Apply any specified qualifiers to the parameter declaration. Note that * for function parameters the default mode is 'in'. */ apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc, false); /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: * * "Samplers 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_inout || var->mode == ir_var_out) && type->contains_sampler()) { _mesa_glsl_error(&loc, state, "out and inout parameters cannot contain samplers"); type = glsl_type::error_type; } /* From page 39 (page 45 of the PDF) of the GLSL 1.10 spec: * * "When calling a function, expressions that do not evaluate to * l-values cannot be passed to parameters declared as out or inout." * * 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." * * 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_inout || var->mode == ir_var_out) && type->is_array() && state->language_version == 110) { _mesa_glsl_error(&loc, state, "Arrays cannot be out or inout parameters in GLSL 1.10"); type = glsl_type::error_type; } instructions->push_tail(var); /* Parameter declarations do not have r-values. */ return NULL; } void ast_parameter_declarator::parameters_to_hir(exec_list *ast_parameters, bool formal, exec_list *ir_parameters, _mesa_glsl_parse_state *state) { ast_parameter_declarator *void_param = NULL; unsigned count = 0; foreach_list_typed (ast_parameter_declarator, param, link, ast_parameters) { param->formal_parameter = formal; param->hir(ir_parameters, state); if (param->is_void) void_param = param; count++; } if ((void_param != NULL) && (count > 1)) { YYLTYPE loc = void_param->get_location(); _mesa_glsl_error(& loc, state, "`void' parameter must be only parameter"); } } void emit_function(_mesa_glsl_parse_state *state, ir_function *f) { /* IR invariants disallow function declarations or definitions * nested within other function definitions. But there is no * requirement about the relative order of function declarations * and definitions with respect to one another. So simply insert * the new ir_function block at the end of the toplevel instruction * list. */ state->toplevel_ir->push_tail(f); } ir_rvalue * ast_function::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { void *ctx = state; ir_function *f = NULL; ir_function_signature *sig = NULL; exec_list hir_parameters; const char *const name = identifier; /* New functions are always added to the top-level IR instruction stream, * so this instruction list pointer is ignored. See also emit_function * (called below). */ (void) instructions; /* From page 21 (page 27 of the PDF) of the GLSL 1.20 spec, * * "Function declarations (prototypes) cannot occur inside of functions; * they must be at global scope, or for the built-in functions, outside * the global scope." * * From page 27 (page 33 of the PDF) of the GLSL ES 1.00.16 spec, * * "User defined functions may only be defined within the global scope." * * Note that this language does not appear in GLSL 1.10. */ if ((state->current_function != NULL) && (state->language_version != 110)) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(&loc, state, "declaration of function `%s' not allowed within " "function body", name); } /* From page 15 (page 21 of the PDF) of the GLSL 1.10 spec, * * "Identifiers starting with "gl_" are reserved for use by * OpenGL, and may not be declared in a shader as either a * variable or a function." */ if (strncmp(name, "gl_", 3) == 0) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(&loc, state, "identifier `%s' uses reserved `gl_' prefix", name); } /* Convert the list of function parameters to HIR now so that they can be * used below to compare this function's signature with previously seen * signatures for functions with the same name. */ ast_parameter_declarator::parameters_to_hir(& this->parameters, is_definition, & hir_parameters, state); const char *return_type_name; const glsl_type *return_type = this->return_type->specifier->glsl_type(& return_type_name, state); if (!return_type) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(&loc, state, "function `%s' has undeclared return type `%s'", name, return_type_name); return_type = glsl_type::error_type; } /* From page 56 (page 62 of the PDF) of the GLSL 1.30 spec: * "No qualifier is allowed on the return type of a function." */ if (this->return_type->has_qualifiers()) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(& loc, state, "function `%s' return type has qualifiers", name); } /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: * * "[Sampler types] can only be declared as function parameters * or uniform variables (see Section 4.3.5 "Uniform")". */ if (return_type->contains_sampler()) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(&loc, state, "function `%s' return type can't contain a sampler", name); } /* 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())) { sig = f->exact_matching_signature(&hir_parameters); if (sig != NULL) { 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); } 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); } if (is_definition && sig->is_defined) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(& loc, state, "function `%s' redefined", name); } } } 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(); _mesa_glsl_error(& loc, state, "main() must return void"); } if (!hir_parameters.is_empty()) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(& loc, state, "main() must not take any parameters"); } } /* Finish storing the information about this new function in its signature. */ if (sig == NULL) { sig = new(ctx) ir_function_signature(return_type); f->add_signature(sig); } sig->replace_parameters(&hir_parameters); signature = sig; /* Function declarations (prototypes) do not have r-values. */ return NULL; } ir_rvalue * ast_function_definition::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { prototype->is_definition = true; prototype->hir(instructions, state); ir_function_signature *signature = prototype->signature; if (signature == NULL) return NULL; assert(state->current_function == NULL); state->current_function = signature; state->found_return = false; /* Duplicate parameters declared in the prototype as concrete variables. * 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); /* 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(); _mesa_glsl_error(& loc, state, "parameter `%s' redeclared", var->name); } else { state->symbols->add_variable(var); } } /* Convert the body of the function to HIR. */ this->body->hir(&signature->body, state); signature->is_defined = true; state->symbols->pop_scope(); assert(state->current_function == signature); state->current_function = NULL; 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); } /* Function definitions do not have r-values. */ return NULL; } ir_rvalue * ast_jump_statement::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { void *ctx = state; switch (mode) { case ast_return: { ir_return *inst; assert(state->current_function); if (opt_return_value) { ir_rvalue *const 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. */ if (state->current_function->return_type != ret_type) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(& loc, state, "`return' with wrong type %s, in function `%s' " "returning %s", ret_type->name, state->current_function->function_name(), state->current_function->return_type->name); } 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; } state->found_return = true; instructions->push_tail(inst); break; } case ast_discard: if (state->target != fragment_shader) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(& loc, state, "`discard' may only appear in a fragment shader"); } instructions->push_tail(new(ctx) ir_discard); break; case ast_break: case ast_continue: if (mode == ast_continue && state->loop_nesting_ast == NULL) { YYLTYPE loc = this->get_location(); _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(); _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); } } break; } /* Jump instructions do not have r-values. */ return NULL; } ir_rvalue * ast_selection_statement::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { void *ctx = state; ir_rvalue *const condition = this->condition->hir(instructions, state); /* From page 66 (page 72 of the PDF) of the GLSL 1.50 spec: * * "Any expression whose type evaluates to a Boolean can be used as the * conditional expression bool-expression. Vector types are not accepted * as the expression to if." * * The checks are separated so that higher quality diagnostics can be * generated for cases where both rules are violated. */ if (!condition->type->is_boolean() || !condition->type->is_scalar()) { YYLTYPE loc = this->condition->get_location(); _mesa_glsl_error(& loc, state, "if-statement condition must be scalar " "boolean"); } ir_if *const stmt = new(ctx) ir_if(condition); if (then_statement != NULL) { state->symbols->push_scope(); then_statement->hir(& stmt->then_instructions, state); state->symbols->pop_scope(); } if (else_statement != NULL) { state->symbols->push_scope(); else_statement->hir(& stmt->else_instructions, state); state->symbols->pop_scope(); } instructions->push_tail(stmt); /* if-statements do not have r-values. */ return NULL; } ir_rvalue * ast_switch_statement::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { void *ctx = state; ir_rvalue *const test_expression = this->test_expression->hir(instructions, state); /* From page 66 (page 55 of the PDF) of the GLSL 1.50 spec: * * "The type of init-expression in a switch statement must be a * scalar integer." */ if (!test_expression->type->is_scalar() || !test_expression->type->is_integer()) { YYLTYPE loc = this->test_expression->get_location(); _mesa_glsl_error(& loc, state, "switch-statement expression must be scalar " "integer"); } /* Track the switch-statement nesting in a stack-like manner. */ struct glsl_switch_state saved = state->switch_state; state->switch_state.is_switch_innermost = true; state->switch_state.switch_nesting_ast = this; state->switch_state.labels_ht = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare); state->switch_state.previous_default = NULL; /* Initalize is_fallthru state to false. */ 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); 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)); /* Initalize is_break state to false. */ ir_rvalue *const is_break_val = new (ctx) ir_constant(false); state->switch_state.is_break_var = new(ctx) ir_variable(glsl_type::bool_type, "switch_is_break_tmp", ir_var_temporary); instructions->push_tail(state->switch_state.is_break_var); ir_dereference_variable *deref_is_break_var = new(ctx) ir_dereference_variable(state->switch_state.is_break_var); instructions->push_tail(new(ctx) ir_assignment(deref_is_break_var, is_break_val)); /* Cache test expression. */ test_to_hir(instructions, state); /* Emit code for body of switch stmt. */ body->hir(instructions, state); hash_table_dtor(state->switch_state.labels_ht); state->switch_state = saved; /* Switch statements do not have r-values. */ return NULL; } void ast_switch_statement::test_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { void *ctx = state; /* Cache value of test expression. */ ir_rvalue *const test_val = test_expression->hir(instructions, state); state->switch_state.test_var = new(ctx) ir_variable(test_val->type, "switch_test_tmp", ir_var_temporary); ir_dereference_variable *deref_test_var = new(ctx) ir_dereference_variable(state->switch_state.test_var); instructions->push_tail(state->switch_state.test_var); instructions->push_tail(new(ctx) ir_assignment(deref_test_var, test_val)); } ir_rvalue * ast_switch_body::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { if (stmts != NULL) stmts->hir(instructions, state); /* Switch bodies do not have r-values. */ return NULL; } ir_rvalue * ast_case_statement_list::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { foreach_list_typed (ast_case_statement, case_stmt, link, & this->cases) case_stmt->hir(instructions, state); /* Case statements do not have r-values. */ return NULL; } ir_rvalue * ast_case_statement::hir(exec_list *instructions, 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); ir_if *const test_fallthru = new(state) ir_if(deref_fallthru_guard); foreach_list_typed (ast_node, stmt, link, & this->stmts) stmt->hir(& test_fallthru->then_instructions, state); instructions->push_tail(test_fallthru); /* Case statements do not have r-values. */ return NULL; } ir_rvalue * ast_case_label_list::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { foreach_list_typed (ast_case_label, label, link, & this->labels) label->hir(instructions, state); /* Case labels do not have r-values. */ return NULL; } ir_rvalue * ast_case_label::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { void *ctx = state; ir_dereference_variable *deref_fallthru_var = new(ctx) ir_dereference_variable(state->switch_state.is_fallthru_var); ir_rvalue *const true_val = new(ctx) ir_constant(true); /* If not default case, ... */ if (this->test_value != NULL) { /* Conditionally set fallthru state based on * comparison of cached test expression value to case label. */ ir_rvalue *const label_rval = this->test_value->hir(instructions, state); ir_constant *label_const = label_rval->constant_expression_value(); if (!label_const) { YYLTYPE loc = this->test_value->get_location(); _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); } 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]); } } ir_dereference_variable *deref_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_assignment *set_fallthru_on_test = 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"); loc = state->switch_state.previous_default->get_location(); _mesa_glsl_error(& loc, state, "this is the first default label"); } state->switch_state.previous_default = this; /* Set falltrhu state. */ ir_assignment *set_fallthru = new(ctx) ir_assignment(deref_fallthru_var, true_val); instructions->push_tail(set_fallthru); } /* Case statements do not have r-values. */ return NULL; } void ast_iteration_statement::condition_to_hir(ir_loop *stmt, struct _mesa_glsl_parse_state *state) { void *ctx = state; if (condition != NULL) { ir_rvalue *const cond = condition->hir(& stmt->body_instructions, state); if ((cond == NULL) || !cond->type->is_boolean() || !cond->type->is_scalar()) { YYLTYPE loc = condition->get_location(); _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); 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); if_stmt->then_instructions.push_tail(break_stmt); stmt->body_instructions.push_tail(if_stmt); } } } ir_rvalue * ast_iteration_statement::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { void *ctx = state; /* For-loops and while-loops start a new scope, but do-while loops do not. */ if (mode != ast_do_while) state->symbols->push_scope(); if (init_statement != NULL) init_statement->hir(instructions, state); ir_loop *const stmt = new(ctx) ir_loop(); instructions->push_tail(stmt); /* Track the current loop nesting. */ ast_iteration_statement *nesting_ast = state->loop_nesting_ast; state->loop_nesting_ast = this; /* Likewise, indicate that following code is closest to a loop, * NOT closest to a switch. */ bool saved_is_switch_innermost = state->switch_state.is_switch_innermost; state->switch_state.is_switch_innermost = false; if (mode != ast_do_while) condition_to_hir(stmt, state); if (body != NULL) body->hir(& stmt->body_instructions, state); if (rest_expression != NULL) rest_expression->hir(& stmt->body_instructions, state); if (mode == ast_do_while) condition_to_hir(stmt, state); if (mode != ast_do_while) state->symbols->pop_scope(); /* Restore previous nesting before returning. */ state->loop_nesting_ast = nesting_ast; state->switch_state.is_switch_innermost = saved_is_switch_innermost; /* Loops do not have r-values. */ return NULL; } ir_rvalue * ast_type_specifier::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { if (!this->is_precision_statement && this->structure == NULL) return NULL; YYLTYPE loc = this->get_location(); if (this->precision != ast_precision_none && state->language_version != 100 && state->language_version < 130) { _mesa_glsl_error(&loc, state, "precision qualifiers exist only in " "GLSL ES 1.00, and GLSL 1.30 and later"); return NULL; } if (this->precision != ast_precision_none && this->structure != NULL) { _mesa_glsl_error(&loc, state, "precision qualifiers do not apply to structures"); return NULL; } /* If this is a precision statement, check that the type to which it is * applied is either float or int. * * From section 4.5.3 of the GLSL 1.30 spec: * "The precision statement * precision precision-qualifier type; * can be used to establish a default precision qualifier. The type * field can be either int or float [...]. Any other types or * qualifiers will result in an error. */ if (this->is_precision_statement) { assert(this->precision != ast_precision_none); assert(this->structure == NULL); /* The check for structures was * performed above. */ if (this->is_array) { _mesa_glsl_error(&loc, state, "default precision statements do not apply to " "arrays"); return NULL; } if (strcmp(this->type_name, "float") != 0 && strcmp(this->type_name, "int") != 0) { _mesa_glsl_error(&loc, state, "default precision statements apply only to types " "float and int"); return NULL; } /* FINISHME: Translate precision statements into IR. */ return NULL; } if (this->structure != NULL) return this->structure->hir(instructions, state); return NULL; } ir_rvalue * ast_struct_specifier::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { unsigned decl_count = 0; /* Make an initial pass over the list of structure fields to determine how * many there are. Each element in this list is an ast_declarator_list. * This means that we actually need to count the number of elements in the * 'declarations' list in each of the elements. */ foreach_list_typed (ast_declarator_list, decl_list, link, &this->declarations) { foreach_list_const (decl_ptr, & decl_list->declarations) { decl_count++; } } /* Allocate storage for the structure fields and process the field * declarations. As the declarations are processed, try to also convert * the types to HIR. This ensures that structure definitions embedded in * other structure definitions are processed. */ glsl_struct_field *const fields = ralloc_array(state, glsl_struct_field, decl_count); unsigned i = 0; foreach_list_typed (ast_declarator_list, decl_list, link, &this->declarations) { const char *type_name; decl_list->type->specifier->hir(instructions, state); /* Section 10.9 of the GLSL ES 1.00 specification states that * embedded structure definitions have been removed from the language. */ if (state->es_shader && decl_list->type->specifier->structure != NULL) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(&loc, state, "Embedded structure definitions are " "not allowed in GLSL ES 1.00."); } const glsl_type *decl_type = decl_list->type->specifier->glsl_type(& type_name, state); foreach_list_typed (ast_declaration, decl, link, &decl_list->declarations) { const struct glsl_type *field_type = decl_type; if (decl->is_array) { YYLTYPE loc = decl->get_location(); field_type = process_array_type(&loc, decl_type, decl->array_size, state); } fields[i].type = (field_type != NULL) ? field_type : glsl_type::error_type; fields[i].name = decl->identifier; i++; } } assert(i == decl_count); const glsl_type *t = glsl_type::get_record_instance(fields, decl_count, this->name); YYLTYPE loc = this->get_location(); if (!state->symbols->add_type(name, t)) { _mesa_glsl_error(& loc, state, "struct `%s' previously defined", name); } else { const glsl_type **s = reralloc(state, state->user_structures, const glsl_type *, state->num_user_structures + 1); if (s != NULL) { s[state->num_user_structures] = t; state->user_structures = s; state->num_user_structures++; } } /* Structure type definitions do not have r-values. */ return NULL; } static struct gl_uniform_block * get_next_uniform_block(struct _mesa_glsl_parse_state *state) { if (state->num_uniform_blocks >= state->uniform_block_array_size) { state->uniform_block_array_size *= 2; if (state->uniform_block_array_size <= 4) state->uniform_block_array_size = 4; state->uniform_blocks = reralloc(state, state->uniform_blocks, struct gl_uniform_block, state->uniform_block_array_size); } memset(&state->uniform_blocks[state->num_uniform_blocks], 0, sizeof(*state->uniform_blocks)); return &state->uniform_blocks[state->num_uniform_blocks++]; } ir_rvalue * ast_uniform_block::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { /* The ast_uniform_block has a list of ast_declarator_lists. We * need to turn those into ir_variables with an association * with this uniform block. */ struct gl_uniform_block *ubo = get_next_uniform_block(state); ubo->Name = ralloc_strdup(state->uniform_blocks, this->block_name); if (!state->symbols->add_uniform_block(ubo)) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(&loc, state, "Uniform block name `%s' already taken in " "the current scope.\n", ubo->Name); } unsigned int num_variables = 0; foreach_list_typed(ast_declarator_list, decl_list, link, &declarations) { foreach_list_const(node, &decl_list->declarations) { num_variables++; } } bool block_row_major = this->layout.flags.q.row_major; ubo->Uniforms = rzalloc_array(state->uniform_blocks, struct gl_uniform_buffer_variable, num_variables); foreach_list_typed(ast_declarator_list, decl_list, link, &declarations) { exec_list declared_variables; decl_list->hir(&declared_variables, state); foreach_list_const(node, &declared_variables) { struct ir_variable *var = (ir_variable *)node; struct gl_uniform_buffer_variable *ubo_var = &ubo->Uniforms[ubo->NumUniforms++]; var->uniform_block = ubo - state->uniform_blocks; ubo_var->Name = ralloc_strdup(state->uniform_blocks, var->name); ubo_var->Type = var->type; ubo_var->Buffer = ubo - state->uniform_blocks; ubo_var->Offset = 0; /* Assigned at link time. */ if (var->type->is_matrix() || (var->type->is_array() && var->type->fields.array->is_matrix())) { ubo_var->RowMajor = block_row_major; if (decl_list->type->qualifier.flags.q.row_major) ubo_var->RowMajor = true; else if (decl_list->type->qualifier.flags.q.column_major) ubo_var->RowMajor = false; } /* From the GL_ARB_uniform_buffer_object 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." */ if (var->type->contains_sampler()) { YYLTYPE loc = decl_list->get_location(); _mesa_glsl_error(&loc, state, "Uniform in non-default uniform block contains sampler\n"); } } instructions->append_list(&declared_variables); } return NULL; } static void detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, exec_list *instructions) { bool gl_FragColor_assigned = false; bool gl_FragData_assigned = false; bool user_defined_fs_output_assigned = false; ir_variable *user_defined_fs_output = NULL; /* It would be nice to have proper location information. */ YYLTYPE loc; memset(&loc, 0, sizeof(loc)); foreach_list(node, instructions) { ir_variable *var = ((ir_instruction *)node)->as_variable(); if (!var || !var->assigned) continue; if (strcmp(var->name, "gl_FragColor") == 0) 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_out || var->mode == ir_var_inout)) { user_defined_fs_output_assigned = true; user_defined_fs_output = var; } } } /* From the GLSL 1.30 spec: * * "If a shader statically assigns a value to gl_FragColor, it * may not assign a value to any element of gl_FragData. If a * shader statically writes a value to any element of * gl_FragData, it may not assign a value to * gl_FragColor. That is, a shader may assign values to either * gl_FragColor or gl_FragData, but not both. Multiple shaders * linked together must also consistently write just one of * these variables. Similarly, if user declared output * variables are in use (statically assigned to), then the * built-in variables gl_FragColor and gl_FragData may not be * assigned to. These incorrect usages all generate compile * time errors." */ if (gl_FragColor_assigned && gl_FragData_assigned) { _mesa_glsl_error(&loc, state, "fragment shader writes to both " "`gl_FragColor' and `gl_FragData'\n"); } else if (gl_FragColor_assigned && user_defined_fs_output_assigned) { _mesa_glsl_error(&loc, state, "fragment shader writes to both " "`gl_FragColor' and `%s'\n", user_defined_fs_output->name); } else if (gl_FragData_assigned && user_defined_fs_output_assigned) { _mesa_glsl_error(&loc, state, "fragment shader writes to both " "`gl_FragData' and `%s'\n", user_defined_fs_output->name); } }