]> git.tdb.fi Git - libs/gl.git/blob - source/programcompiler.cpp
Remove some VariableResolver calls that are no longer needed
[libs/gl.git] / source / programcompiler.cpp
1 #include <msp/core/raii.h>
2 #include <msp/strings/format.h>
3 #include <msp/strings/utils.h>
4 #include "error.h"
5 #include "program.h"
6 #include "programcompiler.h"
7 #include "resources.h"
8 #include "shader.h"
9
10 using namespace std;
11
12 namespace {
13
14 const char builtins_src[] =
15         "////// vertex\n"
16         "out gl_PerVertex {\n"
17         "  vec4 gl_Position;\n"
18         "  float gl_ClipDistance[];\n"
19         "};"
20         "////// geometry\n"
21         "in gl_PerVertex {\n"
22         "  vec4 gl_Position;\n"
23         "  float gl_ClipDistance[];\n"
24         "} gl_in[];\n"
25         "out gl_PerVertex {\n"
26         "  vec4 gl_Position;\n"
27         "  float gl_ClipDistance[];\n"
28         "};\n";
29
30 }
31
32 namespace Msp {
33 namespace GL {
34
35 using namespace ProgramSyntax;
36
37 ProgramCompiler::ProgramCompiler():
38         resources(0),
39         module(0)
40 { }
41
42 void ProgramCompiler::compile(const string &source)
43 {
44         resources = 0;
45         module = &parser.parse(source);
46         process();
47 }
48
49 void ProgramCompiler::compile(IO::Base &io, Resources *res)
50 {
51         resources = res;
52         module = &parser.parse(io);
53         process();
54 }
55
56 void ProgramCompiler::add_shaders(Program &program)
57 {
58         if(!module)
59                 throw invalid_operation("ProgramCompiler::add_shaders");
60
61         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
62         {
63                 if(i->type==VERTEX)
64                 {
65                         program.attach_shader_owned(new VertexShader(apply<Formatter>(*i)));
66                         for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
67                                 program.bind_attribute(j->second, j->first);
68                 }
69                 else if(i->type==GEOMETRY)
70                         program.attach_shader_owned(new GeometryShader(apply<Formatter>(*i)));
71                 else if(i->type==FRAGMENT)
72                 {
73                         program.attach_shader_owned(new FragmentShader(apply<Formatter>(*i)));
74                         for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
75                                 program.bind_fragment_data(j->second, j->first);
76                 }
77         }
78 }
79
80 Module *ProgramCompiler::create_builtins_module()
81 {
82         ProgramParser parser;
83         Module *module = new Module(parser.parse(builtins_src));
84         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
85         {
86                 VariableResolver resolver;
87                 i->content.visit(resolver);
88                 for(map<string, VariableDeclaration *>::iterator j=i->content.variables.begin(); j!=i->content.variables.end(); ++j)
89                         j->second->linked_declaration = j->second;
90         }
91         return module;
92 }
93
94 Module &ProgramCompiler::get_builtins_module()
95 {
96         static RefPtr<Module> builtins_module = create_builtins_module();
97         return *builtins_module;
98 }
99
100 Stage *ProgramCompiler::get_builtins(StageType type)
101 {
102         Module &module = get_builtins_module();
103         for(list<Stage>::iterator i=module.stages.begin(); i!=module.stages.end(); ++i)
104                 if(i->type==type)
105                         return &*i;
106         return 0;
107 }
108
109 void ProgramCompiler::process()
110 {
111         list<Import *> imports = apply<NodeGatherer<Import> >(module->shared);
112         for(list<Import *>::iterator i=imports.end(); i!=imports.begin(); )
113                 import((*--i)->module);
114         apply<NodeRemover>(module->shared, set<Node *>(imports.begin(), imports.end()));
115
116         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
117                 generate(*i);
118         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); )
119         {
120                 if(optimize(*i))
121                         i = module->stages.begin();
122                 else
123                         ++i;
124         }
125 }
126
127 void ProgramCompiler::import(const string &name)
128 {
129         string fn = name+".glsl";
130         RefPtr<IO::Seekable> io = (resources ? resources->open_raw(fn) : Resources::get_builtins().open(fn));
131         if(!io)
132                 throw runtime_error(format("module %s not found", name));
133         ProgramParser import_parser;
134         Module &imported_module = import_parser.parse(*io);
135
136         inject_block(module->shared.content, imported_module.shared.content);
137         apply<DeclarationCombiner>(module->shared);
138         for(list<Stage>::iterator i=imported_module.stages.begin(); i!=imported_module.stages.end(); ++i)
139         {
140                 list<Stage>::iterator j;
141                 for(j=module->stages.begin(); (j!=module->stages.end() && j->type<i->type); ++j) ;
142                 if(j==module->stages.end() || j->type>i->type)
143                 {
144                         j = module->stages.insert(j, *i);
145                         list<Stage>::iterator k = j;
146                         if(++k!=module->stages.end())
147                                 k->previous = &*j;
148                         if(j!=module->stages.begin())
149                                 j->previous = &*--(k=j);
150                 }
151                 else
152                 {
153                         inject_block(j->content, i->content);
154                         apply<DeclarationCombiner>(*j);
155                 }
156         }
157 }
158
159 void ProgramCompiler::generate(Stage &stage)
160 {
161         inject_block(stage.content, module->shared.content);
162
163         apply<FunctionResolver>(stage);
164         apply<VariableResolver>(stage);
165         apply<InterfaceGenerator>(stage);
166         apply<VariableResolver>(stage);
167         apply<VariableRenamer>(stage);
168         apply<LegacyConverter>(stage);
169 }
170
171 bool ProgramCompiler::optimize(Stage &stage)
172 {
173         apply<ConstantConditionEliminator>(stage);
174
175         set<Node *> unused = apply<UnusedVariableLocator>(stage);
176         set<Node *> unused2 = apply<UnusedFunctionLocator>(stage);
177         unused.insert(unused2.begin(), unused2.end());
178         apply<NodeRemover>(stage, unused);
179
180         return !unused.empty();
181 }
182
183 void ProgramCompiler::inject_block(Block &target, const Block &source)
184 {
185         list<RefPtr<Node> >::iterator insert_point = target.body.begin();
186         for(list<RefPtr<Node> >::const_iterator i=source.body.begin(); i!=source.body.end(); ++i)
187                 target.body.insert(insert_point, (*i)->clone());
188 }
189
190 template<typename T>
191 typename T::ResultType ProgramCompiler::apply(Stage &stage)
192 {
193         T visitor;
194         visitor.apply(stage);
195         return visitor.get_result();
196 }
197
198 template<typename T, typename A>
199 typename T::ResultType ProgramCompiler::apply(Stage &stage, const A &arg)
200 {
201         T visitor(arg);
202         visitor.apply(stage);
203         return visitor.get_result();
204 }
205
206
207 ProgramCompiler::Visitor::Visitor():
208         stage(0)
209 { }
210
211 void ProgramCompiler::Visitor::apply(Stage &s)
212 {
213         SetForScope<Stage *> set(stage, &s);
214         stage->content.visit(*this);
215 }
216
217
218 ProgramCompiler::Formatter::Formatter():
219         indent(0),
220         parameter_list(false),
221         else_if(0)
222 { }
223
224 void ProgramCompiler::Formatter::apply(ProgramSyntax::Stage &s)
225 {
226         const Version &ver = s.required_version;
227         if(ver.major)
228                 formatted += format("#version %d%d\n", ver.major, ver.minor);
229         Visitor::apply(s);
230 }
231
232 void ProgramCompiler::Formatter::visit(Literal &literal)
233 {
234         formatted += literal.token;
235 }
236
237 void ProgramCompiler::Formatter::visit(ParenthesizedExpression &parexpr)
238 {
239         formatted += '(';
240         parexpr.expression->visit(*this);
241         formatted += ')';
242 }
243
244 void ProgramCompiler::Formatter::visit(VariableReference &var)
245 {
246         formatted += var.name;
247 }
248
249 void ProgramCompiler::Formatter::visit(MemberAccess &memacc)
250 {
251         memacc.left->visit(*this);
252         formatted += format(".%s", memacc.member);
253 }
254
255 void ProgramCompiler::Formatter::visit(UnaryExpression &unary)
256 {
257         if(unary.prefix)
258                 formatted += unary.oper;
259         unary.expression->visit(*this);
260         if(!unary.prefix)
261                 formatted += unary.oper;
262 }
263
264 void ProgramCompiler::Formatter::visit(BinaryExpression &binary)
265 {
266         binary.left->visit(*this);
267         formatted += binary.oper;
268         binary.right->visit(*this);
269         formatted += binary.after;
270 }
271
272 void ProgramCompiler::Formatter::visit(Assignment &assign)
273 {
274         assign.left->visit(*this);
275         formatted += format(" %s ", assign.oper);
276         assign.right->visit(*this);
277 }
278
279 void ProgramCompiler::Formatter::visit(FunctionCall &call)
280 {
281         formatted += format("%s(", call.name);
282         for(vector<RefPtr<Expression> >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
283         {
284                 if(i!=call.arguments.begin())
285                         formatted += ", ";
286                 (*i)->visit(*this);
287         }
288         formatted += ')';
289 }
290
291 void ProgramCompiler::Formatter::visit(ExpressionStatement &expr)
292 {
293         expr.expression->visit(*this);
294         formatted += ';';
295 }
296
297 void ProgramCompiler::Formatter::visit(Block &block)
298 {
299         if(else_if)
300                 --else_if;
301
302         unsigned brace_indent = indent;
303         bool use_braces = (block.use_braces || (indent && block.body.size()!=1));
304         if(use_braces)
305                 formatted += format("%s{\n", string(brace_indent*2, ' '));
306
307         SetForScope<unsigned> set(indent, indent+(indent>0 || use_braces));
308         string spaces(indent*2, ' ');
309         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
310         {
311                 if(i!=block.body.begin())
312                         formatted += '\n';
313                 formatted += spaces;
314                 (*i)->visit(*this);
315                 else_if = 0;
316         }
317
318         if(use_braces)
319                 formatted += format("\n%s}", string(brace_indent*2, ' '));
320 }
321
322 void ProgramCompiler::Formatter::visit(Import &import)
323 {
324         formatted += format("import %s;", import.module);
325 }
326
327 void ProgramCompiler::Formatter::visit(Layout &layout)
328 {
329         formatted += "layout(";
330         for(vector<Layout::Qualifier>::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i)
331         {
332                 if(i!=layout.qualifiers.begin())
333                         formatted += ", ";
334                 formatted += i->identifier;
335                 if(!i->value.empty())
336                         formatted += format("=%s", i->value);
337         }
338         formatted += ')';
339 }
340
341 void ProgramCompiler::Formatter::visit(InterfaceLayout &layout)
342 {
343         layout.layout.visit(*this);
344         formatted += format(" %s;", layout.interface);
345 }
346
347 void ProgramCompiler::Formatter::visit(StructDeclaration &strct)
348 {
349         formatted += format("struct %s\n", strct.name);
350         strct.members.visit(*this);
351         formatted += ';';
352 }
353
354 void ProgramCompiler::Formatter::visit(VariableDeclaration &var)
355 {
356         if(var.layout)
357         {
358                 var.layout->visit(*this);
359                 formatted += ' ';
360         }
361         if(var.constant)
362                 formatted += "const ";
363         if(!var.sampling.empty())
364                 formatted += format("%s ", var.sampling);
365         if(!var.interface.empty() && var.interface!=block_interface)
366                 formatted += format("%s ", var.interface);
367         formatted += format("%s %s", var.type, var.name);
368         if(var.array)
369         {
370                 formatted += '[';
371                 if(var.array_size)
372                         var.array_size->visit(*this);
373                 formatted += ']';
374         }
375         if(var.init_expression)
376         {
377                 formatted += " = ";
378                 var.init_expression->visit(*this);
379         }
380         if(!parameter_list)
381                 formatted += ';';
382 }
383
384 void ProgramCompiler::Formatter::visit(InterfaceBlock &iface)
385 {
386         SetForScope<string> set(block_interface, iface.interface);
387         formatted += format("%s %s\n", iface.interface, iface.name);
388         iface.members.visit(*this);
389         formatted += ';';
390 }
391
392 void ProgramCompiler::Formatter::visit(FunctionDeclaration &func)
393 {
394         formatted += format("%s %s(", func.return_type, func.name);
395         for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
396         {
397                 if(i!=func.parameters.begin())
398                         formatted += ", ";
399                 SetFlag set(parameter_list);
400                 (*i)->visit(*this);
401         }
402         formatted += ')';
403         if(func.definition==&func)
404         {
405                 formatted += '\n';
406                 func.body.visit(*this);
407         }
408         else
409                 formatted += ';';
410 }
411
412 void ProgramCompiler::Formatter::visit(Conditional &cond)
413 {
414         if(else_if)
415                 formatted.replace(formatted.rfind('\n'), string::npos, 1, ' ');
416
417         indent -= else_if;
418
419         formatted += "if(";
420         cond.condition->visit(*this);
421         formatted += ")\n";
422
423         cond.body.visit(*this);
424         if(!cond.else_body.body.empty())
425         {
426                 formatted += format("\n%selse\n", string(indent*2, ' '));
427                 SetForScope<unsigned> set(else_if, 2);
428                 cond.else_body.visit(*this);
429         }
430 }
431
432 void ProgramCompiler::Formatter::visit(Iteration &iter)
433 {
434         formatted += "for(";
435         iter.init_statement->visit(*this);
436         formatted += ' ';
437         iter.condition->visit(*this);
438         formatted += "; ";
439         iter.loop_expression->visit(*this);
440         formatted += ")\n";
441         iter.body.visit(*this);
442 }
443
444 void ProgramCompiler::Formatter::visit(Return &ret)
445 {
446         formatted += "return ";
447         ret.expression->visit(*this);
448         formatted += ';';
449 }
450
451
452 ProgramCompiler::DeclarationCombiner::DeclarationCombiner():
453         toplevel(true),
454         remove_node(false)
455 { }
456
457 void ProgramCompiler::DeclarationCombiner::visit(Block &block)
458 {
459         if(!toplevel)
460                 return;
461
462         SetForScope<bool> set(toplevel, false);
463         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
464         {
465                 remove_node = false;
466                 (*i)->visit(*this);
467                 if(remove_node)
468                         block.body.erase(i++);
469                 else
470                         ++i;
471         }
472 }
473
474 void ProgramCompiler::DeclarationCombiner::visit(FunctionDeclaration &func)
475 {
476         vector<FunctionDeclaration *> &decls = functions[func.name];
477         if(func.definition)
478         {
479                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
480                 {
481                         (*i)->definition = func.definition;
482                         (*i)->body.body.clear();
483                 }
484         }
485         decls.push_back(&func);
486 }
487
488 void ProgramCompiler::DeclarationCombiner::visit(VariableDeclaration &var)
489 {
490         VariableDeclaration *&ptr = variables[var.name];
491         if(ptr)
492         {
493                 ptr->type = var.type;
494                 if(var.init_expression)
495                         ptr->init_expression = var.init_expression;
496                 remove_node = true;
497         }
498         else
499                 ptr = &var;
500 }
501
502
503 ProgramCompiler::VariableResolver::VariableResolver():
504         anonymous(false),
505         record_target(false),
506         assignment_target(0),
507         self_referencing(false)
508 { }
509
510 void ProgramCompiler::VariableResolver::apply(Stage &s)
511 {
512         SetForScope<Stage *> set(stage, &s);
513         Stage *builtins = get_builtins(stage->type);
514         if(builtins)
515                 blocks.push_back(&builtins->content);
516         stage->content.visit(*this);
517         if(builtins)
518                 blocks.pop_back();
519 }
520
521 void ProgramCompiler::VariableResolver::visit(Block &block)
522 {
523         blocks.push_back(&block);
524         block.variables.clear();
525         TraversingVisitor::visit(block);
526         blocks.pop_back();
527 }
528
529 void ProgramCompiler::VariableResolver::visit(VariableReference &var)
530 {
531         var.declaration = 0;
532         type = 0;
533         for(vector<Block *>::iterator i=blocks.end(); i!=blocks.begin(); )
534         {
535                 --i;
536                 map<string, VariableDeclaration *>::iterator j = (*i)->variables.find(var.name);
537                 if(j!=(*i)->variables.end())
538                 {
539                         var.declaration = j->second;
540                         type = j->second->type_declaration;
541                         break;
542                 }
543         }
544
545         if(record_target)
546         {
547                 if(assignment_target)
548                 {
549                         record_target = false;
550                         assignment_target = 0;
551                 }
552                 else
553                         assignment_target = var.declaration;
554         }
555         else if(var.declaration && var.declaration==assignment_target)
556                 self_referencing = true;
557 }
558
559 void ProgramCompiler::VariableResolver::visit(MemberAccess &memacc)
560 {
561         type = 0;
562         TraversingVisitor::visit(memacc);
563         memacc.declaration = 0;
564         if(type)
565         {
566                 map<string, VariableDeclaration *>::iterator i = type->members.variables.find(memacc.member);
567                 if(i!=type->members.variables.end())
568                 {
569                         memacc.declaration = i->second;
570                         type = i->second->type_declaration;
571                 }
572                 else
573                         type = 0;
574         }
575 }
576
577 void ProgramCompiler::VariableResolver::visit(BinaryExpression &binary)
578 {
579         if(binary.oper=="[")
580         {
581                 {
582                         SetForScope<bool> set(record_target, false);
583                         binary.right->visit(*this);
584                 }
585                 type = 0;
586                 binary.left->visit(*this);
587         }
588         else
589         {
590                 TraversingVisitor::visit(binary);
591                 type = 0;
592         }
593 }
594
595 void ProgramCompiler::VariableResolver::visit(Assignment &assign)
596 {
597         {
598                 SetFlag set(record_target);
599                 assignment_target = 0;
600                 assign.left->visit(*this);
601         }
602
603         self_referencing = false;
604         assign.right->visit(*this);
605
606         assign.self_referencing = (self_referencing || assign.oper!="=");
607         assign.target_declaration = assignment_target;
608 }
609
610 void ProgramCompiler::VariableResolver::visit(StructDeclaration &strct)
611 {
612         TraversingVisitor::visit(strct);
613         blocks.back()->types[strct.name] = &strct;
614 }
615
616 void ProgramCompiler::VariableResolver::visit(VariableDeclaration &var)
617 {
618         for(vector<Block *>::iterator i=blocks.end(); i!=blocks.begin(); )
619         {
620                 --i;
621                 map<string, StructDeclaration *>::iterator j = (*i)->types.find(var.type);
622                 if(j!=(*i)->types.end())
623                         var.type_declaration = j->second;
624         }
625
626         if(!block_interface.empty() && var.interface.empty())
627                 var.interface = block_interface;
628
629         TraversingVisitor::visit(var);
630         blocks.back()->variables[var.name] = &var;
631         if(anonymous && blocks.size()>1)
632                 blocks[blocks.size()-2]->variables[var.name] = &var;
633 }
634
635 void ProgramCompiler::VariableResolver::visit(InterfaceBlock &iface)
636 {
637         SetFlag set(anonymous);
638         SetForScope<string> set2(block_interface, iface.interface);
639         TraversingVisitor::visit(iface);
640 }
641
642
643 void ProgramCompiler::FunctionResolver::visit(FunctionCall &call)
644 {
645         map<string, vector<FunctionDeclaration *> >::iterator i = functions.find(call.name);
646         if(i!=functions.end())
647                 call.declaration = i->second.back();
648
649         TraversingVisitor::visit(call);
650 }
651
652 void ProgramCompiler::FunctionResolver::visit(FunctionDeclaration &func)
653 {
654         vector<FunctionDeclaration *> &decls = functions[func.name];
655         if(func.definition)
656         {
657                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
658                         (*i)->definition = func.definition;
659                 decls.clear();
660                 decls.push_back(&func);
661         }
662         else if(!decls.empty() && decls.back()->definition)
663                 func.definition = decls.back()->definition;
664         else
665                 decls.push_back(&func);
666
667         TraversingVisitor::visit(func);
668 }
669
670
671 ProgramCompiler::BlockModifier::BlockModifier():
672         remove_node(false)
673 { }
674
675 void ProgramCompiler::BlockModifier::flatten_block(Block &block)
676 {
677         insert_nodes.insert(insert_nodes.end(), block.body.begin(), block.body.end());
678         remove_node = true;
679 }
680
681 void ProgramCompiler::BlockModifier::apply_and_increment(Block &block, list<RefPtr<Node> >::iterator &i)
682 {
683         block.body.insert(i, insert_nodes.begin(), insert_nodes.end());
684         insert_nodes.clear();
685
686         if(remove_node)
687                 block.body.erase(i++);
688         else
689                 ++i;
690         remove_node = false;
691 }
692
693 void ProgramCompiler::BlockModifier::visit(Block &block)
694 {
695         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
696         {
697                 (*i)->visit(*this);
698                 apply_and_increment(block, i);
699         }
700 }
701
702
703 ProgramCompiler::InterfaceGenerator::InterfaceGenerator():
704         scope_level(0)
705 { }
706
707 string ProgramCompiler::InterfaceGenerator::get_out_prefix(StageType type)
708 {
709         if(type==VERTEX)
710                 return "_vs_out_";
711         else if(type==GEOMETRY)
712                 return "_gs_out_";
713         else
714                 return string();
715 }
716
717 void ProgramCompiler::InterfaceGenerator::apply(Stage &s)
718 {
719         SetForScope<Stage *> set(stage, &s);
720         if(stage->previous)
721                 in_prefix = get_out_prefix(stage->previous->type);
722         out_prefix = get_out_prefix(stage->type);
723         stage->content.visit(*this);
724 }
725
726 void ProgramCompiler::InterfaceGenerator::visit(Block &block)
727 {
728         SetForScope<unsigned> set(scope_level, scope_level+1);
729         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
730         {
731                 (*i)->visit(*this);
732
733                 if(scope_level==1)
734                 {
735                         for(map<string, RefPtr<VariableDeclaration> >::iterator j=iface_declarations.begin(); j!=iface_declarations.end(); ++j)
736                         {
737                                 list<RefPtr<Node> >::iterator k = block.body.insert(i, j->second);
738                                 (*k)->visit(*this);
739                         }
740                         iface_declarations.clear();
741                 }
742
743                 apply_and_increment(block, i);
744         }
745 }
746
747 string ProgramCompiler::InterfaceGenerator::change_prefix(const string &name, const string &prefix) const
748 {
749         unsigned offset = (name.compare(0, in_prefix.size(), in_prefix) ? 0 : in_prefix.size());
750         return prefix+name.substr(offset);
751 }
752
753 bool ProgramCompiler::InterfaceGenerator::generate_interface(VariableDeclaration &var, const string &iface, const string &name)
754 {
755         const map<string, VariableDeclaration *> &stage_vars = (iface=="in" ? stage->in_variables : stage->out_variables);
756         if(stage_vars.count(name) || iface_declarations.count(name))
757                 return false;
758
759         VariableDeclaration* iface_var = new VariableDeclaration;
760         iface_var->sampling = var.sampling;
761         iface_var->interface = iface;
762         iface_var->type = var.type;
763         iface_var->type_declaration = var.type_declaration;
764         iface_var->name = name;
765         if(stage->type==GEOMETRY)
766                 iface_var->array = ((var.array && var.interface!="in") || iface=="in");
767         else
768                 iface_var->array = var.array;
769         if(iface_var->array)
770                 iface_var->array_size = var.array_size;
771         if(iface=="in")
772                 iface_var->linked_declaration = &var;
773         iface_declarations[name] = iface_var;
774
775         return true;
776 }
777
778 void ProgramCompiler::InterfaceGenerator::insert_assignment(const string &left, ProgramSyntax::Expression *right)
779 {
780         Assignment *assign = new Assignment;
781         VariableReference *ref = new VariableReference;
782         ref->name = left;
783         assign->left = ref;
784         assign->oper = "=";
785         assign->right = right;
786
787         ExpressionStatement *stmt = new ExpressionStatement;
788         stmt->expression = assign;
789         insert_nodes.push_back(stmt);
790 }
791
792 void ProgramCompiler::InterfaceGenerator::visit(VariableReference &var)
793 {
794         if(var.declaration || !stage->previous)
795                 return;
796         if(iface_declarations.count(var.name))
797                 return;
798
799         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
800         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
801         if(i==prev_out.end())
802                 i = prev_out.find(in_prefix+var.name);
803         if(i!=prev_out.end())
804                 generate_interface(*i->second, "in", var.name);
805 }
806
807 void ProgramCompiler::InterfaceGenerator::visit(VariableDeclaration &var)
808 {
809         if(var.interface=="out")
810         {
811                 if(scope_level==1)
812                         stage->out_variables[var.name] = &var;
813                 else if(generate_interface(var, "out", change_prefix(var.name, string())))
814                 {
815                         remove_node = true;
816                         if(var.init_expression)
817                                 insert_assignment(var.name, var.init_expression->clone());
818                 }
819         }
820         else if(var.interface=="in")
821         {
822                 stage->in_variables[var.name] = &var;
823                 if(var.linked_declaration)
824                         var.linked_declaration->linked_declaration = &var;
825                 else if(stage->previous)
826                 {
827                         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
828                         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
829                         if(i!=prev_out.end())
830                         {
831                                 var.linked_declaration = i->second;
832                                 i->second->linked_declaration = &var;
833                         }
834                 }
835         }
836
837         TraversingVisitor::visit(var);
838 }
839
840 void ProgramCompiler::InterfaceGenerator::visit(Passthrough &pass)
841 {
842         vector<VariableDeclaration *> pass_vars;
843
844         for(map<string, VariableDeclaration *>::const_iterator i=stage->in_variables.begin(); i!=stage->in_variables.end(); ++i)
845                 pass_vars.push_back(i->second);
846         for(map<string, RefPtr<VariableDeclaration> >::const_iterator i=iface_declarations.begin(); i!=iface_declarations.end(); ++i)
847                 if(i->second->interface=="in")
848                         pass_vars.push_back(i->second.get());
849
850         if(stage->previous)
851         {
852                 const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
853                 for(map<string, VariableDeclaration *>::const_iterator i=prev_out.begin(); i!=prev_out.end(); ++i)
854                 {
855                         bool linked = false;
856                         for(vector<VariableDeclaration *>::const_iterator j=pass_vars.begin(); (!linked && j!=pass_vars.end()); ++j)
857                                 linked = ((*j)->linked_declaration==i->second);
858
859                         if(!linked && generate_interface(*i->second, "in", i->second->name))
860                                 pass_vars.push_back(i->second);
861                 }
862         }
863
864         if(stage->type==GEOMETRY)
865         {
866                 VariableReference *ref = new VariableReference;
867                 ref->name = "gl_in";
868
869                 BinaryExpression *subscript = new BinaryExpression;
870                 subscript->left = ref;
871                 subscript->oper = "[";
872                 subscript->right = pass.subscript;
873                 subscript->after = "]";
874
875                 MemberAccess *memacc = new MemberAccess;
876                 memacc->left = subscript;
877                 memacc->member = "gl_Position";
878
879                 insert_assignment("gl_Position", memacc);
880         }
881
882         for(vector<VariableDeclaration *>::const_iterator i=pass_vars.begin(); i!=pass_vars.end(); ++i)
883         {
884                 string out_name = change_prefix((*i)->name, out_prefix);
885                 generate_interface(**i, "out", out_name);
886
887                 VariableReference *ref = new VariableReference;
888                 ref->name = (*i)->name;
889                 if(pass.subscript)
890                 {
891                         BinaryExpression *subscript = new BinaryExpression;
892                         subscript->left = ref;
893                         subscript->oper = "[";
894                         subscript->right = pass.subscript;
895                         subscript->after = "]";
896                         insert_assignment(out_name, subscript);
897                 }
898                 else
899                         insert_assignment(out_name, ref);
900         }
901
902         remove_node = true;
903 }
904
905
906 void ProgramCompiler::VariableRenamer::visit(VariableReference &var)
907 {
908         if(var.declaration)
909                 var.name = var.declaration->name;
910 }
911
912 void ProgramCompiler::VariableRenamer::visit(VariableDeclaration &var)
913 {
914         if(var.linked_declaration)
915                 var.name = var.linked_declaration->name;
916         TraversingVisitor::visit(var);
917 }
918
919
920 ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator():
921         variable_values(0),
922         result(0.0f),
923         result_valid(false)
924 { }
925
926 ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(const ValueMap &v):
927         variable_values(&v),
928         result(0.0f),
929         result_valid(false)
930 { }
931
932 void ProgramCompiler::ExpressionEvaluator::visit(Literal &literal)
933 {
934         if(literal.token=="true")
935                 result = 1.0f;
936         else if(literal.token=="false")
937                 result = 0.0f;
938         else
939                 result = lexical_cast<float>(literal.token);
940         result_valid = true;
941 }
942
943 void ProgramCompiler::ExpressionEvaluator::visit(ParenthesizedExpression &parexp)
944 {
945         parexp.expression->visit(*this);
946 }
947
948 void ProgramCompiler::ExpressionEvaluator::visit(VariableReference &var)
949 {
950         if(!var.declaration)
951                 return;
952
953         if(variable_values)
954         {
955                 ValueMap::const_iterator i = variable_values->find(var.declaration);
956                 if(i!=variable_values->end())
957                         i->second->visit(*this);
958         }
959         else if(var.declaration->init_expression)
960                 var.declaration->init_expression->visit(*this);
961 }
962
963 void ProgramCompiler::ExpressionEvaluator::visit(UnaryExpression &unary)
964 {
965         result_valid = false;
966         unary.expression->visit(*this);
967         if(!result_valid)
968                 return;
969
970         if(unary.oper=="!")
971                 result = !result;
972         else
973                 result_valid = false;
974 }
975
976 void ProgramCompiler::ExpressionEvaluator::visit(BinaryExpression &binary)
977 {
978         result_valid = false;
979         binary.left->visit(*this);
980         if(!result_valid)
981                 return;
982
983         float left_result = result;
984         result_valid = false;
985         binary.right->visit(*this);
986         if(!result_valid)
987                 return;
988
989         if(binary.oper=="<")
990                 result = (left_result<result);
991         else if(binary.oper=="<=")
992                 result = (left_result<=result);
993         else if(binary.oper==">")
994                 result = (left_result>result);
995         else if(binary.oper==">=")
996                 result = (left_result>=result);
997         else if(binary.oper=="==")
998                 result = (left_result==result);
999         else if(binary.oper=="!=")
1000                 result = (left_result!=result);
1001         else if(binary.oper=="&&")
1002                 result = (left_result && result);
1003         else if(binary.oper=="||")
1004                 result = (left_result || result);
1005         else
1006                 result_valid = false;
1007 }
1008
1009
1010 ProgramCompiler::ConstantConditionEliminator::ConstantConditionEliminator():
1011         scope_level(0)
1012 { }
1013
1014 void ProgramCompiler::ConstantConditionEliminator::visit(Block &block)
1015 {
1016         SetForScope<unsigned> set(scope_level, scope_level+1);
1017         BlockModifier::visit(block);
1018
1019         for(map<string, VariableDeclaration *>::const_iterator i=block.variables.begin(); i!=block.variables.end(); ++i)
1020                 variable_values.erase(i->second);
1021 }
1022
1023 void ProgramCompiler::ConstantConditionEliminator::visit(Assignment &assign)
1024 {
1025         variable_values.erase(assign.target_declaration);
1026 }
1027
1028 void ProgramCompiler::ConstantConditionEliminator::visit(VariableDeclaration &var)
1029 {
1030         if(var.constant || scope_level>1)
1031                 variable_values[&var] = var.init_expression.get();
1032 }
1033
1034 void ProgramCompiler::ConstantConditionEliminator::visit(Conditional &cond)
1035 {
1036         ExpressionEvaluator eval(variable_values);
1037         cond.condition->visit(eval);
1038         if(eval.result_valid)
1039                 flatten_block(eval.result ? cond.body : cond.else_body);
1040         else
1041                 TraversingVisitor::visit(cond);
1042 }
1043
1044 void ProgramCompiler::ConstantConditionEliminator::visit(Iteration &iter)
1045 {
1046         if(iter.condition)
1047         {
1048                 ExpressionEvaluator eval;
1049                 iter.condition->visit(eval);
1050                 if(eval.result_valid && !eval.result)
1051                 {
1052                         remove_node = true;
1053                         return;
1054                 }
1055         }
1056
1057         TraversingVisitor::visit(iter);
1058 }
1059
1060
1061 ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator():
1062         aggregate(0),
1063         assignment(0),
1064         assignment_target(false)
1065 { }
1066
1067 void ProgramCompiler::UnusedVariableLocator::apply(Stage &s)
1068 {
1069         assignments.push_back(BlockAssignmentMap());
1070         Visitor::apply(s);
1071         assignments.pop_back();
1072 }
1073
1074 void ProgramCompiler::UnusedVariableLocator::visit(VariableReference &var)
1075 {
1076         unused_nodes.erase(var.declaration);
1077
1078         map<VariableDeclaration *, Node *>::iterator i = aggregates.find(var.declaration);
1079         if(i!=aggregates.end())
1080                 unused_nodes.erase(i->second);
1081
1082         if(assignment_target)
1083                 return;
1084
1085         for(vector<BlockAssignmentMap>::iterator j=assignments.end(); j!=assignments.begin(); )
1086         {
1087                 --j;
1088                 BlockAssignmentMap::iterator k = j->find(var.declaration);
1089                 if(k!=j->end())
1090                 {
1091                         for(vector<Node *>::iterator l=k->second.nodes.begin(); l!=k->second.nodes.end(); ++l)
1092                                 unused_nodes.erase(*l);
1093                         j->erase(k);
1094                         break;
1095                 }
1096         }
1097 }
1098
1099 void ProgramCompiler::UnusedVariableLocator::visit(MemberAccess &memacc)
1100 {
1101         TraversingVisitor::visit(memacc);
1102         unused_nodes.erase(memacc.declaration);
1103 }
1104
1105 void ProgramCompiler::UnusedVariableLocator::visit(BinaryExpression &binary)
1106 {
1107         if(binary.oper=="[")
1108         {
1109                 binary.left->visit(*this);
1110                 SetForScope<bool> set(assignment_target, false);
1111                 binary.right->visit(*this);
1112         }
1113         else
1114                 TraversingVisitor::visit(binary);
1115 }
1116
1117 void ProgramCompiler::UnusedVariableLocator::visit(Assignment &assign)
1118 {
1119         {
1120                 SetForScope<bool> set(assignment_target, !assign.self_referencing);
1121                 assign.left->visit(*this);
1122         }
1123         assign.right->visit(*this);
1124         assignment = &assign;
1125 }
1126
1127 void ProgramCompiler::UnusedVariableLocator::record_assignment(VariableDeclaration &var, Node &node, bool self_ref)
1128 {
1129         unused_nodes.insert(&node);
1130         BlockAssignmentMap &block_assignments = assignments.back();
1131         AssignmentList &var_assignments = block_assignments[&var];
1132         if(!self_ref)
1133                 var_assignments.nodes.clear();
1134         var_assignments.nodes.push_back(&node);
1135         var_assignments.conditional = false;
1136         var_assignments.self_referencing = self_ref;
1137 }
1138
1139 void ProgramCompiler::UnusedVariableLocator::visit(ExpressionStatement &expr)
1140 {
1141         assignment = 0;
1142         TraversingVisitor::visit(expr);
1143         if(assignment && assignment->target_declaration)
1144                 record_assignment(*assignment->target_declaration, expr, assignment->self_referencing);
1145 }
1146
1147 void ProgramCompiler::UnusedVariableLocator::visit(StructDeclaration &strct)
1148 {
1149         SetForScope<Node *> set(aggregate, &strct);
1150         unused_nodes.insert(&strct);
1151         TraversingVisitor::visit(strct);
1152 }
1153
1154 void ProgramCompiler::UnusedVariableLocator::visit(VariableDeclaration &var)
1155 {
1156         if(aggregate)
1157                 aggregates[&var] = aggregate;
1158         else
1159         {
1160                 unused_nodes.insert(&var);
1161                 if(var.init_expression)
1162                         record_assignment(var, *var.init_expression, false);
1163         }
1164         unused_nodes.erase(var.type_declaration);
1165         TraversingVisitor::visit(var);
1166 }
1167
1168 void ProgramCompiler::UnusedVariableLocator::visit(InterfaceBlock &iface)
1169 {
1170         SetForScope<Node *> set(aggregate, &iface);
1171         unused_nodes.insert(&iface);
1172         TraversingVisitor::visit(iface);
1173 }
1174
1175 void ProgramCompiler::UnusedVariableLocator::visit(FunctionDeclaration &func)
1176 {
1177         assignments.push_back(BlockAssignmentMap());
1178
1179         for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
1180                 (*i)->visit(*this);
1181         func.body.visit(*this);
1182
1183         BlockAssignmentMap &block_assignments = assignments.back();
1184         for(map<string, VariableDeclaration *>::iterator i=func.body.variables.begin(); i!=func.body.variables.end(); ++i)
1185                 block_assignments.erase(i->second);
1186         for(BlockAssignmentMap::iterator i=block_assignments.begin(); i!=block_assignments.end(); ++i)
1187         {
1188                 if(i->first->interface=="out" && stage->type!=FRAGMENT && !i->first->linked_declaration)
1189                         continue;
1190
1191                 for(vector<Node *>::iterator j=i->second.nodes.begin(); j!=i->second.nodes.end(); ++j)
1192                         unused_nodes.erase(*j);
1193         }
1194
1195         assignments.pop_back();
1196 }
1197
1198 void ProgramCompiler::UnusedVariableLocator::merge_down_assignments()
1199 {
1200         BlockAssignmentMap &parent_assignments = assignments[assignments.size()-2];
1201         BlockAssignmentMap &block_assignments = assignments.back();
1202         for(BlockAssignmentMap::iterator i=block_assignments.begin(); i!=block_assignments.end(); ++i)
1203         {
1204                 BlockAssignmentMap::iterator j = parent_assignments.find(i->first);
1205                 if(j==parent_assignments.end())
1206                         parent_assignments.insert(*i);
1207                 else if(i->second.self_referencing || i->second.conditional)
1208                 {
1209                         j->second.nodes.insert(j->second.nodes.end(), i->second.nodes.begin(), i->second.nodes.end());
1210                         j->second.conditional |= i->second.conditional;
1211                         j->second.self_referencing |= i->second.self_referencing;
1212                 }
1213                 else
1214                         j->second = i->second;
1215         }
1216         assignments.pop_back();
1217 }
1218
1219 void ProgramCompiler::UnusedVariableLocator::visit(Conditional &cond)
1220 {
1221         cond.condition->visit(*this);
1222         assignments.push_back(BlockAssignmentMap());
1223         cond.body.visit(*this);
1224
1225         BlockAssignmentMap if_assignments;
1226         swap(assignments.back(), if_assignments);
1227         cond.else_body.visit(*this);
1228
1229         BlockAssignmentMap &else_assignments = assignments.back();
1230         for(BlockAssignmentMap::iterator i=else_assignments.begin(); i!=else_assignments.end(); ++i)
1231         {
1232                 BlockAssignmentMap::iterator j = if_assignments.find(i->first);
1233                 if(j!=if_assignments.end())
1234                 {
1235                         i->second.nodes.insert(i->second.nodes.end(), j->second.nodes.begin(), j->second.nodes.end());
1236                         i->second.conditional |= j->second.conditional;
1237                         i->second.self_referencing |= j->second.self_referencing;
1238                         if_assignments.erase(j);
1239                 }
1240                 else
1241                         i->second.conditional = true;
1242         }
1243
1244         for(BlockAssignmentMap::iterator i=if_assignments.begin(); i!=if_assignments.end(); ++i)
1245         {
1246                 i->second.conditional = true;
1247                 else_assignments.insert(*i);
1248         }
1249
1250         merge_down_assignments();
1251 }
1252
1253 void ProgramCompiler::UnusedVariableLocator::visit(Iteration &iter)
1254 {
1255         assignments.push_back(BlockAssignmentMap());
1256         TraversingVisitor::visit(iter);
1257         merge_down_assignments();
1258 }
1259
1260
1261 void ProgramCompiler::UnusedFunctionLocator::visit(FunctionCall &call)
1262 {
1263         TraversingVisitor::visit(call);
1264
1265         unused_nodes.erase(call.declaration);
1266         if(call.declaration && call.declaration->definition!=call.declaration)
1267                 used_definitions.insert(call.declaration->definition);
1268 }
1269
1270 void ProgramCompiler::UnusedFunctionLocator::visit(FunctionDeclaration &func)
1271 {
1272         TraversingVisitor::visit(func);
1273
1274         if(func.name!="main" && !used_definitions.count(&func))
1275                 unused_nodes.insert(&func);
1276 }
1277
1278
1279 ProgramCompiler::NodeRemover::NodeRemover(const set<Node *> &r):
1280         to_remove(r)
1281 { }
1282
1283 void ProgramCompiler::NodeRemover::visit(Block &block)
1284 {
1285         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
1286         {
1287                 (*i)->visit(*this);
1288                 if(to_remove.count(i->get()))
1289                         block.body.erase(i++);
1290                 else
1291                         ++i;
1292         }
1293 }
1294
1295 void ProgramCompiler::NodeRemover::visit(VariableDeclaration &var)
1296 {
1297         if(to_remove.count(&var))
1298         {
1299                 stage->in_variables.erase(var.name);
1300                 stage->out_variables.erase(var.name);
1301                 stage->locations.erase(var.name);
1302                 if(var.linked_declaration)
1303                         var.linked_declaration->linked_declaration = 0;
1304         }
1305         else if(var.init_expression && to_remove.count(var.init_expression.get()))
1306                 var.init_expression = 0;
1307 }
1308
1309
1310 ProgramCompiler::LegacyConverter::LegacyConverter():
1311         target_version(get_glsl_version())
1312 { }
1313
1314 ProgramCompiler::LegacyConverter::LegacyConverter(const Version &v):
1315         target_version(v)
1316 { }
1317
1318 bool ProgramCompiler::LegacyConverter::check_version(const Version &feature_version)
1319 {
1320         if(target_version<feature_version)
1321                 return false;
1322         else if(stage->required_version<feature_version)
1323                 stage->required_version = feature_version;
1324
1325         return true;
1326 }
1327
1328 void ProgramCompiler::LegacyConverter::visit(VariableReference &var)
1329 {
1330         if(var.name==frag_out_name && !check_version(Version(1, 30)))
1331         {
1332                 var.name = "gl_FragColor";
1333                 var.declaration = 0;
1334                 type = "vec4";
1335         }
1336         else if(var.declaration)
1337                 type = var.declaration->type;
1338         else
1339                 type = string();
1340 }
1341
1342 void ProgramCompiler::LegacyConverter::visit(FunctionCall &call)
1343 {
1344         if(call.name=="texture" && !call.declaration && !check_version(Version(1, 30)))
1345         {
1346                 vector<RefPtr<Expression> >::iterator i = call.arguments.begin();
1347                 if(i!=call.arguments.end())
1348                 {
1349                         (*i)->visit(*this);
1350                         if(type=="sampler1D")
1351                                 call.name = "texture1D";
1352                         else if(type=="sampler2D")
1353                                 call.name = "texture2D";
1354                         else if(type=="sampler3D")
1355                                 call.name = "texture3D";
1356                         else if(type=="sampler1DShadow")
1357                                 call.name = "shadow1D";
1358                         else if(type=="sampler2DShadow")
1359                                 call.name = "shadow2D";
1360
1361                         for(; i!=call.arguments.end(); ++i)
1362                                 (*i)->visit(*this);
1363                 }
1364         }
1365         else
1366                 TraversingVisitor::visit(call);
1367 }
1368
1369 void ProgramCompiler::LegacyConverter::visit(VariableDeclaration &var)
1370 {
1371         if(var.layout && !check_version(Version(3, 30)))
1372         {
1373                 vector<Layout::Qualifier>::iterator i;
1374                 for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->identifier!="location"); ++i) ;
1375                 if(i!=var.layout->qualifiers.end())
1376                 {
1377                         unsigned location = lexical_cast<unsigned>(i->value);
1378                         if(stage->type==VERTEX && var.interface=="in")
1379                         {
1380                                 stage->locations[var.name] = location;
1381                                 var.layout->qualifiers.erase(i);
1382                         }
1383                         else if(stage->type==FRAGMENT && var.interface=="out")
1384                         {
1385                                 stage->locations[var.name] = location;
1386                                 var.layout->qualifiers.erase(i);
1387                         }
1388
1389                         if(var.layout->qualifiers.empty())
1390                                 var.layout = 0;
1391                 }
1392         }
1393
1394         if((var.interface=="in" || var.interface=="out") && !check_version(Version(1, 30)))
1395         {
1396                 if(stage->type==VERTEX && var.interface=="in")
1397                         var.interface = "attribute";
1398                 else if((stage->type==VERTEX && var.interface=="out") || (stage->type==FRAGMENT && var.interface=="in"))
1399                         var.interface = "varying";
1400                 else if(stage->type==FRAGMENT && var.interface=="out")
1401                 {
1402                         frag_out_name = var.name;
1403                         remove_node = true;
1404                 }
1405         }
1406
1407         TraversingVisitor::visit(var);
1408 }
1409
1410 void ProgramCompiler::LegacyConverter::visit(InterfaceBlock &iface)
1411 {
1412         if(!check_version(Version(1, 50)))
1413                 flatten_block(iface.members);
1414 }
1415
1416 } // namespace GL
1417 } // namespace Msp