From affc1413ac9f1f077a4ba1a1b7135f73d7a71167 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Fri, 26 Mar 2010 01:20:08 -0700 Subject: [PATCH] Move swizzles out of ir_dereference and into their own class. Also turn generate_swizzle into a static "create" method of the new class; we'll want to use it for the IR reader as well. Signed-off-by: Ian Romanick --- ast_to_hir.cpp | 35 ++---------- glsl_types.cpp | 35 ++++++------ hir_field_selection.cpp | 119 ++++------------------------------------ ir.cpp | 104 ++++++++++++++++++++++++++++++++--- ir.h | 33 ++++++++--- ir_print_visitor.cpp | 32 +++++++---- ir_print_visitor.h | 1 + ir_visitor.h | 1 + 8 files changed, 176 insertions(+), 184 deletions(-) diff --git a/ast_to_hir.cpp b/ast_to_hir.cpp index 2fd2e53fda3..c7e73b66304 100644 --- a/ast_to_hir.cpp +++ b/ast_to_hir.cpp @@ -454,23 +454,10 @@ ast_expression::hir(exec_list *instructions, YYLTYPE loc; /* FINISHME: This does not handle 'foo.bar.a.b.c[5].d = 5' */ - loc = this->subexpressions[0]->get_location(); - const ir_dereference *const ref = op[0]->as_dereference(); - if (ref == NULL) { - _mesa_glsl_error(& loc, state, "invalid lvalue in assignment"); + if (!op[0]->is_lvalue()) { + _mesa_glsl_error(& loc, state, "non-lvalue in assignment"); error_emitted = true; - type = glsl_error_type; - } else { - const ir_variable *const var = (ir_variable *) ref->var; - - if (var != NULL && var->read_only) { - _mesa_glsl_error(& loc, state, "cannot assign to read-only " - "variable `%s'", var->name); - error_emitted = true; - - type = glsl_error_type; - } } } @@ -612,24 +599,10 @@ ast_expression::hir(exec_list *instructions, if (!error_emitted) { YYLTYPE loc; - /* FINISHME: This does not handle 'foo.bar.a.b.c[5].d = 5' */ - loc = this->subexpressions[0]->get_location(); - const ir_dereference *const ref = op[0]->as_dereference(); - if (ref == NULL) { - _mesa_glsl_error(& loc, state, "invalid lvalue in assignment"); + if (!op[0]->is_lvalue()) { + _mesa_glsl_error(& loc, state, "non-lvalue in assignment"); error_emitted = true; - type = glsl_error_type; - } else { - const ir_variable *const var = (ir_variable *) ref->var; - - if (var != NULL && var->read_only) { - _mesa_glsl_error(& loc, state, "cannot assign to read-only " - "variable `%s'", var->name); - error_emitted = true; - - type = glsl_error_type; - } } } diff --git a/glsl_types.cpp b/glsl_types.cpp index 846761fff67..bcaa69825c0 100644 --- a/glsl_types.cpp +++ b/glsl_types.cpp @@ -178,17 +178,18 @@ generate_vec_body_from_scalar(exec_list *instructions, /* Generate a single assignment of the parameter to __retval.x and return * __retval.xxxx for however many vector components there are. */ - ir_dereference *const lhs = new ir_dereference(declarations[16]); + ir_dereference *const lhs_ref = new ir_dereference(declarations[16]); ir_dereference *const rhs = new ir_dereference(declarations[0]); - lhs->set_swizzle(0, 0, 0, 0, 1); + ir_swizzle *lhs = new ir_swizzle(lhs_ref, 0, 0, 0, 0, 1); inst = new ir_assignment(lhs, rhs, NULL); instructions->push_tail(inst); - ir_dereference *const retval = new ir_dereference(declarations[16]); + ir_dereference *const retref = new ir_dereference(declarations[16]); - retval->set_swizzle(0, 0, 0, 0, declarations[16]->type->vector_elements); + ir_swizzle *retval = new ir_swizzle(retref, 0, 0, 0, 0, + declarations[16]->type->vector_elements); inst = new ir_return(retval); instructions->push_tail(inst); @@ -210,11 +211,10 @@ generate_vec_body_from_N_scalars(exec_list *instructions, * __retval.x and return __retval. */ for (unsigned i = 0; i < vec_type->vector_elements; i++) { - ir_dereference *const lhs = new ir_dereference(declarations[16]); + ir_dereference *const lhs_ref = new ir_dereference(declarations[16]); ir_dereference *const rhs = new ir_dereference(declarations[i]); - lhs->selector.swizzle.x = i; - lhs->selector.swizzle.num_components = 1; + ir_swizzle *lhs = new ir_swizzle(lhs_ref, 1, 0, 0, 0, 1); inst = new ir_assignment(lhs, rhs, NULL); instructions->push_tail(inst); @@ -262,10 +262,10 @@ generate_mat_body_from_scalar(exec_list *instructions, instructions->push_tail(column); - ir_dereference *const lhs = new ir_dereference(column); + ir_dereference *const lhs_ref = new ir_dereference(column); ir_dereference *const rhs = new ir_dereference(declarations[0]); - lhs->set_swizzle(0, 0, 0, 0, 1); + ir_swizzle *lhs = new ir_swizzle(lhs_ref, 0, 0, 0, 0, 1); inst = new ir_assignment(lhs, rhs, NULL); instructions->push_tail(inst); @@ -274,9 +274,9 @@ generate_mat_body_from_scalar(exec_list *instructions, ir_constant *const zero = new ir_constant(glsl_float_type, &z); for (unsigned i = 1; i < column_type->vector_elements; i++) { - ir_dereference *const lhs = new ir_dereference(column); + ir_dereference *const lhs_ref = new ir_dereference(column); - lhs->set_swizzle(i, 0, 0, 0, 1); + ir_swizzle *lhs = new ir_swizzle(lhs_ref, i, 0, 0, 0, 1); inst = new ir_assignment(lhs, zero, NULL); instructions->push_tail(inst); @@ -285,12 +285,13 @@ generate_mat_body_from_scalar(exec_list *instructions, for (unsigned i = 0; i < row_type->vector_elements; i++) { static const unsigned swiz[] = { 1, 1, 1, 0, 1, 1, 1 }; - ir_dereference *const rhs = new ir_dereference(column); + ir_dereference *const rhs_ref = new ir_dereference(column); /* This will be .xyyy when i=0, .yxyy when i=1, etc. */ - rhs->set_swizzle(swiz[3 - i], swiz[4 - i], swiz[5 - i], swiz[6 - i], - column_type->vector_elements); + ir_swizzle *rhs = new ir_swizzle(rhs_ref, swiz[3 - i], swiz[4 - i], + swiz[5 - i], swiz[6 - i], + column_type->vector_elements); ir_constant *const idx = new ir_constant(glsl_int_type, &i); ir_dereference *const lhs = new ir_dereference(declarations[16], idx); @@ -326,11 +327,11 @@ generate_mat_body_from_N_scalars(exec_list *instructions, ir_dereference *const row_access = new ir_dereference(declarations[16], row_index); - ir_dereference *const component_access = + ir_dereference *const component_access_ref = new ir_dereference(row_access); - component_access->selector.swizzle.x = j; - component_access->selector.swizzle.num_components = 1; + ir_swizzle *component_access = new ir_swizzle(component_access_ref, + j, 0, 0, 0, 1); const unsigned param = (i * row_type->vector_elements) + j; ir_dereference *const rhs = new ir_dereference(declarations[param]); diff --git a/hir_field_selection.cpp b/hir_field_selection.cpp index 41dbd42d3bf..76c48683619 100644 --- a/hir_field_selection.cpp +++ b/hir_field_selection.cpp @@ -28,107 +28,15 @@ #include "glsl_types.h" #include "ir.h" -#define X 1 -#define R 5 -#define S 9 -#define I 13 - -static bool -generate_swizzle(const char *str, ir_dereference *deref, - unsigned vector_length) -{ - /* For each possible swizzle character, this table encodes the value in - * \c idx_map that represents the 0th element of the vector. For invalid - * swizzle characters (e.g., 'k'), a special value is used that will allow - * detection of errors. - */ - static const unsigned char base_idx[26] = { - /* a b c d e f g h i j k l m */ - R, R, I, I, I, I, R, I, I, I, I, I, I, - /* n o p q r s t u v w x y z */ - I, I, S, S, R, S, S, I, I, X, X, X, X - }; - - /* Each valid swizzle character has an entry in the previous table. This - * table encodes the base index encoded in the previous table plus the actual - * index of the swizzle character. When processing swizzles, the first - * character in the string is indexed in the previous table. Each character - * in the string is indexed in this table, and the value found there has the - * value form the first table subtracted. The result must be on the range - * [0,3]. - * - * For example, the string "wzyx" will get X from the first table. Each of - * the charcaters will get X+3, X+2, X+1, and X+0 from this table. After - * subtraction, the swizzle values are { 3, 2, 1, 0 }. - * - * The string "wzrg" will get X from the first table. Each of the characters - * will get X+3, X+2, R+0, and R+1 from this table. After subtraction, the - * swizzle values are { 3, 2, 4, 5 }. Since 4 and 5 are outside the range - * [0,3], the error is detected. - */ - static const unsigned char idx_map[26] = { - /* a b c d e f g h i j k l m */ - R+3, R+2, 0, 0, 0, 0, R+1, 0, 0, 0, 0, 0, 0, - /* n o p q r s t u v w x y z */ - 0, 0, S+2, S+3, R+0, S+0, S+1, 0, 0, X+3, X+0, X+1, X+2 - }; - - int swiz_idx[4] = { 0, 0, 0, 0 }; - unsigned i; - - - /* Validate the first character in the swizzle string and look up the base - * index value as described above. - */ - if ((str[0] < 'a') || (str[0] > 'z')) - return false; - - const unsigned base = base_idx[str[0] - 'a']; - - - for (i = 0; (i < 4) && (str[i] != '\0'); i++) { - /* Validate the next character, and, as described above, convert it to a - * swizzle index. - */ - if ((str[i] < 'a') || (str[i] > 'z')) - return false; - - swiz_idx[i] = idx_map[str[i] - 'a'] - base; - if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length)) - return false; - } - - if (str[i] != '\0') - return false; - - deref->set_swizzle(swiz_idx[0], swiz_idx[1], swiz_idx[2], swiz_idx[3], i); - return true; -} - - struct ir_rvalue * _mesa_ast_field_selection_to_hir(const ast_expression *expr, exec_list *instructions, struct _mesa_glsl_parse_state *state) { + ir_rvalue *result = NULL; ir_rvalue *op; - ir_dereference *deref; - YYLTYPE loc; - op = expr->subexpressions[0]->hir(instructions, state); - deref = new ir_dereference(op); - - /* Initially assume that the resulting type of the field selection is an - * error. This make the error paths below a bit easier to follow. - */ - deref->type = glsl_error_type; - - /* If processing the thing being dereferenced generated an error, bail out - * now. Doing so prevents spurious error messages from being logged below. - */ - if (is_error_type(op->type)) - return deref; /* There are two kinds of field selection. There is the selection of a * specific field from a structure, and there is the selection of a @@ -136,21 +44,18 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr, * by the base type of the thing to which the field selection operator is * being applied. */ - loc = expr->get_location(); - if (op->type->is_vector()) { - if (generate_swizzle(expr->primary_expression.identifier, - deref, op->type->vector_elements)) { - /* Based on the number of elements in the swizzle and the base type - * (i.e., float, int, unsigned, or bool) of the vector being swizzled, - * generate the type of the resulting value. - */ - deref->type = - glsl_type::get_instance(op->type->base_type, - deref->selector.swizzle.num_components, - 1); + YYLTYPE loc = expr->get_location(); + if (op->type == glsl_error_type) { + /* silently propagate the error */ + } else if (op->type->is_vector()) { + ir_swizzle *swiz = ir_swizzle::create(op, + expr->primary_expression.identifier, + op->type->vector_elements); + if (swiz != NULL) { + result = swiz; } else { /* FINISHME: Logging of error messages should be moved into - * FINISHME: generate_swizzle. This allows the generation of more + * FINISHME: ir_swizzle::create. This allows the generation of more * FINISHME: specific error messages. */ _mesa_glsl_error(& loc, state, "Invalid swizzle / mask `%s'", @@ -164,5 +69,5 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr, expr->primary_expression.identifier); } - return deref; + return result ? result : ir_call::get_error_instruction(); } diff --git a/ir.cpp b/ir.cpp index 8051fb41330..58c459ed5db 100644 --- a/ir.cpp +++ b/ir.cpp @@ -97,9 +97,9 @@ ir_dereference::ir_dereference(ir_instruction *var, } -void -ir_dereference::set_swizzle(unsigned x, unsigned y, unsigned z, unsigned w, - unsigned count) +ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z, + unsigned w, unsigned count) + : val(val) { assert((count >= 1) && (count <= 4)); @@ -113,14 +113,100 @@ ir_dereference::set_swizzle(unsigned x, unsigned y, unsigned z, unsigned w, assert(z <= 3); assert(w <= 3); - selector.swizzle.x = x; - selector.swizzle.y = y; - selector.swizzle.z = z; - selector.swizzle.w = w; - selector.swizzle.num_components = count; - selector.swizzle.has_duplicates = dup_mask != 0; + mask.x = x; + mask.y = y; + mask.z = z; + mask.w = w; + mask.num_components = count; + mask.has_duplicates = dup_mask != 0; + + /* Based on the number of elements in the swizzle and the base type + * (i.e., float, int, unsigned, or bool) of the vector being swizzled, + * generate the type of the resulting value. + */ + type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1); } +#define X 1 +#define R 5 +#define S 9 +#define I 13 + +ir_swizzle * +ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length) +{ + /* For each possible swizzle character, this table encodes the value in + * \c idx_map that represents the 0th element of the vector. For invalid + * swizzle characters (e.g., 'k'), a special value is used that will allow + * detection of errors. + */ + static const unsigned char base_idx[26] = { + /* a b c d e f g h i j k l m */ + R, R, I, I, I, I, R, I, I, I, I, I, I, + /* n o p q r s t u v w x y z */ + I, I, S, S, R, S, S, I, I, X, X, X, X + }; + + /* Each valid swizzle character has an entry in the previous table. This + * table encodes the base index encoded in the previous table plus the actual + * index of the swizzle character. When processing swizzles, the first + * character in the string is indexed in the previous table. Each character + * in the string is indexed in this table, and the value found there has the + * value form the first table subtracted. The result must be on the range + * [0,3]. + * + * For example, the string "wzyx" will get X from the first table. Each of + * the charcaters will get X+3, X+2, X+1, and X+0 from this table. After + * subtraction, the swizzle values are { 3, 2, 1, 0 }. + * + * The string "wzrg" will get X from the first table. Each of the characters + * will get X+3, X+2, R+0, and R+1 from this table. After subtraction, the + * swizzle values are { 3, 2, 4, 5 }. Since 4 and 5 are outside the range + * [0,3], the error is detected. + */ + static const unsigned char idx_map[26] = { + /* a b c d e f g h i j k l m */ + R+3, R+2, 0, 0, 0, 0, R+1, 0, 0, 0, 0, 0, 0, + /* n o p q r s t u v w x y z */ + 0, 0, S+2, S+3, R+0, S+0, S+1, 0, 0, X+3, X+0, X+1, X+2 + }; + + int swiz_idx[4] = { 0, 0, 0, 0 }; + unsigned i; + + + /* Validate the first character in the swizzle string and look up the base + * index value as described above. + */ + if ((str[0] < 'a') || (str[0] > 'z')) + return NULL; + + const unsigned base = base_idx[str[0] - 'a']; + + + for (i = 0; (i < 4) && (str[i] != '\0'); i++) { + /* Validate the next character, and, as described above, convert it to a + * swizzle index. + */ + if ((str[i] < 'a') || (str[i] > 'z')) + return NULL; + + swiz_idx[i] = idx_map[str[i] - 'a'] - base; + if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length)) + return NULL; + } + + if (str[i] != '\0') + return NULL; + + return new ir_swizzle(val, swiz_idx[0], swiz_idx[1], swiz_idx[2], + swiz_idx[3], i); +} + +#undef X +#undef R +#undef S +#undef I ir_variable::ir_variable(const struct glsl_type *type, const char *name) diff --git a/ir.h b/ir.h index 29bc055dd7a..63ae0bc3b69 100644 --- a/ir.h +++ b/ir.h @@ -394,6 +394,31 @@ struct ir_swizzle_mask { unsigned has_duplicates:1; }; + +class ir_swizzle : public ir_rvalue { +public: + ir_swizzle(ir_rvalue *, unsigned x, unsigned y, unsigned z, unsigned w, + unsigned count); + /** + * Construct an ir_swizzle from the textual representation. Can fail. + */ + static ir_swizzle *create(ir_rvalue *, const char *, unsigned vector_length); + + virtual void accept(ir_visitor *v) + { + v->visit(this); + } + + bool is_lvalue() + { + return val->is_lvalue(); + } + + ir_rvalue *val; + ir_swizzle_mask mask; +}; + + class ir_dereference : public ir_rvalue { public: ir_dereference(struct ir_instruction *); @@ -415,13 +440,6 @@ public: return var != NULL; } - /** - * Setting the swizzle of a derefernce - */ - void set_swizzle(unsigned x, unsigned y, unsigned z, unsigned w, - unsigned count); - - enum { ir_reference_variable, ir_reference_array, @@ -438,7 +456,6 @@ public: union { ir_rvalue *array_index; const char *field; - struct ir_swizzle_mask swizzle; } selector; }; diff --git a/ir_print_visitor.cpp b/ir_print_visitor.cpp index 8941d3c7b9f..1696be69b55 100644 --- a/ir_print_visitor.cpp +++ b/ir_print_visitor.cpp @@ -102,26 +102,34 @@ void ir_print_visitor::visit(ir_expression *ir) } +void ir_print_visitor::visit(ir_swizzle *ir) +{ + const unsigned swiz[4] = { + ir->mask.x, + ir->mask.y, + ir->mask.z, + ir->mask.w, + }; + + printf("(swiz "); + for (unsigned i = 0; i < ir->mask.num_components; i++) { + printf("%c", "xyzw"[swiz[i]]); + } + printf(" "); + ir->val->accept(this); + printf(")"); +} + + void ir_print_visitor::visit(ir_dereference *ir) { deref_depth++; switch (ir->mode) { case ir_dereference::ir_reference_variable: { - const unsigned swiz[4] = { - ir->selector.swizzle.x, - ir->selector.swizzle.y, - ir->selector.swizzle.z, - ir->selector.swizzle.w, - }; - printf("(var_ref "); ir->var->accept(this); - printf("("); - for (unsigned i = 0; i < ir->selector.swizzle.num_components; i++) { - printf("%c", "xyzw"[swiz[i]]); - } - printf(")) "); + printf(") "); break; } case ir_dereference::ir_reference_array: diff --git a/ir_print_visitor.h b/ir_print_visitor.h index a4309c4f2a4..8fd684eb92a 100644 --- a/ir_print_visitor.h +++ b/ir_print_visitor.h @@ -58,6 +58,7 @@ public: virtual void visit(ir_function_signature *); virtual void visit(ir_function *); virtual void visit(ir_expression *); + virtual void visit(ir_swizzle *); virtual void visit(ir_dereference *); virtual void visit(ir_assignment *); virtual void visit(ir_constant *); diff --git a/ir_visitor.h b/ir_visitor.h index 8ea416eb9f2..76981f7afc1 100644 --- a/ir_visitor.h +++ b/ir_visitor.h @@ -49,6 +49,7 @@ public: virtual void visit(class ir_function_signature *) = 0; virtual void visit(class ir_function *) = 0; virtual void visit(class ir_expression *) = 0; + virtual void visit(class ir_swizzle *) = 0; virtual void visit(class ir_dereference *) = 0; virtual void visit(class ir_assignment *) = 0; virtual void visit(class ir_constant *) = 0; -- 2.30.2