]> git.tdb.fi Git - libs/gl.git/blob - source/programcompiler.cpp
9761177a8086be6ac0e16f69fa29974398548e57
[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         stmt->visit(*this);
864         insert_nodes.push_back(stmt);
865 }
866
867 void ProgramCompiler::InterfaceGenerator::visit(VariableReference &var)
868 {
869         if(var.declaration || !stage->previous)
870                 return;
871         if(iface_declarations.count(var.name))
872                 return;
873
874         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
875         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
876         if(i==prev_out.end())
877                 i = prev_out.find(in_prefix+var.name);
878         if(i!=prev_out.end())
879         {
880                 generate_interface(*i->second, "in", i->second->name);
881                 var.name = i->second->name;
882         }
883 }
884
885 void ProgramCompiler::InterfaceGenerator::visit(VariableDeclaration &var)
886 {
887         if(var.interface=="out")
888         {
889                 if(scope_level==1)
890                         stage->out_variables[var.name] = &var;
891                 else if(generate_interface(var, "out", change_prefix(var.name, string())))
892                 {
893                         remove_node = true;
894                         if(var.init_expression)
895                         {
896                                 insert_assignment(var.name, var.init_expression->clone());
897                                 return;
898                         }
899                 }
900         }
901         else if(var.interface=="in")
902         {
903                 stage->in_variables[var.name] = &var;
904                 if(var.linked_declaration)
905                         var.linked_declaration->linked_declaration = &var;
906                 else if(stage->previous)
907                 {
908                         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
909                         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
910                         if(i!=prev_out.end())
911                         {
912                                 var.linked_declaration = i->second;
913                                 i->second->linked_declaration = &var;
914                         }
915                 }
916         }
917
918         TraversingVisitor::visit(var);
919 }
920
921 void ProgramCompiler::InterfaceGenerator::visit(Passthrough &pass)
922 {
923         vector<VariableDeclaration *> pass_vars;
924
925         for(map<string, VariableDeclaration *>::const_iterator i=stage->in_variables.begin(); i!=stage->in_variables.end(); ++i)
926                 pass_vars.push_back(i->second);
927         for(map<string, RefPtr<VariableDeclaration> >::const_iterator i=iface_declarations.begin(); i!=iface_declarations.end(); ++i)
928                 if(i->second->interface=="in")
929                         pass_vars.push_back(i->second.get());
930
931         if(stage->previous)
932         {
933                 const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
934                 for(map<string, VariableDeclaration *>::const_iterator i=prev_out.begin(); i!=prev_out.end(); ++i)
935                 {
936                         bool linked = false;
937                         for(vector<VariableDeclaration *>::const_iterator j=pass_vars.begin(); (!linked && j!=pass_vars.end()); ++j)
938                                 linked = ((*j)->linked_declaration==i->second);
939
940                         if(!linked && generate_interface(*i->second, "in", i->second->name))
941                                 pass_vars.push_back(i->second);
942                 }
943         }
944
945         if(stage->type==GEOMETRY)
946         {
947                 VariableReference *ref = new VariableReference;
948                 ref->name = "gl_in";
949
950                 BinaryExpression *subscript = new BinaryExpression;
951                 subscript->left = ref;
952                 subscript->oper = "[";
953                 subscript->right = pass.subscript;
954                 subscript->after = "]";
955
956                 MemberAccess *memacc = new MemberAccess;
957                 memacc->left = subscript;
958                 memacc->member = "gl_Position";
959
960                 insert_assignment("gl_Position", memacc);
961         }
962
963         for(vector<VariableDeclaration *>::const_iterator i=pass_vars.begin(); i!=pass_vars.end(); ++i)
964         {
965                 string out_name = change_prefix((*i)->name, out_prefix);
966                 generate_interface(**i, "out", out_name);
967
968                 VariableReference *ref = new VariableReference;
969                 ref->name = (*i)->name;
970                 if(pass.subscript)
971                 {
972                         BinaryExpression *subscript = new BinaryExpression;
973                         subscript->left = ref;
974                         subscript->oper = "[";
975                         subscript->right = pass.subscript;
976                         subscript->after = "]";
977                         insert_assignment(out_name, subscript);
978                 }
979                 else
980                         insert_assignment(out_name, ref);
981         }
982
983         remove_node = true;
984 }
985
986
987 ProgramCompiler::DeclarationReorderer::DeclarationReorderer():
988         kind(NO_DECLARATION)
989 { }
990
991 void ProgramCompiler::DeclarationReorderer::visit(Block &block)
992 {
993         list<RefPtr<Node> >::iterator struct_insert_point = block.body.end();
994         list<RefPtr<Node> >::iterator variable_insert_point = block.body.end();
995
996         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
997         {
998                 kind = NO_DECLARATION;
999                 (*i)->visit(*this);
1000
1001                 bool moved = false;
1002                 if(kind==STRUCT && struct_insert_point!=block.body.end())
1003                 {
1004                         block.body.insert(struct_insert_point, *i);
1005                         moved = true;
1006                 }
1007                 else if(kind>STRUCT && struct_insert_point==block.body.end())
1008                         struct_insert_point = i;
1009
1010                 if(kind==VARIABLE && variable_insert_point!=block.body.end())
1011                 {
1012                         block.body.insert(variable_insert_point, *i);
1013                         moved = true;
1014                 }
1015                 else if(kind>VARIABLE && variable_insert_point==block.body.end())
1016                         variable_insert_point = i;
1017
1018                 if(moved)
1019                         block.body.erase(i++);
1020                 else
1021                         ++i;
1022         }
1023 }
1024
1025
1026 ProgramCompiler::InlineableFunctionLocator::InlineableFunctionLocator():
1027         in_function(0)
1028 { }
1029
1030 void ProgramCompiler::InlineableFunctionLocator::visit(FunctionCall &call)
1031 {
1032         FunctionDeclaration *def = call.declaration;
1033         if(def && def->definition!=def)
1034                 def = def->definition;
1035
1036         if(def)
1037         {
1038                 unsigned &count = refcounts[def];
1039                 ++count;
1040                 if(count>1 || def==in_function)
1041                         inlineable.erase(def);
1042         }
1043
1044         TraversingVisitor::visit(call);
1045 }
1046
1047 void ProgramCompiler::InlineableFunctionLocator::visit(FunctionDeclaration &func)
1048 {
1049         unsigned &count = refcounts[func.definition];
1050         if(!count && func.parameters.empty())
1051                 inlineable.insert(func.definition);
1052
1053         SetForScope<FunctionDeclaration *> set(in_function, &func);
1054         TraversingVisitor::visit(func);
1055 }
1056
1057
1058 ProgramCompiler::FunctionInliner::FunctionInliner():
1059         extract_result(0)
1060 { }
1061
1062 ProgramCompiler::FunctionInliner::FunctionInliner(const set<FunctionDeclaration *> &in):
1063         inlineable(in),
1064         extract_result(0)
1065 { }
1066
1067 void ProgramCompiler::FunctionInliner::visit_and_inline(RefPtr<Expression> &ptr)
1068 {
1069         inline_result = 0;
1070         ptr->visit(*this);
1071         if(inline_result)
1072                 ptr = inline_result;
1073 }
1074
1075 void ProgramCompiler::FunctionInliner::visit(Block &block)
1076 {
1077         if(extract_result)
1078                 --extract_result;
1079
1080         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
1081         {
1082                 (*i)->visit(*this);
1083                 if(extract_result)
1084                         --extract_result;
1085         }
1086 }
1087
1088 void ProgramCompiler::FunctionInliner::visit(UnaryExpression &unary)
1089 {
1090         visit_and_inline(unary.expression);
1091         inline_result = 0;
1092 }
1093
1094 void ProgramCompiler::FunctionInliner::visit(BinaryExpression &binary)
1095 {
1096         visit_and_inline(binary.left);
1097         visit_and_inline(binary.right);
1098         inline_result = 0;
1099 }
1100
1101 void ProgramCompiler::FunctionInliner::visit(FunctionCall &call)
1102 {
1103         for(vector<RefPtr<Expression> >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
1104                 visit_and_inline(*i);
1105
1106         FunctionDeclaration *def = call.declaration;
1107         if(def && def->definition!=def)
1108                 def = def->definition;
1109
1110         if(def && inlineable.count(def))
1111         {
1112                 extract_result = 2;
1113                 def->visit(*this);
1114         }
1115         else
1116                 inline_result = 0;
1117 }
1118
1119 void ProgramCompiler::FunctionInliner::visit(Return &ret)
1120 {
1121         TraversingVisitor::visit(ret);
1122
1123         if(extract_result)
1124                 inline_result = ret.expression->clone();
1125 }
1126
1127
1128 ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator():
1129         variable_values(0),
1130         result(0.0f),
1131         result_valid(false)
1132 { }
1133
1134 ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(const ValueMap &v):
1135         variable_values(&v),
1136         result(0.0f),
1137         result_valid(false)
1138 { }
1139
1140 void ProgramCompiler::ExpressionEvaluator::visit(Literal &literal)
1141 {
1142         if(literal.token=="true")
1143                 result = 1.0f;
1144         else if(literal.token=="false")
1145                 result = 0.0f;
1146         else
1147                 result = lexical_cast<float>(literal.token);
1148         result_valid = true;
1149 }
1150
1151 void ProgramCompiler::ExpressionEvaluator::visit(ParenthesizedExpression &parexp)
1152 {
1153         parexp.expression->visit(*this);
1154 }
1155
1156 void ProgramCompiler::ExpressionEvaluator::visit(VariableReference &var)
1157 {
1158         if(!var.declaration)
1159                 return;
1160
1161         if(variable_values)
1162         {
1163                 ValueMap::const_iterator i = variable_values->find(var.declaration);
1164                 if(i!=variable_values->end())
1165                         i->second->visit(*this);
1166         }
1167         else if(var.declaration->init_expression)
1168                 var.declaration->init_expression->visit(*this);
1169 }
1170
1171 void ProgramCompiler::ExpressionEvaluator::visit(UnaryExpression &unary)
1172 {
1173         result_valid = false;
1174         unary.expression->visit(*this);
1175         if(!result_valid)
1176                 return;
1177
1178         if(unary.oper=="!")
1179                 result = !result;
1180         else
1181                 result_valid = false;
1182 }
1183
1184 void ProgramCompiler::ExpressionEvaluator::visit(BinaryExpression &binary)
1185 {
1186         result_valid = false;
1187         binary.left->visit(*this);
1188         if(!result_valid)
1189                 return;
1190
1191         float left_result = result;
1192         result_valid = false;
1193         binary.right->visit(*this);
1194         if(!result_valid)
1195                 return;
1196
1197         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 if(binary.oper=="&&")
1210                 result = (left_result && result);
1211         else if(binary.oper=="||")
1212                 result = (left_result || result);
1213         else
1214                 result_valid = false;
1215 }
1216
1217
1218 ProgramCompiler::ConstantConditionEliminator::ConstantConditionEliminator():
1219         scope_level(0)
1220 { }
1221
1222 void ProgramCompiler::ConstantConditionEliminator::visit(Block &block)
1223 {
1224         SetForScope<unsigned> set(scope_level, scope_level+1);
1225         BlockModifier::visit(block);
1226
1227         for(map<string, VariableDeclaration *>::const_iterator i=block.variables.begin(); i!=block.variables.end(); ++i)
1228                 variable_values.erase(i->second);
1229 }
1230
1231 void ProgramCompiler::ConstantConditionEliminator::visit(Assignment &assign)
1232 {
1233         variable_values.erase(assign.target_declaration);
1234 }
1235
1236 void ProgramCompiler::ConstantConditionEliminator::visit(VariableDeclaration &var)
1237 {
1238         if(var.constant || scope_level>1)
1239                 variable_values[&var] = var.init_expression.get();
1240 }
1241
1242 void ProgramCompiler::ConstantConditionEliminator::visit(Conditional &cond)
1243 {
1244         ExpressionEvaluator eval(variable_values);
1245         cond.condition->visit(eval);
1246         if(eval.result_valid)
1247                 flatten_block(eval.result ? cond.body : cond.else_body);
1248         else
1249                 TraversingVisitor::visit(cond);
1250 }
1251
1252 void ProgramCompiler::ConstantConditionEliminator::visit(Iteration &iter)
1253 {
1254         if(iter.condition)
1255         {
1256                 ExpressionEvaluator eval;
1257                 iter.condition->visit(eval);
1258                 if(eval.result_valid && !eval.result)
1259                 {
1260                         remove_node = true;
1261                         return;
1262                 }
1263         }
1264
1265         TraversingVisitor::visit(iter);
1266 }
1267
1268
1269 ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator():
1270         aggregate(0),
1271         assignment(0),
1272         assignment_target(false),
1273         global_scope(true)
1274 { }
1275
1276 void ProgramCompiler::UnusedVariableLocator::apply(Stage &s)
1277 {
1278         variables.push_back(BlockVariableMap());
1279         Visitor::apply(s);
1280         BlockVariableMap &global_variables = variables.back();
1281         for(BlockVariableMap::iterator i=global_variables.begin(); i!=global_variables.end(); ++i)
1282         {
1283                 if(i->first->interface=="out" && (s.type==FRAGMENT || i->first->linked_declaration || !i->first->name.compare(0, 3, "gl_")))
1284                         continue;
1285                 if(!i->second.referenced)
1286                 {
1287                         unused_nodes.insert(i->first);
1288                         clear_assignments(i->second, true);
1289                 }
1290         }
1291         variables.pop_back();
1292 }
1293
1294 void ProgramCompiler::UnusedVariableLocator::visit(VariableReference &var)
1295 {
1296         map<VariableDeclaration *, Node *>::iterator i = aggregates.find(var.declaration);
1297         if(i!=aggregates.end())
1298                 unused_nodes.erase(i->second);
1299
1300         if(var.declaration && !assignment_target)
1301         {
1302                 VariableInfo &var_info = variables.back()[var.declaration];
1303                 var_info.assignments.clear();
1304                 var_info.referenced = true;
1305         }
1306 }
1307
1308 void ProgramCompiler::UnusedVariableLocator::visit(MemberAccess &memacc)
1309 {
1310         TraversingVisitor::visit(memacc);
1311         unused_nodes.erase(memacc.declaration);
1312 }
1313
1314 void ProgramCompiler::UnusedVariableLocator::visit(BinaryExpression &binary)
1315 {
1316         if(binary.oper=="[")
1317         {
1318                 binary.left->visit(*this);
1319                 SetForScope<bool> set(assignment_target, false);
1320                 binary.right->visit(*this);
1321         }
1322         else
1323                 TraversingVisitor::visit(binary);
1324 }
1325
1326 void ProgramCompiler::UnusedVariableLocator::visit(Assignment &assign)
1327 {
1328         {
1329                 SetForScope<bool> set(assignment_target, !assign.self_referencing);
1330                 assign.left->visit(*this);
1331         }
1332         assign.right->visit(*this);
1333         assignment = &assign;
1334 }
1335
1336 void ProgramCompiler::UnusedVariableLocator::record_assignment(VariableDeclaration &var, Node &node, bool self_ref)
1337 {
1338         VariableInfo &var_info = variables.back()[&var];
1339         if(!self_ref)
1340                 clear_assignments(var_info, true);
1341         var_info.assignments.push_back(&node);
1342         var_info.conditionally_assigned = false;
1343 }
1344
1345 void ProgramCompiler::UnusedVariableLocator::clear_assignments(VariableInfo &var_info, bool mark_unused)
1346 {
1347         if(mark_unused)
1348         {
1349                 for(vector<Node *>::iterator i=var_info.assignments.begin(); i!=var_info.assignments.end(); ++i)
1350                         unused_nodes.insert(*i);
1351         }
1352         var_info.assignments.clear();
1353 }
1354
1355 void ProgramCompiler::UnusedVariableLocator::visit(ExpressionStatement &expr)
1356 {
1357         assignment = 0;
1358         TraversingVisitor::visit(expr);
1359         if(assignment && assignment->target_declaration)
1360                 record_assignment(*assignment->target_declaration, expr, assignment->self_referencing);
1361 }
1362
1363 void ProgramCompiler::UnusedVariableLocator::visit(StructDeclaration &strct)
1364 {
1365         SetForScope<Node *> set(aggregate, &strct);
1366         unused_nodes.insert(&strct);
1367         TraversingVisitor::visit(strct);
1368 }
1369
1370 void ProgramCompiler::UnusedVariableLocator::visit(VariableDeclaration &var)
1371 {
1372         if(aggregate)
1373                 aggregates[&var] = aggregate;
1374         else
1375         {
1376                 variables.back()[&var].local = true;
1377                 if(var.init_expression)
1378                         record_assignment(var, *var.init_expression, false);
1379         }
1380         unused_nodes.erase(var.type_declaration);
1381         TraversingVisitor::visit(var);
1382 }
1383
1384 void ProgramCompiler::UnusedVariableLocator::visit(InterfaceBlock &iface)
1385 {
1386         SetForScope<Node *> set(aggregate, &iface);
1387         unused_nodes.insert(&iface);
1388         TraversingVisitor::visit(iface);
1389 }
1390
1391 void ProgramCompiler::UnusedVariableLocator::visit(FunctionDeclaration &func)
1392 {
1393         variables.push_back(BlockVariableMap());
1394
1395         {
1396                 SetForScope<bool> set(global_scope, false);
1397                 for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
1398                         (*i)->visit(*this);
1399                 func.body.visit(*this);
1400         }
1401
1402         BlockVariableMap &block_variables = variables.back();
1403         for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
1404                 i->second.conditionally_assigned = true;
1405         for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
1406                 block_variables[i->get()].referenced = true;
1407         merge_down_variables();
1408 }
1409
1410 void ProgramCompiler::UnusedVariableLocator::merge_down_variables()
1411 {
1412         BlockVariableMap &parent_variables = variables[variables.size()-2];
1413         BlockVariableMap &block_variables = variables.back();
1414         for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
1415         {
1416                 if(i->second.local)
1417                 {
1418                         if(!i->second.referenced)
1419                                 unused_nodes.insert(i->first);
1420                         clear_assignments(i->second, true);
1421                         continue;
1422                 }
1423
1424                 BlockVariableMap::iterator j = parent_variables.find(i->first);
1425                 if(j==parent_variables.end())
1426                         parent_variables.insert(*i);
1427                 else
1428                 {
1429                         if(i->second.referenced || !i->second.conditionally_assigned)
1430                                 clear_assignments(j->second, !i->second.referenced);
1431                         j->second.conditionally_assigned = i->second.conditionally_assigned;
1432                         j->second.referenced |= i->second.referenced;
1433                         j->second.assignments.insert(j->second.assignments.end(), i->second.assignments.begin(), i->second.assignments.end());
1434                 }
1435         }
1436         variables.pop_back();
1437 }
1438
1439 void ProgramCompiler::UnusedVariableLocator::visit(Conditional &cond)
1440 {
1441         cond.condition->visit(*this);
1442         variables.push_back(BlockVariableMap());
1443         cond.body.visit(*this);
1444
1445         BlockVariableMap if_variables;
1446         swap(variables.back(), if_variables);
1447         cond.else_body.visit(*this);
1448
1449         BlockVariableMap &else_variables = variables.back();
1450         for(BlockVariableMap::iterator i=else_variables.begin(); i!=else_variables.end(); ++i)
1451         {
1452                 BlockVariableMap::iterator j = if_variables.find(i->first);
1453                 if(j!=if_variables.end())
1454                 {
1455                         i->second.assignments.insert(i->second.assignments.end(), j->second.assignments.begin(), j->second.assignments.end());
1456                         i->second.conditionally_assigned |= j->second.conditionally_assigned;
1457                         if_variables.erase(j);
1458                 }
1459                 else
1460                         i->second.conditionally_assigned = true;
1461         }
1462
1463         for(BlockVariableMap::iterator i=if_variables.begin(); i!=if_variables.end(); ++i)
1464         {
1465                 i->second.conditionally_assigned = true;
1466                 else_variables.insert(*i);
1467         }
1468
1469         merge_down_variables();
1470 }
1471
1472 void ProgramCompiler::UnusedVariableLocator::visit(Iteration &iter)
1473 {
1474         variables.push_back(BlockVariableMap());
1475         TraversingVisitor::visit(iter);
1476
1477         BlockVariableMap &block_variables = variables.back();
1478         for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
1479                 if(!i->second.local && i->second.referenced)
1480                         i->second.assignments.clear();
1481
1482         merge_down_variables();
1483 }
1484
1485
1486 ProgramCompiler::UnusedVariableLocator::VariableInfo::VariableInfo():
1487         local(false),
1488         conditionally_assigned(false),
1489         referenced(false)
1490 { }
1491
1492
1493 void ProgramCompiler::UnusedFunctionLocator::visit(FunctionCall &call)
1494 {
1495         TraversingVisitor::visit(call);
1496
1497         unused_nodes.erase(call.declaration);
1498         if(call.declaration && call.declaration->definition!=call.declaration)
1499                 used_definitions.insert(call.declaration->definition);
1500 }
1501
1502 void ProgramCompiler::UnusedFunctionLocator::visit(FunctionDeclaration &func)
1503 {
1504         TraversingVisitor::visit(func);
1505
1506         if((func.name!="main" || func.body.body.empty()) && !used_definitions.count(&func))
1507                 unused_nodes.insert(&func);
1508 }
1509
1510
1511 ProgramCompiler::NodeRemover::NodeRemover(const set<Node *> &r):
1512         to_remove(r)
1513 { }
1514
1515 void ProgramCompiler::NodeRemover::visit(Block &block)
1516 {
1517         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
1518         {
1519                 (*i)->visit(*this);
1520                 if(to_remove.count(i->get()))
1521                         block.body.erase(i++);
1522                 else
1523                         ++i;
1524         }
1525 }
1526
1527 void ProgramCompiler::NodeRemover::visit(VariableDeclaration &var)
1528 {
1529         if(to_remove.count(&var))
1530         {
1531                 stage->in_variables.erase(var.name);
1532                 stage->out_variables.erase(var.name);
1533                 stage->locations.erase(var.name);
1534                 if(var.linked_declaration)
1535                         var.linked_declaration->linked_declaration = 0;
1536         }
1537         else if(var.init_expression && to_remove.count(var.init_expression.get()))
1538                 var.init_expression = 0;
1539 }
1540
1541
1542 void ProgramCompiler::PrecisionRemover::visit(Precision &)
1543 {
1544         remove_node = true;
1545 }
1546
1547 void ProgramCompiler::PrecisionRemover::visit(VariableDeclaration &var)
1548 {
1549         var.precision.clear();
1550 }
1551
1552
1553 ProgramCompiler::DefaultPrecisionGenerator::DefaultPrecisionGenerator():
1554         toplevel(true)
1555 { }
1556
1557 void ProgramCompiler::DefaultPrecisionGenerator::visit(Block &block)
1558 {
1559         if(toplevel)
1560         {
1561                 SetForScope<bool> set(toplevel, false);
1562                 BlockModifier::visit(block);
1563         }
1564         else
1565                 Visitor::visit(block);
1566 }
1567
1568 void ProgramCompiler::DefaultPrecisionGenerator::visit(Precision &prec)
1569 {
1570         have_default.insert(prec.type);
1571 }
1572
1573 void ProgramCompiler::DefaultPrecisionGenerator::visit(VariableDeclaration &var)
1574 {
1575         if(var.type_declaration)
1576                 return;
1577
1578         string type = var.type;
1579         if(!type.compare(0, 3, "vec") || !type.compare(0, 3, "mat"))
1580                 type = "float";
1581         else if(!type.compare(0, 3, "ivec") || type=="uint")
1582                 type = "int";
1583
1584         if(!have_default.count(type))
1585         {
1586                 Precision *prec = new Precision;
1587                 if(!type.compare(0, 7, "sampler"))
1588                         prec->precision = "lowp";
1589                 else if(stage->type==FRAGMENT)
1590                         prec->precision = "mediump";
1591                 else
1592                         prec->precision = "highp";
1593                 prec->type = type;
1594                 insert_nodes.push_back(prec);
1595
1596                 have_default.insert(type);
1597         }
1598 }
1599
1600
1601 ProgramCompiler::LegacyConverter::LegacyConverter():
1602         target_api(get_gl_api()),
1603         target_version(get_glsl_version()),
1604         frag_out(0)
1605 { }
1606
1607 ProgramCompiler::LegacyConverter::LegacyConverter(const Version &v):
1608         target_api(get_gl_api()),
1609         target_version(v),
1610         frag_out(0)
1611 { }
1612
1613 bool ProgramCompiler::LegacyConverter::check_version(const Version &feature_version) const
1614 {
1615         if(target_version<feature_version)
1616                 return false;
1617         else if(stage->required_version<feature_version)
1618                 stage->required_version = feature_version;
1619
1620         return true;
1621 }
1622
1623 bool ProgramCompiler::LegacyConverter::supports_unified_interface_syntax() const
1624 {
1625         if(target_api==OPENGL_ES2)
1626                 return check_version(Version(3, 0));
1627         else
1628                 return check_version(Version(1, 30));
1629 }
1630
1631 void ProgramCompiler::LegacyConverter::visit(VariableReference &var)
1632 {
1633         if(var.declaration==frag_out && !supports_unified_interface_syntax())
1634         {
1635                 var.name = "gl_FragColor";
1636                 var.declaration = 0;
1637                 type = "vec4";
1638         }
1639         else if(var.declaration)
1640                 type = var.declaration->type;
1641         else
1642                 type = string();
1643 }
1644
1645 void ProgramCompiler::LegacyConverter::visit(Assignment &assign)
1646 {
1647         TraversingVisitor::visit(assign);
1648         if(assign.target_declaration==frag_out && !supports_unified_interface_syntax())
1649                 assign.target_declaration = 0;
1650 }
1651
1652 bool ProgramCompiler::LegacyConverter::supports_unified_sampling_functions() const
1653 {
1654         if(target_api==OPENGL_ES2)
1655                 return check_version(Version(3, 0));
1656         else
1657                 return check_version(Version(1, 30));
1658 }
1659
1660 void ProgramCompiler::LegacyConverter::visit(FunctionCall &call)
1661 {
1662         if(call.name=="texture" && !call.declaration && !supports_unified_sampling_functions())
1663         {
1664                 vector<RefPtr<Expression> >::iterator i = call.arguments.begin();
1665                 if(i!=call.arguments.end())
1666                 {
1667                         (*i)->visit(*this);
1668                         if(type=="sampler1D")
1669                                 call.name = "texture1D";
1670                         else if(type=="sampler2D")
1671                                 call.name = "texture2D";
1672                         else if(type=="sampler3D")
1673                                 call.name = "texture3D";
1674                         else if(type=="sampler1DShadow")
1675                                 call.name = "shadow1D";
1676                         else if(type=="sampler2DShadow")
1677                                 call.name = "shadow2D";
1678
1679                         for(; i!=call.arguments.end(); ++i)
1680                                 (*i)->visit(*this);
1681                 }
1682         }
1683         else
1684                 TraversingVisitor::visit(call);
1685 }
1686
1687 bool ProgramCompiler::LegacyConverter::supports_interface_layouts() const
1688 {
1689         if(target_api==OPENGL_ES2)
1690                 return check_version(Version(3, 0));
1691         else
1692                 return check_version(Version(3, 30));
1693 }
1694
1695 void ProgramCompiler::LegacyConverter::visit(VariableDeclaration &var)
1696 {
1697         if(var.layout && !supports_interface_layouts())
1698         {
1699                 vector<Layout::Qualifier>::iterator i;
1700                 for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->identifier!="location"); ++i) ;
1701                 if(i!=var.layout->qualifiers.end())
1702                 {
1703                         unsigned location = lexical_cast<unsigned>(i->value);
1704                         if(stage->type==VERTEX && var.interface=="in")
1705                         {
1706                                 stage->locations[var.name] = location;
1707                                 var.layout->qualifiers.erase(i);
1708                         }
1709                         else if(stage->type==FRAGMENT && var.interface=="out")
1710                         {
1711                                 if(location!=0)
1712                                         static Require _req(EXT_gpu_shader4);
1713                                 stage->locations[var.name] = location;
1714                                 var.layout->qualifiers.erase(i);
1715                         }
1716
1717                         if(var.layout->qualifiers.empty())
1718                                 var.layout = 0;
1719                 }
1720         }
1721
1722         if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax())
1723         {
1724                 if(stage->type==FRAGMENT && var.interface=="out")
1725                 {
1726                         frag_out = &var;
1727                         remove_node = true;
1728                 }
1729         }
1730
1731         TraversingVisitor::visit(var);
1732 }
1733
1734 bool ProgramCompiler::LegacyConverter::supports_interface_blocks(const string &iface) const
1735 {
1736         if(target_api==OPENGL_ES2)
1737         {
1738                 if(iface=="uniform")
1739                         return check_version(Version(3, 0));
1740                 else
1741                         return check_version(Version(3, 20));
1742         }
1743         else
1744                 return check_version(Version(1, 50));
1745 }
1746
1747 void ProgramCompiler::LegacyConverter::visit(InterfaceBlock &iface)
1748 {
1749         if(!supports_interface_blocks(iface.interface))
1750                 flatten_block(iface.members);
1751 }
1752
1753 } // namespace GL
1754 } // namespace Msp