]> git.tdb.fi Git - libs/gl.git/blobdiff - source/programcompiler.cpp
Remove useless declarations of main() from shaders
[libs/gl.git] / source / programcompiler.cpp
index 0e749c9736588ddaa5192d74a70fb9719dc16f05..0d61c6853c737a75bac34212114077e1b691286c 100644 (file)
@@ -160,6 +160,7 @@ void ProgramCompiler::generate(Stage &stage)
 {
        inject_block(stage.content, module->shared.content);
 
+       apply<DeclarationReorderer>(stage);
        apply<FunctionResolver>(stage);
        apply<VariableResolver>(stage);
        apply<InterfaceGenerator>(stage);
@@ -452,6 +453,12 @@ void ProgramCompiler::Formatter::visit(Return &ret)
        formatted += ';';
 }
 
+void ProgramCompiler::Formatter::visit(Jump &jump)
+{
+       formatted += jump.keyword;
+       formatted += ';';
+}
+
 
 ProgramCompiler::DeclarationCombiner::DeclarationCombiner():
        toplevel(true),
@@ -1206,38 +1213,39 @@ void ProgramCompiler::ConstantConditionEliminator::visit(Iteration &iter)
 ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator():
        aggregate(0),
        assignment(0),
-       assignment_target(false)
+       assignment_target(false),
+       global_scope(true)
 { }
 
 void ProgramCompiler::UnusedVariableLocator::apply(Stage &s)
 {
-       assignments.push_back(BlockAssignmentMap());
+       variables.push_back(BlockVariableMap());
        Visitor::apply(s);
-       assignments.pop_back();
+       BlockVariableMap &global_variables = variables.back();
+       for(BlockVariableMap::iterator i=global_variables.begin(); i!=global_variables.end(); ++i)
+       {
+               if(i->first->interface=="out" && (s.type==FRAGMENT || i->first->linked_declaration || !i->first->name.compare(0, 3, "gl_")))
+                       continue;
+               if(!i->second.referenced)
+               {
+                       unused_nodes.insert(i->first);
+                       clear_assignments(i->second, true);
+               }
+       }
+       variables.pop_back();
 }
 
 void ProgramCompiler::UnusedVariableLocator::visit(VariableReference &var)
 {
-       unused_nodes.erase(var.declaration);
-
        map<VariableDeclaration *, Node *>::iterator i = aggregates.find(var.declaration);
        if(i!=aggregates.end())
                unused_nodes.erase(i->second);
 
-       if(assignment_target)
-               return;
-
-       for(vector<BlockAssignmentMap>::iterator j=assignments.end(); j!=assignments.begin(); )
+       if(var.declaration && !assignment_target)
        {
-               --j;
-               BlockAssignmentMap::iterator k = j->find(var.declaration);
-               if(k!=j->end())
-               {
-                       for(vector<Node *>::iterator l=k->second.nodes.begin(); l!=k->second.nodes.end(); ++l)
-                               unused_nodes.erase(*l);
-                       j->erase(k);
-                       break;
-               }
+               VariableInfo &var_info = variables.back()[var.declaration];
+               var_info.assignments.clear();
+               var_info.referenced = true;
        }
 }
 
@@ -1271,14 +1279,21 @@ void ProgramCompiler::UnusedVariableLocator::visit(Assignment &assign)
 
 void ProgramCompiler::UnusedVariableLocator::record_assignment(VariableDeclaration &var, Node &node, bool self_ref)
 {
-       unused_nodes.insert(&node);
-       BlockAssignmentMap &block_assignments = assignments.back();
-       AssignmentList &var_assignments = block_assignments[&var];
+       VariableInfo &var_info = variables.back()[&var];
        if(!self_ref)
-               var_assignments.nodes.clear();
-       var_assignments.nodes.push_back(&node);
-       var_assignments.conditional = false;
-       var_assignments.self_referencing = self_ref;
+               clear_assignments(var_info, true);
+       var_info.assignments.push_back(&node);
+       var_info.conditionally_assigned = false;
+}
+
+void ProgramCompiler::UnusedVariableLocator::clear_assignments(VariableInfo &var_info, bool mark_unused)
+{
+       if(mark_unused)
+       {
+               for(vector<Node *>::iterator i=var_info.assignments.begin(); i!=var_info.assignments.end(); ++i)
+                       unused_nodes.insert(*i);
+       }
+       var_info.assignments.clear();
 }
 
 void ProgramCompiler::UnusedVariableLocator::visit(ExpressionStatement &expr)
