summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Galibert <galibert@pobox.com>2012-05-08 20:40:35 +0200
committerKenneth Graunke <kenneth@whitecape.org>2012-06-07 00:06:18 -0700
commitabe976755318fa9dd88a5c48289623ab7c12ce02 (patch)
tree6921bd0f129efc5e2c3ca41afe1f8b12d2ed2579
parent1b8a3aad09d67e72903fdcc79beadfc3c77cae62 (diff)
glsl: Bitwise conversion operator support in ir_constant_expression.
A "test_out = floatBitsToUint(-1.0);" fired through the GLSL compiler gives a correct "(assign (x) (var_ref test_out) (constant uint (3212836864)))" Signed-off-by: Olivier Galibert <galibert@pobox.com> Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
-rw-r--r--src/glsl/ir_constant_expression.cpp47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp
index 08a33285b3..7a4d15f43f 100644
--- a/src/glsl/ir_constant_expression.cpp
+++ b/src/glsl/ir_constant_expression.cpp
@@ -71,6 +71,29 @@ dot(ir_constant *op0, ir_constant *op1)
return result;
}
+/* This method is the only one supported by gcc. Unions in particular
+ * are iffy, and read-through-converted-pointer is killed by strict
+ * aliasing. OTOH, the compiler sees through the memcpy, so the
+ * resulting asm is reasonable.
+ */
+static float
+bitcast_u2f(unsigned int u)
+{
+ assert(sizeof(float) == sizeof(unsigned int));
+ float f;
+ memcpy(&f, &u, sizeof(f));
+ return f;
+}
+
+static unsigned int
+bitcast_f2u(float f)
+{
+ assert(sizeof(float) == sizeof(unsigned int));
+ unsigned int u;
+ memcpy(&u, &f, sizeof(f));
+ return u;
+}
+
ir_constant *
ir_rvalue::constant_expression_value(struct hash_table *variable_context)
{
@@ -207,6 +230,30 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
data.u[c] = op[0]->value.i[c];
}
break;
+ case ir_unop_bitcast_i2f:
+ assert(op[0]->type->base_type == GLSL_TYPE_INT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = bitcast_u2f(op[0]->value.i[c]);
+ }
+ break;
+ case ir_unop_bitcast_f2i:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.i[c] = bitcast_f2u(op[0]->value.f[c]);
+ }
+ break;
+ case ir_unop_bitcast_u2f:
+ assert(op[0]->type->base_type == GLSL_TYPE_UINT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.f[c] = bitcast_u2f(op[0]->value.u[c]);
+ }
+ break;
+ case ir_unop_bitcast_f2u:
+ assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned c = 0; c < op[0]->type->components(); c++) {
+ data.u[c] = bitcast_f2u(op[0]->value.f[c]);
+ }
+ break;
case ir_unop_any:
assert(op[0]->type->is_boolean());
data.b[0] = false;