apply<InterfaceGenerator>(stage);
apply<VariableResolver>(stage);
apply<VariableRenamer>(stage);
+ apply<DeclarationReorderer>(stage);
apply<LegacyConverter>(stage);
}
{
apply<ConstantConditionEliminator>(stage);
+ set<FunctionDeclaration *> inlineable = apply<InlineableFunctionLocator>(stage);
+ apply<FunctionInliner>(stage, inlineable);
+
set<Node *> unused = apply<UnusedVariableLocator>(stage);
set<Node *> unused2 = apply<UnusedFunctionLocator>(stage);
unused.insert(unused2.begin(), unused2.end());
formatted += ';';
}
+void ProgramCompiler::Formatter::visit(Jump &jump)
+{
+ formatted += jump.keyword;
+ formatted += ';';
+}
+
ProgramCompiler::DeclarationCombiner::DeclarationCombiner():
toplevel(true),
}
+ProgramCompiler::DeclarationReorderer::DeclarationReorderer():
+ kind(NO_DECLARATION)
+{ }
+
+void ProgramCompiler::DeclarationReorderer::visit(Block &block)
+{
+ list<RefPtr<Node> >::iterator struct_insert_point = block.body.end();
+ list<RefPtr<Node> >::iterator variable_insert_point = block.body.end();
+
+ for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
+ {
+ kind = NO_DECLARATION;
+ (*i)->visit(*this);
+
+ bool moved = false;
+ if(kind==STRUCT && struct_insert_point!=block.body.end())
+ {
+ block.body.insert(struct_insert_point, *i);
+ moved = true;
+ }
+ else if(kind>STRUCT && struct_insert_point==block.body.end())
+ struct_insert_point = i;
+
+ if(kind==VARIABLE && variable_insert_point!=block.body.end())
+ {
+ block.body.insert(variable_insert_point, *i);
+ moved = true;
+ }
+ else if(kind>VARIABLE && variable_insert_point==block.body.end())
+ variable_insert_point = i;
+
+ if(moved)
+ block.body.erase(i++);
+ else
+ ++i;
+ }
+}
+
+
+ProgramCompiler::InlineableFunctionLocator::InlineableFunctionLocator():
+ in_function(0)
+{ }
+
+void ProgramCompiler::InlineableFunctionLocator::visit(FunctionCall &call)
+{
+ FunctionDeclaration *def = call.declaration;
+ if(def && def->definition!=def)
+ def = def->definition;
+
+ if(def)
+ {
+ unsigned &count = refcounts[def];
+ ++count;
+ if(count>1 || def==in_function)
+ inlineable.erase(def);
+ }
+
+ TraversingVisitor::visit(call);
+}
+
+void ProgramCompiler::InlineableFunctionLocator::visit(FunctionDeclaration &func)
+{
+ unsigned &count = refcounts[func.definition];
+ if(!count && func.parameters.empty())
+ inlineable.insert(func.definition);
+
+ SetForScope<FunctionDeclaration *> set(in_function, &func);
+ TraversingVisitor::visit(func);
+}
+
+
+ProgramCompiler::FunctionInliner::FunctionInliner():
+ extract_result(0)
+{ }
+
+ProgramCompiler::FunctionInliner::FunctionInliner(const set<FunctionDeclaration *> &in):
+ inlineable(in),
+ extract_result(0)
+{ }
+
+void ProgramCompiler::FunctionInliner::visit_and_inline(RefPtr<Expression> &ptr)
+{
+ inline_result = 0;
+ ptr->visit(*this);
+ if(inline_result)
+ ptr = inline_result;
+}
+
+void ProgramCompiler::FunctionInliner::visit(Block &block)
+{
+ if(extract_result)
+ --extract_result;
+
+ for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
+ {
+ (*i)->visit(*this);
+ if(extract_result)
+ --extract_result;
+ }
+}
+
+void ProgramCompiler::FunctionInliner::visit(UnaryExpression &unary)
+{
+ visit_and_inline(unary.expression);
+ inline_result = 0;
+}
+
+void ProgramCompiler::FunctionInliner::visit(BinaryExpression &binary)
+{
+ visit_and_inline(binary.left);
+ visit_and_inline(binary.right);
+ inline_result = 0;
+}
+
+void ProgramCompiler::FunctionInliner::visit(FunctionCall &call)
+{
+ for(vector<RefPtr<Expression> >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
+ visit_and_inline(*i);
+
+ FunctionDeclaration *def = call.declaration;
+ if(def && def->definition!=def)
+ def = def->definition;
+
+ if(def && inlineable.count(def))
+ {
+ extract_result = 2;
+ def->visit(*this);
+ }
+ else
+ inline_result = 0;
+}
+
+void ProgramCompiler::FunctionInliner::visit(Return &ret)
+{
+ TraversingVisitor::visit(ret);
+
+ if(extract_result)
+ inline_result = ret.expression->clone();
+}
+
+
ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator():
variable_values(0),
result(0.0f),
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);
+ for(vector<Node *>::iterator j=i->second.assignments.begin(); j!=i->second.assignments.end(); ++j)
+ unused_nodes.insert(*j);
+ }
+ }
+ 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;
}
}
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;
+ var_info.assignments.clear();
+ var_info.assignments.push_back(&node);
+ var_info.conditionally_assigned = false;
}
void ProgramCompiler::UnusedVariableLocator::visit(ExpressionStatement &expr)
aggregates[&var] = aggregate;
else
{
- unused_nodes.insert(&var);
+ variables.back()[&var].local = true;
if(var.init_expression)
record_assignment(var, *var.init_expression, false);
}
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;
+ 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);
+ for(vector<Node *>::iterator j=i->second.assignments.begin(); j!=i->second.assignments.end(); ++j)
+ unused_nodes.insert(*j);
+ 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.conditionally_assigned)
+ {
+ j->second.assignments.clear();
+ j->second.conditionally_assigned = true;
+ }
+ 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);