X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fprogramcompiler.cpp;h=937639a49157bf6f73cda381d306585e1c05b482;hb=f1c6ef565577ac322693255d764eea1f2cab9e77;hp=82a324dec52d8e7c9e92b8d8c56cb15264e423f3;hpb=a0caabaed3aeb8947133d78986bfb4ae5ae3c893;p=libs%2Fgl.git diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index 82a324de..937639a4 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -159,6 +159,7 @@ void ProgramCompiler::generate(Stage &stage) { inject_block(stage.content, module->shared.content); + apply(stage); apply(stage); apply(stage); apply(stage); @@ -167,7 +168,12 @@ void ProgramCompiler::generate(Stage &stage) bool ProgramCompiler::optimize(Stage &stage) { + apply(stage); + apply(stage); + set unused = apply(stage); + set unused2 = apply(stage); + unused.insert(unused2.begin(), unused2.end()); apply(stage, unused); return !unused.empty(); @@ -613,6 +619,34 @@ void ProgramCompiler::VariableResolver::visit(InterfaceBlock &iface) } +void ProgramCompiler::FunctionResolver::visit(FunctionCall &call) +{ + map >::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 &decls = functions[func.name]; + if(func.definition) + { + for(vector::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) @@ -839,6 +873,162 @@ void ProgramCompiler::VariableRenamer::visit(VariableDeclaration &var) } +ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(): + variable_values(0), + result(0.0f), + result_valid(false) +{ } + +ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(const ValueMap &v): + variable_values(&v), + result(0.0f), + result_valid(false) +{ } + +void ProgramCompiler::ExpressionEvaluator::visit(Literal &literal) +{ + if(literal.token=="true") + result = 1.0f; + else if(literal.token=="false") + result = 0.0f; + else + result = lexical_cast(literal.token); + result_valid = true; +} + +void ProgramCompiler::ExpressionEvaluator::visit(VariableReference &var) +{ + if(!var.declaration) + return; + + if(variable_values) + { + ValueMap::const_iterator i = variable_values->find(var.declaration); + if(i!=variable_values->end()) + i->second->visit(*this); + } + else if(var.declaration->init_expression) + var.declaration->init_expression->visit(*this); +} + +void ProgramCompiler::ExpressionEvaluator::visit(UnaryExpression &unary) +{ + result_valid = false; + unary.expression->visit(*this); + if(!result_valid) + return; + + if(unary.oper=="!") + result = !result; + else + result_valid = false; +} + +void ProgramCompiler::ExpressionEvaluator::visit(BinaryExpression &binary) +{ + result_valid = false; + binary.left->visit(*this); + if(!result_valid) + return; + + float left_result = result; + result_valid = false; + binary.right->visit(*this); + if(!result_valid) + return; + + if(binary.oper=="<") + result = (left_result") + result = (left_result>result); + else if(binary.oper==">=") + result = (left_result>=result); + else if(binary.oper=="==") + result = (left_result==result); + else if(binary.oper=="!=") + result = (left_result!=result); + else if(binary.oper=="&&") + result = (left_result && result); + else if(binary.oper=="||") + result = (left_result || result); + else + result_valid = false; +} + + +ProgramCompiler::ConstantConditionEliminator::ConstantConditionEliminator(): + scope_level(0), + remove_node(false), + replacement_block(0) +{ } + +void ProgramCompiler::ConstantConditionEliminator::visit(Block &block) +{ + SetForScope set(scope_level, scope_level+1); + for(list >::iterator i=block.body.begin(); i!=block.body.end(); ) + { + (*i)->visit(*this); + if(replacement_block) + { + for(list >::iterator j=replacement_block->body.begin(); j!=replacement_block->body.end(); ++j) + block.body.insert(i, *j); + replacement_block = 0; + } + + if(remove_node) + block.body.erase(i++); + else + ++i; + remove_node = false; + } + + for(map::const_iterator i=block.variables.begin(); i!=block.variables.end(); ++i) + variable_values.erase(i->second); +} + +void ProgramCompiler::ConstantConditionEliminator::visit(Assignment &assign) +{ + variable_values.erase(assign.target_declaration); +} + +void ProgramCompiler::ConstantConditionEliminator::visit(VariableDeclaration &var) +{ + if(var.constant || scope_level>1) + variable_values[&var] = &*var.init_expression; +} + +void ProgramCompiler::ConstantConditionEliminator::visit(Conditional &cond) +{ + ExpressionEvaluator eval(variable_values); + cond.condition->visit(eval); + if(eval.result_valid) + { + remove_node = true; + replacement_block = (eval.result ? &cond.body : &cond.else_body); + } + else + TraversingVisitor::visit(cond); +} + +void ProgramCompiler::ConstantConditionEliminator::visit(Iteration &iter) +{ + if(iter.condition) + { + ExpressionEvaluator eval; + iter.condition->visit(eval); + if(eval.result_valid && !eval.result) + { + remove_node = true; + return; + } + } + + TraversingVisitor::visit(iter); +} + + ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator(): aggregate(0), assignment(0), @@ -1039,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 &r): to_remove(r) { }