]> git.tdb.fi Git - libs/gl.git/commitdiff
Remove unused functions from the shader source
authorMikko Rasa <tdb@tdb.fi>
Mon, 14 Nov 2016 15:46:35 +0000 (17:46 +0200)
committerMikko Rasa <tdb@tdb.fi>
Mon, 14 Nov 2016 15:46:35 +0000 (17:46 +0200)
source/programcompiler.cpp
source/programcompiler.h
source/programsyntax.cpp
source/programsyntax.h

index 9b3266755b0b4f36c7bdc1ebe3471ebba48e8d40..937639a49157bf6f73cda381d306585e1c05b482 100644 (file)
@@ -159,6 +159,7 @@ void ProgramCompiler::generate(Stage &stage)
 {
        inject_block(stage.content, module->shared.content);
 
+       apply<FunctionResolver>(stage);
        apply<VariableResolver>(stage);
        apply<InterfaceGenerator>(stage);
        apply<VariableResolver>(stage);
@@ -171,6 +172,8 @@ bool ProgramCompiler::optimize(Stage &stage)
        apply<VariableResolver>(stage);
 
        set<Node *> unused = apply<UnusedVariableLocator>(stage);
+       set<Node *> unused2 = apply<UnusedFunctionLocator>(stage);
+       unused.insert(unused2.begin(), unused2.end());
        apply<NodeRemover>(stage, unused);
 
        return !unused.empty();
@@ -616,6 +619,34 @@ void ProgramCompiler::VariableResolver::visit(InterfaceBlock &iface)
 }
 
 
+void ProgramCompiler::FunctionResolver::visit(FunctionCall &call)
+{
+       map<string, vector<FunctionDeclaration *> >::iterator i = functions.find(call.name);
+       if(i!=functions.end())
+               call.declaration = i->second.back();
+
+       TraversingVisitor::visit(call);
+}
+
+void ProgramCompiler::FunctionResolver::visit(FunctionDeclaration &func)
+{
+       vector<FunctionDeclaration *> &decls = functions[func.name];
+       if(func.definition)
+       {
+               for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
+                       (*i)->definition = func.definition;
+               decls.clear();
+               decls.push_back(&func);
+       }
+       else if(!decls.empty() && decls.back()->definition)
+               func.definition = decls.back()->definition;
+       else
+               decls.push_back(&func);
+
+       TraversingVisitor::visit(func);
+}
+
+
 ProgramCompiler::InterfaceGenerator::InterfaceGenerator():
        scope_level(0),
        remove_node(false)
@@ -1198,6 +1229,24 @@ void ProgramCompiler::UnusedVariableLocator::visit(Iteration &iter)
 }
 
 
+void ProgramCompiler::UnusedFunctionLocator::visit(FunctionCall &call)
+{
+       TraversingVisitor::visit(call);
+
+       unused_nodes.erase(call.declaration);
+       if(call.declaration && call.declaration->definition!=call.declaration)
+               used_definitions.insert(call.declaration->definition);
+}
+
+void ProgramCompiler::UnusedFunctionLocator::visit(FunctionDeclaration &func)
+{
+       TraversingVisitor::visit(func);
+
+       if(func.name!="main" && !used_definitions.count(&func))
+               unused_nodes.insert(&func);
+}
+
+
 ProgramCompiler::NodeRemover::NodeRemover(const set<Node *> &r):
        to_remove(r)
 { }
index f585ba92347ae52e580eec7c5d42ce993fc8c483..8681d3638a032cabd389879922fe7378c4a45a76 100644 (file)
@@ -108,6 +108,14 @@ private:
                virtual void visit(ProgramSyntax::InterfaceBlock &);
        };
 
+       struct FunctionResolver: Visitor
+       {
+               std::map<std::string, std::vector<ProgramSyntax::FunctionDeclaration *> > functions;
+
+               virtual void visit(ProgramSyntax::FunctionCall &);
+               virtual void visit(ProgramSyntax::FunctionDeclaration &);
+       };
+
        struct InterfaceGenerator: Visitor
        {
                std::string in_prefix;
@@ -207,6 +215,18 @@ private:
                virtual void visit(ProgramSyntax::Iteration &);
        };
 
+       struct UnusedFunctionLocator: Visitor
+       {
+               typedef std::set<ProgramSyntax::Node *> ResultType;
+
+               std::set<ProgramSyntax::Node *> unused_nodes;
+               std::set<ProgramSyntax::FunctionDeclaration *> used_definitions;
+
+               const ResultType &get_result() const { return unused_nodes; }
+               virtual void visit(ProgramSyntax::FunctionCall &);
+               virtual void visit(ProgramSyntax::FunctionDeclaration &);
+       };
+
        struct NodeRemover: Visitor
        {
                std::set<ProgramSyntax::Node *> to_remove;
index f87488dc7a2b530a56c38841965430c0973f5738..098130f87c2e4920597eadb2838295b782dbf740 100644 (file)
@@ -72,6 +72,7 @@ void Assignment::visit(NodeVisitor &visitor)
 
 
 FunctionCall::FunctionCall():
+       declaration(0),
        constructor(false)
 { }
 
index 9545760c47b31bd8cfa98f61ee59ef626d2d851c..089683323c507b81573b0c908163f9b28337de7d 100644 (file)
@@ -52,6 +52,7 @@ public:
 
 struct StructDeclaration;
 struct VariableDeclaration;
+struct FunctionDeclaration;
 
 struct Block: Node
 {
@@ -145,6 +146,7 @@ struct Assignment: BinaryExpression
 struct FunctionCall: Expression
 {
        std::string name;
+       FunctionDeclaration *declaration;
        bool constructor;
        std::vector<NodePtr<Expression> > arguments;