]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/optimize.cpp
Fix the return value of ConstantFolder::apply
[libs/gl.git] / source / glsl / optimize.cpp
index d21512f6c82e4e6bdef3ccbdf38f70cd6e018e66..ed20bb175dcc9277e1ff84e2e1a1734b2279668f 100644 (file)
@@ -611,6 +611,8 @@ void ConstantFolder::convert_to_result(const Variant &value)
                set_result(static_cast<T>(value.value<bool>()));
        else if(value.check_type<int>())
                set_result(static_cast<T>(value.value<int>()));
+       else if(value.check_type<unsigned>())
+               set_result(static_cast<T>(value.value<unsigned>()));
        else if(value.check_type<float>())
                set_result(static_cast<T>(value.value<float>()));
 }
@@ -640,6 +642,8 @@ void ConstantFolder::visit(RefPtr<Expression> &expr)
                literal->token = (r_constant_value.value<bool>() ? "true" : "false");
        else if(r_constant_value.check_type<int>())
                literal->token = lexical_cast<string>(r_constant_value.value<int>());
+       else if(r_constant_value.check_type<unsigned>())
+               literal->token = lexical_cast<string>(r_constant_value.value<unsigned>())+"u";
        else if(r_constant_value.check_type<float>())
        {
                literal->token = lexical_cast<string>(r_constant_value.value<float>());
@@ -653,6 +657,7 @@ void ConstantFolder::visit(RefPtr<Expression> &expr)
        }
        literal->value = r_constant_value;
        expr = literal;
+       r_any_folded = true;
 }
 
 void ConstantFolder::visit(Literal &literal)
@@ -744,11 +749,15 @@ void ConstantFolder::visit(BinaryExpression &binary)
                        set_result(evaluate_logical(oper, left_value.value<bool>(), r_constant_value.value<bool>()));
                else if(!oper2 && left_value.check_type<int>())
                        set_result(evaluate_logical(oper, left_value.value<int>(), r_constant_value.value<int>()));
+               else if(!oper2 && left_value.check_type<unsigned>())
+                       set_result(evaluate_logical(oper, left_value.value<unsigned>(), r_constant_value.value<unsigned>()));
        }
        else if((oper=='<' || oper=='>') && oper2!=oper)
        {
                if(left_value.check_type<int>())
                        set_result(evaluate_relation(binary.oper->token, left_value.value<int>(), r_constant_value.value<int>()));
+               else if(left_value.check_type<unsigned>())
+                       set_result(evaluate_relation(binary.oper->token, left_value.value<unsigned>(), r_constant_value.value<unsigned>()));
                else if(left_value.check_type<float>())
                        set_result(evaluate_relation(binary.oper->token, left_value.value<float>(), r_constant_value.value<float>()));
        }
@@ -756,13 +765,17 @@ void ConstantFolder::visit(BinaryExpression &binary)
        {
                if(left_value.check_type<int>())
                        set_result((left_value.value<int>()==r_constant_value.value<int>()) == (oper=='='));
-               if(left_value.check_type<float>())
+               else if(left_value.check_type<unsigned>())
+                       set_result((left_value.value<unsigned>()==r_constant_value.value<unsigned>()) == (oper=='='));
+               else if(left_value.check_type<float>())
                        set_result((left_value.value<float>()==r_constant_value.value<float>()) == (oper=='='));
        }
        else if(oper=='+' || oper=='-' || oper=='*' || oper=='/')
        {
                if(left_value.check_type<int>())
                        set_result(evaluate_arithmetic(oper, left_value.value<int>(), r_constant_value.value<int>()));
+               else if(left_value.check_type<unsigned>())
+                       set_result(evaluate_arithmetic(oper, left_value.value<unsigned>(), r_constant_value.value<unsigned>()));
                else if(left_value.check_type<float>())
                        set_result(evaluate_arithmetic(oper, left_value.value<float>(), r_constant_value.value<float>()));
        }
@@ -770,6 +783,8 @@ void ConstantFolder::visit(BinaryExpression &binary)
        {
                if(left_value.check_type<int>())
                        set_result(evaluate_int_special_op(oper, left_value.value<int>(), r_constant_value.value<int>()));
+               else if(left_value.check_type<unsigned>())
+                       set_result(evaluate_int_special_op(oper, left_value.value<unsigned>(), r_constant_value.value<unsigned>()));
        }
 }
 
@@ -800,8 +815,10 @@ void ConstantFolder::visit(FunctionCall &call)
 
                        if(basic->kind==BasicTypeDeclaration::BOOL)
                                convert_to_result<bool>(r_constant_value);
-                       else if(basic->kind==BasicTypeDeclaration::INT && basic->size==32)
+                       else if(basic->kind==BasicTypeDeclaration::INT && basic->size==32 && basic->sign)
                                convert_to_result<int>(r_constant_value);
+                       else if(basic->kind==BasicTypeDeclaration::INT && basic->size==32 && !basic->sign)
+                               convert_to_result<unsigned>(r_constant_value);
                        else if(basic->kind==BasicTypeDeclaration::FLOAT && basic->size==32)
                                convert_to_result<float>(r_constant_value);
 
@@ -1040,7 +1057,8 @@ UnusedVariableRemover::UnusedVariableRemover():
        assignment_target(false),
        r_side_effects(false),
        in_struct(false),
-       composite_reference(false)
+       composite_reference(false),
+       in_loop(0)
 { }
 
 bool UnusedVariableRemover::apply(Stage &s)
@@ -1084,6 +1102,7 @@ void UnusedVariableRemover::referenced(const Assignment::Target &target, Node &n
        var_info.referenced = true;
        if(!assignment_target)
        {
+               bool loop_external = false;
                for(vector<AssignmentInfo *>::const_iterator i=var_info.assignments.begin(); i!=var_info.assignments.end(); ++i)
                {
                        bool covered = true;
@@ -1107,9 +1126,17 @@ void UnusedVariableRemover::referenced(const Assignment::Target &target, Node &n
                                else
                                        covered = ((*i)->target.chain[j]==target.chain[j]);
                        }
+
                        if(covered)
+                       {
                                (*i)->used_by.push_back(&node);
+                               if((*i)->in_loop<in_loop)
+                                       loop_external = true;
+                       }
                }
+
+               if(loop_external)
+                       loop_ext_refs.push_back(&node);
        }
 }
 
@@ -1231,6 +1258,7 @@ void UnusedVariableRemover::record_assignment(const Assignment::Target &target,
        AssignmentInfo &assign_info = assignments.back();
        assign_info.node = &node;
        assign_info.target = target;
+       assign_info.in_loop = in_loop;
 
        /* An assignment to the target hides any assignments to the same target or
        its subfields. */
@@ -1362,7 +1390,18 @@ void UnusedVariableRemover::visit(Conditional &cond)
 void UnusedVariableRemover::visit(Iteration &iter)
 {
        BlockVariableMap saved_vars = variables;
-       TraversingVisitor::visit(iter);
+       vector<Node *> saved_refs;
+       swap(loop_ext_refs, saved_refs);
+       {
+               SetForScope<unsigned> set_loop(in_loop, in_loop+1);
+               TraversingVisitor::visit(iter);
+       }
+       swap(loop_ext_refs, saved_refs);
+
+       /* Visit the external references of the loop again to record assignments
+       done in the loop as used. */
+       for(vector<Node *>::const_iterator i=saved_refs.begin(); i!=saved_refs.end(); ++i)
+               (*i)->visit(*this);
 
        /* Merge assignments from the iteration, without clearing previous state.
        Further analysis is needed to determine which parts of the iteration body