glsl: Add methods to copy parts of one ir_constant into another.

- copy_masked_offset copies part of a constant into another,
  assign-like.

- copy_offset copies a constant into (a subset of) another,
  funcall-return like.

These methods are to be used to trace through assignments and function
calls when computing a constant expression.

Signed-off-by: Olivier Galibert <galibert@pobox.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net> [v1]
This commit is contained in:
Olivier Galibert 2012-05-02 23:11:40 +02:00 committed by Kenneth Graunke
parent a270e86d38
commit 8ec01ba2ff
2 changed files with 114 additions and 0 deletions

View file

@ -856,6 +856,95 @@ ir_constant::get_record_field(const char *name)
return (ir_constant *) node;
}
void
ir_constant::copy_offset(ir_constant *src, int offset)
{
switch (this->type->base_type) {
case GLSL_TYPE_UINT:
case GLSL_TYPE_INT:
case GLSL_TYPE_FLOAT:
case GLSL_TYPE_BOOL: {
unsigned int size = src->type->components();
assert (size <= this->type->components() - offset);
for (unsigned int i=0; i<size; i++) {
switch (this->type->base_type) {
case GLSL_TYPE_UINT:
value.u[i+offset] = src->get_uint_component(i);
break;
case GLSL_TYPE_INT:
value.i[i+offset] = src->get_int_component(i);
break;
case GLSL_TYPE_FLOAT:
value.f[i+offset] = src->get_float_component(i);
break;
case GLSL_TYPE_BOOL:
value.b[i+offset] = src->get_bool_component(i);
break;
default: // Shut up the compiler
break;
}
}
break;
}
case GLSL_TYPE_STRUCT: {
assert (src->type == this->type);
this->components.make_empty();
foreach_list(node, &src->components) {
ir_constant *const orig = (ir_constant *) node;
this->components.push_tail(orig->clone(this, NULL));
}
break;
}
case GLSL_TYPE_ARRAY: {
assert (src->type == this->type);
for (unsigned i = 0; i < this->type->length; i++) {
this->array_elements[i] = src->array_elements[i]->clone(this, NULL);
}
break;
}
default:
assert(!"Should not get here.");
break;
}
}
void
ir_constant::copy_masked_offset(ir_constant *src, int offset, unsigned int mask)
{
assert (!type->is_array() && !type->is_record());
if (!type->is_vector() && !type->is_matrix()) {
offset = 0;
mask = 1;
}
int id = 0;
for (int i=0; i<4; i++) {
if (mask & (1 << i)) {
switch (this->type->base_type) {
case GLSL_TYPE_UINT:
value.u[i+offset] = src->get_uint_component(id++);
break;
case GLSL_TYPE_INT:
value.i[i+offset] = src->get_int_component(id++);
break;
case GLSL_TYPE_FLOAT:
value.f[i+offset] = src->get_float_component(id++);
break;
case GLSL_TYPE_BOOL:
value.b[i+offset] = src->get_bool_component(id++);
break;
default:
assert(!"Should not get here.");
return;
}
}
}
}
bool
ir_constant::has_value(const ir_constant *c) const

View file

@ -1682,6 +1682,31 @@ public:
ir_constant *get_record_field(const char *name);
/**
* Copy the values on another constant at a given offset.
*
* The offset is ignored for array or struct copies, it's only for
* scalars or vectors into vectors or matrices.
*
* With identical types on both sides and zero offset it's clone()
* without creating a new object.
*/
void copy_offset(ir_constant *src, int offset);
/**
* Copy the values on another constant at a given offset and
* following an assign-like mask.
*
* The mask is ignored for scalars.
*
* Note that this function only handles what assign can handle,
* i.e. at most a vector as source and a column of a matrix as
* destination.
*/
void copy_masked_offset(ir_constant *src, int offset, unsigned int mask);
/**
* Determine whether a constant has the same value as another constant
*