X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fprogramcompiler.cpp;h=0e749c9736588ddaa5192d74a70fb9719dc16f05;hb=0ab875bdc9fbf84ecfce883b188410bb45882447;hp=86ea8da93d7e6866590a563c150555393903cafe;hpb=57c1139e4fe21aeca7118b18eb3ba6fa43d7bf90;p=libs%2Fgl.git diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index 86ea8da9..0e749c97 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -165,14 +165,16 @@ void ProgramCompiler::generate(Stage &stage) apply(stage); apply(stage); apply(stage); + apply(stage); apply(stage); - apply(stage); } bool ProgramCompiler::optimize(Stage &stage) { apply(stage); - apply(stage); + + set inlineable = apply(stage); + apply(stage, inlineable); set unused = apply(stage); set unused2 = apply(stage); @@ -919,6 +921,147 @@ void ProgramCompiler::VariableRenamer::visit(VariableDeclaration &var) } +ProgramCompiler::DeclarationReorderer::DeclarationReorderer(): + kind(NO_DECLARATION) +{ } + +void ProgramCompiler::DeclarationReorderer::visit(Block &block) +{ + list >::iterator struct_insert_point = block.body.end(); + list >::iterator variable_insert_point = block.body.end(); + + for(list >::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 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),