X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fprogramcompiler.cpp;h=9b3266755b0b4f36c7bdc1ebe3471ebba48e8d40;hp=82a324dec52d8e7c9e92b8d8c56cb15264e423f3;hb=ba97b71564cadd322fe1bf3d8afe556b38ef0647;hpb=a0caabaed3aeb8947133d78986bfb4ae5ae3c893 diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index 82a324de..9b326675 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -167,6 +167,9 @@ void ProgramCompiler::generate(Stage &stage) bool ProgramCompiler::optimize(Stage &stage) { + apply(stage); + apply(stage); + set unused = apply(stage); apply(stage, unused); @@ -839,6 +842,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),