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;
- }
}
}
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;
- }
}
}
/* 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);
* __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);
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);
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);
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);
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]);
#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
* 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'",
expr->primary_expression.identifier);
}
- return deref;
+ return result ? result : ir_call::get_error_instruction();
}
}
-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));
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)
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 *);
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,
union {
ir_rvalue *array_index;
const char *field;
- struct ir_swizzle_mask swizzle;
} selector;
};
}
+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:
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 *);
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;