1, /* ir_unop_logic_not */
1, /* ir_unop_neg */
1, /* ir_unop_abs */
+ 1, /* ir_unop_sign */
1, /* ir_unop_rcp */
1, /* ir_unop_rsq */
1, /* ir_unop_sqrt */
1, /* ir_unop_ceil */
1, /* ir_unop_floor */
+ 1, /* ir_unop_sin */
+ 1, /* ir_unop_cos */
+
+ 1, /* ir_unop_dFdx */
+ 1, /* ir_unop_dFdy */
+
2, /* ir_binop_add */
2, /* ir_binop_sub */
2, /* ir_binop_mul */
"!",
"neg",
"abs",
+ "sign",
"rcp",
"rsq",
"sqrt",
"trunc",
"ceil",
"floor",
+ "sin",
+ "cos",
+ "dFdx",
+ "dFdy",
"+",
"-",
"*",
return (ir_expression_operation) -1;
}
-ir_constant::ir_constant(const struct glsl_type *type, const void *data)
+ir_constant::ir_constant()
{
- unsigned size = 0;
+ /* empty */
+}
- this->type = type;
- switch (type->base_type) {
- case GLSL_TYPE_UINT: size = sizeof(this->value.u[0]); break;
- case GLSL_TYPE_INT: size = sizeof(this->value.i[0]); break;
- case GLSL_TYPE_FLOAT: size = sizeof(this->value.f[0]); break;
- case GLSL_TYPE_BOOL: size = sizeof(this->value.b[0]); break;
- default:
- /* FINISHME: What to do? Exceptions are not the answer.
- */
- break;
- }
+ir_constant::ir_constant(const struct glsl_type *type,
+ const ir_constant_data *data)
+{
+ assert((type->base_type >= GLSL_TYPE_UINT)
+ && (type->base_type <= GLSL_TYPE_BOOL));
- memcpy(& this->value, data, size * type->components());
+ this->type = type;
+ memcpy(& this->value, data, sizeof(this->value));
}
ir_constant::ir_constant(float f)
this->value.b[0] = b;
}
+ir_constant::ir_constant(const ir_constant *c, unsigned i)
+{
+ this->type = c->type->get_base_type();
+
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: this->value.u[0] = c->value.u[i]; break;
+ case GLSL_TYPE_INT: this->value.i[0] = c->value.i[i]; break;
+ case GLSL_TYPE_FLOAT: this->value.f[0] = c->value.f[i]; break;
+ case GLSL_TYPE_BOOL: this->value.b[0] = c->value.b[i]; break;
+ default: assert(!"Should not get here."); break;
+ }
+}
+
+ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
+{
+ this->type = type;
+
+ /* FINISHME: Support array types. */
+ assert(type->is_scalar() || type->is_vector() || type->is_matrix()
+ || type->is_record());
+
+ /* If the constant is a record, the types of each of the entries in
+ * value_list must be a 1-for-1 match with the structure components. Each
+ * entry must also be a constant. Just move the nodes from the value_list
+ * to the list in the ir_constant.
+ */
+ /* FINISHME: Should there be some type checking and / or assertions here? */
+ /* FINISHME: Should the new constant take ownership of the nodes from
+ * FINISHME: value_list, or should it make copies?
+ */
+ if (type->is_record()) {
+ value_list->move_nodes_to(& this->components);
+ return;
+ }
+
+
+ ir_constant *value = (ir_constant *) (value_list->head);
+
+ /* Use each component from each entry in the value_list to initialize one
+ * component of the constant being constructed.
+ */
+ for (unsigned i = 0; i < type->components(); /* empty */) {
+ assert(value->as_constant() != NULL);
+ assert(!value->is_tail_sentinal());
+
+ for (unsigned j = 0; j < value->type->components(); j++) {
+ switch (type->base_type) {
+ case GLSL_TYPE_UINT:
+ this->value.u[i] = value->get_uint_component(j);
+ break;
+ case GLSL_TYPE_INT:
+ this->value.i[i] = value->get_int_component(j);
+ break;
+ case GLSL_TYPE_FLOAT:
+ this->value.f[i] = value->get_float_component(j);
+ break;
+ case GLSL_TYPE_BOOL:
+ this->value.b[i] = value->get_bool_component(j);
+ break;
+ default:
+ /* FINISHME: What to do? Exceptions are not the answer.
+ */
+ break;
+ }
+
+ i++;
+ if (i >= type->components())
+ break;
+ }
+
+ value = (ir_constant *) value->next;
+ }
+}
+
+ir_constant *
+ir_constant::clone()
+{
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_FLOAT:
+ case GLSL_TYPE_BOOL:
+ return new ir_constant(this->type, &this->value);
+
+ case GLSL_TYPE_STRUCT: {
+ ir_constant *c = new ir_constant;
+
+ c->type = this->type;
+ for (exec_node *node = this->components.head
+ ; !node->is_tail_sentinal()
+ ; node = node->next) {
+ ir_constant *const orig = (ir_constant *) node;
+
+ c->components.push_tail(orig->clone());
+ }
+
+ return c;
+ }
+
+ default:
+ assert(!"Should not get here."); break;
+ return NULL;
+ }
+}
+
+bool
+ir_constant::get_bool_component(unsigned i) const
+{
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: return this->value.u[i] != 0;
+ case GLSL_TYPE_INT: return this->value.i[i] != 0;
+ case GLSL_TYPE_FLOAT: return ((int)this->value.f[i]) != 0;
+ case GLSL_TYPE_BOOL: return this->value.b[i];
+ default: assert(!"Should not get here."); break;
+ }
+
+ /* Must return something to make the compiler happy. This is clearly an
+ * error case.
+ */
+ return false;
+}
+
+float
+ir_constant::get_float_component(unsigned i) const
+{
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: return (float) this->value.u[i];
+ case GLSL_TYPE_INT: return (float) this->value.i[i];
+ case GLSL_TYPE_FLOAT: return this->value.f[i];
+ case GLSL_TYPE_BOOL: return this->value.b[i] ? 1.0 : 0.0;
+ default: assert(!"Should not get here."); break;
+ }
+
+ /* Must return something to make the compiler happy. This is clearly an
+ * error case.
+ */
+ return 0.0;
+}
+
+int
+ir_constant::get_int_component(unsigned i) const
+{
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: return this->value.u[i];
+ case GLSL_TYPE_INT: return this->value.i[i];
+ case GLSL_TYPE_FLOAT: return (int) this->value.f[i];
+ case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0;
+ default: assert(!"Should not get here."); break;
+ }
+
+ /* Must return something to make the compiler happy. This is clearly an
+ * error case.
+ */
+ return 0;
+}
-ir_dereference::ir_dereference(ir_instruction *var)
+unsigned
+ir_constant::get_uint_component(unsigned i) const
+{
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: return this->value.u[i];
+ case GLSL_TYPE_INT: return this->value.i[i];
+ case GLSL_TYPE_FLOAT: return (unsigned) this->value.f[i];
+ case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0;
+ default: assert(!"Should not get here."); break;
+ }
+
+ /* Must return something to make the compiler happy. This is clearly an
+ * error case.
+ */
+ return 0;
+}
+
+
+ir_constant *
+ir_constant::get_record_field(const char *name)
+{
+ int idx = this->type->field_index(name);
+
+ if (idx < 0)
+ return NULL;
+
+ if (this->components.is_empty())
+ return NULL;
+
+ exec_node *node = this->components.head;
+ for (int i = 0; i < idx; i++) {
+ node = node->next;
+
+ /* If the end of the list is encountered before the element matching the
+ * requested field is found, return NULL.
+ */
+ if (node->is_tail_sentinal())
+ return NULL;
+ }
+
+ return (ir_constant *) node;
+}
+
+
+ir_dereference_variable::ir_dereference_variable(ir_variable *var)
{
- this->mode = ir_reference_variable;
this->var = var;
this->type = (var != NULL) ? var->type : glsl_type::error_type;
}
-ir_dereference::ir_dereference(ir_instruction *var,
- ir_rvalue *array_index)
- : mode(ir_reference_array), var(var)
+ir_dereference_array::ir_dereference_array(ir_rvalue *value,
+ ir_rvalue *array_index)
+{
+ this->array_index = array_index;
+ this->set_array(value);
+}
+
+
+ir_dereference_array::ir_dereference_array(ir_variable *var,
+ ir_rvalue *array_index)
+{
+ this->array_index = array_index;
+ this->set_array(new ir_dereference_variable(var));
+}
+
+
+void
+ir_dereference_array::set_array(ir_rvalue *value)
{
- type = glsl_type::error_type;
+ this->array = value;
+ this->type = glsl_type::error_type;
- if (var != NULL) {
- const glsl_type *const vt = var->type;
+ if (this->array != NULL) {
+ const glsl_type *const vt = this->array->type;
if (vt->is_array()) {
type = vt->element_type();
type = vt->get_base_type();
}
}
+}
- this->selector.array_index = array_index;
+
+ir_dereference_record::ir_dereference_record(ir_rvalue *value,
+ const char *field)
+{
+ this->record = value;
+ this->field = field;
+ this->type = (this->record != NULL)
+ ? this->record->type->field_type(field) : glsl_type::error_type;
}
-ir_dereference::ir_dereference(ir_instruction *variable, const char *field)
- : mode(ir_reference_record), var(variable)
+
+ir_dereference_record::ir_dereference_record(ir_variable *var,
+ const char *field)
{
- this->selector.field = field;
- this->type = (var != NULL)
- ? var->type->field_type(field) : glsl_type::error_type;
+ this->record = new ir_dereference_variable(var);
+ this->field = field;
+ this->type = (this->record != NULL)
+ ? this->record->type->field_type(field) : glsl_type::error_type;
}
+
bool
ir_dereference::is_lvalue()
{
- if (var == NULL)
+ ir_variable *var = this->variable_referenced();
+
+ /* Every l-value derference chain eventually ends in a variable.
+ */
+ if ((var == NULL) || var->read_only)
return false;
- ir_variable *const as_var = var->as_variable();
- if (mode == ir_reference_variable) {
- if (as_var == NULL)
- return false;
+ if (this->type->is_array() && !var->array_lvalue)
+ return false;
+
+ return true;
+}
+
- if (as_var->type->is_array() && !as_var->array_lvalue)
- return false;
+const char *tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf" };
+
+const char *ir_texture::opcode_string()
+{
+ assert((unsigned int) op <=
+ sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0]));
+ return tex_opcode_strs[op];
+}
+
+ir_texture_opcode
+ir_texture::get_opcode(const char *str)
+{
+ const int count = sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0]);
+ for (int op = 0; op < count; op++) {
+ if (strcmp(str, tex_opcode_strs[op]) == 0)
+ return (ir_texture_opcode) op;
}
+ return (ir_texture_opcode) -1;
+}
- if (as_var != NULL)
- return !as_var->read_only;
- /* Walk up the dereference chain and figure out if the variable is read-only.
- */
- return this->var->as_rvalue()->is_lvalue();
+void
+ir_texture::set_sampler(ir_dereference *sampler)
+{
+ assert(sampler != NULL);
+ this->sampler = sampler;
+
+ switch (sampler->type->sampler_type) {
+ case GLSL_TYPE_FLOAT:
+ this->type = glsl_type::vec4_type;
+ break;
+ case GLSL_TYPE_INT:
+ this->type = glsl_type::ivec4_type;
+ break;
+ case GLSL_TYPE_UINT:
+ this->type = glsl_type::uvec4_type;
+ break;
+ }
}
+
ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z,
unsigned w, unsigned count)
: val(val)
#undef S
#undef I
+ir_variable *
+ir_swizzle::variable_referenced()
+{
+ return this->val->variable_referenced();
+}
ir_variable::ir_variable(const struct glsl_type *type, const char *name)
: max_array_access(0), read_only(false), centroid(false), invariant(false),
ir_variable *b = (ir_variable *)iter_b.get();
if (a->read_only != b->read_only ||
+ a->mode != b->mode ||
a->interpolation != b->interpolation ||
a->centroid != b->centroid) {