From 29285882676388aacff123e8bdf025904abf8ea9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 24 Jun 2010 15:32:15 -0700 Subject: glsl2: Move the compiler to the subdirectory it will live in in Mesa. --- src/glsl/ir_function.cpp | 225 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 src/glsl/ir_function.cpp (limited to 'src/glsl/ir_function.cpp') diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp new file mode 100644 index 0000000000..5db93f67fb --- /dev/null +++ b/src/glsl/ir_function.cpp @@ -0,0 +1,225 @@ +/* + * 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. + */ + +#include "glsl_types.h" +#include "ir.h" + +int +type_compare(const glsl_type *a, const glsl_type *b) +{ + /* If the types are the same, they trivially match. + */ + if (a == b) + return 0; + + switch (a->base_type) { + case GLSL_TYPE_UINT: + case GLSL_TYPE_INT: + case GLSL_TYPE_BOOL: + /* There is no implicit conversion to or from integer types or bool. + */ + if ((a->is_integer() != b->is_integer()) + || (a->is_boolean() != b->is_boolean())) + return -1; + + /* FALLTHROUGH */ + + case GLSL_TYPE_FLOAT: + if ((a->vector_elements != b->vector_elements) + || (a->matrix_columns != b->matrix_columns)) + return -1; + + return 1; + + case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_STRUCT: + /* Samplers and structures must match exactly. + */ + return -1; + + case GLSL_TYPE_ARRAY: + if ((b->base_type != GLSL_TYPE_ARRAY) + || (a->length != b->length)) + return -1; + + /* From GLSL 1.50 spec, page 27 (page 33 of the PDF): + * "There are no implicit array or structure conversions." + * + * If the comparison of the array element types detects that a conversion + * would be required, the array types do not match. + */ + return (type_compare(a->fields.array, b->fields.array) == 0) ? 0 : -1; + + case GLSL_TYPE_FUNCTION: + case GLSL_TYPE_VOID: + case GLSL_TYPE_ERROR: + default: + /* These are all error conditions. It is invalid for a parameter to + * a function to be declared as error, void, or a function. + */ + return -1; + } + + /* This point should be unreachable. + */ + assert(0); +} + + +static int +parameter_lists_match(exec_list *list_a, exec_list *list_b) +{ + exec_list_iterator iter_a = list_a->iterator(); + exec_list_iterator iter_b = list_b->iterator(); + int total_score = 0; + + for (/* empty */ ; iter_a.has_next(); iter_a.next(), iter_b.next()) { + /* If all of the parameters from the other parameter list have been + * exhausted, the lists have different length and, by definition, + * do not match. + */ + if (!iter_b.has_next()) + return -1; + + + const ir_variable *const param = (ir_variable *) iter_a.get(); + const ir_instruction *const actual = (ir_instruction *) iter_b.get(); + + /* Determine whether or not the types match. If the types are an + * exact match, the match score is zero. If the types don't match + * but the actual parameter can be coerced to the type of the declared + * parameter, the match score is one. + */ + int score; + switch ((enum ir_variable_mode)(param->mode)) { + case ir_var_auto: + case ir_var_uniform: + /* These are all error conditions. It is invalid for a parameter to + * a function to be declared as auto (not in, out, or inout) or + * as uniform. + */ + assert(0); + return -1; + + case ir_var_in: + score = type_compare(param->type, actual->type); + break; + + case ir_var_out: + score = type_compare(actual->type, param->type); + break; + + case ir_var_inout: + /* Since there are no bi-directional automatic conversions (e.g., + * there is int -> float but no float -> int), inout parameters must + * be exact matches. + */ + score = (type_compare(actual->type, param->type) == 0) ? 0 : -1; + break; + } + + if (score < 0) + return -1; + + total_score += score; + } + + /* If all of the parameters from the other parameter list have been + * exhausted, the lists have different length and, by definition, do not + * match. + */ + if (iter_b.has_next()) + return -1; + + return total_score; +} + + +const ir_function_signature * +ir_function::matching_signature(exec_list *actual_parameters) +{ + ir_function_signature *match = NULL; + + foreach_iter(exec_list_iterator, iter, signatures) { + ir_function_signature *const sig = + (ir_function_signature *) iter.get(); + + const int score = parameter_lists_match(& sig->parameters, + actual_parameters); + + if (score == 0) + return sig; + + if (score > 0) { + if (match != NULL) + return NULL; + + match = sig; + } + } + + return match; +} + + +static bool +parameter_lists_match_exact(exec_list *list_a, exec_list *list_b) +{ + exec_list_iterator iter_a = list_a->iterator(); + exec_list_iterator iter_b = list_b->iterator(); + + while (iter_a.has_next() && iter_b.has_next()) { + ir_variable *a = (ir_variable *)iter_a.get(); + ir_variable *b = (ir_variable *)iter_b.get(); + + /* If the types of the parameters do not match, the parameters lists + * are different. + */ + if (a->type != b->type) + return false; + + iter_a.next(); + iter_b.next(); + } + + /* Unless both lists are exhausted, they differ in length and, by + * definition, do not match. + */ + if (iter_a.has_next() != iter_b.has_next()) + return false; + + return true; +} + +ir_function_signature * +ir_function::exact_matching_signature(exec_list *actual_parameters) +{ + foreach_iter(exec_list_iterator, iter, signatures) { + ir_function_signature *const sig = + (ir_function_signature *) iter.get(); + + if (parameter_lists_match_exact(&sig->parameters, actual_parameters)) + return sig; + } + return NULL; +} -- cgit v1.2.3 From 11fc7beb2fa82179cfd9202449e1365b28f868a9 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 12 Jul 2010 18:35:20 -0700 Subject: ir_function: Make matching_signature not return const The linker needs to use this function to get specific function signatures, but it also needs to modify the returned signature. Since this method isn't itself const (i.e., const this pointer), there is no value in making a const and non-const version. --- src/glsl/ir.h | 2 +- src/glsl/ir_function.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/glsl/ir_function.cpp') diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 25bf6c6d15..053b6fecd1 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -379,7 +379,7 @@ public: * Find a signature that matches a set of actual parameters, taking implicit * conversions into account. */ - const ir_function_signature *matching_signature(exec_list *actual_param); + ir_function_signature *matching_signature(exec_list *actual_param); /** * Find a signature that exactly matches a set of actual parameters without diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp index 5db93f67fb..fcdb83be56 100644 --- a/src/glsl/ir_function.cpp +++ b/src/glsl/ir_function.cpp @@ -155,7 +155,7 @@ parameter_lists_match(exec_list *list_a, exec_list *list_b) } -const ir_function_signature * +ir_function_signature * ir_function::matching_signature(exec_list *actual_parameters) { ir_function_signature *match = NULL; -- cgit v1.2.3 From b95897b89d36a25c237a021c299a4eb295856476 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 15 Jul 2010 13:09:25 -0700 Subject: glsl2: Explicitly walk lists in ir_function::parameter_lists_match Give ir_function::parameter_lists_match_exist similar treatment. Make the parameters const, and propogate the constness as far as it will trivially go. --- src/glsl/ir.h | 4 ++-- src/glsl/ir_function.cpp | 44 +++++++++++++++++++++----------------------- 2 files changed, 23 insertions(+), 25 deletions(-) (limited to 'src/glsl/ir_function.cpp') diff --git a/src/glsl/ir.h b/src/glsl/ir.h index ff91a8dbce..1d667be89c 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -398,13 +398,13 @@ public: * Find a signature that matches a set of actual parameters, taking implicit * conversions into account. */ - ir_function_signature *matching_signature(exec_list *actual_param); + ir_function_signature *matching_signature(const exec_list *actual_param); /** * Find a signature that exactly matches a set of actual parameters without * any implicit type conversions. */ - ir_function_signature *exact_matching_signature(exec_list *actual_ps); + ir_function_signature *exact_matching_signature(const exec_list *actual_ps); /** * Name of the function. diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp index fcdb83be56..e85b18ce02 100644 --- a/src/glsl/ir_function.cpp +++ b/src/glsl/ir_function.cpp @@ -87,23 +87,25 @@ type_compare(const glsl_type *a, const glsl_type *b) static int -parameter_lists_match(exec_list *list_a, exec_list *list_b) +parameter_lists_match(const exec_list *list_a, const exec_list *list_b) { - exec_list_iterator iter_a = list_a->iterator(); - exec_list_iterator iter_b = list_b->iterator(); + const exec_node *node_a = list_a->head; + const exec_node *node_b = list_b->head; int total_score = 0; - for (/* empty */ ; iter_a.has_next(); iter_a.next(), iter_b.next()) { + for (/* empty */ + ; !node_a->is_tail_sentinal() + ; node_a = node_a->next, node_b = node_b->next) { /* If all of the parameters from the other parameter list have been * exhausted, the lists have different length and, by definition, * do not match. */ - if (!iter_b.has_next()) + if (node_b->is_tail_sentinal()) return -1; - const ir_variable *const param = (ir_variable *) iter_a.get(); - const ir_instruction *const actual = (ir_instruction *) iter_b.get(); + const ir_variable *const param = (ir_variable *) node_a; + const ir_instruction *const actual = (ir_instruction *) node_b; /* Determine whether or not the types match. If the types are an * exact match, the match score is zero. If the types don't match @@ -148,7 +150,7 @@ parameter_lists_match(exec_list *list_a, exec_list *list_b) * exhausted, the lists have different length and, by definition, do not * match. */ - if (iter_b.has_next()) + if (!node_b->is_tail_sentinal()) return -1; return total_score; @@ -156,7 +158,7 @@ parameter_lists_match(exec_list *list_a, exec_list *list_b) ir_function_signature * -ir_function::matching_signature(exec_list *actual_parameters) +ir_function::matching_signature(const exec_list *actual_parameters) { ir_function_signature *match = NULL; @@ -183,36 +185,32 @@ ir_function::matching_signature(exec_list *actual_parameters) static bool -parameter_lists_match_exact(exec_list *list_a, exec_list *list_b) +parameter_lists_match_exact(const exec_list *list_a, const exec_list *list_b) { - exec_list_iterator iter_a = list_a->iterator(); - exec_list_iterator iter_b = list_b->iterator(); + const exec_node *node_a = list_a->head; + const exec_node *node_b = list_b->head; - while (iter_a.has_next() && iter_b.has_next()) { - ir_variable *a = (ir_variable *)iter_a.get(); - ir_variable *b = (ir_variable *)iter_b.get(); + for (/* empty */ + ; !node_a->is_tail_sentinal() && !node_b->is_tail_sentinal() + ; node_a = node_a->next, node_b = node_b->next) { + ir_variable *a = (ir_variable *) node_a; + ir_variable *b = (ir_variable *) node_b; /* If the types of the parameters do not match, the parameters lists * are different. */ if (a->type != b->type) return false; - - iter_a.next(); - iter_b.next(); } /* Unless both lists are exhausted, they differ in length and, by * definition, do not match. */ - if (iter_a.has_next() != iter_b.has_next()) - return false; - - return true; + return (node_a->is_tail_sentinal() == node_b->is_tail_sentinal()); } ir_function_signature * -ir_function::exact_matching_signature(exec_list *actual_parameters) +ir_function::exact_matching_signature(const exec_list *actual_parameters) { foreach_iter(exec_list_iterator, iter, signatures) { ir_function_signature *const sig = -- cgit v1.2.3 From 7e2aa91507a5883e33473e0a94215ee3985baad1 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 19 Jul 2010 17:12:42 -0700 Subject: glsl2: Add and use new variable mode ir_var_temporary This is quite a large patch because breaking it into smaller pieces would result in the tree being intermitently broken. The big changes are: * Add the ir_var_temporary variable mode * Change the ir_variable constructor to take the mode as a parameter and correctly specify the mode for all ir_varables. * Change the linker to not cross validate ir_var_temporary variables. * Change the linker to pull all ir_var_temporary variables from global scope into 'main'. --- src/glsl/ast_function.cpp | 21 +++++++++----- src/glsl/ast_to_hir.cpp | 26 ++++++++++------- src/glsl/glsl_types.cpp | 7 ++--- src/glsl/ir.cpp | 6 ++-- src/glsl/ir.h | 5 ++-- src/glsl/ir_clone.cpp | 4 +-- src/glsl/ir_expression_flattening.cpp | 2 +- src/glsl/ir_function.cpp | 1 + src/glsl/ir_function_inlining.cpp | 3 +- src/glsl/ir_if_return.cpp | 3 +- src/glsl/ir_if_to_cond_assign.cpp | 3 +- src/glsl/ir_mat_op_to_vec.cpp | 3 +- src/glsl/ir_mod_to_fract.cpp | 3 +- src/glsl/ir_reader.cpp | 3 +- src/glsl/ir_variable.cpp | 3 +- src/glsl/ir_vec_index_to_cond_assign.cpp | 12 +++++--- src/glsl/linker.cpp | 50 ++++++++++++++++++++++++++++---- src/mesa/shader/ir_to_mesa.cpp | 1 + 18 files changed, 109 insertions(+), 47 deletions(-) (limited to 'src/glsl/ir_function.cpp') diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index 643eb229a7..14c36af911 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -115,7 +115,8 @@ process_call(exec_list *instructions, ir_function *f, var = new(ctx) ir_variable(sig->return_type, talloc_asprintf(ctx, "%s_retval", - sig->function_name())); + sig->function_name()), + ir_var_temporary); instructions->push_tail(var); deref = new(ctx) ir_dereference_variable(var); @@ -509,7 +510,8 @@ emit_inline_vector_constructor(const glsl_type *type, assert(!parameters->is_empty()); ir_variable *var = new(ctx) ir_variable(type, - talloc_strdup(ctx, "vec_ctor")); + talloc_strdup(ctx, "vec_ctor"), + ir_var_temporary); instructions->push_tail(var); /* There are two kinds of vector constructors. @@ -621,7 +623,8 @@ emit_inline_matrix_constructor(const glsl_type *type, assert(!parameters->is_empty()); ir_variable *var = new(ctx) ir_variable(type, - talloc_strdup(ctx, "mat_ctor")); + talloc_strdup(ctx, "mat_ctor"), + ir_var_temporary); instructions->push_tail(var); /* There are three kinds of matrix constructors. @@ -645,7 +648,8 @@ emit_inline_matrix_constructor(const glsl_type *type, */ ir_variable *rhs_var = new(ctx) ir_variable(glsl_type::vec4_type, - talloc_strdup(ctx, "mat_ctor_vec")); + talloc_strdup(ctx, "mat_ctor_vec"), + ir_var_temporary); instructions->push_tail(rhs_var); ir_constant_data zero; @@ -759,7 +763,8 @@ emit_inline_matrix_constructor(const glsl_type *type, */ ir_variable *const rhs_var = new(ctx) ir_variable(first_param->type, - talloc_strdup(ctx, "mat_ctor_mat")); + talloc_strdup(ctx, "mat_ctor_mat"), + ir_var_temporary); instructions->push_tail(rhs_var); ir_dereference *const rhs_var_ref = @@ -825,7 +830,8 @@ emit_inline_matrix_constructor(const glsl_type *type, */ ir_variable *rhs_var = new(ctx) ir_variable(rhs->type, - talloc_strdup(ctx, "mat_ctor_vec")); + talloc_strdup(ctx, "mat_ctor_vec"), + ir_var_temporary); instructions->push_tail(rhs_var); ir_dereference *rhs_var_ref = @@ -1036,7 +1042,8 @@ ast_function_expression::hir(exec_list *instructions, continue; /* Create a temporary containing the matrix. */ - ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp"); + ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp", + ir_var_temporary); instructions->push_tail(var); instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var), matrix, NULL)); diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index f20c7ead33..c68e136256 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -527,7 +527,8 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, * 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_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, @@ -549,7 +550,8 @@ get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue) ir_variable *var; /* FINISHME: Give unique names to the temporaries. */ - var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp"); + var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp", + ir_var_temporary); instructions->push_tail(var); var->mode = ir_var_auto; @@ -806,7 +808,8 @@ ast_expression::hir(exec_list *instructions, type = glsl_type::bool_type; } else { ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type, - "and_tmp"); + "and_tmp", + ir_var_temporary); instructions->push_tail(tmp); ir_if *const stmt = new(ctx) ir_if(op[0]); @@ -870,7 +873,8 @@ ast_expression::hir(exec_list *instructions, type = glsl_type::bool_type; } else { ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type, - "or_tmp"); + "or_tmp", + ir_var_temporary); instructions->push_tail(tmp); ir_if *const stmt = new(ctx) ir_if(op[0]); @@ -1049,7 +1053,8 @@ ast_expression::hir(exec_list *instructions, && (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_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]); @@ -1474,6 +1479,9 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, } } + /* If there is no qualifier that changes the mode of the variable, leave + * the setting alone. + */ if (qual->in && qual->out) var->mode = ir_var_inout; else if (qual->attribute || qual->in @@ -1483,8 +1491,6 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, var->mode = ir_var_out; else if (qual->uniform) var->mode = ir_var_uniform; - else - var->mode = ir_var_auto; if (qual->uniform) var->shader_in = true; @@ -1633,7 +1639,7 @@ ast_declarator_list::hir(exec_list *instructions, var_type = decl_type; } - var = new(ctx) ir_variable(var_type, decl->identifier); + 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; * @@ -1993,7 +1999,7 @@ ast_parameter_declarator::hir(exec_list *instructions, } is_void = false; - ir_variable *var = new(ctx) ir_variable(type, this->identifier); + ir_variable *var = new(ctx) ir_variable(type, this->identifier, ir_var_in); /* FINISHME: Handle array declarations. Note that this requires * FINISHME: complete handling of constant expressions. @@ -2003,8 +2009,6 @@ ast_parameter_declarator::hir(exec_list *instructions, * for function parameters the default mode is 'in'. */ apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc); - if (var->mode == ir_var_auto) - var->mode = ir_var_in; instructions->push_tail(var); diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp index 77c591ed69..5cb327c89d 100644 --- a/src/glsl/glsl_types.cpp +++ b/src/glsl/glsl_types.cpp @@ -251,10 +251,9 @@ glsl_type::generate_constructor(glsl_symbol_table *symtab) const snprintf(param_name, 10, "p%08X", i); ir_variable *var = (this->base_type == GLSL_TYPE_ARRAY) - ? new(ctx) ir_variable(fields.array, param_name) - : new(ctx) ir_variable(fields.structure[i].type, param_name); + ? new(ctx) ir_variable(fields.array, param_name, ir_var_in) + : new(ctx) ir_variable(fields.structure[i].type, param_name, ir_var_in); - var->mode = ir_var_in; declarations[i] = var; sig->parameters.push_tail(var); } @@ -264,7 +263,7 @@ glsl_type::generate_constructor(glsl_symbol_table *symtab) const * the same type as the constructor. After initializing __retval, * __retval is returned. */ - ir_variable *retval = new(ctx) ir_variable(this, "__retval"); + ir_variable *retval = new(ctx) ir_variable(this, "__retval", ir_var_auto); sig->body.push_tail(retval); for (unsigned i = 0; i < length; i++) { diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index ba8ee7b9ac..146ff17af3 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -748,10 +748,12 @@ ir_swizzle::variable_referenced() return this->val->variable_referenced(); } -ir_variable::ir_variable(const struct glsl_type *type, const char *name) + +ir_variable::ir_variable(const struct glsl_type *type, const char *name, + ir_variable_mode mode) : max_array_access(0), read_only(false), centroid(false), invariant(false), shader_in(false), shader_out(false), - mode(ir_var_auto), interpolation(ir_var_smooth), array_lvalue(false) + mode(mode), interpolation(ir_var_smooth), array_lvalue(false) { this->ir_type = ir_type_variable; this->type = type; diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 3be096270d..9fd9850391 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -162,7 +162,8 @@ enum ir_variable_mode { ir_var_uniform, ir_var_in, ir_var_out, - ir_var_inout + ir_var_inout, + ir_var_temporary /**< Temporary variable generated during compilation. */ }; enum ir_variable_interpolation { @@ -174,7 +175,7 @@ enum ir_variable_interpolation { class ir_variable : public ir_instruction { public: - ir_variable(const struct glsl_type *, const char *); + ir_variable(const struct glsl_type *, const char *, ir_variable_mode); virtual ir_variable *clone(struct hash_table *ht) const; diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index 91d6977354..f7e8794728 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -39,7 +39,8 @@ ir_variable * ir_variable::clone(struct hash_table *ht) const { void *ctx = talloc_parent(this); - ir_variable *var = new(ctx) ir_variable(type, name); + ir_variable *var = new(ctx) ir_variable(this->type, this->name, + (ir_variable_mode) this->mode); var->max_array_access = this->max_array_access; var->read_only = this->read_only; @@ -47,7 +48,6 @@ ir_variable::clone(struct hash_table *ht) const var->invariant = this->invariant; var->shader_in = this->shader_in; var->shader_out = this->shader_out; - var->mode = this->mode; var->interpolation = this->interpolation; var->array_lvalue = this->array_lvalue; var->location = this->location; diff --git a/src/glsl/ir_expression_flattening.cpp b/src/glsl/ir_expression_flattening.cpp index f18659342f..6dbebc6378 100644 --- a/src/glsl/ir_expression_flattening.cpp +++ b/src/glsl/ir_expression_flattening.cpp @@ -89,7 +89,7 @@ ir_expression_flattening_visitor::operand_to_temp(ir_rvalue *ir) if (!this->predicate(ir)) return ir; - var = new(ctx) ir_variable(ir->type, "flattening_tmp"); + var = new(ctx) ir_variable(ir->type, "flattening_tmp", ir_var_temporary); base_ir->insert_before(var); assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var), diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp index e85b18ce02..28a5c399f1 100644 --- a/src/glsl/ir_function.cpp +++ b/src/glsl/ir_function.cpp @@ -116,6 +116,7 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b) switch ((enum ir_variable_mode)(param->mode)) { case ir_var_auto: case ir_var_uniform: + case ir_var_temporary: /* These are all error conditions. It is invalid for a parameter to * a function to be declared as auto (not in, out, or inout) or * as uniform. diff --git a/src/glsl/ir_function_inlining.cpp b/src/glsl/ir_function_inlining.cpp index a3f7089cdc..05dd83f7ff 100644 --- a/src/glsl/ir_function_inlining.cpp +++ b/src/glsl/ir_function_inlining.cpp @@ -122,7 +122,8 @@ ir_call::generate_inline(ir_instruction *next_ir) /* Generate storage for the return value. */ if (this->callee->return_type) { - retval = new(ctx) ir_variable(this->callee->return_type, "__retval"); + retval = new(ctx) ir_variable(this->callee->return_type, "__retval", + ir_var_auto); next_ir->insert_before(retval); } diff --git a/src/glsl/ir_if_return.cpp b/src/glsl/ir_if_return.cpp index f68dcfb501..a9af7166b9 100644 --- a/src/glsl/ir_if_return.cpp +++ b/src/glsl/ir_if_return.cpp @@ -102,7 +102,8 @@ ir_if_return_visitor::visit_enter(ir_if *ir) } else { ir_assignment *assign; ir_variable *new_var = new(ir) ir_variable(then_return->value->type, - "if_return_tmp"); + "if_return_tmp", + ir_var_temporary); ir->insert_before(new_var); assign = new(ir) ir_assignment(new(ir) ir_dereference_variable(new_var), diff --git a/src/glsl/ir_if_to_cond_assign.cpp b/src/glsl/ir_if_to_cond_assign.cpp index 274874bbb7..0b87413941 100644 --- a/src/glsl/ir_if_to_cond_assign.cpp +++ b/src/glsl/ir_if_to_cond_assign.cpp @@ -145,7 +145,8 @@ ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir) * simpler. */ cond_var = new(mem_ctx) ir_variable(glsl_type::bool_type, - "if_to_cond_assign_condition"); + "if_to_cond_assign_condition", + ir_var_temporary); ir->insert_before(cond_var); deref = new(mem_ctx) ir_dereference_variable(cond_var); diff --git a/src/glsl/ir_mat_op_to_vec.cpp b/src/glsl/ir_mat_op_to_vec.cpp index 7bdb9057d8..742fc2a295 100644 --- a/src/glsl/ir_mat_op_to_vec.cpp +++ b/src/glsl/ir_mat_op_to_vec.cpp @@ -298,7 +298,8 @@ ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *assign) ir_assignment *assign; op_var[i] = new(base_ir) ir_variable(expr->operands[i]->type, - "mat_op_to_vec"); + "mat_op_to_vec", + ir_var_temporary); base_ir->insert_before(op_var[i]); lhs_deref = new(base_ir) ir_dereference_variable(op_var[i]); diff --git a/src/glsl/ir_mod_to_fract.cpp b/src/glsl/ir_mod_to_fract.cpp index ec1e65092d..71c9472b12 100644 --- a/src/glsl/ir_mod_to_fract.cpp +++ b/src/glsl/ir_mod_to_fract.cpp @@ -60,7 +60,8 @@ ir_mod_to_fract_visitor::visit_leave(ir_expression *ir) if (ir->operation != ir_binop_mod) return visit_continue; - ir_variable *temp = new(ir) ir_variable(ir->operands[1]->type, "mod_b"); + ir_variable *temp = new(ir) ir_variable(ir->operands[1]->type, "mod_b", + ir_var_temporary); this->base_ir->insert_before(temp); ir_assignment *assign; diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp index a1e5a7ad74..ed68496587 100644 --- a/src/glsl/ir_reader.cpp +++ b/src/glsl/ir_reader.cpp @@ -401,7 +401,8 @@ read_declaration(_mesa_glsl_parse_state *st, s_list *list) return NULL; } - ir_variable *var = new(ctx) ir_variable(type, var_name->value()); + ir_variable *var = new(ctx) ir_variable(type, var_name->value(), + ir_var_auto); foreach_iter(exec_list_iterator, it, quals->subexpressions) { s_symbol *qualifier = SX_AS_SYMBOL(it.get()); diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp index 4593c18112..700c5de648 100644 --- a/src/glsl/ir_variable.cpp +++ b/src/glsl/ir_variable.cpp @@ -39,9 +39,8 @@ add_variable(const char *name, enum ir_variable_mode mode, int slot, const glsl_type *type, exec_list *instructions, glsl_symbol_table *symtab) { - ir_variable *var = new(symtab) ir_variable(type, name); + ir_variable *var = new(symtab) ir_variable(type, name, mode); - var->mode = mode; switch (var->mode) { case ir_var_auto: var->read_only = true; diff --git a/src/glsl/ir_vec_index_to_cond_assign.cpp b/src/glsl/ir_vec_index_to_cond_assign.cpp index ac420454e8..7e04389b5f 100644 --- a/src/glsl/ir_vec_index_to_cond_assign.cpp +++ b/src/glsl/ir_vec_index_to_cond_assign.cpp @@ -86,14 +86,16 @@ ir_vec_index_to_cond_assign_visitor::convert_vec_index_to_cond_assign(ir_rvalue /* Store the index to a temporary to avoid reusing its tree. */ index = new(base_ir) ir_variable(glsl_type::int_type, - "vec_index_tmp_i"); + "vec_index_tmp_i", + ir_var_temporary); base_ir->insert_before(index); deref = new(base_ir) ir_dereference_variable(index); assign = new(base_ir) ir_assignment(deref, orig_deref->array_index, NULL); base_ir->insert_before(assign); /* Temporary where we store whichever value we swizzle out. */ - var = new(base_ir) ir_variable(ir->type, "vec_index_tmp_v"); + var = new(base_ir) ir_variable(ir->type, "vec_index_tmp_v", + ir_var_temporary); base_ir->insert_before(var); /* Generate a conditional move of each vector element to the temp. */ @@ -166,14 +168,16 @@ ir_vec_index_to_cond_assign_visitor::visit_leave(ir_assignment *ir) assert(orig_deref->array_index->type->base_type == GLSL_TYPE_INT); /* Store the index to a temporary to avoid reusing its tree. */ - index = new(ir) ir_variable(glsl_type::int_type, "vec_index_tmp_i"); + index = new(ir) ir_variable(glsl_type::int_type, "vec_index_tmp_i", + ir_var_temporary); ir->insert_before(index); deref = new(ir) ir_dereference_variable(index); assign = new(ir) ir_assignment(deref, orig_deref->array_index, NULL); ir->insert_before(assign); /* Store the RHS to a temporary to avoid reusing its tree. */ - var = new(ir) ir_variable(ir->rhs->type, "vec_index_tmp_v"); + var = new(ir) ir_variable(ir->rhs->type, "vec_index_tmp_v", + ir_var_temporary); ir->insert_before(var); deref = new(ir) ir_dereference_variable(var); assign = new(ir) ir_assignment(deref, ir->rhs, NULL); diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 4869dbe1ca..eb4eb9d20e 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -246,6 +246,8 @@ mode_string(const ir_variable *var) case ir_var_in: return "shader input"; case ir_var_out: return "shader output"; case ir_var_inout: return "shader inout"; + + case ir_var_temporary: default: assert(!"Should not get here."); return "invalid variable"; @@ -276,6 +278,12 @@ cross_validate_globals(struct gl_shader_program *prog, if (uniforms_only && (var->mode != ir_var_uniform)) continue; + /* Don't cross validate temporaries that are at global scope. These + * will eventually get pulled into the shaders 'main'. + */ + if (var->mode == ir_var_temporary) + continue; + /* If a global with this name has already been seen, verify that the * new instance has the same type. In addition, if the globals have * initializers, the values of the initializers must be the same. @@ -480,18 +488,28 @@ populate_symbol_table(gl_shader *sh) */ void remap_variables(ir_instruction *inst, glsl_symbol_table *symbols, - exec_list *instructions) + exec_list *instructions, hash_table *temps) { class remap_visitor : public ir_hierarchical_visitor { public: - remap_visitor(glsl_symbol_table *symbols, exec_list *instructions) + remap_visitor(glsl_symbol_table *symbols, exec_list *instructions, + hash_table *temps) { this->symbols = symbols; this->instructions = instructions; + this->temps = temps; } virtual ir_visitor_status visit(ir_dereference_variable *ir) { + if (ir->var->mode == ir_var_temporary) { + ir_variable *var = (ir_variable *) hash_table_find(temps, ir->var); + + assert(var != NULL); + ir->var = var; + return visit_continue; + } + ir_variable *const existing = this->symbols->get_variable(ir->var->name); if (existing != NULL) @@ -501,6 +519,7 @@ remap_variables(ir_instruction *inst, glsl_symbol_table *symbols, this->symbols->add_variable(copy->name, copy); this->instructions->push_head(copy); + ir->var = copy; } return visit_continue; @@ -509,9 +528,10 @@ remap_variables(ir_instruction *inst, glsl_symbol_table *symbols, private: glsl_symbol_table *symbols; exec_list *instructions; + hash_table *temps; }; - remap_visitor v(symbols, instructions); + remap_visitor v(symbols, instructions, temps); inst->accept(&v); } @@ -542,17 +562,32 @@ exec_node * move_non_declarations(exec_list *instructions, exec_node *last, bool make_copies, gl_shader *target) { + hash_table *temps = NULL; + + if (make_copies) + temps = hash_table_ctor(0, hash_table_pointer_hash, + hash_table_pointer_compare); + foreach_list_safe(node, instructions) { ir_instruction *inst = (ir_instruction *) node; - if (inst->as_variable() || inst->as_function()) + if (inst->as_function()) + continue; + + ir_variable *var = inst->as_variable(); + if ((var != NULL) && (var->mode != ir_var_temporary)) continue; - assert(inst->as_assignment()); + assert(inst->as_assignment() + || ((var != NULL) && (var->mode == ir_var_temporary))); if (make_copies) { inst = inst->clone(NULL); - remap_variables(inst, target->symbols, target->ir); + + if (var != NULL) + hash_table_insert(temps, inst, var); + else + remap_variables(inst, target->symbols, target->ir, temps); } else { inst->remove(); } @@ -561,6 +596,9 @@ move_non_declarations(exec_list *instructions, exec_node *last, last = inst; } + if (make_copies) + hash_table_dtor(temps); + return last; } diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp index 352b496625..7cc469f3a7 100644 --- a/src/mesa/shader/ir_to_mesa.cpp +++ b/src/mesa/shader/ir_to_mesa.cpp @@ -1133,6 +1133,7 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) break; case ir_var_auto: + case ir_var_temporary: entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_TEMPORARY, this->next_temp); this->variables.push_tail(entry); -- cgit v1.2.3 From 62c4763b707e2227409f81b09dd5cf6e4410ea6a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 29 Jul 2010 13:52:25 -0700 Subject: glsl2: Fix spelling of "sentinel." --- src/glsl/ast_function.cpp | 6 +++--- src/glsl/ir.cpp | 8 ++++---- src/glsl/ir_clone.cpp | 2 +- src/glsl/ir_function.cpp | 10 +++++----- src/glsl/ir_function_inlining.cpp | 2 +- src/glsl/linker.cpp | 2 +- src/glsl/list.h | 32 ++++++++++++++++---------------- 7 files changed, 31 insertions(+), 31 deletions(-) (limited to 'src/glsl/ir_function.cpp') diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index bb45e2530d..bbc3bc1a59 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -398,7 +398,7 @@ constant_record_constructor(const glsl_type *constructor_type, for (unsigned i = 0; i < constructor_type->length; i++) { ir_instruction *ir = (ir_instruction *) node; - if (node->is_tail_sentinal()) { + if (node->is_tail_sentinel()) { _mesa_glsl_error(loc, state, "insufficient parameters to constructor for `%s'", constructor_type->name); @@ -531,7 +531,7 @@ single_scalar_parameter(exec_list *parameters) const ir_rvalue *const p = (ir_rvalue *) parameters->head; assert(((ir_rvalue *)p)->as_rvalue() != NULL); - return (p->type->is_scalar() && p->next->is_tail_sentinal()); + return (p->type->is_scalar() && p->next->is_tail_sentinel()); } @@ -763,7 +763,7 @@ emit_inline_matrix_constructor(const glsl_type *type, * identity matrix. If a matrix argument is given to a matrix * constructor, it is an error to have any other arguments." */ - assert(first_param->next->is_tail_sentinal()); + assert(first_param->next->is_tail_sentinel()); ir_rvalue *const src_matrix = first_param; /* If the source matrix is smaller, pre-initialize the relavent parts of diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index bb58d95624..7178c68e6b 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -295,7 +295,7 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) */ for (unsigned i = 0; i < type->components(); /* empty */) { assert(value->as_constant() != NULL); - assert(!value->is_tail_sentinal()); + assert(!value->is_tail_sentinel()); for (unsigned j = 0; j < value->type->components(); j++) { switch (type->base_type) { @@ -433,7 +433,7 @@ ir_constant::get_record_field(const char *name) /* If the end of the list is encountered before the element matching the * requested field is found, return NULL. */ - if (node->is_tail_sentinal()) + if (node->is_tail_sentinel()) return NULL; } @@ -459,8 +459,8 @@ ir_constant::has_value(const ir_constant *c) const const exec_node *a_node = this->components.head; const exec_node *b_node = c->components.head; - while (!a_node->is_tail_sentinal()) { - assert(!b_node->is_tail_sentinal()); + while (!a_node->is_tail_sentinel()) { + assert(!b_node->is_tail_sentinel()); const ir_constant *const a_field = (ir_constant *) a_node; const ir_constant *const b_field = (ir_constant *) b_node; diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index f97080d205..6be3e59a95 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -330,7 +330,7 @@ ir_constant::clone(struct hash_table *ht) const c->type = this->type; for (exec_node *node = this->components.head - ; !node->is_tail_sentinal() + ; !node->is_tail_sentinel() ; node = node->next) { ir_constant *const orig = (ir_constant *) node; diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp index 28a5c399f1..0a97e01424 100644 --- a/src/glsl/ir_function.cpp +++ b/src/glsl/ir_function.cpp @@ -94,13 +94,13 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b) int total_score = 0; for (/* empty */ - ; !node_a->is_tail_sentinal() + ; !node_a->is_tail_sentinel() ; node_a = node_a->next, node_b = node_b->next) { /* If all of the parameters from the other parameter list have been * exhausted, the lists have different length and, by definition, * do not match. */ - if (node_b->is_tail_sentinal()) + if (node_b->is_tail_sentinel()) return -1; @@ -151,7 +151,7 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b) * exhausted, the lists have different length and, by definition, do not * match. */ - if (!node_b->is_tail_sentinal()) + if (!node_b->is_tail_sentinel()) return -1; return total_score; @@ -192,7 +192,7 @@ parameter_lists_match_exact(const exec_list *list_a, const exec_list *list_b) const exec_node *node_b = list_b->head; for (/* empty */ - ; !node_a->is_tail_sentinal() && !node_b->is_tail_sentinal() + ; !node_a->is_tail_sentinel() && !node_b->is_tail_sentinel() ; node_a = node_a->next, node_b = node_b->next) { ir_variable *a = (ir_variable *) node_a; ir_variable *b = (ir_variable *) node_b; @@ -207,7 +207,7 @@ parameter_lists_match_exact(const exec_list *list_a, const exec_list *list_b) /* Unless both lists are exhausted, they differ in length and, by * definition, do not match. */ - return (node_a->is_tail_sentinal() == node_b->is_tail_sentinal()); + return (node_a->is_tail_sentinel() == node_b->is_tail_sentinel()); } ir_function_signature * diff --git a/src/glsl/ir_function_inlining.cpp b/src/glsl/ir_function_inlining.cpp index 9daffeb017..77c264f288 100644 --- a/src/glsl/ir_function_inlining.cpp +++ b/src/glsl/ir_function_inlining.cpp @@ -96,7 +96,7 @@ replace_return_with_assignment(ir_instruction *ir, void *data) /* un-valued return has to be the last return, or we shouldn't * have reached here. (see can_inline()). */ - assert(!ret->next->is_tail_sentinal()); + assert(!ret->next->is_tail_sentinel()); ret->remove(); } } diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index fa4fb493f2..e9daad28ec 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -542,7 +542,7 @@ remap_variables(ir_instruction *inst, glsl_symbol_table *symbols, * Move non-declarations from one instruction stream to another * * The intended usage pattern of this function is to pass the pointer to the - * head sentinal of a list (i.e., a pointer to the list cast to an \c exec_node + * head sentinel of a list (i.e., a pointer to the list cast to an \c exec_node * pointer) for \c last and \c false for \c make_copies on the first * call. Successive calls pass the return value of the previous call for * \c last and \c true for \c make_copies. diff --git a/src/glsl/list.h b/src/glsl/list.h index 7348e323c1..a70b79d571 100644 --- a/src/glsl/list.h +++ b/src/glsl/list.h @@ -25,28 +25,28 @@ * \file list.h * \brief Doubly-linked list abstract container type. * - * Each doubly-linked list has a sentinal head and tail node. These nodes - * contain no data. The head sentinal can be identified by its \c prev - * pointer being \c NULL. The tail sentinal can be identified by its + * Each doubly-linked list has a sentinel head and tail node. These nodes + * contain no data. The head sentinel can be identified by its \c prev + * pointer being \c NULL. The tail sentinel can be identified by its * \c next pointer being \c NULL. * - * A list is empty if either the head sentinal's \c next pointer points to the - * tail sentinal or the tail sentinal's \c prev poiner points to the head - * sentinal. + * A list is empty if either the head sentinel's \c next pointer points to the + * tail sentinel or the tail sentinel's \c prev poiner points to the head + * sentinel. * * Instead of tracking two separate \c node structures and a \c list structure - * that points to them, the sentinal nodes are in a single structure. Noting - * that each sentinal node always has one \c NULL pointer, the \c NULL + * that points to them, the sentinel nodes are in a single structure. Noting + * that each sentinel node always has one \c NULL pointer, the \c NULL * pointers occupy the same memory location. In the \c list structure * contains a the following: * * - A \c head pointer that represents the \c next pointer of the - * head sentinal node. + * head sentinel node. * - A \c tail pointer that represents the \c prev pointer of the head - * sentinal node and the \c next pointer of the tail sentinal node. This + * sentinel node and the \c next pointer of the tail sentinel node. This * pointer is \b always \c NULL. * - A \c tail_prev pointer that represents the \c prev pointer of the - * tail sentinal node. + * tail sentinel node. * * Therefore, if \c head->next is \c NULL or \c tail_prev->prev is \c NULL, * the list is empty. @@ -178,17 +178,17 @@ struct exec_node { } /** - * Is this the sentinal at the tail of the list? + * Is this the sentinel at the tail of the list? */ - bool is_tail_sentinal() const + bool is_tail_sentinel() const { return this->next == NULL; } /** - * Is this the sentinal at the head of the list? + * Is this the sentinel at the head of the list? */ - bool is_head_sentinal() const + bool is_head_sentinel() const { return this->prev == NULL; } @@ -320,7 +320,7 @@ struct exec_list { * * - Check to see if the \c head points to the \c tail. * - Check to see if the \c tail_pred points to the \c head. - * - Check to see if the \c head is the sentinal node by test whether its + * - Check to see if the \c head is the sentinel node by test whether its * \c next pointer is \c NULL. * * The first two methods tend to generate better code on modern systems -- cgit v1.2.3