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