]> git.tdb.fi Git - libs/gl.git/commitdiff
Also break up arrays which are only indexed by constants
authorMikko Rasa <tdb@tdb.fi>
Sat, 9 Oct 2021 16:58:51 +0000 (19:58 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sat, 9 Oct 2021 17:14:48 +0000 (20:14 +0300)
source/glsl/optimize.cpp
source/glsl/optimize.h
tests/glsl/unary_operators.glsl

index 768cfd5dc761659f504011780e3e0cbc74f90c0d..42e4a86ec7feb3466f7e0a119b4bf1a4feb28916 100644 (file)
@@ -532,11 +532,19 @@ bool AggregateDismantler::apply(Stage &stage)
 
                for(const AggregateMember &m: kvp.second.members)
                {
+                       string name;
+                       if(m.declaration)
+                               name = format("%s_%s", kvp.second.declaration->name, m.declaration->name);
+                       else
+                               name = format("%s_%d", kvp.second.declaration->name, m.index);
+
                        VariableDeclaration *var = new VariableDeclaration;
                        var->source = kvp.first->source;
                        var->line = kvp.first->line;
-                       var->name = get_unused_variable_name(*kvp.second.decl_scope, format("%s_%s", kvp.second.declaration->name, m.declaration->name));
-                       var->type = m.declaration->type;
+                       var->name = get_unused_variable_name(*kvp.second.decl_scope, name);
+                       /* XXX This is kind of brittle and depends on the array declaration's
+                       textual type not having brackets in it. */
+                       var->type = (m.declaration ? m.declaration : kvp.second.declaration)->type;
                        if(m.initializer)
                                var->init_expression = m.initializer->clone();
 
@@ -570,10 +578,17 @@ void AggregateDismantler::visit(RefPtr<Expression> &expr)
 {
        r_aggregate_ref = 0;
        expr->visit(*this);
-       if(r_aggregate_ref && r_reference.chain_len==1 && (r_reference.chain[0]&0x3F)!=0x3F)
+       if(r_aggregate_ref && r_reference.chain_len==1)
        {
-               r_aggregate_ref->members[r_reference.chain[0]&0x3F].references.push_back(&expr);
-               r_aggregate_ref->members_referenced = true;
+               if((r_reference.chain[0]&0x3F)!=0x3F)
+               {
+                       r_aggregate_ref->members[r_reference.chain[0]&0x3F].references.push_back(&expr);
+                       r_aggregate_ref->members_referenced = true;
+               }
+               else
+                       /* If the accessed member is not known, mark the entire aggregate as
+                       referenced. */
+                       r_aggregate_ref->referenced = true;
        }
        r_aggregate_ref = 0;
 }
@@ -584,6 +599,8 @@ void AggregateDismantler::visit(VariableReference &var)
                r_reference.declaration = var.declaration;
        else
        {
+               /* If an aggregate variable is referenced as a whole, it should not be
+               dismantled. */
                auto i = aggregates.find(var.declaration);
                if(i!=aggregates.end())
                        i->second.referenced = true;
@@ -624,7 +641,19 @@ void AggregateDismantler::visit(BinaryExpression &binary)
                        visit(binary.right);
                }
 
-               add_to_chain(r_reference, Assignment::Target::ARRAY, 0x3F);
+               unsigned index = 0x3F;
+               if(Literal *literal_subscript = dynamic_cast<Literal *>(binary.right.get()))
+                       if(literal_subscript->value.check_type<int>())
+                               index = literal_subscript->value.value<int>();
+               add_to_chain(r_reference, Assignment::Target::ARRAY, index);
+
+               if(r_reference.declaration && r_reference.chain_len==1)
+               {
+                       auto i = aggregates.find(r_reference.declaration);
+                       r_aggregate_ref = (i!=aggregates.end() ? &i->second : 0);
+               }
+               else
+                       r_aggregate_ref = 0;
        }
        else
        {
@@ -638,6 +667,7 @@ void AggregateDismantler::visit(VariableDeclaration &var)
        TraversingVisitor::visit(var);
 
        if(var.interface.empty())
+       {
                if(const StructDeclaration *strct = dynamic_cast<const StructDeclaration *>(var.type_declaration))
                {
                        const FunctionCall *init_call = dynamic_cast<const FunctionCall *>(var.init_expression.get());
@@ -656,6 +686,7 @@ void AggregateDismantler::visit(VariableDeclaration &var)
                                        {
                                                AggregateMember member;
                                                member.declaration = mem_decl;
+                                               member.index = i;
                                                if(init_call)
                                                        member.initializer = init_call->arguments[i];
                                                aggre.members.push_back(member);
@@ -664,6 +695,26 @@ void AggregateDismantler::visit(VariableDeclaration &var)
                                }
                        }
                }
+               else if(const Literal *literal_size = dynamic_cast<const Literal *>(var.array_size.get()))
+               {
+                       if(literal_size->value.check_type<int>())
+                       {
+                               Aggregate &aggre = aggregates[&var];
+                               aggre.declaration = &var;
+                               aggre.decl_scope = current_block;
+                               aggre.insert_point = insert_point;
+
+                               int size = literal_size->value.value<int>();
+                               for(int i=0; i<size; ++i)
+                               {
+                                       AggregateMember member;
+                                       member.index = i;
+                                       // Array initializers are not supported yet
+                                       aggre.members.push_back(member);
+                               }
+                       }
+               }
+       }
 }
 
 
index 1eb0464e7daea97d654576c15792a13e764d8c27..aebe080c585206b14d533a4c09ef3c926878392d 100644 (file)
@@ -161,6 +161,7 @@ private:
        struct AggregateMember
        {
                const VariableDeclaration *declaration = 0;
+               unsigned index = 0;
                RefPtr<Expression> initializer;
                std::vector<RefPtr<Expression> *> references;
        };
index bd9803b2bfba7f8b807de165692da5722bd35ecb..baef6451885904fb87e4c53c4e5a02d673d05f07 100644 (file)
@@ -22,7 +22,7 @@ void main()
        --i;
        i++;
        i--;
-       int arr[3];
-       ++arr[0];
+       int arr_0;
+       ++arr_0;
 }
 */