]> git.tdb.fi Git - libs/gl.git/blob - source/programcompiler.cpp
88ec6e59d88054480457be91cd0da9e14f201f02
[libs/gl.git] / source / programcompiler.cpp
1 #include <msp/core/raii.h>
2 #include <msp/gl/extensions/ext_gpu_shader4.h>
3 #include <msp/strings/format.h>
4 #include <msp/strings/utils.h>
5 #include "error.h"
6 #include "program.h"
7 #include "programcompiler.h"
8 #include "resources.h"
9 #include "shader.h"
10
11 using namespace std;
12
13 namespace {
14
15 const char builtins_src[] =
16         "#pragma MSP stage(vertex)\n"
17         "out gl_PerVertex {\n"
18         "  vec4 gl_Position;\n"
19         "  float gl_ClipDistance[];\n"
20         "};\n"
21         "#pragma MSP stage(geometry)\n"
22         "in gl_PerVertex {\n"
23         "  vec4 gl_Position;\n"
24         "  float gl_ClipDistance[];\n"
25         "} gl_in[];\n"
26         "out gl_PerVertex {\n"
27         "  vec4 gl_Position;\n"
28         "  float gl_ClipDistance[];\n"
29         "};\n";
30
31 }
32
33 namespace Msp {
34 namespace GL {
35
36 using namespace ProgramSyntax;
37
38 ProgramCompiler::ProgramCompiler():
39         resources(0),
40         module(0)
41 { }
42
43 ProgramCompiler::~ProgramCompiler()
44 {
45         delete module;
46 }
47
48 void ProgramCompiler::compile(const string &source, const string &src_name)
49 {
50         resources = 0;
51         delete module;
52         module = new Module();
53         ProgramParser parser;
54         imported_names.insert(src_name);
55         append_module(parser.parse(source, src_name));
56         process();
57 }
58
59 void ProgramCompiler::compile(IO::Base &io, Resources *res, const string &src_name)
60 {
61         resources = res;
62         delete module;
63         module = new Module();
64         ProgramParser parser;
65         imported_names.insert(src_name);
66         append_module(parser.parse(io, src_name));
67         process();
68 }
69
70 void ProgramCompiler::compile(IO::Base &io, const string &src_name)
71 {
72         compile(io, 0, src_name);
73 }
74
75 void ProgramCompiler::add_shaders(Program &program)
76 {
77         if(!module)
78                 throw invalid_operation("ProgramCompiler::add_shaders");
79
80         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
81         {
82                 if(i->type==VERTEX)
83                 {
84                         program.attach_shader_owned(new VertexShader(apply<Formatter>(*i)));
85                         for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
86                                 program.bind_attribute(j->second, j->first);
87                 }
88                 else if(i->type==GEOMETRY)
89                         program.attach_shader_owned(new GeometryShader(apply<Formatter>(*i)));
90                 else if(i->type==FRAGMENT)
91                 {
92                         program.attach_shader_owned(new FragmentShader(apply<Formatter>(*i)));
93                         if(EXT_gpu_shader4)
94                         {
95                                 for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
96                                         program.bind_fragment_data(j->second, j->first);
97                         }
98                 }
99         }
100 }
101
102 Module *ProgramCompiler::create_builtins_module()
103 {
104         ProgramParser parser;
105         Module *module = new Module(parser.parse(builtins_src, "<builtin>"));
106         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
107         {
108                 VariableResolver resolver;
109                 i->content.visit(resolver);
110                 for(map<string, VariableDeclaration *>::iterator j=i->content.variables.begin(); j!=i->content.variables.end(); ++j)
111                         j->second->linked_declaration = j->second;
112         }
113         return module;
114 }
115
116 Module &ProgramCompiler::get_builtins_module()
117 {
118         static RefPtr<Module> builtins_module = create_builtins_module();
119         return *builtins_module;
120 }
121
122 Stage *ProgramCompiler::get_builtins(StageType type)
123 {
124         Module &module = get_builtins_module();
125         for(list<Stage>::iterator i=module.stages.begin(); i!=module.stages.end(); ++i)
126                 if(i->type==type)
127                         return &*i;
128         return 0;
129 }
130
131 void ProgramCompiler::append_module(ProgramSyntax::Module &mod)
132 {
133         vector<Import *> imports = apply<NodeGatherer<Import> >(mod.shared);
134         for(vector<Import *>::iterator i=imports.begin(); i!=imports.end(); ++i)
135                 import((*i)->module);
136         apply<NodeRemover>(mod.shared, set<Node *>(imports.begin(), imports.end()));
137
138         append_stage(mod.shared);
139         for(list<Stage>::iterator i=mod.stages.begin(); i!=mod.stages.end(); ++i)
140                 append_stage(*i);
141 }
142
143 void ProgramCompiler::append_stage(Stage &stage)
144 {
145         Stage *target = 0;
146         if(stage.type==SHARED)
147                 target = &module->shared;
148         else
149         {
150                 list<Stage>::iterator i;
151                 for(i=module->stages.begin(); (i!=module->stages.end() && i->type<stage.type); ++i) ;
152                 if(i==module->stages.end() || i->type>stage.type)
153                 {
154                         list<Stage>::iterator j = module->stages.insert(i, stage.type);
155                         if(i!=module->stages.end())
156                                 i->previous = &*j;
157                         i = j;
158                         if(i!=module->stages.begin())
159                                 i->previous = &*--j;
160                 }
161
162                 target = &*i;
163         }
164
165         for(NodeList<Node>::iterator i=stage.content.body.begin(); i!=stage.content.body.end(); ++i)
166                 target->content.body.push_back(*i);
167         apply<DeclarationCombiner>(*target);
168 }
169
170 void ProgramCompiler::process()
171 {
172         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
173                 generate(*i);
174         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); )
175         {
176                 if(optimize(*i))
177                         i = module->stages.begin();
178                 else
179                         ++i;
180         }
181         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
182                 finalize(*i);
183 }
184
185 void ProgramCompiler::import(const string &name)
186 {
187         string fn = name+".glsl";
188         if(imported_names.count(fn))
189                 return;
190         imported_names.insert(fn);
191
192         RefPtr<IO::Seekable> io = (resources ? resources->open_raw(fn) : Resources::get_builtins().open(fn));
193         if(!io)
194                 throw runtime_error(format("module %s not found", name));
195         ProgramParser import_parser;
196         append_module(import_parser.parse(*io, fn));
197 }
198
199 void ProgramCompiler::generate(Stage &stage)
200 {
201         inject_block(stage.content, module->shared.content);
202
203         apply<DeclarationReorderer>(stage);
204         apply<FunctionResolver>(stage);
205         apply<VariableResolver>(stage);
206         apply<InterfaceGenerator>(stage);
207         apply<VariableResolver>(stage);
208         apply<DeclarationReorderer>(stage);
209         apply<FunctionResolver>(stage);
210         apply<LegacyConverter>(stage);
211 }
212
213 bool ProgramCompiler::optimize(Stage &stage)
214 {
215         apply<ConstantConditionEliminator>(stage);
216
217         set<FunctionDeclaration *> inlineable = apply<InlineableFunctionLocator>(stage);
218         apply<FunctionInliner>(stage, inlineable);
219
220         set<Node *> unused = apply<UnusedVariableLocator>(stage);
221         set<Node *> unused2 = apply<UnusedFunctionLocator>(stage);
222         unused.insert(unused2.begin(), unused2.end());
223         apply<NodeRemover>(stage, unused);
224
225         return !unused.empty();
226 }
227
228 void ProgramCompiler::finalize(Stage &stage)
229 {
230         if(get_gl_api()==OPENGL_ES2)
231                 apply<DefaultPrecisionGenerator>(stage);
232         else
233                 apply<PrecisionRemover>(stage);
234 }
235
236 void ProgramCompiler::inject_block(Block &target, const Block &source)
237 {
238         list<RefPtr<Node> >::iterator insert_point = target.body.begin();
239         for(list<RefPtr<Node> >::const_iterator i=source.body.begin(); i!=source.body.end(); ++i)
240                 target.body.insert(insert_point, (*i)->clone());
241 }
242
243 template<typename T>
244 typename T::ResultType ProgramCompiler::apply(Stage &stage)
245 {
246         T visitor;
247         visitor.apply(stage);
248         return visitor.get_result();
249 }
250
251 template<typename T, typename A>
252 typename T::ResultType ProgramCompiler::apply(Stage &stage, const A &arg)
253 {
254         T visitor(arg);
255         visitor.apply(stage);
256         return visitor.get_result();
257 }
258
259
260 ProgramCompiler::Visitor::Visitor():
261         stage(0)
262 { }
263
264 void ProgramCompiler::Visitor::apply(Stage &s)
265 {
266         SetForScope<Stage *> set(stage, &s);
267         stage->content.visit(*this);
268 }
269
270
271 ProgramCompiler::BlockModifier::BlockModifier():
272         remove_node(false)
273 { }
274
275 void ProgramCompiler::BlockModifier::flatten_block(Block &block)
276 {
277         insert_nodes.insert(insert_nodes.end(), block.body.begin(), block.body.end());
278         remove_node = true;
279 }
280
281 void ProgramCompiler::BlockModifier::apply_and_increment(Block &block, list<RefPtr<Node> >::iterator &i)
282 {
283         block.body.insert(i, insert_nodes.begin(), insert_nodes.end());
284         insert_nodes.clear();
285
286         if(remove_node)
287                 block.body.erase(i++);
288         else
289                 ++i;
290         remove_node = false;
291 }
292
293 void ProgramCompiler::BlockModifier::visit(Block &block)
294 {
295         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
296         {
297                 (*i)->visit(*this);
298                 apply_and_increment(block, i);
299         }
300 }
301
302
303 ProgramCompiler::Formatter::Formatter():
304         indent(0),
305         parameter_list(false),
306         else_if(0)
307 { }
308
309 void ProgramCompiler::Formatter::apply(ProgramSyntax::Stage &s)
310 {
311         GLApi api = get_gl_api();
312         const Version &ver = s.required_version;
313
314         if(ver)
315         {
316                 formatted += format("#version %d%02d", ver.major, ver.minor);
317                 if(api==OPENGL_ES2 && ver>=Version(3, 0))
318                         formatted += " es";
319                 formatted += '\n';
320         }
321
322         Visitor::apply(s);
323 }
324
325 void ProgramCompiler::Formatter::visit(Literal &literal)
326 {
327         formatted += literal.token;
328 }
329
330 void ProgramCompiler::Formatter::visit(ParenthesizedExpression &parexpr)
331 {
332         formatted += '(';
333         parexpr.expression->visit(*this);
334         formatted += ')';
335 }
336
337 void ProgramCompiler::Formatter::visit(VariableReference &var)
338 {
339         formatted += var.name;
340 }
341
342 void ProgramCompiler::Formatter::visit(MemberAccess &memacc)
343 {
344         memacc.left->visit(*this);
345         formatted += format(".%s", memacc.member);
346 }
347
348 void ProgramCompiler::Formatter::visit(UnaryExpression &unary)
349 {
350         if(unary.prefix)
351                 formatted += unary.oper;
352         unary.expression->visit(*this);
353         if(!unary.prefix)
354                 formatted += unary.oper;
355 }
356
357 void ProgramCompiler::Formatter::visit(BinaryExpression &binary)
358 {
359         binary.left->visit(*this);
360         formatted += binary.oper;
361         binary.right->visit(*this);
362         formatted += binary.after;
363 }
364
365 void ProgramCompiler::Formatter::visit(Assignment &assign)
366 {
367         assign.left->visit(*this);
368         formatted += format(" %s ", assign.oper);
369         assign.right->visit(*this);
370 }
371
372 void ProgramCompiler::Formatter::visit(FunctionCall &call)
373 {
374         formatted += format("%s(", call.name);
375         for(vector<RefPtr<Expression> >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
376         {
377                 if(i!=call.arguments.begin())
378                         formatted += ", ";
379                 (*i)->visit(*this);
380         }
381         formatted += ')';
382 }
383
384 void ProgramCompiler::Formatter::visit(ExpressionStatement &expr)
385 {
386         expr.expression->visit(*this);
387         formatted += ';';
388 }
389
390 void ProgramCompiler::Formatter::visit(Block &block)
391 {
392         if(else_if)
393                 --else_if;
394
395         unsigned brace_indent = indent;
396         bool use_braces = (block.use_braces || (indent && block.body.size()!=1));
397         if(use_braces)
398                 formatted += format("%s{\n", string(brace_indent*2, ' '));
399
400         SetForScope<unsigned> set(indent, indent+(indent>0 || use_braces));
401         string spaces(indent*2, ' ');
402         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
403         {
404                 if(i!=block.body.begin())
405                         formatted += '\n';
406                 formatted += spaces;
407                 (*i)->visit(*this);
408                 else_if = 0;
409         }
410
411         if(use_braces)
412                 formatted += format("\n%s}", string(brace_indent*2, ' '));
413 }
414
415 void ProgramCompiler::Formatter::visit(Import &import)
416 {
417         formatted += format("import %s;", import.module);
418 }
419
420 void ProgramCompiler::Formatter::visit(Precision &prec)
421 {
422         formatted += format("precision %s %s;", prec.precision, prec.type);
423 }
424
425 void ProgramCompiler::Formatter::visit(Layout &layout)
426 {
427         formatted += "layout(";
428         for(vector<Layout::Qualifier>::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i)
429         {
430                 if(i!=layout.qualifiers.begin())
431                         formatted += ", ";
432                 formatted += i->identifier;
433                 if(!i->value.empty())
434                         formatted += format("=%s", i->value);
435         }
436         formatted += ')';
437 }
438
439 void ProgramCompiler::Formatter::visit(InterfaceLayout &layout)
440 {
441         layout.layout.visit(*this);
442         formatted += format(" %s;", layout.interface);
443 }
444
445 void ProgramCompiler::Formatter::visit(StructDeclaration &strct)
446 {
447         formatted += format("struct %s\n", strct.name);
448         strct.members.visit(*this);
449         formatted += ';';
450 }
451
452 void ProgramCompiler::Formatter::visit(VariableDeclaration &var)
453 {
454         if(var.layout)
455         {
456                 var.layout->visit(*this);
457                 formatted += ' ';
458         }
459         if(var.constant)
460                 formatted += "const ";
461         if(!var.interpolation.empty())
462                 formatted += format("%s ", var.interpolation);
463         if(!var.sampling.empty())
464                 formatted += format("%s ", var.sampling);
465         if(!var.interface.empty() && var.interface!=block_interface)
466         {
467                 string interface = var.interface;
468                 if(stage->required_version<Version(1, 30))
469                 {
470                         if(stage->type==VERTEX && var.interface=="in")
471                                 interface = "attribute";
472                         else if((stage->type==VERTEX && var.interface=="out") || (stage->type==FRAGMENT && var.interface=="in"))
473                                 interface = "varying";
474                 }
475                 formatted += format("%s ", interface);
476         }
477         if(!var.precision.empty())
478                 formatted += format("%s ", var.precision);
479         formatted += format("%s %s", var.type, var.name);
480         if(var.array)
481         {
482                 formatted += '[';
483                 if(var.array_size)
484                         var.array_size->visit(*this);
485                 formatted += ']';
486         }
487         if(var.init_expression)
488         {
489                 formatted += " = ";
490                 var.init_expression->visit(*this);
491         }
492         if(!parameter_list)
493                 formatted += ';';
494 }
495
496 void ProgramCompiler::Formatter::visit(InterfaceBlock &iface)
497 {
498         SetForScope<string> set(block_interface, iface.interface);
499         formatted += format("%s %s\n", iface.interface, iface.name);
500         iface.members.visit(*this);
501         formatted += ';';
502 }
503
504 void ProgramCompiler::Formatter::visit(FunctionDeclaration &func)
505 {
506         formatted += format("%s %s(", func.return_type, func.name);
507         for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
508         {
509                 if(i!=func.parameters.begin())
510                         formatted += ", ";
511                 SetFlag set(parameter_list);
512                 (*i)->visit(*this);
513         }
514         formatted += ')';
515         if(func.definition==&func)
516         {
517                 formatted += '\n';
518                 func.body.visit(*this);
519         }
520         else
521                 formatted += ';';
522 }
523
524 void ProgramCompiler::Formatter::visit(Conditional &cond)
525 {
526         if(else_if)
527                 formatted.replace(formatted.rfind('\n'), string::npos, 1, ' ');
528
529         indent -= else_if;
530
531         formatted += "if(";
532         cond.condition->visit(*this);
533         formatted += ")\n";
534
535         cond.body.visit(*this);
536         if(!cond.else_body.body.empty())
537         {
538                 formatted += format("\n%selse\n", string(indent*2, ' '));
539                 SetForScope<unsigned> set(else_if, 2);
540                 cond.else_body.visit(*this);
541         }
542 }
543
544 void ProgramCompiler::Formatter::visit(Iteration &iter)
545 {
546         formatted += "for(";
547         if(iter.init_statement)
548                 iter.init_statement->visit(*this);
549         else
550                 formatted += ';';
551         if(iter.condition)
552         {
553                 formatted += ' ';
554                 iter.condition->visit(*this);
555         }
556         formatted += ';';
557         if(iter.loop_expression)
558         {
559                 formatted += ' ';
560                 iter.loop_expression->visit(*this);
561         }
562         formatted += ')';
563         iter.body.visit(*this);
564 }
565
566 void ProgramCompiler::Formatter::visit(Return &ret)
567 {
568         formatted += "return";
569         if(ret.expression)
570         {
571                 formatted += ' ';
572                 ret.expression->visit(*this);
573         }
574         formatted += ';';
575 }
576
577 void ProgramCompiler::Formatter::visit(Jump &jump)
578 {
579         formatted += jump.keyword;
580         formatted += ';';
581 }
582
583
584 ProgramCompiler::DeclarationCombiner::DeclarationCombiner():
585         toplevel(true)
586 { }
587
588 void ProgramCompiler::DeclarationCombiner::visit(Block &block)
589 {
590         if(!toplevel)
591                 return;
592
593         SetForScope<bool> set(toplevel, false);
594         BlockModifier::visit(block);
595 }
596
597 void ProgramCompiler::DeclarationCombiner::visit(FunctionDeclaration &func)
598 {
599         vector<FunctionDeclaration *> &decls = functions[func.name];
600         if(func.definition)
601         {
602                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
603                 {
604                         (*i)->definition = func.definition;
605                         (*i)->body.body.clear();
606                 }
607         }
608         decls.push_back(&func);
609 }
610
611 void ProgramCompiler::DeclarationCombiner::visit(VariableDeclaration &var)
612 {
613         VariableDeclaration *&ptr = variables[var.name];
614         if(ptr)
615         {
616                 ptr->type = var.type;
617                 if(var.init_expression)
618                         ptr->init_expression = var.init_expression;
619                 remove_node = true;
620         }
621         else
622                 ptr = &var;
623 }
624
625
626 ProgramCompiler::VariableResolver::VariableResolver():
627         anonymous(false),
628         record_target(false),
629         assignment_target(0),
630         self_referencing(false)
631 { }
632
633 void ProgramCompiler::VariableResolver::apply(Stage &s)
634 {
635         SetForScope<Stage *> set(stage, &s);
636         Stage *builtins = get_builtins(stage->type);
637         if(builtins)
638                 blocks.push_back(&builtins->content);
639         stage->content.visit(*this);
640         if(builtins)
641                 blocks.pop_back();
642 }
643
644 void ProgramCompiler::VariableResolver::visit(Block &block)
645 {
646         blocks.push_back(&block);
647         block.variables.clear();
648         TraversingVisitor::visit(block);
649         blocks.pop_back();
650 }
651
652 void ProgramCompiler::VariableResolver::visit(VariableReference &var)
653 {
654         var.declaration = 0;
655         type = 0;
656         for(vector<Block *>::iterator i=blocks.end(); i!=blocks.begin(); )
657         {
658                 --i;
659                 map<string, VariableDeclaration *>::iterator j = (*i)->variables.find(var.name);
660                 if(j!=(*i)->variables.end())
661                 {
662                         var.declaration = j->second;
663                         type = j->second->type_declaration;
664                         break;
665                 }
666         }
667
668         if(record_target)
669         {
670                 if(assignment_target)
671                 {
672                         record_target = false;
673                         assignment_target = 0;
674                 }
675                 else
676                         assignment_target = var.declaration;
677         }
678         else if(var.declaration && var.declaration==assignment_target)
679                 self_referencing = true;
680 }
681
682 void ProgramCompiler::VariableResolver::visit(MemberAccess &memacc)
683 {
684         type = 0;
685         TraversingVisitor::visit(memacc);
686         memacc.declaration = 0;
687         if(type)
688         {
689                 map<string, VariableDeclaration *>::iterator i = type->members.variables.find(memacc.member);
690                 if(i!=type->members.variables.end())
691                 {
692                         memacc.declaration = i->second;
693                         type = i->second->type_declaration;
694                 }
695                 else
696                         type = 0;
697         }
698 }
699
700 void ProgramCompiler::VariableResolver::visit(BinaryExpression &binary)
701 {
702         if(binary.oper=="[")
703         {
704                 {
705                         SetForScope<bool> set(record_target, false);
706                         binary.right->visit(*this);
707                 }
708                 type = 0;
709                 binary.left->visit(*this);
710         }
711         else
712         {
713                 TraversingVisitor::visit(binary);
714                 type = 0;
715         }
716 }
717
718 void ProgramCompiler::VariableResolver::visit(Assignment &assign)
719 {
720         {
721                 SetFlag set(record_target);
722                 assignment_target = 0;
723                 assign.left->visit(*this);
724         }
725
726         self_referencing = false;
727         assign.right->visit(*this);
728
729         assign.self_referencing = (self_referencing || assign.oper!="=");
730         assign.target_declaration = assignment_target;
731 }
732
733 void ProgramCompiler::VariableResolver::visit(StructDeclaration &strct)
734 {
735         TraversingVisitor::visit(strct);
736         blocks.back()->types[strct.name] = &strct;
737 }
738
739 void ProgramCompiler::VariableResolver::visit(VariableDeclaration &var)
740 {
741         for(vector<Block *>::iterator i=blocks.end(); i!=blocks.begin(); )
742         {
743                 --i;
744                 map<string, StructDeclaration *>::iterator j = (*i)->types.find(var.type);
745                 if(j!=(*i)->types.end())
746                         var.type_declaration = j->second;
747         }
748
749         if(!block_interface.empty() && var.interface.empty())
750                 var.interface = block_interface;
751
752         TraversingVisitor::visit(var);
753         blocks.back()->variables[var.name] = &var;
754         if(anonymous && blocks.size()>1)
755                 blocks[blocks.size()-2]->variables[var.name] = &var;
756 }
757
758 void ProgramCompiler::VariableResolver::visit(InterfaceBlock &iface)
759 {
760         SetFlag set(anonymous);
761         SetForScope<string> set2(block_interface, iface.interface);
762         TraversingVisitor::visit(iface);
763 }
764
765
766 void ProgramCompiler::FunctionResolver::visit(FunctionCall &call)
767 {
768         map<string, vector<FunctionDeclaration *> >::iterator i = functions.find(call.name);
769         if(i!=functions.end())
770                 call.declaration = i->second.back();
771
772         TraversingVisitor::visit(call);
773 }
774
775 void ProgramCompiler::FunctionResolver::visit(FunctionDeclaration &func)
776 {
777         vector<FunctionDeclaration *> &decls = functions[func.name];
778         if(func.definition)
779         {
780                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
781                         (*i)->definition = func.definition;
782                 decls.clear();
783                 decls.push_back(&func);
784         }
785         else if(!decls.empty() && decls.back()->definition)
786                 func.definition = decls.back()->definition;
787         else
788                 decls.push_back(&func);
789
790         TraversingVisitor::visit(func);
791 }
792
793
794 ProgramCompiler::InterfaceGenerator::InterfaceGenerator():
795         scope_level(0)
796 { }
797
798 string ProgramCompiler::InterfaceGenerator::get_out_prefix(StageType type)
799 {
800         if(type==VERTEX)
801                 return "_vs_out_";
802         else if(type==GEOMETRY)
803                 return "_gs_out_";
804         else
805                 return string();
806 }
807
808 void ProgramCompiler::InterfaceGenerator::apply(Stage &s)
809 {
810         SetForScope<Stage *> set(stage, &s);
811         if(stage->previous)
812                 in_prefix = get_out_prefix(stage->previous->type);
813         out_prefix = get_out_prefix(stage->type);
814         stage->content.visit(*this);
815 }
816
817 void ProgramCompiler::InterfaceGenerator::visit(Block &block)
818 {
819         SetForScope<unsigned> set(scope_level, scope_level+1);
820         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
821         {
822                 (*i)->visit(*this);
823
824                 if(scope_level==1)
825                 {
826                         for(map<string, RefPtr<VariableDeclaration> >::iterator j=iface_declarations.begin(); j!=iface_declarations.end(); ++j)
827                         {
828                                 list<RefPtr<Node> >::iterator k = block.body.insert(i, j->second);
829                                 (*k)->visit(*this);
830                         }
831                         iface_declarations.clear();
832                 }
833
834                 apply_and_increment(block, i);
835         }
836 }
837
838 string ProgramCompiler::InterfaceGenerator::change_prefix(const string &name, const string &prefix) const
839 {
840         unsigned offset = (name.compare(0, in_prefix.size(), in_prefix) ? 0 : in_prefix.size());
841         return prefix+name.substr(offset);
842 }
843
844 bool ProgramCompiler::InterfaceGenerator::generate_interface(VariableDeclaration &var, const string &iface, const string &name)
845 {
846         const map<string, VariableDeclaration *> &stage_vars = (iface=="in" ? stage->in_variables : stage->out_variables);
847         if(stage_vars.count(name) || iface_declarations.count(name))
848                 return false;
849
850         VariableDeclaration* iface_var = new VariableDeclaration;
851         iface_var->sampling = var.sampling;
852         iface_var->interface = iface;
853         iface_var->type = var.type;
854         iface_var->type_declaration = var.type_declaration;
855         iface_var->name = name;
856         if(stage->type==GEOMETRY)
857                 iface_var->array = ((var.array && var.interface!="in") || iface=="in");
858         else
859                 iface_var->array = var.array;
860         if(iface_var->array)
861                 iface_var->array_size = var.array_size;
862         if(iface=="in")
863                 iface_var->linked_declaration = &var;
864         iface_declarations[name] = iface_var;
865
866         return true;
867 }
868
869 void ProgramCompiler::InterfaceGenerator::insert_assignment(const string &left, ProgramSyntax::Expression *right)
870 {
871         Assignment *assign = new Assignment;
872         VariableReference *ref = new VariableReference;
873         ref->name = left;
874         assign->left = ref;
875         assign->oper = "=";
876         assign->right = right;
877
878         ExpressionStatement *stmt = new ExpressionStatement;
879         stmt->expression = assign;
880         stmt->visit(*this);
881         insert_nodes.push_back(stmt);
882 }
883
884 void ProgramCompiler::InterfaceGenerator::visit(VariableReference &var)
885 {
886         if(var.declaration || !stage->previous)
887                 return;
888         if(iface_declarations.count(var.name))
889                 return;
890
891         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
892         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
893         if(i==prev_out.end())
894                 i = prev_out.find(in_prefix+var.name);
895         if(i!=prev_out.end())
896         {
897                 generate_interface(*i->second, "in", i->second->name);
898                 var.name = i->second->name;
899         }
900 }
901
902 void ProgramCompiler::InterfaceGenerator::visit(VariableDeclaration &var)
903 {
904         if(var.interface=="out")
905         {
906                 if(scope_level==1)
907                         stage->out_variables[var.name] = &var;
908                 else if(generate_interface(var, "out", change_prefix(var.name, string())))
909                 {
910                         remove_node = true;
911                         if(var.init_expression)
912                         {
913                                 insert_assignment(var.name, var.init_expression->clone());
914                                 return;
915                         }
916                 }
917         }
918         else if(var.interface=="in")
919         {
920                 stage->in_variables[var.name] = &var;
921                 if(var.linked_declaration)
922                         var.linked_declaration->linked_declaration = &var;
923                 else if(stage->previous)
924                 {
925                         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
926                         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
927                         if(i!=prev_out.end())
928                         {
929                                 var.linked_declaration = i->second;
930                                 i->second->linked_declaration = &var;
931                         }
932                 }
933         }
934
935         TraversingVisitor::visit(var);
936 }
937
938 void ProgramCompiler::InterfaceGenerator::visit(Passthrough &pass)
939 {
940         vector<VariableDeclaration *> pass_vars;
941
942         for(map<string, VariableDeclaration *>::const_iterator i=stage->in_variables.begin(); i!=stage->in_variables.end(); ++i)
943                 pass_vars.push_back(i->second);
944         for(map<string, RefPtr<VariableDeclaration> >::const_iterator i=iface_declarations.begin(); i!=iface_declarations.end(); ++i)
945                 if(i->second->interface=="in")
946                         pass_vars.push_back(i->second.get());
947
948         if(stage->previous)
949         {
950                 const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
951                 for(map<string, VariableDeclaration *>::const_iterator i=prev_out.begin(); i!=prev_out.end(); ++i)
952                 {
953                         bool linked = false;
954                         for(vector<VariableDeclaration *>::const_iterator j=pass_vars.begin(); (!linked && j!=pass_vars.end()); ++j)
955                                 linked = ((*j)->linked_declaration==i->second);
956
957                         if(!linked && generate_interface(*i->second, "in", i->second->name))
958                                 pass_vars.push_back(i->second);
959                 }
960         }
961
962         if(stage->type==GEOMETRY)
963         {
964                 VariableReference *ref = new VariableReference;
965                 ref->name = "gl_in";
966
967                 BinaryExpression *subscript = new BinaryExpression;
968                 subscript->left = ref;
969                 subscript->oper = "[";
970                 subscript->right = pass.subscript;
971                 subscript->after = "]";
972
973                 MemberAccess *memacc = new MemberAccess;
974                 memacc->left = subscript;
975                 memacc->member = "gl_Position";
976
977                 insert_assignment("gl_Position", memacc);
978         }
979
980         for(vector<VariableDeclaration *>::const_iterator i=pass_vars.begin(); i!=pass_vars.end(); ++i)
981         {
982                 string out_name = change_prefix((*i)->name, out_prefix);
983                 generate_interface(**i, "out", out_name);
984
985                 VariableReference *ref = new VariableReference;
986                 ref->name = (*i)->name;
987                 if(pass.subscript)
988                 {
989                         BinaryExpression *subscript = new BinaryExpression;
990                         subscript->left = ref;
991                         subscript->oper = "[";
992                         subscript->right = pass.subscript;
993                         subscript->after = "]";
994                         insert_assignment(out_name, subscript);
995                 }
996                 else
997                         insert_assignment(out_name, ref);
998         }
999
1000         remove_node = true;
1001 }
1002
1003
1004 ProgramCompiler::DeclarationReorderer::DeclarationReorderer():
1005         scope_level(0),
1006         kind(NO_DECLARATION)
1007 { }
1008
1009 void ProgramCompiler::DeclarationReorderer::visit(FunctionCall &call)
1010 {
1011         FunctionDeclaration *def = call.declaration;
1012         if(def)
1013                 def = def->definition;
1014         if(def && !ordered_funcs.count(def))
1015                 needed_funcs.insert(def);
1016 }
1017
1018 void ProgramCompiler::DeclarationReorderer::visit(Block &block)
1019 {
1020         SetForScope<unsigned> set(scope_level, scope_level+1);
1021         if(scope_level>1)
1022                 return Visitor::visit(block);
1023
1024         list<RefPtr<Node> >::iterator struct_insert_point = block.body.end();
1025         list<RefPtr<Node> >::iterator variable_insert_point = block.body.end();
1026         list<RefPtr<Node> >::iterator function_insert_point = block.body.end();
1027         unsigned unordered_func_count = 0;
1028         bool ordered_any_funcs = false;
1029
1030         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
1031         {
1032                 kind = NO_DECLARATION;
1033                 (*i)->visit(*this);
1034
1035                 bool moved = false;
1036                 if(kind==STRUCT && struct_insert_point!=block.body.end())
1037                 {
1038                         block.body.insert(struct_insert_point, *i);
1039                         moved = true;
1040                 }
1041                 else if(kind>STRUCT && struct_insert_point==block.body.end())
1042                         struct_insert_point = i;
1043
1044                 if(kind==VARIABLE && variable_insert_point!=block.body.end())
1045                 {
1046                         block.body.insert(variable_insert_point, *i);
1047                         moved = true;
1048                 }
1049                 else if(kind>VARIABLE && variable_insert_point==block.body.end())
1050                         variable_insert_point = i;
1051
1052                 if(kind==FUNCTION)
1053                 {
1054                         if(function_insert_point==block.body.end())
1055                                 function_insert_point = i;
1056
1057                         if(needed_funcs.empty())
1058                         {
1059                                 ordered_funcs.insert(i->get());
1060                                 if(i!=function_insert_point)
1061                                 {
1062                                         block.body.insert(function_insert_point, *i);
1063                                         moved = true;
1064                                 }
1065                                 else
1066                                         ++function_insert_point;
1067                                 ordered_any_funcs = true;
1068                         }
1069                         else
1070                                 ++unordered_func_count;
1071                 }
1072
1073                 if(moved)
1074                 {
1075                         if(function_insert_point==i)
1076                                 ++function_insert_point;
1077                         block.body.erase(i++);
1078                 }
1079                 else
1080                         ++i;
1081
1082                 if(i==block.body.end() && unordered_func_count)
1083                 {
1084                         if(!ordered_any_funcs)
1085                                 // A subset of the remaining functions forms a recursive loop
1086                                 /* TODO pick a function and move it up, adding any necessary
1087                                 declarations */
1088                                 break;
1089
1090                         i = function_insert_point;
1091                         unordered_func_count = 0;
1092                 }
1093         }
1094 }
1095
1096 void ProgramCompiler::DeclarationReorderer::visit(ProgramSyntax::VariableDeclaration &var)
1097 {
1098         Visitor::visit(var);
1099         kind = VARIABLE;
1100 }
1101
1102 void ProgramCompiler::DeclarationReorderer::visit(FunctionDeclaration &func)
1103 {
1104         needed_funcs.clear();
1105         func.body.visit(*this);
1106         needed_funcs.erase(&func);
1107         kind = FUNCTION;
1108 }
1109
1110
1111 ProgramCompiler::InlineableFunctionLocator::InlineableFunctionLocator():
1112         in_function(0)
1113 { }
1114
1115 void ProgramCompiler::InlineableFunctionLocator::visit(FunctionCall &call)
1116 {
1117         FunctionDeclaration *def = call.declaration;
1118         if(def && def->definition!=def)
1119                 def = def->definition;
1120
1121         if(def)
1122         {
1123                 unsigned &count = refcounts[def];
1124                 ++count;
1125                 if(count>1 || def==in_function)
1126                         inlineable.erase(def);
1127         }
1128
1129         TraversingVisitor::visit(call);
1130 }
1131
1132 void ProgramCompiler::InlineableFunctionLocator::visit(FunctionDeclaration &func)
1133 {
1134         unsigned &count = refcounts[func.definition];
1135         if(!count && func.parameters.empty())
1136                 inlineable.insert(func.definition);
1137
1138         SetForScope<FunctionDeclaration *> set(in_function, &func);
1139         TraversingVisitor::visit(func);
1140 }
1141
1142
1143 ProgramCompiler::FunctionInliner::FunctionInliner():
1144         extract_result(0)
1145 { }
1146
1147 ProgramCompiler::FunctionInliner::FunctionInliner(const set<FunctionDeclaration *> &in):
1148         inlineable(in),
1149         extract_result(0)
1150 { }
1151
1152 void ProgramCompiler::FunctionInliner::visit_and_inline(RefPtr<Expression> &ptr)
1153 {
1154         inline_result = 0;
1155         ptr->visit(*this);
1156         if(inline_result)
1157                 ptr = inline_result;
1158 }
1159
1160 void ProgramCompiler::FunctionInliner::visit(Block &block)
1161 {
1162         if(extract_result)
1163                 --extract_result;
1164
1165         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
1166         {
1167                 (*i)->visit(*this);
1168                 if(extract_result)
1169                         --extract_result;
1170         }
1171 }
1172
1173 void ProgramCompiler::FunctionInliner::visit(UnaryExpression &unary)
1174 {
1175         visit_and_inline(unary.expression);
1176         inline_result = 0;
1177 }
1178
1179 void ProgramCompiler::FunctionInliner::visit(BinaryExpression &binary)
1180 {
1181         visit_and_inline(binary.left);
1182         visit_and_inline(binary.right);
1183         inline_result = 0;
1184 }
1185
1186 void ProgramCompiler::FunctionInliner::visit(MemberAccess &memacc)
1187 {
1188         visit_and_inline(memacc.left);
1189         inline_result = 0;
1190 }
1191
1192 void ProgramCompiler::FunctionInliner::visit(FunctionCall &call)
1193 {
1194         for(vector<RefPtr<Expression> >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
1195                 visit_and_inline(*i);
1196
1197         FunctionDeclaration *def = call.declaration;
1198         if(def && def->definition!=def)
1199                 def = def->definition;
1200
1201         if(def && inlineable.count(def))
1202         {
1203                 extract_result = 2;
1204                 def->visit(*this);
1205         }
1206         else
1207                 inline_result = 0;
1208 }
1209
1210 void ProgramCompiler::FunctionInliner::visit(Return &ret)
1211 {
1212         TraversingVisitor::visit(ret);
1213
1214         if(extract_result)
1215                 inline_result = ret.expression->clone();
1216 }
1217
1218
1219 ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator():
1220         variable_values(0),
1221         result(0.0f),
1222         result_valid(false)
1223 { }
1224
1225 ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(const ValueMap &v):
1226         variable_values(&v),
1227         result(0.0f),
1228         result_valid(false)
1229 { }
1230
1231 void ProgramCompiler::ExpressionEvaluator::visit(Literal &literal)
1232 {
1233         if(literal.token=="true")
1234                 result = 1.0f;
1235         else if(literal.token=="false")
1236                 result = 0.0f;
1237         else
1238                 result = lexical_cast<float>(literal.token);
1239         result_valid = true;
1240 }
1241
1242 void ProgramCompiler::ExpressionEvaluator::visit(ParenthesizedExpression &parexp)
1243 {
1244         parexp.expression->visit(*this);
1245 }
1246
1247 void ProgramCompiler::ExpressionEvaluator::visit(VariableReference &var)
1248 {
1249         if(!var.declaration)
1250                 return;
1251
1252         if(variable_values)
1253         {
1254                 ValueMap::const_iterator i = variable_values->find(var.declaration);
1255                 if(i!=variable_values->end())
1256                         i->second->visit(*this);
1257         }
1258         else if(var.declaration->init_expression)
1259                 var.declaration->init_expression->visit(*this);
1260 }
1261
1262 void ProgramCompiler::ExpressionEvaluator::visit(UnaryExpression &unary)
1263 {
1264         result_valid = false;
1265         unary.expression->visit(*this);
1266         if(!result_valid)
1267                 return;
1268
1269         if(unary.oper=="!")
1270                 result = !result;
1271         else
1272                 result_valid = false;
1273 }
1274
1275 void ProgramCompiler::ExpressionEvaluator::visit(BinaryExpression &binary)
1276 {
1277         result_valid = false;
1278         binary.left->visit(*this);
1279         if(!result_valid)
1280                 return;
1281
1282         float left_result = result;
1283         result_valid = false;
1284         binary.right->visit(*this);
1285         if(!result_valid)
1286                 return;
1287
1288         if(binary.oper=="<")
1289                 result = (left_result<result);
1290         else if(binary.oper=="<=")
1291                 result = (left_result<=result);
1292         else if(binary.oper==">")
1293                 result = (left_result>result);
1294         else if(binary.oper==">=")
1295                 result = (left_result>=result);
1296         else if(binary.oper=="==")
1297                 result = (left_result==result);
1298         else if(binary.oper=="!=")
1299                 result = (left_result!=result);
1300         else if(binary.oper=="&&")
1301                 result = (left_result && result);
1302         else if(binary.oper=="||")
1303                 result = (left_result || result);
1304         else
1305                 result_valid = false;
1306 }
1307
1308
1309 ProgramCompiler::ConstantConditionEliminator::ConstantConditionEliminator():
1310         scope_level(0),
1311         record_only(false)
1312 { }
1313
1314 void ProgramCompiler::ConstantConditionEliminator::visit(Block &block)
1315 {
1316         SetForScope<unsigned> set(scope_level, scope_level+1);
1317         BlockModifier::visit(block);
1318
1319         for(map<string, VariableDeclaration *>::const_iterator i=block.variables.begin(); i!=block.variables.end(); ++i)
1320                 variable_values.erase(i->second);
1321 }
1322
1323 void ProgramCompiler::ConstantConditionEliminator::visit(UnaryExpression &unary)
1324 {
1325         if(VariableReference *var = dynamic_cast<VariableReference *>(unary.expression.get()))
1326                 if(unary.oper=="++" || unary.oper=="--")
1327                         variable_values.erase(var->declaration);
1328 }
1329
1330 void ProgramCompiler::ConstantConditionEliminator::visit(Assignment &assign)
1331 {
1332         variable_values.erase(assign.target_declaration);
1333 }
1334
1335 void ProgramCompiler::ConstantConditionEliminator::visit(VariableDeclaration &var)
1336 {
1337         if(var.constant || scope_level>1)
1338                 variable_values[&var] = var.init_expression.get();
1339 }
1340
1341 void ProgramCompiler::ConstantConditionEliminator::visit(Conditional &cond)
1342 {
1343         if(!record_only)
1344         {
1345                 ExpressionEvaluator eval(variable_values);
1346                 cond.condition->visit(eval);
1347                 if(eval.result_valid)
1348                 {
1349                         flatten_block(eval.result ? cond.body : cond.else_body);
1350                         return;
1351                 }
1352         }
1353
1354         TraversingVisitor::visit(cond);
1355 }
1356
1357 void ProgramCompiler::ConstantConditionEliminator::visit(Iteration &iter)
1358 {
1359         if(!record_only)
1360         {
1361                 if(iter.condition)
1362                 {
1363                         /* If the loop condition is always false on the first iteration, the
1364                         entire loop can be removed */
1365                         if(iter.init_statement)
1366                                 iter.init_statement->visit(*this);
1367                         ExpressionEvaluator eval(variable_values);
1368                         iter.condition->visit(eval);
1369                         if(eval.result_valid && !eval.result)
1370                         {
1371                                 remove_node = true;
1372                                 return;
1373                         }
1374                 }
1375
1376                 /* Record all assignments that occur inside the loop body so those
1377                 variables won't be considered as constant */
1378                 SetFlag set_record(record_only);
1379                 TraversingVisitor::visit(iter);
1380         }
1381
1382         TraversingVisitor::visit(iter);
1383
1384         if(VariableDeclaration *init_decl = dynamic_cast<VariableDeclaration *>(iter.init_statement.get()))
1385                 variable_values.erase(init_decl);
1386 }
1387
1388
1389 ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator():
1390         aggregate(0),
1391         assignment(0),
1392         assignment_target(false),
1393         global_scope(true)
1394 { }
1395
1396 void ProgramCompiler::UnusedVariableLocator::apply(Stage &s)
1397 {
1398         variables.push_back(BlockVariableMap());
1399         Visitor::apply(s);
1400         BlockVariableMap &global_variables = variables.back();
1401         for(BlockVariableMap::iterator i=global_variables.begin(); i!=global_variables.end(); ++i)
1402         {
1403                 if(i->first->interface=="out" && (s.type==FRAGMENT || i->first->linked_declaration || !i->first->name.compare(0, 3, "gl_")))
1404                         continue;
1405                 if(!i->second.referenced)
1406                 {
1407                         unused_nodes.insert(i->first);
1408                         clear_assignments(i->second, true);
1409                 }
1410         }
1411         variables.pop_back();
1412 }
1413
1414 void ProgramCompiler::UnusedVariableLocator::visit(VariableReference &var)
1415 {
1416         map<VariableDeclaration *, Node *>::iterator i = aggregates.find(var.declaration);
1417         if(i!=aggregates.end())
1418                 unused_nodes.erase(i->second);
1419
1420         if(var.declaration && !assignment_target)
1421         {
1422                 VariableInfo &var_info = variables.back()[var.declaration];
1423                 var_info.assignments.clear();
1424                 var_info.referenced = true;
1425         }
1426 }
1427
1428 void ProgramCompiler::UnusedVariableLocator::visit(MemberAccess &memacc)
1429 {
1430         TraversingVisitor::visit(memacc);
1431         unused_nodes.erase(memacc.declaration);
1432 }
1433
1434 void ProgramCompiler::UnusedVariableLocator::visit(BinaryExpression &binary)
1435 {
1436         if(binary.oper=="[")
1437         {
1438                 binary.left->visit(*this);
1439                 SetForScope<bool> set(assignment_target, false);
1440                 binary.right->visit(*this);
1441         }
1442         else
1443                 TraversingVisitor::visit(binary);
1444 }
1445
1446 void ProgramCompiler::UnusedVariableLocator::visit(Assignment &assign)
1447 {
1448         {
1449                 SetForScope<bool> set(assignment_target, !assign.self_referencing);
1450                 assign.left->visit(*this);
1451         }
1452         assign.right->visit(*this);
1453         assignment = &assign;
1454 }
1455
1456 void ProgramCompiler::UnusedVariableLocator::record_assignment(VariableDeclaration &var, Node &node, bool self_ref)
1457 {
1458         VariableInfo &var_info = variables.back()[&var];
1459         if(!self_ref)
1460                 clear_assignments(var_info, true);
1461         var_info.assignments.push_back(&node);
1462         var_info.conditionally_assigned = false;
1463 }
1464
1465 void ProgramCompiler::UnusedVariableLocator::clear_assignments(VariableInfo &var_info, bool mark_unused)
1466 {
1467         if(mark_unused)
1468         {
1469                 for(vector<Node *>::iterator i=var_info.assignments.begin(); i!=var_info.assignments.end(); ++i)
1470                         unused_nodes.insert(*i);
1471         }
1472         var_info.assignments.clear();
1473 }
1474
1475 void ProgramCompiler::UnusedVariableLocator::visit(ExpressionStatement &expr)
1476 {
1477         assignment = 0;
1478         TraversingVisitor::visit(expr);
1479         if(assignment && assignment->target_declaration)
1480                 record_assignment(*assignment->target_declaration, expr, assignment->self_referencing);
1481 }
1482
1483 void ProgramCompiler::UnusedVariableLocator::visit(StructDeclaration &strct)
1484 {
1485         SetForScope<Node *> set(aggregate, &strct);
1486         unused_nodes.insert(&strct);
1487         TraversingVisitor::visit(strct);
1488 }
1489
1490 void ProgramCompiler::UnusedVariableLocator::visit(VariableDeclaration &var)
1491 {
1492         if(aggregate)
1493                 aggregates[&var] = aggregate;
1494         else
1495         {
1496                 variables.back()[&var].local = true;
1497                 if(var.init_expression)
1498                         record_assignment(var, *var.init_expression, false);
1499         }
1500         unused_nodes.erase(var.type_declaration);
1501         TraversingVisitor::visit(var);
1502 }
1503
1504 void ProgramCompiler::UnusedVariableLocator::visit(InterfaceBlock &iface)
1505 {
1506         SetForScope<Node *> set(aggregate, &iface);
1507         unused_nodes.insert(&iface);
1508         TraversingVisitor::visit(iface);
1509 }
1510
1511 void ProgramCompiler::UnusedVariableLocator::visit(FunctionDeclaration &func)
1512 {
1513         variables.push_back(BlockVariableMap());
1514
1515         {
1516                 SetForScope<bool> set(global_scope, false);
1517                 for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
1518                         (*i)->visit(*this);
1519                 func.body.visit(*this);
1520         }
1521
1522         BlockVariableMap &block_variables = variables.back();
1523         for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
1524                 i->second.conditionally_assigned = true;
1525         for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
1526                 block_variables[i->get()].referenced = true;
1527         merge_down_variables();
1528 }
1529
1530 void ProgramCompiler::UnusedVariableLocator::merge_down_variables()
1531 {
1532         BlockVariableMap &parent_variables = variables[variables.size()-2];
1533         BlockVariableMap &block_variables = variables.back();
1534         for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
1535         {
1536                 if(i->second.local)
1537                 {
1538                         if(!i->second.referenced)
1539                                 unused_nodes.insert(i->first);
1540                         clear_assignments(i->second, true);
1541                         continue;
1542                 }
1543
1544                 BlockVariableMap::iterator j = parent_variables.find(i->first);
1545                 if(j==parent_variables.end())
1546                         parent_variables.insert(*i);
1547                 else
1548                 {
1549                         if(i->second.referenced || !i->second.conditionally_assigned)
1550                                 clear_assignments(j->second, !i->second.referenced);
1551                         j->second.conditionally_assigned = i->second.conditionally_assigned;
1552                         j->second.referenced |= i->second.referenced;
1553                         j->second.assignments.insert(j->second.assignments.end(), i->second.assignments.begin(), i->second.assignments.end());
1554                 }
1555         }
1556         variables.pop_back();
1557 }
1558
1559 void ProgramCompiler::UnusedVariableLocator::visit(Conditional &cond)
1560 {
1561         cond.condition->visit(*this);
1562         variables.push_back(BlockVariableMap());
1563         cond.body.visit(*this);
1564
1565         BlockVariableMap if_variables;
1566         swap(variables.back(), if_variables);
1567         cond.else_body.visit(*this);
1568
1569         BlockVariableMap &else_variables = variables.back();
1570         for(BlockVariableMap::iterator i=else_variables.begin(); i!=else_variables.end(); ++i)
1571         {
1572                 BlockVariableMap::iterator j = if_variables.find(i->first);
1573                 if(j!=if_variables.end())
1574                 {
1575                         i->second.assignments.insert(i->second.assignments.end(), j->second.assignments.begin(), j->second.assignments.end());
1576                         i->second.conditionally_assigned |= j->second.conditionally_assigned;
1577                         if_variables.erase(j);
1578                 }
1579                 else
1580                         i->second.conditionally_assigned = true;
1581         }
1582
1583         for(BlockVariableMap::iterator i=if_variables.begin(); i!=if_variables.end(); ++i)
1584         {
1585                 i->second.conditionally_assigned = true;
1586                 else_variables.insert(*i);
1587         }
1588
1589         merge_down_variables();
1590 }
1591
1592 void ProgramCompiler::UnusedVariableLocator::visit(Iteration &iter)
1593 {
1594         variables.push_back(BlockVariableMap());
1595         TraversingVisitor::visit(iter);
1596
1597         BlockVariableMap &block_variables = variables.back();
1598         for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
1599                 if(!i->second.local && i->second.referenced)
1600                         i->second.assignments.clear();
1601
1602         merge_down_variables();
1603 }
1604
1605
1606 ProgramCompiler::UnusedVariableLocator::VariableInfo::VariableInfo():
1607         local(false),
1608         conditionally_assigned(false),
1609         referenced(false)
1610 { }
1611
1612
1613 void ProgramCompiler::UnusedFunctionLocator::visit(FunctionCall &call)
1614 {
1615         TraversingVisitor::visit(call);
1616
1617         unused_nodes.erase(call.declaration);
1618         if(call.declaration && call.declaration->definition!=call.declaration)
1619                 used_definitions.insert(call.declaration->definition);
1620 }
1621
1622 void ProgramCompiler::UnusedFunctionLocator::visit(FunctionDeclaration &func)
1623 {
1624         TraversingVisitor::visit(func);
1625
1626         if((func.name!="main" || func.body.body.empty()) && !used_definitions.count(&func))
1627                 unused_nodes.insert(&func);
1628 }
1629
1630
1631 ProgramCompiler::NodeRemover::NodeRemover(const set<Node *> &r):
1632         to_remove(r)
1633 { }
1634
1635 void ProgramCompiler::NodeRemover::visit(Block &block)
1636 {
1637         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
1638         {
1639                 (*i)->visit(*this);
1640                 if(to_remove.count(i->get()))
1641                         block.body.erase(i++);
1642                 else
1643                         ++i;
1644         }
1645 }
1646
1647 void ProgramCompiler::NodeRemover::visit(VariableDeclaration &var)
1648 {
1649         if(to_remove.count(&var))
1650         {
1651                 stage->in_variables.erase(var.name);
1652                 stage->out_variables.erase(var.name);
1653                 stage->locations.erase(var.name);
1654                 if(var.linked_declaration)
1655                         var.linked_declaration->linked_declaration = 0;
1656         }
1657         else if(var.init_expression && to_remove.count(var.init_expression.get()))
1658                 var.init_expression = 0;
1659 }
1660
1661
1662 void ProgramCompiler::PrecisionRemover::visit(Precision &)
1663 {
1664         remove_node = true;
1665 }
1666
1667 void ProgramCompiler::PrecisionRemover::visit(VariableDeclaration &var)
1668 {
1669         var.precision.clear();
1670 }
1671
1672
1673 ProgramCompiler::DefaultPrecisionGenerator::DefaultPrecisionGenerator():
1674         toplevel(true)
1675 { }
1676
1677 void ProgramCompiler::DefaultPrecisionGenerator::visit(Block &block)
1678 {
1679         if(toplevel)
1680         {
1681                 SetForScope<bool> set(toplevel, false);
1682                 BlockModifier::visit(block);
1683         }
1684         else
1685                 Visitor::visit(block);
1686 }
1687
1688 void ProgramCompiler::DefaultPrecisionGenerator::visit(Precision &prec)
1689 {
1690         have_default.insert(prec.type);
1691 }
1692
1693 void ProgramCompiler::DefaultPrecisionGenerator::visit(VariableDeclaration &var)
1694 {
1695         if(var.type_declaration)
1696                 return;
1697
1698         string type = var.type;
1699         if(!type.compare(0, 3, "vec") || !type.compare(0, 3, "mat"))
1700                 type = "float";
1701         else if(!type.compare(0, 3, "ivec") || type=="uint")
1702                 type = "int";
1703
1704         if(!have_default.count(type))
1705         {
1706                 Precision *prec = new Precision;
1707                 if(!type.compare(0, 7, "sampler"))
1708                         prec->precision = "lowp";
1709                 else if(stage->type==FRAGMENT)
1710                         prec->precision = "mediump";
1711                 else
1712                         prec->precision = "highp";
1713                 prec->type = type;
1714                 insert_nodes.push_back(prec);
1715
1716                 have_default.insert(type);
1717         }
1718 }
1719
1720
1721 ProgramCompiler::LegacyConverter::LegacyConverter():
1722         target_api(get_gl_api()),
1723         target_version(get_glsl_version()),
1724         frag_out(0)
1725 { }
1726
1727 ProgramCompiler::LegacyConverter::LegacyConverter(const Version &v):
1728         target_api(get_gl_api()),
1729         target_version(v),
1730         frag_out(0)
1731 { }
1732
1733 bool ProgramCompiler::LegacyConverter::check_version(const Version &feature_version) const
1734 {
1735         if(target_version<feature_version)
1736                 return false;
1737         else if(stage->required_version<feature_version)
1738                 stage->required_version = feature_version;
1739
1740         return true;
1741 }
1742
1743 bool ProgramCompiler::LegacyConverter::supports_unified_interface_syntax() const
1744 {
1745         if(target_api==OPENGL_ES2)
1746                 return check_version(Version(3, 0));
1747         else
1748                 return check_version(Version(1, 30));
1749 }
1750
1751 void ProgramCompiler::LegacyConverter::visit(VariableReference &var)
1752 {
1753         if(var.declaration==frag_out && !supports_unified_interface_syntax())
1754         {
1755                 var.name = "gl_FragColor";
1756                 var.declaration = 0;
1757                 type = "vec4";
1758         }
1759         else if(var.declaration)
1760                 type = var.declaration->type;
1761         else
1762                 type = string();
1763 }
1764
1765 void ProgramCompiler::LegacyConverter::visit(Assignment &assign)
1766 {
1767         TraversingVisitor::visit(assign);
1768         if(assign.target_declaration==frag_out && !supports_unified_interface_syntax())
1769                 assign.target_declaration = 0;
1770 }
1771
1772 bool ProgramCompiler::LegacyConverter::supports_unified_sampling_functions() const
1773 {
1774         if(target_api==OPENGL_ES2)
1775                 return check_version(Version(3, 0));
1776         else
1777                 return check_version(Version(1, 30));
1778 }
1779
1780 void ProgramCompiler::LegacyConverter::visit(FunctionCall &call)
1781 {
1782         if(call.name=="texture" && !call.declaration && !supports_unified_sampling_functions())
1783         {
1784                 vector<RefPtr<Expression> >::iterator i = call.arguments.begin();
1785                 if(i!=call.arguments.end())
1786                 {
1787                         (*i)->visit(*this);
1788                         if(type=="sampler1D")
1789                                 call.name = "texture1D";
1790                         else if(type=="sampler2D")
1791                                 call.name = "texture2D";
1792                         else if(type=="sampler3D")
1793                                 call.name = "texture3D";
1794                         else if(type=="sampler1DShadow")
1795                                 call.name = "shadow1D";
1796                         else if(type=="sampler2DShadow")
1797                                 call.name = "shadow2D";
1798
1799                         for(; i!=call.arguments.end(); ++i)
1800                                 (*i)->visit(*this);
1801                 }
1802         }
1803         else
1804                 TraversingVisitor::visit(call);
1805 }
1806
1807 bool ProgramCompiler::LegacyConverter::supports_interface_layouts() const
1808 {
1809         if(target_api==OPENGL_ES2)
1810                 return check_version(Version(3, 0));
1811         else
1812                 return check_version(Version(3, 30));
1813 }
1814
1815 bool ProgramCompiler::LegacyConverter::supports_centroid_sampling() const
1816 {
1817         if(target_api==OPENGL_ES2)
1818                 return check_version(Version(3, 0));
1819         else
1820                 return check_version(Version(1, 20));
1821 }
1822
1823 bool ProgramCompiler::LegacyConverter::supports_sample_sampling() const
1824 {
1825         if(target_api==OPENGL_ES2)
1826                 return check_version(Version(3, 20));
1827         else
1828                 return check_version(Version(4, 0));
1829 }
1830
1831 void ProgramCompiler::LegacyConverter::visit(VariableDeclaration &var)
1832 {
1833         if(var.layout && !supports_interface_layouts())
1834         {
1835                 vector<Layout::Qualifier>::iterator i;
1836                 for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->identifier!="location"); ++i) ;
1837                 if(i!=var.layout->qualifiers.end())
1838                 {
1839                         unsigned location = lexical_cast<unsigned>(i->value);
1840                         if(stage->type==VERTEX && var.interface=="in")
1841                         {
1842                                 stage->locations[var.name] = location;
1843                                 var.layout->qualifiers.erase(i);
1844                         }
1845                         else if(stage->type==FRAGMENT && var.interface=="out")
1846                         {
1847                                 if(location!=0)
1848                                         static Require _req(EXT_gpu_shader4);
1849                                 stage->locations[var.name] = location;
1850                                 var.layout->qualifiers.erase(i);
1851                         }
1852
1853                         if(var.layout->qualifiers.empty())
1854                                 var.layout = 0;
1855                 }
1856         }
1857
1858         if(var.sampling=="centroid")
1859         {
1860                 if(!supports_centroid_sampling())
1861                         var.sampling = string();
1862         }
1863         else if(var.sampling=="sample")
1864         {
1865                 if(!supports_sample_sampling())
1866                         var.sampling = string();
1867         }
1868
1869         if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax())
1870         {
1871                 if(stage->type==FRAGMENT && var.interface=="out")
1872                 {
1873                         frag_out = &var;
1874                         remove_node = true;
1875                 }
1876         }
1877
1878         TraversingVisitor::visit(var);
1879 }
1880
1881 bool ProgramCompiler::LegacyConverter::supports_interface_blocks(const string &iface) const
1882 {
1883         if(target_api==OPENGL_ES2)
1884         {
1885                 if(iface=="uniform")
1886                         return check_version(Version(3, 0));
1887                 else
1888                         return check_version(Version(3, 20));
1889         }
1890         else
1891                 return check_version(Version(1, 50));
1892 }
1893
1894 void ProgramCompiler::LegacyConverter::visit(InterfaceBlock &iface)
1895 {
1896         if(!supports_interface_blocks(iface.interface))
1897                 flatten_block(iface.members);
1898 }
1899
1900 } // namespace GL
1901 } // namespace Msp