]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/generate.cpp
Resolve the return types of functions
[libs/gl.git] / source / glsl / generate.cpp
1 #include <msp/core/hash.h>
2 #include <msp/core/raii.h>
3 #include <msp/strings/lexicalcast.h>
4 #include "builtin.h"
5 #include "generate.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace GL {
11 namespace SL {
12
13 void DeclarationCombiner::apply(Stage &stage)
14 {
15         stage.content.visit(*this);
16         NodeRemover().apply(stage, nodes_to_remove);
17 }
18
19 void DeclarationCombiner::visit(Block &block)
20 {
21         if(current_block)
22                 return;
23
24         TraversingVisitor::visit(block);
25 }
26
27 void DeclarationCombiner::visit(VariableDeclaration &var)
28 {
29         VariableDeclaration *&ptr = variables[var.name];
30         if(ptr)
31         {
32                 ptr->type = var.type;
33                 if(var.init_expression)
34                         ptr->init_expression = var.init_expression;
35                 if(var.layout)
36                 {
37                         if(ptr->layout)
38                         {
39                                 for(vector<Layout::Qualifier>::iterator i=var.layout->qualifiers.begin(); i!=var.layout->qualifiers.end(); ++i)
40                                 {
41                                         bool found = false;
42                                         for(vector<Layout::Qualifier>::iterator j=ptr->layout->qualifiers.begin(); (!found && j!=ptr->layout->qualifiers.end()); ++j)
43                                                 if(j->name==i->name)
44                                                 {
45                                                         j->has_value = i->value;
46                                                         j->value = i->value;
47                                                         found = true;
48                                                 }
49
50                                         if(!found)
51                                                 ptr->layout->qualifiers.push_back(*i);
52                                 }
53                         }
54                         else
55                                 ptr->layout = var.layout;
56                 }
57                 nodes_to_remove.insert(&var);
58         }
59         else
60                 ptr = &var;
61 }
62
63
64 ConstantSpecializer::ConstantSpecializer():
65         values(0)
66 { }
67
68 void ConstantSpecializer::apply(Stage &stage, const map<string, int> *v)
69 {
70         values = v;
71         stage.content.visit(*this);
72 }
73
74 void ConstantSpecializer::visit(VariableDeclaration &var)
75 {
76         bool specializable = false;
77         if(var.layout)
78         {
79                 vector<Layout::Qualifier> &qualifiers = var.layout->qualifiers;
80                 for(vector<Layout::Qualifier>::iterator i=qualifiers.begin(); i!=qualifiers.end(); ++i)
81                         if(i->name=="constant_id")
82                         {
83                                 specializable = true;
84                                 if(values)
85                                         qualifiers.erase(i);
86                                 else if(i->value==-1)
87                                         i->value = hash32(var.name)&0x7FFFFFFF;
88                                 break;
89                         }
90
91                 if(qualifiers.empty())
92                         var.layout = 0;
93         }
94
95         if(specializable && values)
96         {
97                 map<string, int>::const_iterator i = values->find(var.name);
98                 if(i!=values->end())
99                 {
100                         RefPtr<Literal> literal = new Literal;
101                         if(var.type=="bool")
102                                 literal->token = (i->second ? "true" : "false");
103                         else if(var.type=="int")
104                                 literal->token = lexical_cast<string>(i->second);
105                         var.init_expression = literal;
106                 }
107         }
108 }
109
110
111 void BlockHierarchyResolver::enter(Block &block)
112 {
113         block.parent = current_block;
114 }
115
116
117 TypeResolver::TypeResolver():
118         stage(0)
119 { }
120
121 void TypeResolver::apply(Stage &s)
122 {
123         stage = &s;
124         s.types.clear();
125         s.content.visit(*this);
126 }
127
128 void TypeResolver::visit(BasicTypeDeclaration &type)
129 {
130         map<string, TypeDeclaration *>::iterator i = stage->types.find(type.base);
131         type.base_type = (i!=stage->types.end() ? i->second : 0);
132
133         if(type.kind==BasicTypeDeclaration::VECTOR && type.base_type)
134                 if(BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type))
135                         if(basic_base->kind==BasicTypeDeclaration::VECTOR)
136                         {
137                                 type.kind = BasicTypeDeclaration::MATRIX;
138                                 type.size |= basic_base->size<<16;
139                         }
140
141         stage->types.insert(make_pair(type.name, &type));
142 }
143
144 void TypeResolver::visit(ImageTypeDeclaration &type)
145 {
146         map<string, TypeDeclaration *>::iterator i = stage->types.find(type.base);
147         type.base_type = (i!=stage->types.end() ? i->second : 0);
148
149         stage->types.insert(make_pair(type.name, &type));
150 }
151
152 void TypeResolver::visit(StructDeclaration &strct)
153 {
154         stage->types.insert(make_pair(strct.name, &strct));
155         TraversingVisitor::visit(strct);
156 }
157
158 void TypeResolver::visit(VariableDeclaration &var)
159 {
160         map<string, TypeDeclaration *>::iterator i = stage->types.find(var.type);
161         if(i!=stage->types.end())
162                 var.type_declaration = i->second;
163 }
164
165 void TypeResolver::visit(FunctionDeclaration &func)
166 {
167         map<string, TypeDeclaration *>::iterator i = stage->types.find(func.return_type);
168         func.return_type_declaration = (i!=stage->types.end() ? i->second : 0);
169         TraversingVisitor::visit(func);
170 }
171
172
173 VariableResolver::VariableResolver():
174         stage(0),
175         r_members(0),
176         record_target(false),
177         r_self_referencing(false),
178         r_assignment_target(0)
179 { }
180
181 void VariableResolver::apply(Stage &s)
182 {
183         stage = &s;
184         s.interface_blocks.clear();
185         s.content.visit(*this);
186 }
187
188 void VariableResolver::enter(Block &block)
189 {
190         block.variables.clear();
191 }
192
193 void VariableResolver::visit(VariableReference &var)
194 {
195         var.declaration = 0;
196         r_members = 0;
197         /* Look for variable declarations in the block hierarchy first.  Interface
198         blocks are always defined in the top level so we can't accidentally skip
199         one. */
200         for(Block *block=current_block; (!var.declaration && block); block=block->parent)
201         {
202                 map<string, VariableDeclaration *>::iterator i = block->variables.find(var.name);
203                 if(i!=block->variables.end())
204                         var.declaration = i->second;
205         }
206
207         if(!var.declaration)
208         {
209                 const map<string, InterfaceBlock *> &blocks = stage->interface_blocks;
210                 map<string, InterfaceBlock *>::const_iterator i = blocks.find("_"+var.name);
211                 if(i!=blocks.end())
212                 {
213                         /* The name refers to an interface block with an instance name rather
214                         than a variable.  Prepare a new syntax tree node accordingly. */
215                         r_iface_ref = new InterfaceBlockReference;
216                         r_iface_ref->source = var.source;
217                         r_iface_ref->line = var.line;
218                         r_iface_ref->name = var.name;
219                         r_iface_ref->declaration = i->second;
220                         r_members = &i->second->members.variables;
221                 }
222                 else
223                 {
224                         // Look for the variable in anonymous interface blocks.
225                         for(i=blocks.begin(); (!var.declaration && i!=blocks.end()); ++i)
226                                 if(i->second->instance_name.empty())
227                                 {
228                                         map<string, VariableDeclaration *>::iterator j = i->second->members.variables.find(var.name);
229                                         if(j!=i->second->members.variables.end())
230                                                 var.declaration = j->second;
231                                 }
232                 }
233         }
234
235         if(var.declaration)
236                 if(StructDeclaration *strct = dynamic_cast<StructDeclaration *>(var.declaration->type_declaration))
237                         r_members = &strct->members.variables;
238
239         if(record_target)
240         {
241                 if(r_assignment_target)
242                 {
243                         /* More than one variable reference found in assignment target.
244                         Unable to determine what the primary target is. */
245                         record_target = false;
246                         r_assignment_target = 0;
247                 }
248                 else
249                         r_assignment_target = var.declaration;
250         }
251         else if(var.declaration && var.declaration==r_assignment_target)
252                 r_self_referencing = true;
253 }
254
255 void VariableResolver::visit(InterfaceBlockReference &iface)
256 {
257         iface.declaration = 0;
258         for(Block *block=current_block; block; block=block->parent)
259         {
260                 map<string, InterfaceBlock *>::iterator i = stage->interface_blocks.find("_"+iface.name);
261                 if(i!=stage->interface_blocks.end())
262                 {
263                         iface.declaration = i->second;
264                         r_members = &i->second->members.variables;
265                         break;
266                 }
267         }
268 }
269
270 void VariableResolver::visit(MemberAccess &memacc)
271 {
272         r_members = 0;
273         r_iface_ref = 0;
274         memacc.left->visit(*this);
275
276         if(r_iface_ref)
277                 memacc.left = r_iface_ref;
278         r_iface_ref = 0;
279
280         memacc.declaration = 0;
281         if(r_members)
282         {
283                 map<string, VariableDeclaration *>::iterator i = r_members->find(memacc.member);
284                 if(i!=r_members->end())
285                 {
286                         memacc.declaration = i->second;
287                         if(StructDeclaration *strct = dynamic_cast<StructDeclaration *>(i->second->type_declaration))
288                                 r_members = &strct->members.variables;
289                 }
290                 else
291                         r_members = 0;
292         }
293 }
294
295 void VariableResolver::visit(UnaryExpression &unary)
296 {
297         TraversingVisitor::visit(unary);
298         r_members = 0;
299         r_iface_ref = 0;
300 }
301
302 void VariableResolver::visit(BinaryExpression &binary)
303 {
304         if(binary.oper->token[0]=='[')
305         {
306                 {
307                         /* The subscript expression is not a part of the primary assignment
308                         target. */
309                         SetFlag set(record_target, false);
310                         binary.right->visit(*this);
311                 }
312                 r_members = 0;
313                 r_iface_ref = 0;
314                 binary.left->visit(*this);
315                 if(r_iface_ref)
316                         binary.left = r_iface_ref;
317         }
318         else
319         {
320                 TraversingVisitor::visit(binary);
321                 r_members = 0;
322         }
323
324         r_iface_ref = 0;
325 }
326
327 void VariableResolver::visit(Assignment &assign)
328 {
329         {
330                 SetFlag set(record_target);
331                 r_assignment_target = 0;
332                 assign.left->visit(*this);
333                 assign.target_declaration = r_assignment_target;
334         }
335
336         r_self_referencing = false;
337         assign.right->visit(*this);
338         assign.self_referencing = (r_self_referencing || assign.oper->token[0]!='=');
339
340         r_members = 0;
341         r_iface_ref = 0;
342 }
343
344 void VariableResolver::visit(FunctionCall &call)
345 {
346         TraversingVisitor::visit(call);
347         r_members = 0;
348         r_iface_ref = 0;
349 }
350
351 void VariableResolver::visit(VariableDeclaration &var)
352 {
353         if(!block_interface.empty() && var.interface.empty())
354                 var.interface = block_interface;
355
356         TraversingVisitor::visit(var);
357         current_block->variables.insert(make_pair(var.name, &var));
358 }
359
360 void VariableResolver::visit(InterfaceBlock &iface)
361 {
362         /* Block names can be reused in different interfaces.  Prefix the name with
363         the first character of the interface to avoid conflicts. */
364         stage->interface_blocks.insert(make_pair(iface.interface+iface.name, &iface));
365         if(!iface.instance_name.empty())
366                 stage->interface_blocks.insert(make_pair("_"+iface.instance_name, &iface));
367
368         SetForScope<string> set_iface(block_interface, iface.interface);
369         TraversingVisitor::visit(iface);
370 }
371
372
373 void FunctionResolver::apply(Stage &s)
374 {
375         stage = &s;
376         s.functions.clear();
377         s.content.visit(*this);
378 }
379
380 void FunctionResolver::visit(FunctionCall &call)
381 {
382         map<string, FunctionDeclaration *>::iterator i = stage->functions.find(call.name);
383         if(i!=stage->functions.end())
384                 call.declaration = i->second;
385
386         TraversingVisitor::visit(call);
387 }
388
389 void FunctionResolver::visit(FunctionDeclaration &func)
390 {
391         FunctionDeclaration *&stage_decl = stage->functions[func.name];
392         vector<FunctionDeclaration *> &decls = declarations[func.name];
393         if(func.definition==&func)
394         {
395                 stage_decl = &func;
396
397                 // Set all previous declarations to use this definition.
398                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
399                 {
400                         (*i)->definition = func.definition;
401                         (*i)->body.body.clear();
402                 }
403         }
404         else
405         {
406                 func.definition = 0;
407                 if(!stage_decl)
408                         stage_decl = &func;
409                 else
410                         func.definition = stage_decl->definition;
411         }
412         decls.push_back(&func);
413
414         TraversingVisitor::visit(func);
415 }
416
417
418 InterfaceGenerator::InterfaceGenerator():
419         stage(0),
420         function_scope(false),
421         iface_block(0),
422         copy_block(false),
423         iface_target_block(0)
424 { }
425
426 string InterfaceGenerator::get_out_prefix(Stage::Type type)
427 {
428         if(type==Stage::VERTEX)
429                 return "_vs_out_";
430         else if(type==Stage::GEOMETRY)
431                 return "_gs_out_";
432         else
433                 return string();
434 }
435
436 void InterfaceGenerator::apply(Stage &s)
437 {
438         stage = &s;
439         iface_target_block = &stage->content;
440         if(stage->previous)
441                 in_prefix = get_out_prefix(stage->previous->type);
442         out_prefix = get_out_prefix(stage->type);
443         s.content.visit(*this);
444         NodeRemover().apply(s, nodes_to_remove);
445 }
446
447 void InterfaceGenerator::visit(Block &block)
448 {
449         SetForScope<Block *> set_block(current_block, &block);
450         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
451         {
452                 assignment_insert_point = i;
453                 if(&block==&stage->content)
454                         iface_insert_point = i;
455
456                 (*i)->visit(*this);
457         }
458 }
459
460 string InterfaceGenerator::change_prefix(const string &name, const string &prefix) const
461 {
462         unsigned offset = (name.compare(0, in_prefix.size(), in_prefix) ? 0 : in_prefix.size());
463         return prefix+name.substr(offset);
464 }
465
466 VariableDeclaration *InterfaceGenerator::generate_interface(VariableDeclaration &var, const string &iface, const string &name)
467 {
468         if(stage->content.variables.count(name))
469                 return 0;
470
471         VariableDeclaration* iface_var = new VariableDeclaration;
472         iface_var->sampling = var.sampling;
473         iface_var->interface = iface;
474         iface_var->type = var.type;
475         iface_var->name = name;
476         /* Geometry shader inputs are always arrays.  But if we're bringing in an
477         entire block, the array is on the block and not individual variables. */
478         if(stage->type==Stage::GEOMETRY && !copy_block)
479                 iface_var->array = ((var.array && var.interface!="in") || iface=="in");
480         else
481                 iface_var->array = var.array;
482         if(iface_var->array)
483                 iface_var->array_size = var.array_size;
484         if(iface=="in")
485         {
486                 iface_var->layout = var.layout;
487                 iface_var->linked_declaration = &var;
488                 var.linked_declaration = iface_var;
489         }
490
491         iface_target_block->body.insert(iface_insert_point, iface_var);
492         iface_target_block->variables.insert(make_pair(name, iface_var));
493
494         return iface_var;
495 }
496
497 InterfaceBlock *InterfaceGenerator::generate_interface(InterfaceBlock &out_block)
498 {
499         if(stage->interface_blocks.count("in"+out_block.name))
500                 return 0;
501
502         InterfaceBlock *in_block = new InterfaceBlock;
503         in_block->interface = "in";
504         in_block->name = out_block.name;
505         in_block->instance_name = out_block.instance_name;
506         if(stage->type==Stage::GEOMETRY)
507                 in_block->array = true;
508         else
509                 in_block->array = out_block.array;
510         in_block->linked_block = &out_block;
511         out_block.linked_block = in_block;
512
513         {
514                 SetFlag set_copy(copy_block, true);
515                 SetForScope<Block *> set_target(iface_target_block, &in_block->members);
516                 SetForScope<NodeList<Statement>::iterator> set_ins_pt(iface_insert_point, in_block->members.body.end());
517                 out_block.members.visit(*this);
518         }
519
520         iface_target_block->body.insert(iface_insert_point, in_block);
521         stage->interface_blocks.insert(make_pair("in"+in_block->name, in_block));
522         if(!in_block->instance_name.empty())
523                 stage->interface_blocks.insert(make_pair("_"+in_block->instance_name, in_block));
524
525         SetFlag set_scope(function_scope, false);
526         SetForScope<Block *> set_block(current_block, &stage->content);
527         in_block->visit(*this);
528
529         return in_block;
530 }
531
532 ExpressionStatement &InterfaceGenerator::insert_assignment(const string &left, Expression *right)
533 {
534         Assignment *assign = new Assignment;
535         VariableReference *ref = new VariableReference;
536         ref->name = left;
537         assign->left = ref;
538         assign->oper = &Operator::get_operator("=", Operator::BINARY);
539         assign->right = right;
540
541         ExpressionStatement *stmt = new ExpressionStatement;
542         stmt->expression = assign;
543         current_block->body.insert(assignment_insert_point, stmt);
544         stmt->visit(*this);
545
546         return *stmt;
547 }
548
549 void InterfaceGenerator::visit(VariableReference &var)
550 {
551         if(var.declaration || !stage->previous)
552                 return;
553         /* Don't pull a variable from previous stage if we just generated an output
554         interface in this stage */
555         if(stage->content.variables.count(var.name))
556                 return;
557
558         const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
559         map<string, VariableDeclaration *>::const_iterator i = prev_vars.find(var.name);
560         if(i==prev_vars.end() || i->second->interface!="out")
561                 i = prev_vars.find(in_prefix+var.name);
562         if(i!=prev_vars.end() && i->second->interface=="out")
563         {
564                 generate_interface(*i->second, "in", i->second->name);
565                 var.name = i->second->name;
566                 return;
567         }
568
569         const map<string, InterfaceBlock *> &prev_blocks = stage->previous->interface_blocks;
570         map<string, InterfaceBlock *>::const_iterator j = prev_blocks.find("_"+var.name);
571         if(j!=prev_blocks.end() && j->second->interface=="out")
572         {
573                 generate_interface(*j->second);
574                 /* Let VariableResolver convert the variable reference into an interface
575                 block reference. */
576                 return;
577         }
578
579         for(j=prev_blocks.begin(); j!=prev_blocks.end(); ++j)
580                 if(j->second->instance_name.empty())
581                 {
582                         i = j->second->members.variables.find(var.name);
583                         if(i!=j->second->members.variables.end())
584                         {
585                                 generate_interface(*j->second);
586                                 return;
587                         }
588                 }
589 }
590
591 void InterfaceGenerator::visit(VariableDeclaration &var)
592 {
593         if(copy_block)
594         {
595                 generate_interface(var, "in", var.name);
596                 return;
597         }
598
599         if(iface_block)
600         {
601                 if(iface_block->linked_block)
602                 {
603                         // Link all variables to their counterparts in the linked block.
604                         const map<string, VariableDeclaration *> &linked_vars = iface_block->linked_block->members.variables;
605                         map<string, VariableDeclaration *>::const_iterator i = linked_vars.find(var.name);
606                         if(i!=linked_vars.end())
607                         {
608                                 var.linked_declaration = i->second;
609                                 var.linked_declaration->linked_declaration = &var;
610                         }
611                 }
612                 return;
613         }
614
615         if(var.interface=="out")
616         {
617                 /* For output variables in function scope, generate a global interface
618                 and replace the local declaration with an assignment. */
619                 VariableDeclaration *out_var = 0;
620                 if(function_scope && (out_var=generate_interface(var, "out", var.name)))
621                 {
622                         out_var->source = var.source;
623                         out_var->line = var.line;
624                         nodes_to_remove.insert(&var);
625                         if(var.init_expression)
626                         {
627                                 ExpressionStatement &stmt = insert_assignment(var.name, var.init_expression->clone());
628                                 stmt.source = var.source;
629                                 stmt.line = var.line;
630                                 return;
631                         }
632                 }
633         }
634         else if(var.interface=="in")
635         {
636                 /* Try to link input variables in global scope with output variables from
637                 previous stage. */
638                 if(current_block==&stage->content && !var.linked_declaration && stage->previous)
639                 {
640                         const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
641                         map<string, VariableDeclaration *>::const_iterator i = prev_vars.find(var.name);
642                         if(i!=prev_vars.end() && i->second->interface=="out")
643                         {
644                                 var.linked_declaration = i->second;
645                                 i->second->linked_declaration = &var;
646                         }
647                 }
648         }
649
650         TraversingVisitor::visit(var);
651 }
652
653 void InterfaceGenerator::visit(InterfaceBlock &iface)
654 {
655         if(iface.interface=="in")
656         {
657                 /* Try to link input blocks with output blocks sharing the same block
658                 name from previous stage. */
659                 if(!iface.linked_block && stage->previous)
660                 {
661                         const map<string, InterfaceBlock *> &prev_blocks = stage->previous->interface_blocks;
662                         map<string, InterfaceBlock *>::const_iterator i = prev_blocks.find("out"+iface.name);
663                         if(i!=prev_blocks.end())
664                         {
665                                 iface.linked_block = i->second;
666                                 i->second->linked_block = &iface;
667                         }
668                 }
669         }
670
671         SetForScope<InterfaceBlock *> set_iface(iface_block, &iface);
672         TraversingVisitor::visit(iface);
673 }
674
675 void InterfaceGenerator::visit(FunctionDeclaration &func)
676 {
677         SetFlag set_scope(function_scope, true);
678         // Skip parameters because they're not useful here
679         func.body.visit(*this);
680 }
681
682 void InterfaceGenerator::visit(Passthrough &pass)
683 {
684         vector<VariableDeclaration *> pass_vars;
685
686         // Pass through all input variables of this stage.
687         for(map<string, VariableDeclaration *>::const_iterator i=stage->content.variables.begin(); i!=stage->content.variables.end(); ++i)
688                 if(i->second->interface=="in")
689                         pass_vars.push_back(i->second);
690
691         if(stage->previous)
692         {
693                 const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
694                 for(map<string, VariableDeclaration *>::const_iterator i=prev_vars.begin(); i!=prev_vars.end(); ++i)
695                 {
696                         if(i->second->interface!="out")
697                                 continue;
698
699                         /* Pass through output variables from the previous stage, but only
700                         those which are not already linked to an input here. */
701                         if(!i->second->linked_declaration && generate_interface(*i->second, "in", i->second->name))
702                                 pass_vars.push_back(i->second);
703                 }
704         }
705
706         if(stage->type==Stage::GEOMETRY)
707         {
708                 /* Special case for geometry shader: copy gl_Position from input to
709                 output. */
710                 InterfaceBlockReference *ref = new InterfaceBlockReference;
711                 ref->name = "gl_in";
712
713                 BinaryExpression *subscript = new BinaryExpression;
714                 subscript->left = ref;
715                 subscript->oper = &Operator::get_operator("[", Operator::BINARY);
716                 subscript->right = pass.subscript;
717
718                 MemberAccess *memacc = new MemberAccess;
719                 memacc->left = subscript;
720                 memacc->member = "gl_Position";
721
722                 insert_assignment("gl_Position", memacc);
723         }
724
725         for(vector<VariableDeclaration *>::const_iterator i=pass_vars.begin(); i!=pass_vars.end(); ++i)
726         {
727                 string out_name = change_prefix((*i)->name, out_prefix);
728                 generate_interface(**i, "out", out_name);
729
730                 VariableReference *ref = new VariableReference;
731                 ref->name = (*i)->name;
732                 if(pass.subscript)
733                 {
734                         BinaryExpression *subscript = new BinaryExpression;
735                         subscript->left = ref;
736                         subscript->oper = &Operator::get_operator("[", Operator::BINARY);
737                         subscript->right = pass.subscript;
738                         insert_assignment(out_name, subscript);
739                 }
740                 else
741                         insert_assignment(out_name, ref);
742         }
743
744         nodes_to_remove.insert(&pass);
745 }
746
747 } // namespace SL
748 } // namespace GL
749 } // namespace Msp