X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=ir.cpp;h=a68d01cca9688956c7e2320a739a5041f09dde1b;hb=ff236fa9b6a35ce261098d288f77f238c3286e15;hp=1b5947a4704d5a8de2f0d845ded2167135b6ec51;hpb=b7592c362b69a8ddbef9c1c6c2bde33e40653774;p=mesa.git diff --git a/ir.cpp b/ir.cpp index 1b5947a4704..a68d01cca96 100644 --- a/ir.cpp +++ b/ir.cpp @@ -24,21 +24,20 @@ #include "main/imports.h" #include "main/simple_list.h" #include "ir.h" +#include "ir_visitor.h" #include "glsl_types.h" -ir_assignment::ir_assignment(ir_instruction *lhs, ir_instruction *rhs, - ir_expression *condition) - : ir_instruction(ir_op_assign) +ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, + ir_rvalue *condition) { - this->lhs = (ir_dereference *) lhs; + this->lhs = lhs; this->rhs = rhs; this->condition = condition; } ir_expression::ir_expression(int op, const struct glsl_type *type, - ir_instruction *op0, ir_instruction *op1) - : ir_instruction(ir_op_expression) + ir_rvalue *op0, ir_rvalue *op1) { this->type = type; this->operation = ir_expression_operation(op); @@ -46,20 +45,78 @@ ir_expression::ir_expression(int op, const struct glsl_type *type, this->operands[1] = op1; } +unsigned int +ir_expression::get_num_operands(void) +{ +/* Update ir_print_visitor.cpp when updating this list. */ + const int num_operands[] = { + 1, /* ir_unop_bit_not */ + 1, /* ir_unop_logic_not */ + 1, /* ir_unop_neg */ + 1, /* ir_unop_abs */ + 1, /* ir_unop_rcp */ + 1, /* ir_unop_rsq */ + 1, /* ir_unop_sqrt */ + 1, /* ir_unop_exp */ + 1, /* ir_unop_log */ + 1, /* ir_unop_exp2 */ + 1, /* ir_unop_log2 */ + 1, /* ir_unop_f2i */ + 1, /* ir_unop_i2f */ + 1, /* ir_unop_f2b */ + 1, /* ir_unop_b2f */ + 1, /* ir_unop_i2b */ + 1, /* ir_unop_b2i */ + 1, /* ir_unop_u2f */ + + 1, /* ir_unop_trunc */ + 1, /* ir_unop_ceil */ + 1, /* ir_unop_floor */ + + 2, /* ir_binop_add */ + 2, /* ir_binop_sub */ + 2, /* ir_binop_mul */ + 2, /* ir_binop_div */ + 2, /* ir_binop_mod */ + + 2, /* ir_binop_less */ + 2, /* ir_binop_greater */ + 2, /* ir_binop_lequal */ + 2, /* ir_binop_gequal */ + 2, /* ir_binop_equal */ + 2, /* ir_binop_nequal */ + + 2, /* ir_binop_lshift */ + 2, /* ir_binop_rshift */ + 2, /* ir_binop_bit_and */ + 2, /* ir_binop_bit_xor */ + 2, /* ir_binop_bit_or */ + + 2, /* ir_binop_logic_and */ + 2, /* ir_binop_logic_xor */ + 2, /* ir_binop_logic_or */ + + 2, /* ir_binop_dot */ + 2, /* ir_binop_min */ + 2, /* ir_binop_max */ + + 2, /* ir_binop_pow */ + }; -ir_label::ir_label(const char *label) - : ir_instruction(ir_op_label), label(label) + assert(sizeof(num_operands) / sizeof(num_operands[0]) == ir_binop_pow + 1); + + return num_operands[this->operation]; +} + +ir_label::ir_label(const char *label, ir_function_signature *signature) + : label(label), signature(signature) { /* empty */ } ir_constant::ir_constant(const struct glsl_type *type, const void *data) - : ir_instruction(ir_op_constant) { - const unsigned elements = - ((type->vector_elements == 0) ? 1 : type->vector_elements) - * ((type->matrix_columns == 0) ? 1 : type->matrix_columns); unsigned size = 0; this->type = type; @@ -74,32 +131,90 @@ ir_constant::ir_constant(const struct glsl_type *type, const void *data) break; } - memcpy(& this->value, data, size * elements); + memcpy(& this->value, data, size * type->components()); +} + +ir_constant::ir_constant(float f) +{ + this->type = glsl_type::float_type; + this->value.f[0] = f; +} + +ir_constant::ir_constant(unsigned int u) +{ + this->type = glsl_type::uint_type; + this->value.u[0] = u; +} + +ir_constant::ir_constant(int i) +{ + this->type = glsl_type::int_type; + this->value.i[0] = i; +} + +ir_constant::ir_constant(bool b) +{ + this->type = glsl_type::bool_type; + this->value.b[0] = b; } ir_dereference::ir_dereference(ir_instruction *var) - : ir_instruction(ir_op_dereference) { this->mode = ir_reference_variable; this->var = var; - this->type = (var != NULL) ? var->type : glsl_error_type; + this->type = (var != NULL) ? var->type : glsl_type::error_type; } ir_dereference::ir_dereference(ir_instruction *var, - ir_instruction *array_index) - : ir_instruction(ir_op_dereference), mode(ir_reference_array), - var(var) + ir_rvalue *array_index) + : mode(ir_reference_array), var(var) { - this->type = (var != NULL) ? var->type : glsl_error_type; + type = glsl_type::error_type; + + if (var != NULL) { + const glsl_type *const vt = var->type; + + if (vt->is_array()) { + type = vt->element_type(); + } else if (vt->is_matrix()) { + type = vt->column_type(); + } else if (vt->is_vector()) { + type = vt->get_base_type(); + } + } + this->selector.array_index = array_index; } +bool +ir_dereference::is_lvalue() +{ + if (var == NULL) + return false; -void -ir_dereference::set_swizzle(unsigned x, unsigned y, unsigned z, unsigned w, - unsigned count) + if (mode == ir_reference_variable) { + ir_variable *const as_var = var->as_variable(); + if (as_var == NULL) + return false; + + if (as_var->type->is_array() && !as_var->array_lvalue) + return false; + + return !as_var->read_only; + } else if (mode == ir_reference_array) { + /* FINISHME: Walk up the dereference chain and figure out if + * FINISHME: the variable is read-only. + */ + } + + return true; +} + +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,34 +228,124 @@ 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) - : ir_instruction(ir_op_var_decl), read_only(false), centroid(false), - invariant(false), mode(ir_var_auto), interpolation(ir_var_smooth) + : max_array_access(0), read_only(false), centroid(false), invariant(false), + mode(ir_var_auto), interpolation(ir_var_smooth) { this->type = type; this->name = name; + this->constant_value = NULL; + + if (type && type->base_type == GLSL_TYPE_SAMPLER) + this->read_only = true; } ir_function_signature::ir_function_signature(const glsl_type *return_type) - : ir_instruction(ir_op_func_sig), return_type(return_type), definition(NULL) + : return_type(return_type), definition(NULL) { /* empty */ } ir_function::ir_function(const char *name) - : ir_instruction(ir_op_func), name(name) + : name(name) { /* empty */ } @@ -151,6 +356,15 @@ ir_call::get_error_instruction() { ir_call *call = new ir_call; - call->type = glsl_error_type; + call->type = glsl_type::error_type; return call; } + +void +visit_exec_list(exec_list *list, ir_visitor *visitor) +{ + foreach_iter(exec_list_iterator, iter, *list) { + ((ir_instruction *)iter.get())->accept(visitor); + } +} +