]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/generate.cpp
Split SL::Compiler into several files
[libs/gl.git] / source / glsl / generate.cpp
1 #include <msp/core/raii.h>
2 #include "builtin.h"
3 #include "generate.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace GL {
9 namespace SL {
10
11 DeclarationCombiner::DeclarationCombiner():
12         toplevel(true)
13 { }
14
15 void DeclarationCombiner::visit(Block &block)
16 {
17         if(!toplevel)
18                 return;
19
20         SetForScope<bool> set(toplevel, false);
21         BlockModifier::visit(block);
22 }
23
24 void DeclarationCombiner::visit(FunctionDeclaration &func)
25 {
26         vector<FunctionDeclaration *> &decls = functions[func.name];
27         if(func.definition)
28         {
29                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
30                 {
31                         (*i)->definition = func.definition;
32                         (*i)->body.body.clear();
33                 }
34         }
35         decls.push_back(&func);
36 }
37
38 void DeclarationCombiner::visit(VariableDeclaration &var)
39 {
40         VariableDeclaration *&ptr = variables[var.name];
41         if(ptr)
42         {
43                 ptr->type = var.type;
44                 if(var.init_expression)
45                         ptr->init_expression = var.init_expression;
46                 if(var.layout)
47                 {
48                         if(ptr->layout)
49                         {
50                                 for(vector<Layout::Qualifier>::iterator i=var.layout->qualifiers.begin(); i!=var.layout->qualifiers.end(); ++i)
51                                 {
52                                         bool found = false;
53                                         for(vector<Layout::Qualifier>::iterator j=ptr->layout->qualifiers.begin(); (!found && j!=ptr->layout->qualifiers.end()); ++j)
54                                                 if(j->identifier==i->identifier)
55                                                 {
56                                                         j->value = i->value;
57                                                         found = true;
58                                                 }
59
60                                         if(!found)
61                                                 ptr->layout->qualifiers.push_back(*i);
62                                 }
63                         }
64                         else
65                                 ptr->layout = var.layout;
66                 }
67                 remove_node = true;
68         }
69         else
70                 ptr = &var;
71 }
72
73
74 VariableResolver::VariableResolver():
75         anonymous(false),
76         record_target(false),
77         assignment_target(0),
78         self_referencing(false)
79 { }
80
81 void VariableResolver::apply(Stage &s)
82 {
83         SetForScope<Stage *> set(stage, &s);
84         Stage *builtins = get_builtins(stage->type);
85         if(builtins)
86                 blocks.push_back(&builtins->content);
87         stage->content.visit(*this);
88         if(builtins)
89                 blocks.pop_back();
90 }
91
92 void VariableResolver::visit(Block &block)
93 {
94         blocks.push_back(&block);
95         block.variables.clear();
96         TraversingVisitor::visit(block);
97         blocks.pop_back();
98 }
99
100 void VariableResolver::visit(VariableReference &var)
101 {
102         var.declaration = 0;
103         type = 0;
104         for(vector<Block *>::iterator i=blocks.end(); i!=blocks.begin(); )
105         {
106                 --i;
107                 map<string, VariableDeclaration *>::iterator j = (*i)->variables.find(var.name);
108                 if(j!=(*i)->variables.end())
109                 {
110                         var.declaration = j->second;
111                         type = j->second->type_declaration;
112                         break;
113                 }
114         }
115
116         if(record_target)
117         {
118                 if(assignment_target)
119                 {
120                         record_target = false;
121                         assignment_target = 0;
122                 }
123                 else
124                         assignment_target = var.declaration;
125         }
126         else if(var.declaration && var.declaration==assignment_target)
127                 self_referencing = true;
128 }
129
130 void VariableResolver::visit(MemberAccess &memacc)
131 {
132         type = 0;
133         TraversingVisitor::visit(memacc);
134         memacc.declaration = 0;
135         if(type)
136         {
137                 map<string, VariableDeclaration *>::iterator i = type->members.variables.find(memacc.member);
138                 if(i!=type->members.variables.end())
139                 {
140                         memacc.declaration = i->second;
141                         type = i->second->type_declaration;
142                 }
143                 else
144                         type = 0;
145         }
146 }
147
148 void VariableResolver::visit(BinaryExpression &binary)
149 {
150         if(binary.oper=="[")
151         {
152                 {
153                         SetForScope<bool> set(record_target, false);
154                         binary.right->visit(*this);
155                 }
156                 type = 0;
157                 binary.left->visit(*this);
158         }
159         else
160         {
161                 TraversingVisitor::visit(binary);
162                 type = 0;
163         }
164 }
165
166 void VariableResolver::visit(Assignment &assign)
167 {
168         {
169                 SetFlag set(record_target);
170                 assignment_target = 0;
171                 assign.left->visit(*this);
172         }
173
174         self_referencing = false;
175         assign.right->visit(*this);
176
177         assign.self_referencing = (self_referencing || assign.oper!="=");
178         assign.target_declaration = assignment_target;
179 }
180
181 void VariableResolver::visit(StructDeclaration &strct)
182 {
183         TraversingVisitor::visit(strct);
184         blocks.back()->types[strct.name] = &strct;
185 }
186
187 void VariableResolver::visit(VariableDeclaration &var)
188 {
189         for(vector<Block *>::iterator i=blocks.end(); i!=blocks.begin(); )
190         {
191                 --i;
192                 map<string, StructDeclaration *>::iterator j = (*i)->types.find(var.type);
193                 if(j!=(*i)->types.end())
194                         var.type_declaration = j->second;
195         }
196
197         if(!block_interface.empty() && var.interface.empty())
198                 var.interface = block_interface;
199
200         TraversingVisitor::visit(var);
201         blocks.back()->variables[var.name] = &var;
202         if(anonymous && blocks.size()>1)
203                 blocks[blocks.size()-2]->variables[var.name] = &var;
204 }
205
206 void VariableResolver::visit(InterfaceBlock &iface)
207 {
208         SetFlag set(anonymous);
209         SetForScope<string> set2(block_interface, iface.interface);
210         TraversingVisitor::visit(iface);
211 }
212
213
214 void FunctionResolver::visit(FunctionCall &call)
215 {
216         map<string, vector<FunctionDeclaration *> >::iterator i = functions.find(call.name);
217         if(i!=functions.end())
218                 call.declaration = i->second.back();
219
220         TraversingVisitor::visit(call);
221 }
222
223 void FunctionResolver::visit(FunctionDeclaration &func)
224 {
225         vector<FunctionDeclaration *> &decls = functions[func.name];
226         if(func.definition)
227         {
228                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
229                         (*i)->definition = func.definition;
230                 decls.clear();
231                 decls.push_back(&func);
232         }
233         else if(!decls.empty() && decls.back()->definition)
234                 func.definition = decls.back()->definition;
235         else
236                 decls.push_back(&func);
237
238         TraversingVisitor::visit(func);
239 }
240
241
242 InterfaceGenerator::InterfaceGenerator():
243         scope_level(0)
244 { }
245
246 string InterfaceGenerator::get_out_prefix(StageType type)
247 {
248         if(type==VERTEX)
249                 return "_vs_out_";
250         else if(type==GEOMETRY)
251                 return "_gs_out_";
252         else
253                 return string();
254 }
255
256 void InterfaceGenerator::apply(Stage &s)
257 {
258         SetForScope<Stage *> set(stage, &s);
259         if(stage->previous)
260                 in_prefix = get_out_prefix(stage->previous->type);
261         out_prefix = get_out_prefix(stage->type);
262         stage->content.visit(*this);
263 }
264
265 void InterfaceGenerator::visit(Block &block)
266 {
267         SetForScope<unsigned> set(scope_level, scope_level+1);
268         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); )
269         {
270                 (*i)->visit(*this);
271
272                 if(scope_level==1)
273                 {
274                         for(map<string, RefPtr<VariableDeclaration> >::iterator j=iface_declarations.begin(); j!=iface_declarations.end(); ++j)
275                         {
276                                 NodeList<Statement>::iterator k = block.body.insert(i, j->second);
277                                 (*k)->visit(*this);
278                         }
279                         iface_declarations.clear();
280                 }
281
282                 apply_and_increment(block, i);
283         }
284 }
285
286 string InterfaceGenerator::change_prefix(const string &name, const string &prefix) const
287 {
288         unsigned offset = (name.compare(0, in_prefix.size(), in_prefix) ? 0 : in_prefix.size());
289         return prefix+name.substr(offset);
290 }
291
292 bool InterfaceGenerator::generate_interface(VariableDeclaration &var, const string &iface, const string &name)
293 {
294         const map<string, VariableDeclaration *> &stage_vars = (iface=="in" ? stage->in_variables : stage->out_variables);
295         if(stage_vars.count(name) || iface_declarations.count(name))
296                 return false;
297
298         VariableDeclaration* iface_var = new VariableDeclaration;
299         iface_var->sampling = var.sampling;
300         iface_var->interface = iface;
301         iface_var->type = var.type;
302         iface_var->type_declaration = var.type_declaration;
303         iface_var->name = name;
304         if(stage->type==GEOMETRY)
305                 iface_var->array = ((var.array && var.interface!="in") || iface=="in");
306         else
307                 iface_var->array = var.array;
308         if(iface_var->array)
309                 iface_var->array_size = var.array_size;
310         if(iface=="in")
311                 iface_var->linked_declaration = &var;
312         iface_declarations[name] = iface_var;
313
314         return true;
315 }
316
317 ExpressionStatement &InterfaceGenerator::insert_assignment(const string &left, Expression *right)
318 {
319         Assignment *assign = new Assignment;
320         VariableReference *ref = new VariableReference;
321         ref->name = left;
322         assign->left = ref;
323         assign->oper = "=";
324         assign->right = right;
325
326         ExpressionStatement *stmt = new ExpressionStatement;
327         stmt->expression = assign;
328         stmt->visit(*this);
329         insert_nodes.push_back(stmt);
330
331         return *stmt;
332 }
333
334 void InterfaceGenerator::visit(VariableReference &var)
335 {
336         if(var.declaration || !stage->previous)
337                 return;
338         if(iface_declarations.count(var.name))
339                 return;
340
341         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
342         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
343         if(i==prev_out.end())
344                 i = prev_out.find(in_prefix+var.name);
345         if(i!=prev_out.end())
346         {
347                 generate_interface(*i->second, "in", i->second->name);
348                 var.name = i->second->name;
349         }
350 }
351
352 void InterfaceGenerator::visit(VariableDeclaration &var)
353 {
354         if(var.interface=="out")
355         {
356                 if(scope_level==1)
357                         stage->out_variables[var.name] = &var;
358                 else if(generate_interface(var, "out", change_prefix(var.name, string())))
359                 {
360                         remove_node = true;
361                         if(var.init_expression)
362                         {
363                                 ExpressionStatement &stmt = insert_assignment(var.name, var.init_expression->clone());
364                                 stmt.source = var.source;
365                                 stmt.line = var.line;
366                                 return;
367                         }
368                 }
369         }
370         else if(var.interface=="in")
371         {
372                 stage->in_variables[var.name] = &var;
373                 if(var.linked_declaration)
374                         var.linked_declaration->linked_declaration = &var;
375                 else if(stage->previous)
376                 {
377                         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
378                         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
379                         if(i!=prev_out.end())
380                         {
381                                 var.linked_declaration = i->second;
382                                 i->second->linked_declaration = &var;
383                         }
384                 }
385         }
386
387         TraversingVisitor::visit(var);
388 }
389
390 void InterfaceGenerator::visit(Passthrough &pass)
391 {
392         vector<VariableDeclaration *> pass_vars;
393
394         for(map<string, VariableDeclaration *>::const_iterator i=stage->in_variables.begin(); i!=stage->in_variables.end(); ++i)
395                 pass_vars.push_back(i->second);
396         for(map<string, RefPtr<VariableDeclaration> >::const_iterator i=iface_declarations.begin(); i!=iface_declarations.end(); ++i)
397                 if(i->second->interface=="in")
398                         pass_vars.push_back(i->second.get());
399
400         if(stage->previous)
401         {
402                 const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
403                 for(map<string, VariableDeclaration *>::const_iterator i=prev_out.begin(); i!=prev_out.end(); ++i)
404                 {
405                         bool linked = false;
406                         for(vector<VariableDeclaration *>::const_iterator j=pass_vars.begin(); (!linked && j!=pass_vars.end()); ++j)
407                                 linked = ((*j)->linked_declaration==i->second);
408
409                         if(!linked && generate_interface(*i->second, "in", i->second->name))
410                                 pass_vars.push_back(i->second);
411                 }
412         }
413
414         if(stage->type==GEOMETRY)
415         {
416                 VariableReference *ref = new VariableReference;
417                 ref->name = "gl_in";
418
419                 BinaryExpression *subscript = new BinaryExpression;
420                 subscript->left = ref;
421                 subscript->oper = "[";
422                 subscript->right = pass.subscript;
423                 subscript->after = "]";
424
425                 MemberAccess *memacc = new MemberAccess;
426                 memacc->left = subscript;
427                 memacc->member = "gl_Position";
428
429                 insert_assignment("gl_Position", memacc);
430         }
431
432         for(vector<VariableDeclaration *>::const_iterator i=pass_vars.begin(); i!=pass_vars.end(); ++i)
433         {
434                 string out_name = change_prefix((*i)->name, out_prefix);
435                 generate_interface(**i, "out", out_name);
436
437                 VariableReference *ref = new VariableReference;
438                 ref->name = (*i)->name;
439                 if(pass.subscript)
440                 {
441                         BinaryExpression *subscript = new BinaryExpression;
442                         subscript->left = ref;
443                         subscript->oper = "[";
444                         subscript->right = pass.subscript;
445                         subscript->after = "]";
446                         insert_assignment(out_name, subscript);
447                 }
448                 else
449                         insert_assignment(out_name, ref);
450         }
451
452         remove_node = true;
453 }
454
455
456 DeclarationReorderer::DeclarationReorderer():
457         scope_level(0),
458         kind(NO_DECLARATION)
459 { }
460
461 void DeclarationReorderer::visit(FunctionCall &call)
462 {
463         FunctionDeclaration *def = call.declaration;
464         if(def)
465                 def = def->definition;
466         if(def && !ordered_funcs.count(def))
467                 needed_funcs.insert(def);
468 }
469
470 void DeclarationReorderer::visit(Block &block)
471 {
472         SetForScope<unsigned> set(scope_level, scope_level+1);
473         if(scope_level>1)
474                 return StageVisitor::visit(block);
475
476         NodeList<Statement>::iterator struct_insert_point = block.body.end();
477         NodeList<Statement>::iterator variable_insert_point = block.body.end();
478         NodeList<Statement>::iterator function_insert_point = block.body.end();
479         unsigned unordered_func_count = 0;
480         bool ordered_any_funcs = false;
481
482         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); )
483         {
484                 kind = NO_DECLARATION;
485                 (*i)->visit(*this);
486
487                 bool moved = false;
488                 if(kind==STRUCT && struct_insert_point!=block.body.end())
489                 {
490                         block.body.insert(struct_insert_point, *i);
491                         moved = true;
492                 }
493                 else if(kind>STRUCT && struct_insert_point==block.body.end())
494                         struct_insert_point = i;
495
496                 if(kind==VARIABLE && variable_insert_point!=block.body.end())
497                 {
498                         block.body.insert(variable_insert_point, *i);
499                         moved = true;
500                 }
501                 else if(kind>VARIABLE && variable_insert_point==block.body.end())
502                         variable_insert_point = i;
503
504                 if(kind==FUNCTION)
505                 {
506                         if(function_insert_point==block.body.end())
507                                 function_insert_point = i;
508
509                         if(needed_funcs.empty())
510                         {
511                                 ordered_funcs.insert(i->get());
512                                 if(i!=function_insert_point)
513                                 {
514                                         block.body.insert(function_insert_point, *i);
515                                         moved = true;
516                                 }
517                                 else
518                                         ++function_insert_point;
519                                 ordered_any_funcs = true;
520                         }
521                         else
522                                 ++unordered_func_count;
523                 }
524
525                 if(moved)
526                 {
527                         if(function_insert_point==i)
528                                 ++function_insert_point;
529                         block.body.erase(i++);
530                 }
531                 else
532                         ++i;
533
534                 if(i==block.body.end() && unordered_func_count)
535                 {
536                         if(!ordered_any_funcs)
537                                 // A subset of the remaining functions forms a recursive loop
538                                 /* TODO pick a function and move it up, adding any necessary
539                                 declarations */
540                                 break;
541
542                         i = function_insert_point;
543                         unordered_func_count = 0;
544                 }
545         }
546 }
547
548 void DeclarationReorderer::visit(VariableDeclaration &var)
549 {
550         StageVisitor::visit(var);
551         kind = VARIABLE;
552 }
553
554 void DeclarationReorderer::visit(FunctionDeclaration &func)
555 {
556         needed_funcs.clear();
557         func.body.visit(*this);
558         needed_funcs.erase(&func);
559         kind = FUNCTION;
560 }
561
562 } // namespace SL
563 } // namespace GL
564 } // namespace Msp