X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fprogramcompiler.cpp;h=0e749c9736588ddaa5192d74a70fb9719dc16f05;hp=7224df1efba672d4afb7ecb12923a0109ae9f6f6;hb=6a045019fbd68738b77849629e6dfd3dfd9a4d93;hpb=00be85f53c5bec0be00a7ed6271e1f5a38e0b534 diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index 7224df1e..0e749c97 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -173,6 +173,9 @@ bool ProgramCompiler::optimize(Stage &stage) { apply(stage); + set inlineable = apply(stage); + apply(stage, inlineable); + set unused = apply(stage); set unused2 = apply(stage); unused.insert(unused2.begin(), unused2.end()); @@ -957,6 +960,108 @@ void ProgramCompiler::DeclarationReorderer::visit(Block &block) } +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 set(in_function, &func); + TraversingVisitor::visit(func); +} + + +ProgramCompiler::FunctionInliner::FunctionInliner(): + extract_result(0) +{ } + +ProgramCompiler::FunctionInliner::FunctionInliner(const set &in): + inlineable(in), + extract_result(0) +{ } + +void ProgramCompiler::FunctionInliner::visit_and_inline(RefPtr &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 >::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 >::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),