X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fprogramcompiler.cpp;h=4e4b4814f171b531bfffedea17c9b9d46101fab1;hb=ced18c244f874638dc17ae486802bb3bb01ecf71;hp=86ea8da93d7e6866590a563c150555393903cafe;hpb=57c1139e4fe21aeca7118b18eb3ba6fa43d7bf90;p=libs%2Fgl.git diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index 86ea8da9..4e4b4814 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); @@ -450,6 +452,12 @@ void ProgramCompiler::Formatter::visit(Return &ret) formatted += ';'; } +void ProgramCompiler::Formatter::visit(Jump &jump) +{ + formatted += jump.keyword; + formatted += ';'; +} + ProgramCompiler::DeclarationCombiner::DeclarationCombiner(): toplevel(true), @@ -919,6 +927,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), @@ -1063,7 +1212,8 @@ void ProgramCompiler::ConstantConditionEliminator::visit(Iteration &iter) ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator(): aggregate(0), assignment(0), - assignment_target(false) + assignment_target(false), + iteration(false) { } void ProgramCompiler::UnusedVariableLocator::apply(Stage &s) @@ -1084,6 +1234,9 @@ void ProgramCompiler::UnusedVariableLocator::visit(VariableReference &var) if(assignment_target) return; + if(iteration) + used_in_iteration.insert(var.declaration); + for(vector::iterator j=assignments.end(); j!=assignments.begin(); ) { --j; @@ -1128,7 +1281,8 @@ void ProgramCompiler::UnusedVariableLocator::visit(Assignment &assign) void ProgramCompiler::UnusedVariableLocator::record_assignment(VariableDeclaration &var, Node &node, bool self_ref) { - unused_nodes.insert(&node); + if(!used_in_iteration.count(&var)) + unused_nodes.insert(&node); BlockAssignmentMap &block_assignments = assignments.back(); AssignmentList &var_assignments = block_assignments[&var]; if(!self_ref) @@ -1255,8 +1409,13 @@ void ProgramCompiler::UnusedVariableLocator::visit(Conditional &cond) void ProgramCompiler::UnusedVariableLocator::visit(Iteration &iter) { assignments.push_back(BlockAssignmentMap()); - TraversingVisitor::visit(iter); + { + SetFlag set(iteration); + TraversingVisitor::visit(iter); + } merge_down_assignments(); + if(!iteration) + used_in_iteration.clear(); }