diff options
author | Ian Romanick <ian.d.romanick@intel.com> | 2010-03-29 16:17:56 -0700 |
---|---|---|
committer | Ian Romanick <ian.d.romanick@intel.com> | 2010-03-29 16:29:21 -0700 |
commit | 0104536568ed031654c1c3c957b0216bbca4a1d6 (patch) | |
tree | 3e119bdb4281525a9ad67e62b9d819c9c69af0f3 | |
parent | 70348543ac8f2c4d3d25996869461c53ea82b6a8 (diff) |
Apply implicit conversions to arithmetic operators
-rw-r--r-- | ast_to_hir.cpp | 84 |
1 files changed, 67 insertions, 17 deletions
diff --git a/ast_to_hir.cpp b/ast_to_hir.cpp index 661dd704dc..34762df18d 100644 --- a/ast_to_hir.cpp +++ b/ast_to_hir.cpp @@ -73,12 +73,70 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) } +/** + * If a conversion is available, convert one operand to a different type + * + * The \c from \c ir_rvalue is converted "in place". + * + * \param to Type that the operand it to be converted to + * \param from Operand that is being converted + * \param state GLSL compiler state + * + * \return + * If a conversion is possible (or unnecessary), \c true is returned. + * Otherwise \c false is returned. + */ +static bool +apply_implicit_conversion(const glsl_type *to, ir_rvalue **from, + struct _mesa_glsl_parse_state *state) +{ + if (to->base_type == (*from)->type->base_type) + return true; + + /* This conversion was added in GLSL 1.20. If the compilation mode is + * GLSL 1.10, the conversion is skipped. + */ + if (state->language_version < 120) + return false; + + /* From page 27 (page 33 of the PDF) of the GLSL 1.50 spec: + * + * "There are no implicit array or structure conversions. For + * example, an array of int cannot be implicitly converted to an + * array of float. There are no implicit conversions between + * signed and unsigned integers." + */ + /* FINISHME: The above comment is partially a lie. There is int/uint + * FINISHME: conversion for immediate constants. + */ + if (!to->is_float() || !(*from)->type->is_numeric()) + return false; + + switch (((*from))->type->base_type) { + case GLSL_TYPE_INT: + (*from) = new ir_expression(ir_unop_i2f, to, (*from), NULL); + break; + case GLSL_TYPE_UINT: + (*from) = new ir_expression(ir_unop_u2f, to, (*from), NULL); + break; + case GLSL_TYPE_BOOL: + assert(!"FINISHME: Convert bool to float."); + default: + assert(0); + } + + return true; +} + + static const struct glsl_type * -arithmetic_result_type(const struct glsl_type *type_a, - const struct glsl_type *type_b, +arithmetic_result_type(ir_rvalue **value_a, ir_rvalue **value_b, bool multiply, struct _mesa_glsl_parse_state *state) { + const glsl_type *const type_a = (*value_a)->type; + const glsl_type *const type_b = (*value_b)->type; + /* From GLSL 1.50 spec, page 56: * * "The arithmetic binary operators add (+), subtract (-), @@ -93,16 +151,10 @@ arithmetic_result_type(const struct glsl_type *type_a, /* "If one operand is floating-point based and the other is * not, then the conversions from Section 4.1.10 "Implicit * Conversions" are applied to the non-floating-point-based operand." - * - * This conversion was added in GLSL 1.20. If the compilation mode is - * GLSL 1.10, the conversion is skipped. */ - if (state->language_version >= 120) { - if ((type_a->base_type == GLSL_TYPE_FLOAT) - && (type_b->base_type != GLSL_TYPE_FLOAT)) { - } else if ((type_a->base_type != GLSL_TYPE_FLOAT) - && (type_b->base_type == GLSL_TYPE_FLOAT)) { - } + if (!apply_implicit_conversion(type_a, value_b, state) + && !apply_implicit_conversion(type_b, value_a, state)) { + return glsl_type::error_type; } /* "If the operands are integer types, they must both be signed or @@ -551,7 +603,7 @@ ast_expression::hir(exec_list *instructions, op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); - type = arithmetic_result_type(op[0]->type, op[1]->type, + type = arithmetic_result_type(& op[0], & op[1], (this->oper == ast_mul), state); @@ -649,7 +701,7 @@ ast_expression::hir(exec_list *instructions, op[0] = this->subexpressions[0]->hir(instructions, state); op[1] = this->subexpressions[1]->hir(instructions, state); - type = arithmetic_result_type(op[0]->type, op[1]->type, + type = arithmetic_result_type(& op[0], & op[1], (this->oper == ast_mul_assign), state); @@ -772,8 +824,7 @@ ast_expression::hir(exec_list *instructions, else op[1] = new ir_constant(1); - type = arithmetic_result_type(op[0]->type, op[1]->type, - false, state); + type = arithmetic_result_type(& op[0], & op[1], false, state); struct ir_rvalue *temp_rhs; temp_rhs = new ir_expression(operations[this->oper], type, @@ -796,8 +847,7 @@ ast_expression::hir(exec_list *instructions, error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); - type = arithmetic_result_type(op[0]->type, op[1]->type, - false, state); + type = arithmetic_result_type(& op[0], & op[1], false, state); struct ir_rvalue *temp_rhs; temp_rhs = new ir_expression(operations[this->oper], type, |