]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/generate.cpp
Properly resolve arithmetic assignment operators
[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                         {
103                                 literal->token = (i->second ? "true" : "false");
104                                 literal->value = static_cast<bool>(i->second);
105                         }
106                         else if(var.type=="int")
107                         {
108                                 literal->token = lexical_cast<string>(i->second);
109                                 literal->value = i->second;
110                         }
111                         var.init_expression = literal;
112                 }
113         }
114 }
115
116
117 void BlockHierarchyResolver::enter(Block &block)
118 {
119         block.parent = current_block;
120 }
121
122
123 TypeResolver::TypeResolver():
124         stage(0)
125 { }
126
127 void TypeResolver::apply(Stage &s)
128 {
129         stage = &s;
130         s.types.clear();
131         s.content.visit(*this);
132 }
133
134 TypeDeclaration *TypeResolver::resolve_type(const string &name)
135 {
136         map<string, TypeDeclaration *>::iterator i = stage->types.find(name);
137         if(i!=stage->types.end())
138         {
139                 map<TypeDeclaration *, TypeDeclaration *>::iterator j = alias_map.find(i->second);
140                 return (j!=alias_map.end() ? j->second : i->second);
141         }
142         else
143                 return 0;
144 }
145
146 void TypeResolver::visit(Block &block)
147 {
148         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
149         {
150                 if(!block.parent)
151                         type_insert_point = i;
152                 (*i)->visit(*this);
153         }
154 }
155
156 void TypeResolver::visit(BasicTypeDeclaration &type)
157 {
158         type.base_type = resolve_type(type.base);
159
160         if(type.kind==BasicTypeDeclaration::VECTOR && type.base_type)
161                 if(BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type))
162                         if(basic_base->kind==BasicTypeDeclaration::VECTOR)
163                         {
164                                 type.kind = BasicTypeDeclaration::MATRIX;
165                                 type.size |= basic_base->size<<16;
166                         }
167
168         if(type.kind==BasicTypeDeclaration::ALIAS && type.base_type)
169                 alias_map[&type] = type.base_type;
170         else if(type.kind==BasicTypeDeclaration::ARRAY && type.base_type)
171                 array_types[type.base_type] = &type;
172
173         stage->types.insert(make_pair(type.name, &type));
174 }
175
176 void TypeResolver::visit(ImageTypeDeclaration &type)
177 {
178         type.base_type = resolve_type(type.base);
179         stage->types.insert(make_pair(type.name, &type));
180 }
181
182 void TypeResolver::visit(StructDeclaration &strct)
183 {
184         stage->types.insert(make_pair(strct.name, &strct));
185         TraversingVisitor::visit(strct);
186 }
187
188 void TypeResolver::visit(VariableDeclaration &var)
189 {
190         TypeDeclaration *type = resolve_type(var.type);
191         if(var.array && type)
192         {
193                 map<TypeDeclaration *, TypeDeclaration *>::iterator i = array_types.find(type);
194                 if(i==array_types.end())
195                 {
196                         BasicTypeDeclaration *array = new BasicTypeDeclaration;
197                         array->source = BUILTIN_SOURCE;
198                         array->name = type->name+"[]";
199                         array->kind = BasicTypeDeclaration::ARRAY;
200                         array->base = type->name;
201                         array->base_type = type;
202                         stage->content.body.insert(type_insert_point, array);
203                         array->visit(*this);
204                         type = array;
205                 }
206                 else
207                         type = i->second;
208         }
209         var.type_declaration = type;
210 }
211
212 void TypeResolver::visit(FunctionDeclaration &func)
213 {
214         func.return_type_declaration = resolve_type(func.return_type);
215         TraversingVisitor::visit(func);
216 }
217
218
219 VariableResolver::VariableResolver():
220         stage(0),
221         r_any_resolved(false),
222         record_target(false),
223         r_self_referencing(false),
224         r_assignment_target(0)
225 { }
226
227 bool VariableResolver::apply(Stage &s)
228 {
229         stage = &s;
230         s.interface_blocks.clear();
231         r_any_resolved = false;
232         s.content.visit(*this);
233         return r_any_resolved;
234 }
235
236 void VariableResolver::enter(Block &block)
237 {
238         block.variables.clear();
239 }
240
241 void VariableResolver::visit_and_replace(RefPtr<Expression> &expr)
242 {
243         r_replacement_expr = 0;
244         expr->visit(*this);
245         if(r_replacement_expr)
246                 expr = r_replacement_expr;
247         r_replacement_expr = 0;
248 }
249
250 void VariableResolver::visit(VariableReference &var)
251 {
252         VariableDeclaration *declaration = 0;
253
254         /* Look for variable declarations in the block hierarchy first.  Interface
255         blocks are always defined in the top level so we can't accidentally skip
256         one. */
257         for(Block *block=current_block; (!declaration && block); block=block->parent)
258         {
259                 map<string, VariableDeclaration *>::iterator i = block->variables.find(var.name);
260                 if(i!=block->variables.end())
261                         declaration = i->second;
262         }
263
264         if(!declaration)
265         {
266                 const map<string, InterfaceBlock *> &blocks = stage->interface_blocks;
267                 map<string, InterfaceBlock *>::const_iterator i = blocks.find("_"+var.name);
268                 if(i!=blocks.end())
269                 {
270                         /* The name refers to an interface block with an instance name rather
271                         than a variable.  Prepare a new syntax tree node accordingly. */
272                         InterfaceBlockReference *iface_ref = new InterfaceBlockReference;
273                         iface_ref->source = var.source;
274                         iface_ref->line = var.line;
275                         iface_ref->name = var.name;
276                         iface_ref->declaration = i->second;
277                         r_replacement_expr = iface_ref;
278                 }
279                 else
280                 {
281                         // Look for the variable in anonymous interface blocks.
282                         for(i=blocks.begin(); (!declaration && i!=blocks.end()); ++i)
283                                 if(i->second->instance_name.empty())
284                                 {
285                                         map<string, VariableDeclaration *>::iterator j = i->second->members.variables.find(var.name);
286                                         if(j!=i->second->members.variables.end())
287                                                 declaration = j->second;
288                                 }
289                 }
290         }
291
292         r_any_resolved |= (declaration!=var.declaration);
293         var.declaration = declaration;
294
295         if(record_target)
296         {
297                 if(r_assignment_target)
298                 {
299                         /* More than one variable reference found in assignment target.
300                         Unable to determine what the primary target is. */
301                         record_target = false;
302                         r_assignment_target = 0;
303                 }
304                 else
305                         r_assignment_target = var.declaration;
306         }
307         else if(var.declaration && var.declaration==r_assignment_target)
308                 r_self_referencing = true;
309 }
310
311 void VariableResolver::visit(InterfaceBlockReference &iface)
312 {
313         map<string, InterfaceBlock *>::iterator i = stage->interface_blocks.find("_"+iface.name);
314         InterfaceBlock *declaration = (i!=stage->interface_blocks.end() ? i->second : 0);
315         r_any_resolved |= (declaration!=iface.declaration);
316         iface.declaration = declaration;
317 }
318
319 void VariableResolver::visit(MemberAccess &memacc)
320 {
321         visit_and_replace(memacc.left);
322
323         map<string, VariableDeclaration *> *members = 0;
324         if(StructDeclaration *strct = dynamic_cast<StructDeclaration *>(memacc.left->type))
325                 members = &strct->members.variables;
326         else if(InterfaceBlockReference *iface_ref = dynamic_cast<InterfaceBlockReference *>(memacc.left.get()))
327         {
328                 if(iface_ref->declaration)
329                         members = &iface_ref->declaration->members.variables;
330         }
331
332         VariableDeclaration *declaration = 0;
333         if(members)
334         {
335                 map<string, VariableDeclaration *>::iterator i = members->find(memacc.member);
336                 if(i!=members->end())
337                         declaration = i->second;
338         }
339
340         r_any_resolved |= (declaration!=memacc.declaration);
341         memacc.declaration = declaration;
342 }
343
344 void VariableResolver::visit(UnaryExpression &unary)
345 {
346         visit_and_replace(unary.expression);
347 }
348
349 void VariableResolver::visit(BinaryExpression &binary)
350 {
351         if(binary.oper->token[0]=='[')
352         {
353                 {
354                         /* The subscript expression is not a part of the primary assignment
355                         target. */
356                         SetFlag set(record_target, false);
357                         visit_and_replace(binary.right);
358                 }
359                 visit_and_replace(binary.left);
360         }
361         else
362         {
363                 visit_and_replace(binary.left);
364                 visit_and_replace(binary.right);
365         }
366 }
367
368 void VariableResolver::visit(Assignment &assign)
369 {
370         {
371                 SetFlag set(record_target);
372                 r_assignment_target = 0;
373                 visit_and_replace(assign.left);
374                 r_any_resolved |= (r_assignment_target!=assign.target_declaration);
375                 assign.target_declaration = r_assignment_target;
376         }
377
378         r_self_referencing = false;
379         visit_and_replace(assign.right);
380         assign.self_referencing = (r_self_referencing || assign.oper->token[0]!='=');
381 }
382
383 void VariableResolver::visit(FunctionCall &call)
384 {
385         for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
386                 visit_and_replace(*i);
387 }
388
389 void VariableResolver::visit(VariableDeclaration &var)
390 {
391         if(!block_interface.empty() && var.interface.empty())
392                 var.interface = block_interface;
393
394         TraversingVisitor::visit(var);
395         current_block->variables.insert(make_pair(var.name, &var));
396 }
397
398 void VariableResolver::visit(InterfaceBlock &iface)
399 {
400         /* Block names can be reused in different interfaces.  Prefix the name with
401         the first character of the interface to avoid conflicts. */
402         stage->interface_blocks.insert(make_pair(iface.interface+iface.name, &iface));
403         if(!iface.instance_name.empty())
404                 stage->interface_blocks.insert(make_pair("_"+iface.instance_name, &iface));
405
406         SetForScope<string> set_iface(block_interface, iface.interface);
407         TraversingVisitor::visit(iface);
408 }
409
410
411 ExpressionResolver::ExpressionResolver():
412         stage(0),
413         r_any_resolved(false)
414 { }
415
416 bool ExpressionResolver::apply(Stage &s)
417 {
418         stage = &s;
419         r_any_resolved = false;
420         s.content.visit(*this);
421         return r_any_resolved;
422 }
423
424 bool ExpressionResolver::is_scalar(BasicTypeDeclaration &type)
425 {
426         return (type.kind==BasicTypeDeclaration::INT || type.kind==BasicTypeDeclaration::FLOAT);
427 }
428
429 bool ExpressionResolver::is_vector_or_matrix(BasicTypeDeclaration &type)
430 {
431         return (type.kind==BasicTypeDeclaration::VECTOR || type.kind==BasicTypeDeclaration::MATRIX);
432 }
433
434 BasicTypeDeclaration *ExpressionResolver::get_element_type(BasicTypeDeclaration &type)
435 {
436         if(is_vector_or_matrix(type) || type.kind==BasicTypeDeclaration::ARRAY)
437         {
438                 BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type);
439                 return (basic_base ? get_element_type(*basic_base) : 0);
440         }
441         else
442                 return &type;
443 }
444
445 bool ExpressionResolver::can_convert(BasicTypeDeclaration &from, BasicTypeDeclaration &to)
446 {
447         if(from.kind==BasicTypeDeclaration::INT && to.kind==BasicTypeDeclaration::FLOAT)
448                 return from.size<=to.size;
449         else if(from.kind!=to.kind)
450                 return false;
451         else if((from.kind==BasicTypeDeclaration::VECTOR || from.kind==BasicTypeDeclaration::MATRIX) && from.size==to.size)
452         {
453                 BasicTypeDeclaration *from_base = dynamic_cast<BasicTypeDeclaration *>(from.base_type);
454                 BasicTypeDeclaration *to_base = dynamic_cast<BasicTypeDeclaration *>(to.base_type);
455                 return (from_base && to_base && can_convert(*from_base, *to_base));
456         }
457         else
458                 return false;
459 }
460
461 ExpressionResolver::Compatibility ExpressionResolver::get_compatibility(BasicTypeDeclaration &left, BasicTypeDeclaration &right)
462 {
463         if(&left==&right)
464                 return SAME_TYPE;
465         else if(can_convert(left, right))
466                 return LEFT_CONVERTIBLE;
467         else if(can_convert(right, left))
468                 return RIGHT_CONVERTIBLE;
469         else
470                 return NOT_COMPATIBLE;
471 }
472
473 BasicTypeDeclaration *ExpressionResolver::find_type(BasicTypeDeclaration::Kind kind, unsigned size)
474 {
475         for(vector<BasicTypeDeclaration *>::const_iterator i=basic_types.begin(); i!=basic_types.end(); ++i)
476                 if((*i)->kind==kind && (*i)->size==size)
477                         return *i;
478         return 0;
479 }
480
481 BasicTypeDeclaration *ExpressionResolver::find_type(BasicTypeDeclaration &elem_type, BasicTypeDeclaration::Kind kind, unsigned size)
482 {
483         for(vector<BasicTypeDeclaration *>::const_iterator i=basic_types.begin(); i!=basic_types.end(); ++i)
484                 if(get_element_type(**i)==&elem_type && (*i)->kind==kind && (*i)->size==size)
485                         return *i;
486         return 0;
487 }
488
489 void ExpressionResolver::convert_to(RefPtr<Expression> &expr, BasicTypeDeclaration &type)
490 {
491         RefPtr<FunctionCall> call = new FunctionCall;
492         call->name = type.name;
493         call->constructor = true;
494         call->arguments.push_back(0);
495         call->arguments.back() = expr;
496         call->type = &type;
497         expr = call;
498 }
499
500 bool ExpressionResolver::convert_to_element(RefPtr<Expression> &expr, BasicTypeDeclaration &elem_type)
501 {
502         if(BasicTypeDeclaration *expr_type = dynamic_cast<BasicTypeDeclaration *>(expr->type))
503         {
504                 BasicTypeDeclaration *to_type = &elem_type;
505                 if(is_vector_or_matrix(*expr_type))
506                         to_type = find_type(elem_type, expr_type->kind, expr_type->size);
507                 if(to_type)
508                 {
509                         convert_to(expr, *to_type);
510                         return true;
511                 }
512         }
513
514         return false;
515 }
516
517 void ExpressionResolver::resolve(Expression &expr, TypeDeclaration *type, bool lvalue)
518 {
519         r_any_resolved |= (type!=expr.type || lvalue!=expr.lvalue);
520         expr.type = type;
521         expr.lvalue = lvalue;
522 }
523
524 void ExpressionResolver::visit(Literal &literal)
525 {
526         if(literal.value.check_type<bool>())
527                 resolve(literal, find_type(BasicTypeDeclaration::BOOL, 1), false);
528         else if(literal.value.check_type<int>())
529                 resolve(literal, find_type(BasicTypeDeclaration::INT, 32), false);
530         else if(literal.value.check_type<float>())
531                 resolve(literal, find_type(BasicTypeDeclaration::FLOAT, 32), false);
532 }
533
534 void ExpressionResolver::visit(ParenthesizedExpression &parexpr)
535 {
536         TraversingVisitor::visit(parexpr);
537         resolve(parexpr, parexpr.expression->type, parexpr.expression->lvalue);
538 }
539
540 void ExpressionResolver::visit(VariableReference &var)
541 {
542         if(var.declaration)
543                 resolve(var, var.declaration->type_declaration, true);
544 }
545
546 void ExpressionResolver::visit(InterfaceBlockReference &iface)
547 {
548         resolve(iface, 0, true);
549 }
550
551 void ExpressionResolver::visit(MemberAccess &memacc)
552 {
553         TraversingVisitor::visit(memacc);
554
555         if(memacc.declaration)
556                 resolve(memacc, memacc.declaration->type_declaration, memacc.left->lvalue);
557 }
558
559 void ExpressionResolver::visit(UnaryExpression &unary)
560 {
561         TraversingVisitor::visit(unary);
562
563         BasicTypeDeclaration *basic = dynamic_cast<BasicTypeDeclaration *>(unary.expression->type);
564         if(!basic)
565                 return;
566
567         char oper = unary.oper->token[0];
568         if(oper=='!')
569         {
570                 if(basic->kind!=BasicTypeDeclaration::BOOL)
571                         return;
572         }
573         else if(oper=='~')
574         {
575                 if(basic->kind!=BasicTypeDeclaration::INT)
576                         return;
577         }
578         else if(oper=='+' || oper=='-')
579         {
580                 BasicTypeDeclaration *elem = get_element_type(*basic);
581                 if(!elem || !is_scalar(*elem))
582                         return;
583         }
584         resolve(unary, basic, unary.expression->lvalue);
585 }
586
587 void ExpressionResolver::visit(BinaryExpression &binary, bool assign)
588 {
589         /* Binary operators are only defined for basic types (not for image or
590         structure types). */
591         BasicTypeDeclaration *basic_left = dynamic_cast<BasicTypeDeclaration *>(binary.left->type);
592         BasicTypeDeclaration *basic_right = dynamic_cast<BasicTypeDeclaration *>(binary.right->type);
593         if(!basic_left || !basic_right)
594                 return;
595
596         char oper = binary.oper->token[0];
597         if(oper=='[')
598         {
599                 /* Subscripting operates on vectors, matrices and arrays, and the right
600                 operand must be an integer. */
601                 if((!is_vector_or_matrix(*basic_left) && basic_left->kind!=BasicTypeDeclaration::ARRAY) || basic_right->kind!=BasicTypeDeclaration::INT)
602                         return;
603
604                 resolve(binary, basic_left->base_type, binary.left->lvalue);
605                 return;
606         }
607         else if(basic_left->kind==BasicTypeDeclaration::ARRAY || basic_right->kind==BasicTypeDeclaration::ARRAY)
608                 // No other binary operator can be used with arrays.
609                 return;
610
611         BasicTypeDeclaration *elem_left = get_element_type(*basic_left);
612         BasicTypeDeclaration *elem_right = get_element_type(*basic_right);
613         if(!elem_left || !elem_right)
614                 return;
615
616         Compatibility compat = get_compatibility(*basic_left, *basic_right);
617         Compatibility elem_compat = get_compatibility(*elem_left, *elem_right);
618         if(elem_compat==NOT_COMPATIBLE)
619                 return;
620         if(assign && (compat==LEFT_CONVERTIBLE || elem_compat==LEFT_CONVERTIBLE))
621                 return;
622
623         TypeDeclaration *type = 0;
624         char oper2 = binary.oper->token[1];
625         if((oper=='<' && oper2!='<') || (oper=='>' && oper2!='>'))
626         {
627                 /* Relational operators compare two scalar integer or floating-point
628                 values. */
629                 if(!is_scalar(*elem_left) || !is_scalar(*elem_right) || compat==NOT_COMPATIBLE)
630                         return;
631
632                 type = find_type(BasicTypeDeclaration::BOOL, 1);
633         }
634         else if((oper=='=' || oper=='!') && oper2=='=')
635         {
636                 // Equality comparison can be done on any compatible types.
637                 if(compat==NOT_COMPATIBLE)
638                         return;
639
640                 type = find_type(BasicTypeDeclaration::BOOL, 1);
641         }
642         else if(oper2=='&' || oper2=='|' || oper2=='^')
643         {
644                 // Logical operators can only be applied to booleans.
645                 if(basic_left->kind!=BasicTypeDeclaration::BOOL || basic_right->kind!=BasicTypeDeclaration::BOOL)
646                         return;
647
648                 type = basic_left;
649         }
650         else if((oper=='&' || oper=='|' || oper=='^' || oper=='%') && !oper2)
651         {
652                 // Bitwise operators and modulo can only be applied to integers.
653                 if(basic_left->kind!=BasicTypeDeclaration::INT || basic_right->kind!=BasicTypeDeclaration::INT)
654                         return;
655
656                 type = (compat==LEFT_CONVERTIBLE ? basic_right : basic_left);
657         }
658         else if((oper=='<' || oper=='>') && oper2==oper)
659         {
660                 // Shifts only apply to integers.
661                 if(basic_left->kind!=BasicTypeDeclaration::INT || basic_right->kind!=BasicTypeDeclaration::INT)
662                         return;
663
664                 type = basic_left;
665         }
666         else if(oper=='+' || oper=='-' || oper=='*' || oper=='/')
667         {
668                 // Arithmetic operators require scalar elements.
669                 if(!is_scalar(*elem_left) || !is_scalar(*elem_right))
670                         return;
671
672                 if(oper=='*' && is_vector_or_matrix(*basic_left) && is_vector_or_matrix(*basic_right) &&
673                         (basic_left->kind==BasicTypeDeclaration::MATRIX || basic_right->kind==BasicTypeDeclaration::MATRIX))
674                 {
675                         /* Multiplication has special rules when at least one operand is a
676                         matrix and the other is a vector or a matrix. */
677                         unsigned left_columns = basic_left->size&0xFFFF;
678                         unsigned right_rows = basic_right->size;
679                         if(basic_right->kind==BasicTypeDeclaration::MATRIX)
680                                 right_rows >>= 16;
681                         if(left_columns!=right_rows)
682                                 return;
683
684                         BasicTypeDeclaration *elem_result = (elem_compat==LEFT_CONVERTIBLE ? elem_right : elem_left);
685
686                         if(basic_left->kind==BasicTypeDeclaration::VECTOR)
687                                 type = find_type(*elem_result, BasicTypeDeclaration::VECTOR, basic_right->size&0xFFFF);
688                         else if(basic_right->kind==BasicTypeDeclaration::VECTOR)
689                                 type = find_type(*elem_result, BasicTypeDeclaration::VECTOR, basic_left->size>>16);
690                         else
691                                 type = find_type(*elem_result, BasicTypeDeclaration::MATRIX, (basic_left->size&0xFFFF0000)|(basic_right->size&0xFFFF));
692                 }
693                 else if(compat==NOT_COMPATIBLE)
694                 {
695                         // Arithmetic between scalars and matrices or vectors is supported.
696                         if(is_scalar(*basic_left) && is_vector_or_matrix(*basic_right))
697                                 type = (elem_compat==RIGHT_CONVERTIBLE ? find_type(*elem_left, basic_right->kind, basic_right->size) : basic_right);
698                         else if(is_vector_or_matrix(*basic_left) && is_scalar(*basic_right))
699                                 type = (elem_compat==LEFT_CONVERTIBLE ? find_type(*elem_right, basic_left->kind, basic_left->size) : basic_left);
700                         else
701                                 return;
702                 }
703                 else if(compat==LEFT_CONVERTIBLE)
704                         type = basic_right;
705                 else
706                         type = basic_left;
707         }
708         else
709                 return;
710
711         if(assign && type!=basic_left)
712                 return;
713
714         bool converted = true;
715         if(compat==LEFT_CONVERTIBLE)
716                 convert_to(binary.left, *basic_right);
717         else if(compat==RIGHT_CONVERTIBLE)
718                 convert_to(binary.right, *basic_left);
719         else if(elem_compat==LEFT_CONVERTIBLE)
720                 converted = convert_to_element(binary.left, *elem_right);
721         else if(elem_compat==RIGHT_CONVERTIBLE)
722                 converted = convert_to_element(binary.right, *elem_left);
723
724         if(!converted)
725                 type = 0;
726
727         resolve(binary, type, assign);
728 }
729
730 void ExpressionResolver::visit(BinaryExpression &binary)
731 {
732         TraversingVisitor::visit(binary);
733         visit(binary, false);
734 }
735
736 void ExpressionResolver::visit(Assignment &assign)
737 {
738         TraversingVisitor::visit(assign);
739
740         if(assign.oper->token[0]!='=')
741                 return visit(assign, true);
742         else if(assign.left->type!=assign.right->type)
743         {
744                 BasicTypeDeclaration *basic_left = dynamic_cast<BasicTypeDeclaration *>(assign.left->type);
745                 BasicTypeDeclaration *basic_right = dynamic_cast<BasicTypeDeclaration *>(assign.right->type);
746                 if(!basic_left || !basic_right)
747                         return;
748
749                 Compatibility compat = get_compatibility(*basic_left, *basic_right);
750                 if(compat==RIGHT_CONVERTIBLE)
751                         convert_to(assign.right, *basic_left);
752                 else if(compat!=SAME_TYPE)
753                         return;
754         }
755
756         resolve(assign, assign.left->type, true);
757 }
758
759 void ExpressionResolver::visit(FunctionCall &call)
760 {
761         TraversingVisitor::visit(call);
762
763         TypeDeclaration *type = 0;
764         if(call.declaration)
765                 type = call.declaration->return_type_declaration;
766         else if(call.constructor)
767         {
768                 map<string, TypeDeclaration *>::const_iterator i=stage->types.find(call.name);
769                 type = (i!=stage->types.end() ? i->second : 0);
770         }
771         resolve(call, type, false);
772 }
773
774 void ExpressionResolver::visit(BasicTypeDeclaration &type)
775 {
776         basic_types.push_back(&type);
777 }
778
779 void ExpressionResolver::visit(VariableDeclaration &var)
780 {
781         TraversingVisitor::visit(var);
782         if(!var.init_expression)
783                 return;
784
785         BasicTypeDeclaration *var_basic = dynamic_cast<BasicTypeDeclaration *>(var.type_declaration);
786         BasicTypeDeclaration *init_basic = dynamic_cast<BasicTypeDeclaration *>(var.init_expression->type);
787         if(!var_basic || !init_basic)
788                 return;
789
790         Compatibility compat = get_compatibility(*var_basic, *init_basic);
791         if(compat==RIGHT_CONVERTIBLE)
792                 convert_to(var.init_expression, *var_basic);
793 }
794
795
796 void FunctionResolver::apply(Stage &s)
797 {
798         stage = &s;
799         s.functions.clear();
800         s.content.visit(*this);
801 }
802
803 void FunctionResolver::visit(FunctionCall &call)
804 {
805         map<string, FunctionDeclaration *>::iterator i = stage->functions.find(call.name);
806         if(i!=stage->functions.end())
807                 call.declaration = i->second;
808
809         TraversingVisitor::visit(call);
810 }
811
812 void FunctionResolver::visit(FunctionDeclaration &func)
813 {
814         FunctionDeclaration *&stage_decl = stage->functions[func.name];
815         vector<FunctionDeclaration *> &decls = declarations[func.name];
816         if(func.definition==&func)
817         {
818                 stage_decl = &func;
819
820                 // Set all previous declarations to use this definition.
821                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
822                 {
823                         (*i)->definition = func.definition;
824                         (*i)->body.body.clear();
825                 }
826         }
827         else
828         {
829                 func.definition = 0;
830                 if(!stage_decl)
831                         stage_decl = &func;
832                 else
833                         func.definition = stage_decl->definition;
834         }
835         decls.push_back(&func);
836
837         TraversingVisitor::visit(func);
838 }
839
840
841 InterfaceGenerator::InterfaceGenerator():
842         stage(0),
843         function_scope(false),
844         iface_block(0),
845         copy_block(false),
846         iface_target_block(0)
847 { }
848
849 string InterfaceGenerator::get_out_prefix(Stage::Type type)
850 {
851         if(type==Stage::VERTEX)
852                 return "_vs_out_";
853         else if(type==Stage::GEOMETRY)
854                 return "_gs_out_";
855         else
856                 return string();
857 }
858
859 void InterfaceGenerator::apply(Stage &s)
860 {
861         stage = &s;
862         iface_target_block = &stage->content;
863         if(stage->previous)
864                 in_prefix = get_out_prefix(stage->previous->type);
865         out_prefix = get_out_prefix(stage->type);
866         s.content.visit(*this);
867         NodeRemover().apply(s, nodes_to_remove);
868 }
869
870 void InterfaceGenerator::visit(Block &block)
871 {
872         SetForScope<Block *> set_block(current_block, &block);
873         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
874         {
875                 assignment_insert_point = i;
876                 if(&block==&stage->content)
877                         iface_insert_point = i;
878
879                 (*i)->visit(*this);
880         }
881 }
882
883 string InterfaceGenerator::change_prefix(const string &name, const string &prefix) const
884 {
885         unsigned offset = (name.compare(0, in_prefix.size(), in_prefix) ? 0 : in_prefix.size());
886         return prefix+name.substr(offset);
887 }
888
889 VariableDeclaration *InterfaceGenerator::generate_interface(VariableDeclaration &var, const string &iface, const string &name)
890 {
891         if(stage->content.variables.count(name))
892                 return 0;
893
894         VariableDeclaration* iface_var = new VariableDeclaration;
895         iface_var->sampling = var.sampling;
896         iface_var->interface = iface;
897         iface_var->type = var.type;
898         iface_var->name = name;
899         /* Geometry shader inputs are always arrays.  But if we're bringing in an
900         entire block, the array is on the block and not individual variables. */
901         if(stage->type==Stage::GEOMETRY && !copy_block)
902                 iface_var->array = ((var.array && var.interface!="in") || iface=="in");
903         else
904                 iface_var->array = var.array;
905         if(iface_var->array)
906                 iface_var->array_size = var.array_size;
907         if(iface=="in")
908         {
909                 iface_var->layout = var.layout;
910                 iface_var->linked_declaration = &var;
911                 var.linked_declaration = iface_var;
912         }
913
914         iface_target_block->body.insert(iface_insert_point, iface_var);
915         iface_target_block->variables.insert(make_pair(name, iface_var));
916
917         return iface_var;
918 }
919
920 InterfaceBlock *InterfaceGenerator::generate_interface(InterfaceBlock &out_block)
921 {
922         if(stage->interface_blocks.count("in"+out_block.name))
923                 return 0;
924
925         InterfaceBlock *in_block = new InterfaceBlock;
926         in_block->interface = "in";
927         in_block->name = out_block.name;
928         in_block->instance_name = out_block.instance_name;
929         if(stage->type==Stage::GEOMETRY)
930                 in_block->array = true;
931         else
932                 in_block->array = out_block.array;
933         in_block->linked_block = &out_block;
934         out_block.linked_block = in_block;
935
936         {
937                 SetFlag set_copy(copy_block, true);
938                 SetForScope<Block *> set_target(iface_target_block, &in_block->members);
939                 SetForScope<NodeList<Statement>::iterator> set_ins_pt(iface_insert_point, in_block->members.body.end());
940                 out_block.members.visit(*this);
941         }
942
943         iface_target_block->body.insert(iface_insert_point, in_block);
944         stage->interface_blocks.insert(make_pair("in"+in_block->name, in_block));
945         if(!in_block->instance_name.empty())
946                 stage->interface_blocks.insert(make_pair("_"+in_block->instance_name, in_block));
947
948         SetFlag set_scope(function_scope, false);
949         SetForScope<Block *> set_block(current_block, &stage->content);
950         in_block->visit(*this);
951
952         return in_block;
953 }
954
955 ExpressionStatement &InterfaceGenerator::insert_assignment(const string &left, Expression *right)
956 {
957         Assignment *assign = new Assignment;
958         VariableReference *ref = new VariableReference;
959         ref->name = left;
960         assign->left = ref;
961         assign->oper = &Operator::get_operator("=", Operator::BINARY);
962         assign->right = right;
963
964         ExpressionStatement *stmt = new ExpressionStatement;
965         stmt->expression = assign;
966         current_block->body.insert(assignment_insert_point, stmt);
967         stmt->visit(*this);
968
969         return *stmt;
970 }
971
972 void InterfaceGenerator::visit(VariableReference &var)
973 {
974         if(var.declaration || !stage->previous)
975                 return;
976         /* Don't pull a variable from previous stage if we just generated an output
977         interface in this stage */
978         if(stage->content.variables.count(var.name))
979                 return;
980
981         const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
982         map<string, VariableDeclaration *>::const_iterator i = prev_vars.find(var.name);
983         if(i==prev_vars.end() || i->second->interface!="out")
984                 i = prev_vars.find(in_prefix+var.name);
985         if(i!=prev_vars.end() && i->second->interface=="out")
986         {
987                 generate_interface(*i->second, "in", i->second->name);
988                 var.name = i->second->name;
989                 return;
990         }
991
992         const map<string, InterfaceBlock *> &prev_blocks = stage->previous->interface_blocks;
993         map<string, InterfaceBlock *>::const_iterator j = prev_blocks.find("_"+var.name);
994         if(j!=prev_blocks.end() && j->second->interface=="out")
995         {
996                 generate_interface(*j->second);
997                 /* Let VariableResolver convert the variable reference into an interface
998                 block reference. */
999                 return;
1000         }
1001
1002         for(j=prev_blocks.begin(); j!=prev_blocks.end(); ++j)
1003                 if(j->second->instance_name.empty())
1004                 {
1005                         i = j->second->members.variables.find(var.name);
1006                         if(i!=j->second->members.variables.end())
1007                         {
1008                                 generate_interface(*j->second);
1009                                 return;
1010                         }
1011                 }
1012 }
1013
1014 void InterfaceGenerator::visit(VariableDeclaration &var)
1015 {
1016         if(copy_block)
1017         {
1018                 generate_interface(var, "in", var.name);
1019                 return;
1020         }
1021
1022         if(iface_block)
1023         {
1024                 if(iface_block->linked_block)
1025                 {
1026                         // Link all variables to their counterparts in the linked block.
1027                         const map<string, VariableDeclaration *> &linked_vars = iface_block->linked_block->members.variables;
1028                         map<string, VariableDeclaration *>::const_iterator i = linked_vars.find(var.name);
1029                         if(i!=linked_vars.end())
1030                         {
1031                                 var.linked_declaration = i->second;
1032                                 var.linked_declaration->linked_declaration = &var;
1033                         }
1034                 }
1035                 return;
1036         }
1037
1038         if(var.interface=="out")
1039         {
1040                 /* For output variables in function scope, generate a global interface
1041                 and replace the local declaration with an assignment. */
1042                 VariableDeclaration *out_var = 0;
1043                 if(function_scope && (out_var=generate_interface(var, "out", var.name)))
1044                 {
1045                         out_var->source = var.source;
1046                         out_var->line = var.line;
1047                         nodes_to_remove.insert(&var);
1048                         if(var.init_expression)
1049                         {
1050                                 ExpressionStatement &stmt = insert_assignment(var.name, var.init_expression->clone());
1051                                 stmt.source = var.source;
1052                                 stmt.line = var.line;
1053                                 return;
1054                         }
1055                 }
1056         }
1057         else if(var.interface=="in")
1058         {
1059                 /* Try to link input variables in global scope with output variables from
1060                 previous stage. */
1061                 if(current_block==&stage->content && !var.linked_declaration && stage->previous)
1062                 {
1063                         const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
1064                         map<string, VariableDeclaration *>::const_iterator i = prev_vars.find(var.name);
1065                         if(i!=prev_vars.end() && i->second->interface=="out")
1066                         {
1067                                 var.linked_declaration = i->second;
1068                                 i->second->linked_declaration = &var;
1069                         }
1070                 }
1071         }
1072
1073         TraversingVisitor::visit(var);
1074 }
1075
1076 void InterfaceGenerator::visit(InterfaceBlock &iface)
1077 {
1078         if(iface.interface=="in")
1079         {
1080                 /* Try to link input blocks with output blocks sharing the same block
1081                 name from previous stage. */
1082                 if(!iface.linked_block && stage->previous)
1083                 {
1084                         const map<string, InterfaceBlock *> &prev_blocks = stage->previous->interface_blocks;
1085                         map<string, InterfaceBlock *>::const_iterator i = prev_blocks.find("out"+iface.name);
1086                         if(i!=prev_blocks.end())
1087                         {
1088                                 iface.linked_block = i->second;
1089                                 i->second->linked_block = &iface;
1090                         }
1091                 }
1092         }
1093
1094         SetForScope<InterfaceBlock *> set_iface(iface_block, &iface);
1095         TraversingVisitor::visit(iface);
1096 }
1097
1098 void InterfaceGenerator::visit(FunctionDeclaration &func)
1099 {
1100         SetFlag set_scope(function_scope, true);
1101         // Skip parameters because they're not useful here
1102         func.body.visit(*this);
1103 }
1104
1105 void InterfaceGenerator::visit(Passthrough &pass)
1106 {
1107         vector<VariableDeclaration *> pass_vars;
1108
1109         // Pass through all input variables of this stage.
1110         for(map<string, VariableDeclaration *>::const_iterator i=stage->content.variables.begin(); i!=stage->content.variables.end(); ++i)
1111                 if(i->second->interface=="in")
1112                         pass_vars.push_back(i->second);
1113
1114         if(stage->previous)
1115         {
1116                 const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
1117                 for(map<string, VariableDeclaration *>::const_iterator i=prev_vars.begin(); i!=prev_vars.end(); ++i)
1118                 {
1119                         if(i->second->interface!="out")
1120                                 continue;
1121
1122                         /* Pass through output variables from the previous stage, but only
1123                         those which are not already linked to an input here. */
1124                         if(!i->second->linked_declaration && generate_interface(*i->second, "in", i->second->name))
1125                                 pass_vars.push_back(i->second);
1126                 }
1127         }
1128
1129         if(stage->type==Stage::GEOMETRY)
1130         {
1131                 /* Special case for geometry shader: copy gl_Position from input to
1132                 output. */
1133                 InterfaceBlockReference *ref = new InterfaceBlockReference;
1134                 ref->name = "gl_in";
1135
1136                 BinaryExpression *subscript = new BinaryExpression;
1137                 subscript->left = ref;
1138                 subscript->oper = &Operator::get_operator("[", Operator::BINARY);
1139                 subscript->right = pass.subscript;
1140
1141                 MemberAccess *memacc = new MemberAccess;
1142                 memacc->left = subscript;
1143                 memacc->member = "gl_Position";
1144
1145                 insert_assignment("gl_Position", memacc);
1146         }
1147
1148         for(vector<VariableDeclaration *>::const_iterator i=pass_vars.begin(); i!=pass_vars.end(); ++i)
1149         {
1150                 string out_name = change_prefix((*i)->name, out_prefix);
1151                 generate_interface(**i, "out", out_name);
1152
1153                 VariableReference *ref = new VariableReference;
1154                 ref->name = (*i)->name;
1155                 if(pass.subscript)
1156                 {
1157                         BinaryExpression *subscript = new BinaryExpression;
1158                         subscript->left = ref;
1159                         subscript->oper = &Operator::get_operator("[", Operator::BINARY);
1160                         subscript->right = pass.subscript;
1161                         insert_assignment(out_name, subscript);
1162                 }
1163                 else
1164                         insert_assignment(out_name, ref);
1165         }
1166
1167         nodes_to_remove.insert(&pass);
1168 }
1169
1170 } // namespace SL
1171 } // namespace GL
1172 } // namespace Msp