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