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