@@ -1302,7 +1317,7 @@ void ProgramCompiler::UnusedVariableLocator::visit(VariableDeclaration &var)
                aggregates[&var] = aggregate;
        else
        {
-               unused_nodes.insert(&var);
+               variables.back()[&var].local = true;
                if(var.init_expression)
                        record_assignment(var, *var.init_expression, false);
        }
@@ -1319,90 +1334,106 @@ void ProgramCompiler::UnusedVariableLocator::visit(InterfaceBlock &iface)
 
 void ProgramCompiler::UnusedVariableLocator::visit(FunctionDeclaration &func)
 {
-       assignments.push_back(BlockAssignmentMap());
-
-       for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
-               (*i)->visit(*this);
-       func.body.visit(*this);
+       variables.push_back(BlockVariableMap());
 
-       BlockAssignmentMap &block_assignments = assignments.back();
-       for(map<string, VariableDeclaration *>::iterator i=func.body.variables.begin(); i!=func.body.variables.end(); ++i)
-               block_assignments.erase(i->second);
-       for(BlockAssignmentMap::iterator i=block_assignments.begin(); i!=block_assignments.end(); ++i)
        {
-               if(i->first->interface=="out" && stage->type!=FRAGMENT && !i->first->linked_declaration)
-                       continue;
-
-               for(vector<Node *>::iterator j=i->second.nodes.begin(); j!=i->second.nodes.end(); ++j)
-                       unused_nodes.erase(*j);
+               SetForScope<bool> set(global_scope, false);
+               for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
+                       (*i)->visit(*this);
+               func.body.visit(*this);
        }
 
-       assignments.pop_back();
+       BlockVariableMap &block_variables = variables.back();
+       for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
+               i->second.conditionally_assigned = true;
+       for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
+               block_variables[i->get()].referenced = true;
+       merge_down_variables();
 }
 
