From abe976755318fa9dd88a5c48289623ab7c12ce02 Mon Sep 17 00:00:00 2001 From: Olivier Galibert Date: Tue, 8 May 2012 20:40:35 +0200 Subject: [PATCH] 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 Reviewed-by: Kenneth Graunke --- src/glsl/ir_constant_expression.cpp | 47 +++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp index 08a33285b3a..7a4d15f43fb 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; -- 2.30.2