]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/generate.cpp
Handle redeclaration of variables in VariableResolver
[libs/gl.git] / source / glsl / generate.cpp
1 #include <algorithm>
2 #include <msp/core/hash.h>
3 #include <msp/core/raii.h>
4 #include <msp/strings/lexicalcast.h>
5 #include <msp/strings/utils.h>
6 #include "builtin.h"
7 #include "generate.h"
8
9 using namespace std;
10
11 namespace Msp {
12 namespace GL {
13 namespace SL {
14
15 ConstantSpecializer::ConstantSpecializer():
16         values(0)
17 { }
18
19 void ConstantSpecializer::apply(Stage &stage, const map<string, int> *v)
20 {
21         values = v;
22         stage.content.visit(*this);
23 }
24
25 void ConstantSpecializer::visit(VariableDeclaration &var)
26 {
27         bool specializable = false;
28         if(var.layout)
29         {
30                 vector<Layout::Qualifier> &qualifiers = var.layout->qualifiers;
31                 for(vector<Layout::Qualifier>::iterator i=qualifiers.begin(); i!=qualifiers.end(); ++i)
32                         if(i->name=="constant_id")
33                         {
34                                 specializable = true;
35                                 if(values)
36                                         qualifiers.erase(i);
37                                 else if(i->value==-1)
38                                         i->value = hash32(var.name)&0x7FFFFFFF;
39                                 break;
40                         }
41
42                 if(qualifiers.empty())
43                         var.layout = 0;
44         }
45
46         if(specializable && values)
47         {
48                 map<string, int>::const_iterator i = values->find(var.name);
49                 if(i!=values->end())
50                 {
51                         RefPtr<Literal> literal = new Literal;
52                         if(var.type=="bool")
53                         {
54                                 literal->token = (i->second ? "true" : "false");
55                                 literal->value = static_cast<bool>(i->second);
56                         }
57                         else if(var.type=="int")
58                         {
59                                 literal->token = lexical_cast<string>(i->second);
60                                 literal->value = i->second;
61                         }
62                         var.init_expression = literal;
63                 }
64         }
65 }
66
67
68 void BlockHierarchyResolver::enter(Block &block)
69 {
70         r_any_resolved |= (current_block!=block.parent);
71         block.parent = current_block;
72 }
73
74
75 TypeResolver::TypeResolver():
76         stage(0),
77         iface_block(0),
78         r_any_resolved(false)
79 { }
80
81 bool TypeResolver::apply(Stage &s)
82 {
83         stage = &s;
84         s.types.clear();
85         r_any_resolved = false;
86         s.content.visit(*this);
87         return r_any_resolved;
88 }
89
90 TypeDeclaration *TypeResolver::get_or_create_array_type(TypeDeclaration &type)
91 {
92         map<TypeDeclaration *, TypeDeclaration *>::iterator i = array_types.find(&type);
93         if(i!=array_types.end())
94                 return i->second;
95
96         BasicTypeDeclaration *array = new BasicTypeDeclaration;
97         array->source = BUILTIN_SOURCE;
98         array->name = type.name+"[]";
99         array->kind = BasicTypeDeclaration::ARRAY;
100         array->base = type.name;
101         array->base_type = &type;
102         stage->content.body.insert(type_insert_point, array);
103         array_types[&type] = array;
104         return array;
105 }
106
107 void TypeResolver::resolve_type(TypeDeclaration *&type, const string &name, bool array)
108 {
109         TypeDeclaration *resolved = 0;
110         map<string, TypeDeclaration *>::iterator i = stage->types.find(name);
111         if(i!=stage->types.end())
112         {
113                 map<TypeDeclaration *, TypeDeclaration *>::iterator j = alias_map.find(i->second);
114                 resolved = (j!=alias_map.end() ? j->second : i->second);
115         }
116
117         if(resolved && array)
118                 resolved = get_or_create_array_type(*resolved);
119
120         r_any_resolved |= (resolved!=type);
121         type=resolved;
122 }
123
124 void TypeResolver::visit(Block &block)
125 {
126         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
127         {
128                 if(!block.parent)
129                         type_insert_point = i;
130                 (*i)->visit(*this);
131         }
132 }
133
134 void TypeResolver::visit(BasicTypeDeclaration &type)
135 {
136         resolve_type(type.base_type, type.base, false);
137
138         if(type.kind==BasicTypeDeclaration::VECTOR && type.base_type)
139                 if(BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type))
140                         if(basic_base->kind==BasicTypeDeclaration::VECTOR)
141                         {
142                                 type.kind = BasicTypeDeclaration::MATRIX;
143                                 /* A matrix's base type is its column vector type.  This will put
144                                 the column vector's size, i.e. the matrix's row count, in the high
145                                 half of the size. */
146                                 type.size |= basic_base->size<<16;
147                         }
148
149         if(type.kind==BasicTypeDeclaration::ALIAS && type.base_type)
150                 alias_map[&type] = type.base_type;
151         else if(type.kind==BasicTypeDeclaration::ARRAY && type.base_type)
152                 array_types[type.base_type] = &type;
153
154         stage->types.insert(make_pair(type.name, &type));
155 }
156
157 void TypeResolver::visit(ImageTypeDeclaration &type)
158 {
159         resolve_type(type.base_type, type.base, false);
160         stage->types.insert(make_pair(type.name, &type));
161 }
162
163 void TypeResolver::visit(StructDeclaration &strct)
164 {
165         stage->types.insert(make_pair(strct.name, &strct));
166         TraversingVisitor::visit(strct);
167 }
168
169 void TypeResolver::visit(VariableDeclaration &var)
170 {
171         resolve_type(var.type_declaration, var.type, var.array);
172         if(iface_block && var.interface==iface_block->interface)
173                 var.interface.clear();
174 }
175
176 void TypeResolver::visit(InterfaceBlock &iface)
177 {
178         if(iface.members)
179         {
180                 SetForScope<InterfaceBlock *> set_iface(iface_block, &iface);
181                 iface.members->visit(*this);
182
183                 StructDeclaration *strct = new StructDeclaration;
184                 strct->source = INTERNAL_SOURCE;
185                 strct->name = format("_%s_%s", iface.interface, iface.name);
186                 strct->members.body.splice(strct->members.body.begin(), iface.members->body);
187                 stage->content.body.insert(type_insert_point, strct);
188                 stage->types.insert(make_pair(strct->name, strct));
189
190                 iface.members = 0;
191                 strct->interface_block = &iface;
192                 iface.struct_declaration = strct;
193         }
194
195         TypeDeclaration *type = iface.struct_declaration;
196         if(type && iface.array)
197                 type = get_or_create_array_type(*type);
198         r_any_resolved = (type!=iface.type_declaration);
199         iface.type_declaration = type;
200 }
201
202 void TypeResolver::visit(FunctionDeclaration &func)
203 {
204         resolve_type(func.return_type_declaration, func.return_type, false);
205         TraversingVisitor::visit(func);
206 }
207
208
209 VariableResolver::VariableResolver():
210         stage(0),
211         r_any_resolved(false),
212         record_target(false),
213         r_self_referencing(false)
214 { }
215
216 bool VariableResolver::apply(Stage &s)
217 {
218         stage = &s;
219         s.interface_blocks.clear();
220         r_any_resolved = false;
221         s.content.visit(*this);
222         NodeRemover().apply(s, nodes_to_remove);
223         return r_any_resolved;
224 }
225
226 void VariableResolver::enter(Block &block)
227 {
228         block.variables.clear();
229 }
230
231 void VariableResolver::visit(RefPtr<Expression> &expr)
232 {
233         r_replacement_expr = 0;
234         expr->visit(*this);
235         if(r_replacement_expr)
236         {
237                 expr = r_replacement_expr;
238                 /* Don't record assignment target when doing a replacement, because chain
239                 information won't be correct. */
240                 r_assignment_target.declaration = 0;
241                 r_any_resolved = true;
242         }
243         r_replacement_expr = 0;
244 }
245
246 void VariableResolver::check_assignment_target(Statement *declaration)
247 {
248         if(record_target)
249         {
250                 if(r_assignment_target.declaration)
251                 {
252                         /* More than one reference found in assignment target.  Unable to
253                         determine what the primary target is. */
254                         record_target = false;
255                         r_assignment_target.declaration = 0;
256                 }
257                 else
258                         r_assignment_target.declaration = declaration;
259         }
260         // TODO This check is overly broad and may prevent some optimizations.
261         else if(declaration && declaration==r_assignment_target.declaration)
262                 r_self_referencing = true;
263 }
264
265 void VariableResolver::visit(VariableReference &var)
266 {
267         VariableDeclaration *declaration = 0;
268
269         /* Look for variable declarations in the block hierarchy first.  Interface
270         blocks are always defined in the top level so we can't accidentally skip
271         one. */
272         for(Block *block=current_block; (!declaration && block); block=block->parent)
273         {
274                 map<string, VariableDeclaration *>::iterator i = block->variables.find(var.name);
275                 if(i!=block->variables.end())
276                         declaration = i->second;
277         }
278
279         if(!declaration)
280         {
281                 const map<string, InterfaceBlock *> &blocks = stage->interface_blocks;
282                 map<string, InterfaceBlock *>::const_iterator i = blocks.find("_"+var.name);
283                 if(i!=blocks.end())
284                 {
285                         /* The name refers to an interface block with an instance name rather
286                         than a variable.  Prepare a new syntax tree node accordingly. */
287                         InterfaceBlockReference *iface_ref = new InterfaceBlockReference;
288                         iface_ref->source = var.source;
289                         iface_ref->line = var.line;
290                         iface_ref->name = var.name;
291                         iface_ref->declaration = i->second;
292                         r_replacement_expr = iface_ref;
293                 }
294                 else
295                 {
296                         // Look for the variable in anonymous interface blocks.
297                         for(i=blocks.begin(); (!declaration && i!=blocks.end()); ++i)
298                                 if(i->second->instance_name.empty() && i->second->struct_declaration)
299                                 {
300                                         const map<string, VariableDeclaration *> &iface_vars = i->second->struct_declaration->members.variables;
301                                         map<string, VariableDeclaration *>::const_iterator j = iface_vars.find(var.name);
302                                         if(j!=iface_vars.end())
303                                                 declaration = j->second;
304                                 }
305                 }
306         }
307
308         r_any_resolved |= (declaration!=var.declaration);
309         var.declaration = declaration;
310
311         check_assignment_target(var.declaration);
312 }
313
314 void VariableResolver::visit(InterfaceBlockReference &iface)
315 {
316         map<string, InterfaceBlock *>::iterator i = stage->interface_blocks.find("_"+iface.name);
317         InterfaceBlock *declaration = (i!=stage->interface_blocks.end() ? i->second : 0);
318         r_any_resolved |= (declaration!=iface.declaration);
319         iface.declaration = declaration;
320
321         check_assignment_target(iface.declaration);
322 }
323
324 void VariableResolver::add_to_chain(Assignment::Target::ChainType type, unsigned index)
325 {
326         if(r_assignment_target.chain_len<7)
327                 r_assignment_target.chain[r_assignment_target.chain_len] = type | min<unsigned>(index, 0x3F);
328         ++r_assignment_target.chain_len;
329 }
330
331 void VariableResolver::visit(MemberAccess &memacc)
332 {
333         TraversingVisitor::visit(memacc);
334
335         VariableDeclaration *declaration = 0;
336         if(StructDeclaration *strct = dynamic_cast<StructDeclaration *>(memacc.left->type))
337         {
338                 map<string, VariableDeclaration *>::iterator i = strct->members.variables.find(memacc.member);
339                 if(i!=strct->members.variables.end())
340                 {
341                         declaration = i->second;
342
343                         if(record_target)
344                         {
345                                 unsigned index = 0;
346                                 for(NodeList<Statement>::const_iterator j=strct->members.body.begin(); (j!=strct->members.body.end() && j->get()!=i->second); ++j)
347                                         ++index;
348
349                                 add_to_chain(Assignment::Target::MEMBER, index);
350                         }
351                 }
352         }
353         else if(BasicTypeDeclaration *basic = dynamic_cast<BasicTypeDeclaration *>(memacc.left->type))
354         {
355                 bool scalar_swizzle = ((basic->kind==BasicTypeDeclaration::INT || basic->kind==BasicTypeDeclaration::FLOAT) && memacc.member.size()==1);
356                 bool vector_swizzle = (basic->kind==BasicTypeDeclaration::VECTOR && memacc.member.size()<=4);
357                 if(scalar_swizzle || vector_swizzle)
358                 {
359                         static const char component_names[] = { 'x', 'r', 's', 'y', 'g', 't', 'z', 'b', 'p', 'w', 'a', 'q' };
360
361                         bool ok = true;
362                         UInt8 components[4] = { };
363                         for(unsigned i=0; (ok && i<memacc.member.size()); ++i)
364                                 ok = ((components[i] = (find(component_names, component_names+12, memacc.member[i])-component_names)/3) < 4);
365
366                         if(ok)
367                         {
368                                 Swizzle *swizzle = new Swizzle;
369                                 swizzle->source = memacc.source;
370                                 swizzle->line = memacc.line;
371                                 swizzle->oper = memacc.oper;
372                                 swizzle->left = memacc.left;
373                                 swizzle->component_group = memacc.member;
374                                 swizzle->count = memacc.member.size();
375                                 copy(components, components+memacc.member.size(), swizzle->components);
376                                 r_replacement_expr = swizzle;
377                         }
378                 }
379         }
380
381         r_any_resolved |= (declaration!=memacc.declaration);
382         memacc.declaration = declaration;
383 }
384
385 void VariableResolver::visit(Swizzle &swizzle)
386 {
387         TraversingVisitor::visit(swizzle);
388
389         if(record_target)
390         {
391                 unsigned mask = 0;
392                 for(unsigned i=0; i<swizzle.count; ++i)
393                         mask |= 1<<swizzle.components[i];
394                 add_to_chain(Assignment::Target::SWIZZLE, mask);
395         }
396 }
397
398 void VariableResolver::visit(BinaryExpression &binary)
399 {
400         if(binary.oper->token[0]=='[')
401         {
402                 {
403                         /* The subscript expression is not a part of the primary assignment
404                         target. */
405                         SetFlag set(record_target, false);
406                         visit(binary.right);
407                 }
408                 visit(binary.left);
409
410                 if(record_target)
411                 {
412                         unsigned index = 0x3F;
413                         if(Literal *literal_subscript = dynamic_cast<Literal *>(binary.right.get()))
414                                 if(literal_subscript->value.check_type<int>())
415                                         index = literal_subscript->value.value<int>();
416                         add_to_chain(Assignment::Target::ARRAY, index);
417                 }
418         }
419         else
420                 TraversingVisitor::visit(binary);
421 }
422
423 void VariableResolver::visit(Assignment &assign)
424 {
425         {
426                 SetFlag set(record_target);
427                 r_assignment_target = Assignment::Target();
428                 visit(assign.left);
429                 r_any_resolved |= (r_assignment_target<assign.target || assign.target<r_assignment_target);
430                 assign.target = r_assignment_target;
431         }
432
433         r_self_referencing = false;
434         visit(assign.right);
435         assign.self_referencing = (r_self_referencing || assign.oper->token[0]!='=');
436 }
437
438 void VariableResolver::merge_layouts(Layout &to_layout, const Layout &from_layout)
439 {
440         for(vector<Layout::Qualifier>::const_iterator i=from_layout.qualifiers.begin(); i!=from_layout.qualifiers.end(); ++i)
441         {
442                 bool found = false;
443                 for(vector<Layout::Qualifier>::iterator j=to_layout.qualifiers.begin(); (!found && j!=to_layout.qualifiers.end()); ++j)
444                         if(j->name==i->name)
445                         {
446                                 j->has_value = i->value;
447                                 j->value = i->value;
448                                 found = true;
449                         }
450
451                 if(!found)
452                         to_layout.qualifiers.push_back(*i);
453         }
454 }
455
456 void VariableResolver::visit(VariableDeclaration &var)
457 {
458         TraversingVisitor::visit(var);
459         VariableDeclaration *&ptr = current_block->variables[var.name];
460         if(!ptr)
461                 ptr = &var;
462         else if(!current_block->parent && ptr->interface==var.interface && ptr->type==var.type)
463         {
464                 if(var.init_expression)
465                         ptr->init_expression = var.init_expression;
466                 if(var.layout)
467                 {
468                         if(ptr->layout)
469                                 merge_layouts(*ptr->layout, *var.layout);
470                         else
471                                 ptr->layout = var.layout;
472                 }
473                 nodes_to_remove.insert(&var);
474
475                 r_any_resolved = true;
476         }
477 }
478
479 void VariableResolver::visit(InterfaceBlock &iface)
480 {
481         /* Block names can be reused in different interfaces.  Prefix the name with
482         the first character of the interface to avoid conflicts. */
483         stage->interface_blocks.insert(make_pair(iface.interface+iface.name, &iface));
484         if(!iface.instance_name.empty())
485                 stage->interface_blocks.insert(make_pair("_"+iface.instance_name, &iface));
486
487         TraversingVisitor::visit(iface);
488 }
489
490
491 ExpressionResolver::ExpressionResolver():
492         stage(0),
493         r_any_resolved(false)
494 { }
495
496 bool ExpressionResolver::apply(Stage &s)
497 {
498         stage = &s;
499         r_any_resolved = false;
500         s.content.visit(*this);
501         return r_any_resolved;
502 }
503
504 bool ExpressionResolver::is_scalar(BasicTypeDeclaration &type)
505 {
506         return (type.kind==BasicTypeDeclaration::INT || type.kind==BasicTypeDeclaration::FLOAT);
507 }
508
509 bool ExpressionResolver::is_vector_or_matrix(BasicTypeDeclaration &type)
510 {
511         return (type.kind==BasicTypeDeclaration::VECTOR || type.kind==BasicTypeDeclaration::MATRIX);
512 }
513
514 BasicTypeDeclaration *ExpressionResolver::get_element_type(BasicTypeDeclaration &type)
515 {
516         if(is_vector_or_matrix(type) || type.kind==BasicTypeDeclaration::ARRAY)
517         {
518                 BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type);
519                 return (basic_base ? get_element_type(*basic_base) : 0);
520         }
521         else
522                 return &type;
523 }
524
525 bool ExpressionResolver::can_convert(BasicTypeDeclaration &from, BasicTypeDeclaration &to)
526 {
527         if(from.kind==BasicTypeDeclaration::INT && to.kind==BasicTypeDeclaration::FLOAT)
528                 return from.size<=to.size;
529         else if(from.kind!=to.kind)
530                 return false;
531         else if((from.kind==BasicTypeDeclaration::VECTOR || from.kind==BasicTypeDeclaration::MATRIX) && from.size==to.size)
532         {
533                 BasicTypeDeclaration *from_base = dynamic_cast<BasicTypeDeclaration *>(from.base_type);
534                 BasicTypeDeclaration *to_base = dynamic_cast<BasicTypeDeclaration *>(to.base_type);
535                 return (from_base && to_base && can_convert(*from_base, *to_base));
536         }
537         else
538                 return false;
539 }
540
541 ExpressionResolver::Compatibility ExpressionResolver::get_compatibility(BasicTypeDeclaration &left, BasicTypeDeclaration &right)
542 {
543         if(&left==&right)
544                 return SAME_TYPE;
545         else if(can_convert(left, right))
546                 return LEFT_CONVERTIBLE;
547         else if(can_convert(right, left))
548                 return RIGHT_CONVERTIBLE;
549         else
550                 return NOT_COMPATIBLE;
551 }
552
553 BasicTypeDeclaration *ExpressionResolver::find_type(BasicTypeDeclaration::Kind kind, unsigned size)
554 {
555         for(vector<BasicTypeDeclaration *>::const_iterator i=basic_types.begin(); i!=basic_types.end(); ++i)
556                 if((*i)->kind==kind && (*i)->size==size)
557                         return *i;
558         return 0;
559 }
560
561 BasicTypeDeclaration *ExpressionResolver::find_type(BasicTypeDeclaration &elem_type, BasicTypeDeclaration::Kind kind, unsigned size)
562 {
563         for(vector<BasicTypeDeclaration *>::const_iterator i=basic_types.begin(); i!=basic_types.end(); ++i)
564                 if(get_element_type(**i)==&elem_type && (*i)->kind==kind && (*i)->size==size)
565                         return *i;
566         return 0;
567 }
568
569 void ExpressionResolver::convert_to(RefPtr<Expression> &expr, BasicTypeDeclaration &type)
570 {
571         RefPtr<FunctionCall> call = new FunctionCall;
572         call->name = type.name;
573         call->constructor = true;
574         call->arguments.push_back(0);
575         call->arguments.back() = expr;
576         call->type = &type;
577         expr = call;
578 }
579
580 bool ExpressionResolver::convert_to_element(RefPtr<Expression> &expr, BasicTypeDeclaration &elem_type)
581 {
582         if(BasicTypeDeclaration *expr_basic = dynamic_cast<BasicTypeDeclaration *>(expr->type))
583         {
584                 BasicTypeDeclaration *to_type = &elem_type;
585                 if(is_vector_or_matrix(*expr_basic))
586                         to_type = find_type(elem_type, expr_basic->kind, expr_basic->size);
587                 if(to_type)
588                 {
589                         convert_to(expr, *to_type);
590                         return true;
591                 }
592         }
593
594         return false;
595 }
596
597 void ExpressionResolver::resolve(Expression &expr, TypeDeclaration *type, bool lvalue)
598 {
599         r_any_resolved |= (type!=expr.type || lvalue!=expr.lvalue);
600         expr.type = type;
601         expr.lvalue = lvalue;
602 }
603
604 void ExpressionResolver::visit(Literal &literal)
605 {
606         if(literal.value.check_type<bool>())
607                 resolve(literal, find_type(BasicTypeDeclaration::BOOL, 1), false);
608         else if(literal.value.check_type<int>())
609                 resolve(literal, find_type(BasicTypeDeclaration::INT, 32), false);
610         else if(literal.value.check_type<float>())
611                 resolve(literal, find_type(BasicTypeDeclaration::FLOAT, 32), false);
612 }
613
614 void ExpressionResolver::visit(ParenthesizedExpression &parexpr)
615 {
616         TraversingVisitor::visit(parexpr);
617         resolve(parexpr, parexpr.expression->type, parexpr.expression->lvalue);
618 }
619
620 void ExpressionResolver::visit(VariableReference &var)
621 {
622         if(var.declaration)
623                 resolve(var, var.declaration->type_declaration, true);
624 }
625
626 void ExpressionResolver::visit(InterfaceBlockReference &iface)
627 {
628         if(iface.declaration)
629                 resolve(iface, iface.declaration->type_declaration, true);
630 }
631
632 void ExpressionResolver::visit(MemberAccess &memacc)
633 {
634         TraversingVisitor::visit(memacc);
635
636         if(memacc.declaration)
637                 resolve(memacc, memacc.declaration->type_declaration, memacc.left->lvalue);
638 }
639
640 void ExpressionResolver::visit(Swizzle &swizzle)
641 {
642         TraversingVisitor::visit(swizzle);
643
644         if(BasicTypeDeclaration *left_basic = dynamic_cast<BasicTypeDeclaration *>(swizzle.left->type))
645         {
646                 BasicTypeDeclaration *left_elem = get_element_type(*left_basic);
647                 if(swizzle.count==1)
648                         resolve(swizzle, left_elem, swizzle.left->lvalue);
649                 else if(left_basic->kind==BasicTypeDeclaration::VECTOR && left_elem)
650                         resolve(swizzle, find_type(*left_elem, left_basic->kind, swizzle.count), swizzle.left->lvalue);
651         }
652 }
653
654 void ExpressionResolver::visit(UnaryExpression &unary)
655 {
656         TraversingVisitor::visit(unary);
657
658         BasicTypeDeclaration *basic = dynamic_cast<BasicTypeDeclaration *>(unary.expression->type);
659         if(!basic)
660                 return;
661
662         char oper = unary.oper->token[0];
663         if(oper=='!')
664         {
665                 if(basic->kind!=BasicTypeDeclaration::BOOL)
666                         return;
667         }
668         else if(oper=='~')
669         {
670                 if(basic->kind!=BasicTypeDeclaration::INT)
671                         return;
672         }
673         else if(oper=='+' || oper=='-')
674         {
675                 BasicTypeDeclaration *elem = get_element_type(*basic);
676                 if(!elem || !is_scalar(*elem))
677                         return;
678         }
679         resolve(unary, basic, unary.expression->lvalue);
680 }
681
682 void ExpressionResolver::visit(BinaryExpression &binary, bool assign)
683 {
684         /* Binary operators are only defined for basic types (not for image or
685         structure types). */
686         BasicTypeDeclaration *basic_left = dynamic_cast<BasicTypeDeclaration *>(binary.left->type);
687         BasicTypeDeclaration *basic_right = dynamic_cast<BasicTypeDeclaration *>(binary.right->type);
688         if(!basic_left || !basic_right)
689                 return;
690
691         char oper = binary.oper->token[0];
692         if(oper=='[')
693         {
694                 /* Subscripting operates on vectors, matrices and arrays, and the right
695                 operand must be an integer. */
696                 if((!is_vector_or_matrix(*basic_left) && basic_left->kind!=BasicTypeDeclaration::ARRAY) || basic_right->kind!=BasicTypeDeclaration::INT)
697                         return;
698
699                 resolve(binary, basic_left->base_type, binary.left->lvalue);
700                 return;
701         }
702         else if(basic_left->kind==BasicTypeDeclaration::ARRAY || basic_right->kind==BasicTypeDeclaration::ARRAY)
703                 // No other binary operator can be used with arrays.
704                 return;
705
706         BasicTypeDeclaration *elem_left = get_element_type(*basic_left);
707         BasicTypeDeclaration *elem_right = get_element_type(*basic_right);
708         if(!elem_left || !elem_right)
709                 return;
710
711         Compatibility compat = get_compatibility(*basic_left, *basic_right);
712         Compatibility elem_compat = get_compatibility(*elem_left, *elem_right);
713         if(elem_compat==NOT_COMPATIBLE)
714                 return;
715         if(assign && (compat==LEFT_CONVERTIBLE || elem_compat==LEFT_CONVERTIBLE))
716                 return;
717
718         TypeDeclaration *type = 0;
719         char oper2 = binary.oper->token[1];
720         if((oper=='<' && oper2!='<') || (oper=='>' && oper2!='>'))
721         {
722                 /* Relational operators compare two scalar integer or floating-point
723                 values. */
724                 if(!is_scalar(*elem_left) || !is_scalar(*elem_right) || compat==NOT_COMPATIBLE)
725                         return;
726
727                 type = find_type(BasicTypeDeclaration::BOOL, 1);
728         }
729         else if((oper=='=' || oper=='!') && oper2=='=')
730         {
731                 // Equality comparison can be done on any compatible types.
732                 if(compat==NOT_COMPATIBLE)
733                         return;
734
735                 type = find_type(BasicTypeDeclaration::BOOL, 1);
736         }
737         else if(oper2=='&' || oper2=='|' || oper2=='^')
738         {
739                 // Logical operators can only be applied to booleans.
740                 if(basic_left->kind!=BasicTypeDeclaration::BOOL || basic_right->kind!=BasicTypeDeclaration::BOOL)
741                         return;
742
743                 type = basic_left;
744         }
745         else if((oper=='&' || oper=='|' || oper=='^' || oper=='%') && !oper2)
746         {
747                 // Bitwise operators and modulo can only be applied to integers.
748                 if(basic_left->kind!=BasicTypeDeclaration::INT || basic_right->kind!=BasicTypeDeclaration::INT)
749                         return;
750
751                 type = (compat==LEFT_CONVERTIBLE ? basic_right : basic_left);
752         }
753         else if((oper=='<' || oper=='>') && oper2==oper)
754         {
755                 // Shifts apply to integer scalars and vectors, with some restrictions.
756                 if(elem_left->kind!=BasicTypeDeclaration::INT || elem_right->kind!=BasicTypeDeclaration::INT)
757                         return;
758                 unsigned left_size = (basic_left->kind==BasicTypeDeclaration::INT ? 1 : basic_left->kind==BasicTypeDeclaration::VECTOR ? basic_left->size : 0);
759                 unsigned right_size = (basic_right->kind==BasicTypeDeclaration::INT ? 1 : basic_right->kind==BasicTypeDeclaration::VECTOR ? basic_right->size : 0);
760                 if(!left_size || (left_size==1 && right_size!=1) || (left_size>1 && right_size!=1 && right_size!=left_size))
761                         return;
762
763                 type = basic_left;
764                 // Don't perform conversion even if the operands are of different sizes.
765                 compat = SAME_TYPE;
766         }
767         else if(oper=='+' || oper=='-' || oper=='*' || oper=='/')
768         {
769                 // Arithmetic operators require scalar elements.
770                 if(!is_scalar(*elem_left) || !is_scalar(*elem_right))
771                         return;
772
773                 if(oper=='*' && is_vector_or_matrix(*basic_left) && is_vector_or_matrix(*basic_right) &&
774                         (basic_left->kind==BasicTypeDeclaration::MATRIX || basic_right->kind==BasicTypeDeclaration::MATRIX))
775                 {
776                         /* Multiplication has special rules when at least one operand is a
777                         matrix and the other is a vector or a matrix. */
778                         unsigned left_columns = basic_left->size&0xFFFF;
779                         unsigned right_rows = basic_right->size;
780                         if(basic_right->kind==BasicTypeDeclaration::MATRIX)
781                                 right_rows >>= 16;
782                         if(left_columns!=right_rows)
783                                 return;
784
785                         BasicTypeDeclaration *elem_result = (elem_compat==LEFT_CONVERTIBLE ? elem_right : elem_left);
786
787                         if(basic_left->kind==BasicTypeDeclaration::VECTOR)
788                                 type = find_type(*elem_result, BasicTypeDeclaration::VECTOR, basic_right->size&0xFFFF);
789                         else if(basic_right->kind==BasicTypeDeclaration::VECTOR)
790                                 type = find_type(*elem_result, BasicTypeDeclaration::VECTOR, basic_left->size>>16);
791                         else
792                                 type = find_type(*elem_result, BasicTypeDeclaration::MATRIX, (basic_left->size&0xFFFF0000)|(basic_right->size&0xFFFF));
793                 }
794                 else if(compat==NOT_COMPATIBLE)
795                 {
796                         // Arithmetic between scalars and matrices or vectors is supported.
797                         if(is_scalar(*basic_left) && is_vector_or_matrix(*basic_right))
798                                 type = (elem_compat==RIGHT_CONVERTIBLE ? find_type(*elem_left, basic_right->kind, basic_right->size) : basic_right);
799                         else if(is_vector_or_matrix(*basic_left) && is_scalar(*basic_right))
800                                 type = (elem_compat==LEFT_CONVERTIBLE ? find_type(*elem_right, basic_left->kind, basic_left->size) : basic_left);
801                         else
802                                 return;
803                 }
804                 else if(compat==LEFT_CONVERTIBLE)
805                         type = basic_right;
806                 else
807                         type = basic_left;
808         }
809         else
810                 return;
811
812         if(assign && type!=basic_left)
813                 return;
814
815         bool converted = true;
816         if(compat==LEFT_CONVERTIBLE)
817                 convert_to(binary.left, *basic_right);
818         else if(compat==RIGHT_CONVERTIBLE)
819                 convert_to(binary.right, *basic_left);
820         else if(elem_compat==LEFT_CONVERTIBLE)
821                 converted = convert_to_element(binary.left, *elem_right);
822         else if(elem_compat==RIGHT_CONVERTIBLE)
823                 converted = convert_to_element(binary.right, *elem_left);
824
825         if(!converted)
826                 type = 0;
827
828         resolve(binary, type, assign);
829 }
830
831 void ExpressionResolver::visit(BinaryExpression &binary)
832 {
833         TraversingVisitor::visit(binary);
834         visit(binary, false);
835 }
836
837 void ExpressionResolver::visit(Assignment &assign)
838 {
839         TraversingVisitor::visit(assign);
840
841         if(assign.oper->token[0]!='=')
842                 return visit(assign, true);
843         else if(assign.left->type!=assign.right->type)
844         {
845                 BasicTypeDeclaration *basic_left = dynamic_cast<BasicTypeDeclaration *>(assign.left->type);
846                 BasicTypeDeclaration *basic_right = dynamic_cast<BasicTypeDeclaration *>(assign.right->type);
847                 if(!basic_left || !basic_right)
848                         return;
849
850                 Compatibility compat = get_compatibility(*basic_left, *basic_right);
851                 if(compat==RIGHT_CONVERTIBLE)
852                         convert_to(assign.right, *basic_left);
853                 else if(compat!=SAME_TYPE)
854                         return;
855         }
856
857         resolve(assign, assign.left->type, true);
858 }
859
860 void ExpressionResolver::visit(TernaryExpression &ternary)
861 {
862         TraversingVisitor::visit(ternary);
863
864         BasicTypeDeclaration *basic_cond = dynamic_cast<BasicTypeDeclaration *>(ternary.condition->type);
865         if(!basic_cond || basic_cond->kind!=BasicTypeDeclaration::BOOL)
866                 return;
867
868         TypeDeclaration *type = 0;
869         if(ternary.true_expr->type==ternary.false_expr->type)
870                 type = ternary.true_expr->type;
871         else
872         {
873                 BasicTypeDeclaration *basic_true = dynamic_cast<BasicTypeDeclaration *>(ternary.true_expr->type);
874                 BasicTypeDeclaration *basic_false = dynamic_cast<BasicTypeDeclaration *>(ternary.false_expr->type);
875                 Compatibility compat = get_compatibility(*basic_true, *basic_false);
876                 if(compat==NOT_COMPATIBLE)
877                         return;
878
879                 type = (compat==LEFT_CONVERTIBLE ? basic_true : basic_false);
880
881                 if(compat==LEFT_CONVERTIBLE)
882                         convert_to(ternary.true_expr, *basic_false);
883                 else if(compat==RIGHT_CONVERTIBLE)
884                         convert_to(ternary.false_expr, *basic_true);
885         }
886
887         resolve(ternary, type, false);
888 }
889
890 void ExpressionResolver::visit(FunctionCall &call)
891 {
892         TraversingVisitor::visit(call);
893
894         TypeDeclaration *type = 0;
895         if(call.declaration)
896                 type = call.declaration->return_type_declaration;
897         else if(call.constructor)
898         {
899                 map<string, TypeDeclaration *>::const_iterator i=stage->types.find(call.name);
900                 type = (i!=stage->types.end() ? i->second : 0);
901         }
902         resolve(call, type, false);
903 }
904
905 void ExpressionResolver::visit(BasicTypeDeclaration &type)
906 {
907         basic_types.push_back(&type);
908 }
909
910 void ExpressionResolver::visit(VariableDeclaration &var)
911 {
912         TraversingVisitor::visit(var);
913         if(!var.init_expression)
914                 return;
915
916         BasicTypeDeclaration *var_basic = dynamic_cast<BasicTypeDeclaration *>(var.type_declaration);
917         BasicTypeDeclaration *init_basic = dynamic_cast<BasicTypeDeclaration *>(var.init_expression->type);
918         if(!var_basic || !init_basic)
919                 return;
920
921         Compatibility compat = get_compatibility(*var_basic, *init_basic);
922         if(compat==RIGHT_CONVERTIBLE)
923                 convert_to(var.init_expression, *var_basic);
924 }
925
926
927 bool FunctionResolver::apply(Stage &s)
928 {
929         stage = &s;
930         s.functions.clear();
931         r_any_resolved = false;
932         s.content.visit(*this);
933         return r_any_resolved;
934 }
935
936 void FunctionResolver::visit(FunctionCall &call)
937 {
938         string arg_types;
939         bool has_signature = true;
940         for(NodeArray<Expression>::const_iterator i=call.arguments.begin(); (has_signature && i!=call.arguments.end()); ++i)
941         {
942                 if((*i)->type)
943                         append(arg_types, ",", (*i)->type->name);
944                 else
945                         has_signature = false;
946         }
947
948         FunctionDeclaration *declaration = 0;
949         if(has_signature)
950         {
951                 map<string, FunctionDeclaration *>::iterator i = stage->functions.find(format("%s(%s)", call.name, arg_types));
952                 declaration = (i!=stage->functions.end() ? i->second : 0);
953         }
954         r_any_resolved |= (declaration!=call.declaration);
955         call.declaration = declaration;
956
957         TraversingVisitor::visit(call);
958 }
959
960 void FunctionResolver::visit(FunctionDeclaration &func)
961 {
962         if(func.signature.empty())
963         {
964                 string param_types;
965                 for(NodeArray<VariableDeclaration>::const_iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
966                 {
967                         if((*i)->type_declaration)
968                                 append(param_types, ",", (*i)->type_declaration->name);
969                         else
970                                 return;
971                 }
972                 func.signature = format("(%s)", param_types);
973                 r_any_resolved = true;
974         }
975
976         string key = func.name+func.signature;
977         FunctionDeclaration *&stage_decl = stage->functions[key];
978         vector<FunctionDeclaration *> &decls = declarations[key];
979         if(func.definition==&func)
980         {
981                 stage_decl = &func;
982
983                 // Set all previous declarations to use this definition.
984                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
985                 {
986                         r_any_resolved |= (func.definition!=(*i)->definition);
987                         (*i)->definition = func.definition;
988                         (*i)->body.body.clear();
989                 }
990         }
991         else
992         {
993                 FunctionDeclaration *definition = (stage_decl ? stage_decl->definition : 0);
994                 r_any_resolved |= (definition!=func.definition);
995                 func.definition = definition;
996
997                 if(!stage_decl)
998                         stage_decl = &func;
999         }
1000         decls.push_back(&func);
1001
1002         TraversingVisitor::visit(func);
1003 }
1004
1005
1006 InterfaceGenerator::InterfaceGenerator():
1007         stage(0),
1008         function_scope(false),
1009         copy_block(false),
1010         iface_target_block(0)
1011 { }
1012
1013 string InterfaceGenerator::get_out_prefix(Stage::Type type)
1014 {
1015         if(type==Stage::VERTEX)
1016                 return "_vs_out_";
1017         else if(type==Stage::GEOMETRY)
1018                 return "_gs_out_";
1019         else
1020                 return string();
1021 }
1022
1023 void InterfaceGenerator::apply(Stage &s)
1024 {
1025         stage = &s;
1026         iface_target_block = &stage->content;
1027         if(stage->previous)
1028                 in_prefix = get_out_prefix(stage->previous->type);
1029         out_prefix = get_out_prefix(stage->type);
1030         s.content.visit(*this);
1031         NodeRemover().apply(s, nodes_to_remove);
1032 }
1033
1034 void InterfaceGenerator::visit(Block &block)
1035 {
1036         SetForScope<Block *> set_block(current_block, &block);
1037         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
1038         {
1039                 assignment_insert_point = i;
1040                 if(&block==&stage->content)
1041                         iface_insert_point = i;
1042
1043                 (*i)->visit(*this);
1044         }
1045 }
1046
1047 string InterfaceGenerator::change_prefix(const string &name, const string &prefix) const
1048 {
1049         unsigned offset = (name.compare(0, in_prefix.size(), in_prefix) ? 0 : in_prefix.size());
1050         return prefix+name.substr(offset);
1051 }
1052
1053 VariableDeclaration *InterfaceGenerator::generate_interface(VariableDeclaration &var, const string &iface, const string &name)
1054 {
1055         if(stage->content.variables.count(name))
1056                 return 0;
1057
1058         if(stage->type==Stage::GEOMETRY && !copy_block && var.interface=="out" && var.array)
1059                 return 0;
1060
1061         VariableDeclaration* iface_var = new VariableDeclaration;
1062         iface_var->sampling = var.sampling;
1063         iface_var->interface = iface;
1064         iface_var->type = var.type;
1065         iface_var->name = name;
1066         /* Geometry shader inputs are always arrays.  But if we're bringing in an
1067         entire block, the array is on the block and not individual variables. */
1068         if(stage->type==Stage::GEOMETRY && !copy_block)
1069                 iface_var->array = ((var.array && var.interface!="in") || iface=="in");
1070         else
1071                 iface_var->array = var.array;
1072         if(iface_var->array)
1073                 iface_var->array_size = var.array_size;
1074         if(iface=="in")
1075         {
1076                 iface_var->layout = var.layout;
1077                 iface_var->linked_declaration = &var;
1078                 var.linked_declaration = iface_var;
1079         }
1080
1081         iface_target_block->body.insert(iface_insert_point, iface_var);
1082         iface_target_block->variables.insert(make_pair(name, iface_var));
1083         if(iface_target_block==&stage->content && iface=="in")
1084                 declared_inputs.push_back(iface_var);
1085
1086         return iface_var;
1087 }
1088
1089 InterfaceBlock *InterfaceGenerator::generate_interface(InterfaceBlock &out_block)
1090 {
1091         if(stage->interface_blocks.count("in"+out_block.name))
1092                 return 0;
1093
1094         InterfaceBlock *in_block = new InterfaceBlock;
1095         in_block->interface = "in";
1096         in_block->name = out_block.name;
1097         in_block->members = new Block;
1098         in_block->instance_name = out_block.instance_name;
1099         if(stage->type==Stage::GEOMETRY)
1100                 in_block->array = true;
1101         else
1102                 in_block->array = out_block.array;
1103         in_block->linked_block = &out_block;
1104         out_block.linked_block = in_block;
1105
1106         {
1107                 SetFlag set_copy(copy_block, true);
1108                 SetForScope<Block *> set_target(iface_target_block, in_block->members.get());
1109                 SetForScope<NodeList<Statement>::iterator> set_ins_pt(iface_insert_point, in_block->members->body.end());
1110                 if(out_block.struct_declaration)
1111                         out_block.struct_declaration->members.visit(*this);
1112                 else if(out_block.members)
1113                         out_block.members->visit(*this);
1114         }
1115
1116         iface_target_block->body.insert(iface_insert_point, in_block);
1117         stage->interface_blocks.insert(make_pair("in"+in_block->name, in_block));
1118         if(!in_block->instance_name.empty())
1119                 stage->interface_blocks.insert(make_pair("_"+in_block->instance_name, in_block));
1120
1121         SetFlag set_scope(function_scope, false);
1122         SetForScope<Block *> set_block(current_block, &stage->content);
1123         in_block->visit(*this);
1124
1125         return in_block;
1126 }
1127
1128 ExpressionStatement &InterfaceGenerator::insert_assignment(const string &left, Expression *right)
1129 {
1130         Assignment *assign = new Assignment;
1131         VariableReference *ref = new VariableReference;
1132         ref->name = left;
1133         assign->left = ref;
1134         assign->oper = &Operator::get_operator("=", Operator::BINARY);
1135         assign->right = right;
1136
1137         ExpressionStatement *stmt = new ExpressionStatement;
1138         stmt->expression = assign;
1139         current_block->body.insert(assignment_insert_point, stmt);
1140         stmt->visit(*this);
1141
1142         return *stmt;
1143 }
1144
1145 void InterfaceGenerator::visit(VariableReference &var)
1146 {
1147         if(var.declaration || !stage->previous)
1148                 return;
1149         /* Don't pull a variable from previous stage if we just generated an output
1150         interface in this stage */
1151         if(stage->content.variables.count(var.name))
1152                 return;
1153
1154         const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
1155         map<string, VariableDeclaration *>::const_iterator i = prev_vars.find(var.name);
1156         if(i==prev_vars.end() || i->second->interface!="out")
1157                 i = prev_vars.find(in_prefix+var.name);
1158         if(i!=prev_vars.end() && i->second->interface=="out")
1159         {
1160                 if(stage->type==Stage::GEOMETRY && i->second->array)
1161                         stage->diagnostics.push_back(Diagnostic(Diagnostic::WARN, var.source, var.line,
1162                                 format("Can't access '%s' through automatic interface because it's an array", var.name)));
1163                 else
1164                 {
1165                         generate_interface(*i->second, "in", i->second->name);
1166                         var.name = i->second->name;
1167                 }
1168                 return;
1169         }
1170
1171         const map<string, InterfaceBlock *> &prev_blocks = stage->previous->interface_blocks;
1172         map<string, InterfaceBlock *>::const_iterator j = prev_blocks.find("_"+var.name);
1173         if(j!=prev_blocks.end() && j->second->interface=="out")
1174         {
1175                 generate_interface(*j->second);
1176                 /* Let VariableResolver convert the variable reference into an interface
1177                 block reference. */
1178                 return;
1179         }
1180
1181         for(j=prev_blocks.begin(); j!=prev_blocks.end(); ++j)
1182                 if(j->second->instance_name.empty() && j->second->struct_declaration)
1183                 {
1184                         const map<string, VariableDeclaration *> &iface_vars = j->second->struct_declaration->members.variables;
1185                         i = iface_vars.find(var.name);
1186                         if(i!=iface_vars.end())
1187                         {
1188                                 generate_interface(*j->second);
1189                                 return;
1190                         }
1191                 }
1192 }
1193
1194 void InterfaceGenerator::visit(VariableDeclaration &var)
1195 {
1196         if(copy_block)
1197                 generate_interface(var, "in", var.name);
1198         else if(var.interface=="out")
1199         {
1200                 /* For output variables in function scope, generate a global interface
1201                 and replace the local declaration with an assignment. */
1202                 VariableDeclaration *out_var = 0;
1203                 if(function_scope && (out_var=generate_interface(var, "out", var.name)))
1204                 {
1205                         out_var->source = var.source;
1206                         out_var->line = var.line;
1207                         nodes_to_remove.insert(&var);
1208                         if(var.init_expression)
1209                         {
1210                                 ExpressionStatement &stmt = insert_assignment(var.name, var.init_expression->clone());
1211                                 stmt.source = var.source;
1212                                 stmt.line = var.line;
1213                                 return;
1214                         }
1215                 }
1216         }
1217         else if(var.interface=="in" && current_block==&stage->content)
1218         {
1219                 declared_inputs.push_back(&var);
1220
1221                 /* Try to link input variables in global scope with output variables from
1222                 previous stage. */
1223                 if(!var.linked_declaration && stage->previous)
1224                 {
1225                         const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
1226                         map<string, VariableDeclaration *>::const_iterator i = prev_vars.find(var.name);
1227                         if(i!=prev_vars.end() && i->second->interface=="out")
1228                         {
1229                                 var.linked_declaration = i->second;
1230                                 i->second->linked_declaration = &var;
1231                         }
1232                 }
1233         }
1234
1235         TraversingVisitor::visit(var);
1236 }
1237
1238 void InterfaceGenerator::visit(InterfaceBlock &iface)
1239 {
1240         if(iface.interface=="in")
1241         {
1242                 /* Try to link input blocks with output blocks sharing the same block
1243                 name from previous stage. */
1244                 if(!iface.linked_block && stage->previous)
1245                 {
1246                         const map<string, InterfaceBlock *> &prev_blocks = stage->previous->interface_blocks;
1247                         map<string, InterfaceBlock *>::const_iterator i = prev_blocks.find("out"+iface.name);
1248                         if(i!=prev_blocks.end())
1249                         {
1250                                 iface.linked_block = i->second;
1251                                 i->second->linked_block = &iface;
1252                         }
1253                 }
1254         }
1255
1256         TraversingVisitor::visit(iface);
1257 }
1258
1259 void InterfaceGenerator::visit(FunctionDeclaration &func)
1260 {
1261         SetFlag set_scope(function_scope, true);
1262         // Skip parameters because they're not useful here
1263         func.body.visit(*this);
1264 }
1265
1266 void InterfaceGenerator::visit(Passthrough &pass)
1267 {
1268         // Pass through all input variables declared so far.
1269         vector<VariableDeclaration *> pass_vars = declared_inputs;
1270
1271         if(stage->previous)
1272         {
1273                 const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
1274                 for(map<string, VariableDeclaration *>::const_iterator i=prev_vars.begin(); i!=prev_vars.end(); ++i)
1275                 {
1276                         if(i->second->interface!="out")
1277                                 continue;
1278
1279                         /* Pass through output variables from the previous stage, but only
1280                         those which are not already linked to an input here. */
1281                         if(!i->second->linked_declaration && generate_interface(*i->second, "in", i->second->name))
1282                                 pass_vars.push_back(i->second);
1283                 }
1284         }
1285
1286         if(stage->type==Stage::GEOMETRY)
1287         {
1288                 /* Special case for geometry shader: copy gl_Position from input to
1289                 output. */
1290                 InterfaceBlockReference *ref = new InterfaceBlockReference;
1291                 ref->name = "gl_in";
1292
1293                 BinaryExpression *subscript = new BinaryExpression;
1294                 subscript->left = ref;
1295                 subscript->oper = &Operator::get_operator("[", Operator::BINARY);
1296                 subscript->right = pass.subscript;
1297
1298                 MemberAccess *memacc = new MemberAccess;
1299                 memacc->left = subscript;
1300                 memacc->member = "gl_Position";
1301
1302                 insert_assignment("gl_Position", memacc);
1303         }
1304
1305         for(vector<VariableDeclaration *>::const_iterator i=pass_vars.begin(); i!=pass_vars.end(); ++i)
1306         {
1307                 string out_name = change_prefix((*i)->name, out_prefix);
1308                 generate_interface(**i, "out", out_name);
1309
1310                 VariableReference *ref = new VariableReference;
1311                 ref->name = (*i)->name;
1312                 if(pass.subscript)
1313                 {
1314                         BinaryExpression *subscript = new BinaryExpression;
1315                         subscript->left = ref;
1316                         subscript->oper = &Operator::get_operator("[", Operator::BINARY);
1317                         subscript->right = pass.subscript;
1318                         insert_assignment(out_name, subscript);
1319                 }
1320                 else
1321                         insert_assignment(out_name, ref);
1322         }
1323
1324         nodes_to_remove.insert(&pass);
1325 }
1326
1327 } // namespace SL
1328 } // namespace GL
1329 } // namespace Msp