-void ProgramCompiler::UnusedVariableLocator::merge_down_assignments()
+void ProgramCompiler::UnusedVariableLocator::merge_down_variables()
 {
-       BlockAssignmentMap &parent_assignments = assignments[assignments.size()-2];
-       BlockAssignmentMap &block_assignments = assignments.back();
-       for(BlockAssignmentMap::iterator i=block_assignments.begin(); i!=block_assignments.end(); ++i)
+       BlockVariableMap &parent_variables = variables[variables.size()-2];
+       BlockVariableMap &block_variables = variables.back();
+       for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
        {
-               BlockAssignmentMap::iterator j = parent_assignments.find(i->first);
-               if(j==parent_assignments.end())
-                       parent_assignments.insert(*i);
-               else if(i->second.self_referencing || i->second.conditional)
+               if(i->second.local)
                {
-                       j->second.nodes.insert(j->second.nodes.end(), i->second.nodes.begin(), i->second.nodes.end());
-                       j->second.conditional |= i->second.conditional;
-                       j->second.self_referencing |= i->second.self_referencing;
+                       if(!i->second.referenced)
+                               unused_nodes.insert(i->first);
+                       clear_assignments(i->second, true);
+                       continue;
                }
+
+               BlockVariableMap::iterator j = parent_variables.find(i->first);
+               if(j==parent_variables.end())
+                       parent_variables.insert(*i);
                else
-                       j->second = i->second;
+               {
+                       if(i->second.referenced || !i->second.conditionally_assigned)
+                               clear_assignments(j->second, !i->second.referenced);
+                       j->second.conditionally_assigned = i->second.conditionally_assigned;
+                       j->second.referenced |= i->second.referenced;
+                       j->second.assignments.insert(j->second.assignments.end(), i->second.assignments.begin(), i->second.assignments.end());
+               }
        }
-       assignments.pop_back();
+       variables.pop_back();
 }
 
 void ProgramCompiler::UnusedVariableLocator::visit(Conditional &cond)
 {
        cond.condition->visit(*this);
-       assignments.push_back(BlockAssignmentMap());
+       variables.push_back(BlockVariableMap());
        cond.body.visit(*this);
 
-       BlockAssignmentMap if_assignments;
-       swap(assignments.back(), if_assignments);
+       BlockVariableMap if_variables;
+       swap(variables.back(), if_variables);
        cond.else_body.visit(*this);
 
-       BlockAssignmentMap &else_assignments = assignments.back();
-       for(BlockAssignmentMap::iterator i=else_assignments.begin(); i!=else_assignments.end(); ++i)
+       BlockVariableMap &else_variables = variables.back();
+       for(BlockVariableMap::iterator i=else_variables.begin(); i!=else_variables.end(); ++i)
        {
-               BlockAssignmentMap::iterator j = if_assignments.find(i->first);
-               if(j!=if_assignments.end())
+               BlockVariableMap::iterator j = if_variables.find(i->first);
+               if(j!=if_variables.end())
                {
-                       i->second.nodes.insert(i->second.nodes.end(), j->second.nodes.begin(), j->second.nodes.end());
-                       i->second.conditional |= j->second.conditional;
-                       i->second.self_referencing |= j->second.self_referencing;
-                       if_assignments.erase(j);
+                       i->second.assignments.insert(i->second.assignments.end(), j->second.assignments.begin(), j->second.assignments.end());
+                       i->second.conditionally_assigned |= j->second.conditionally_assigned;
+                       if_variables.erase(j);
                }
                else
-                       i->second.conditional = true;
+                       i->second.conditionally_assigned = true;
        }
 
-       for(BlockAssignmentMap::iterator i=if_assignments.begin(); i!=if_assignments.end(); ++i)
+       for(BlockVariableMap::iterator i=if_variables.begin(); i!=if_variables.end(); ++i)
        {
-               i->second.conditional = true;
-               else_assignments.insert(*i);
+               i->second.conditionally_assigned = true;
+               else_variables.insert(*i);
        }
 
-       merge_down_assignments();
+       merge_down_variables();
 }
 
 void ProgramCompiler::UnusedVariableLocator::visit(Iteration &iter)
 {
-       assignments.push_back(BlockAssignmentMap());
+       variables.push_back(BlockVariableMap());
        TraversingVisitor::visit(iter);
-       merge_down_assignments();
+
+       BlockVariableMap &block_variables = variables.back();
+       for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
+               if(!i->second.local && i->second.referenced)
+                       i->second.assignments.clear();
+
+       merge_down_variables();
 }
 
 
+ProgramCompiler::UnusedVariableLocator::VariableInfo::VariableInfo():
+       local(false),
+       conditionally_assigned(false),
+       referenced(false)
+{ }
+
+
 void ProgramCompiler::UnusedFunctionLocator::visit(FunctionCall &call)
 {
        TraversingVisitor::visit(call);
@@ -1416,7 +1447,7 @@ void ProgramCompiler::UnusedFunctionLocator::visit(FunctionDeclaration &func)
 {
        TraversingVisitor::visit(func);
 
-       if(func.name!="main" && !used_definitions.count(&func))
+       if((func.name!="main" || func.body.body.empty()) && !used_definitions.count(&func))
                unused_nodes.insert(&func);
 }