]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/syntax.cpp
Fixes for handling extended alignment in GLSL
[libs/gl.git] / source / glsl / syntax.cpp
1 #include <msp/core/algorithm.h>
2 #include <msp/core/maputils.h>
3 #include "syntax.h"
4 #include "visitor.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace GL {
10 namespace SL {
11
12 const Operator Operator::operators[] =
13 {
14         { "[", "]", 2, BINARY, LEFT_TO_RIGHT },
15         { "(", ")", 2, POSTFIX, LEFT_TO_RIGHT },
16         { ".", { }, 2, POSTFIX, LEFT_TO_RIGHT },
17         { "++", { }, 2, POSTFIX, LEFT_TO_RIGHT },
18         { "--", { }, 2, POSTFIX, LEFT_TO_RIGHT },
19         { "++", { }, 3, PREFIX, RIGHT_TO_LEFT },
20         { "--", { }, 3, PREFIX, RIGHT_TO_LEFT },
21         { "+", { }, 3, PREFIX, RIGHT_TO_LEFT },
22         { "-", { }, 3, PREFIX, RIGHT_TO_LEFT },
23         { "~", { }, 3, PREFIX, RIGHT_TO_LEFT },
24         { "!", { }, 3, PREFIX, RIGHT_TO_LEFT },
25         { "*", { }, 4, BINARY, ASSOCIATIVE },
26         { "/", { }, 4, BINARY, LEFT_TO_RIGHT },
27         { "%", { }, 4, BINARY, LEFT_TO_RIGHT },
28         { "+", { }, 5, BINARY, ASSOCIATIVE },
29         { "-", { }, 5, BINARY, LEFT_TO_RIGHT },
30         { "<<", { }, 6, BINARY, LEFT_TO_RIGHT },
31         { ">>", { }, 6, BINARY, LEFT_TO_RIGHT },
32         { "<", { }, 7, BINARY, LEFT_TO_RIGHT },
33         { ">", { }, 7, BINARY, LEFT_TO_RIGHT },
34         { "<=", { }, 7, BINARY, LEFT_TO_RIGHT },
35         { ">=", { }, 7, BINARY, LEFT_TO_RIGHT },
36         { "==", { }, 8, BINARY, LEFT_TO_RIGHT },
37         { "!=", { }, 8, BINARY, LEFT_TO_RIGHT },
38         { "&", { }, 9, BINARY, ASSOCIATIVE },
39         { "^", { }, 10, BINARY, ASSOCIATIVE },
40         { "|", { }, 11, BINARY, ASSOCIATIVE },
41         { "&&", { }, 12, BINARY, ASSOCIATIVE },
42         { "^^", { }, 13, BINARY, ASSOCIATIVE },
43         { "||", { }, 14, BINARY, ASSOCIATIVE },
44         { "?", ":", 15, TERNARY, RIGHT_TO_LEFT },
45         { "=", { }, 16, BINARY, RIGHT_TO_LEFT },
46         { "+=", { }, 16, BINARY, RIGHT_TO_LEFT },
47         { "-=", { }, 16, BINARY, RIGHT_TO_LEFT },
48         { "*=", { }, 16, BINARY, RIGHT_TO_LEFT },
49         { "/=", { }, 16, BINARY, RIGHT_TO_LEFT },
50         { "%=", { }, 16, BINARY, RIGHT_TO_LEFT },
51         { "<<=", { }, 16, BINARY, RIGHT_TO_LEFT },
52         { ">>=", { }, 16, BINARY, RIGHT_TO_LEFT },
53         { "&=", { }, 16, BINARY, RIGHT_TO_LEFT },
54         { "^=", { }, 16, BINARY, RIGHT_TO_LEFT },
55         { "|=", { }, 16, BINARY, RIGHT_TO_LEFT },
56         { ",", { }, 17, BINARY, LEFT_TO_RIGHT },
57         { { 0 }, { }, 18, NO_OPERATOR, LEFT_TO_RIGHT }
58 };
59
60 const Operator &Operator::get_operator(const string &token, Type type)
61 {
62         for(const Operator *i=operators; i->type; ++i)
63                 if(i->type==type && i->token==token)
64                         return *i;
65         throw key_error(token);
66 }
67
68
69 template<typename C>
70 NodeContainer<C>::NodeContainer(const NodeContainer &c):
71         C(c)
72 {
73         for(auto &i: *this)
74                 i = i->clone();
75 }
76
77
78 Block::Block(const Block &other):
79         Node(other),
80         body(other.body),
81         use_braces(other.use_braces)
82 { }
83
84 void Block::visit(NodeVisitor &visitor)
85 {
86         visitor.visit(*this);
87 }
88
89
90 void Literal::visit(NodeVisitor &visitor)
91 {
92         visitor.visit(*this);
93 }
94
95
96 VariableReference::VariableReference(const VariableReference &other):
97         Expression(other),
98         name(other.name)
99 { }
100
101 void VariableReference::visit(NodeVisitor &visitor)
102 {
103         visitor.visit(*this);
104 }
105
106
107 InterfaceBlockReference::InterfaceBlockReference(const InterfaceBlockReference &other):
108         Expression(other),
109         name(other.name)
110 { }
111
112 void InterfaceBlockReference::visit(NodeVisitor &visitor)
113 {
114         visitor.visit(*this);
115 }
116
117
118 MemberAccess::MemberAccess(const MemberAccess &other):
119         Expression(other),
120         left(other.left),
121         member(other.member)
122         // Do not copy declaration
123 { }
124
125 void MemberAccess::visit(NodeVisitor &visitor)
126 {
127         visitor.visit(*this);
128 }
129
130
131 void Swizzle::visit(NodeVisitor &visitor)
132 {
133         visitor.visit(*this);
134 }
135
136
137 void UnaryExpression::visit(NodeVisitor &visitor)
138 {
139         visitor.visit(*this);
140 }
141
142
143 void BinaryExpression::visit(NodeVisitor &visitor)
144 {
145         visitor.visit(*this);
146 }
147
148
149 Assignment::Assignment(const Assignment &other):
150         BinaryExpression(other),
151         self_referencing(other.self_referencing)
152         // Do not copy target
153 { }
154
155 void Assignment::visit(NodeVisitor &visitor)
156 {
157         visitor.visit(*this);
158 }
159
160
161 bool Assignment::Target::operator<(const Target &other) const
162 {
163         if(declaration!=other.declaration)
164                 return declaration<other.declaration;
165         for(unsigned i=0; (i<7 && i<chain_len && i<other.chain_len); ++i)
166                 if(chain[i]!=other.chain[i])
167                         return chain[i]<other.chain[i];
168         return chain_len<other.chain_len;
169 }
170
171
172 void TernaryExpression::visit(NodeVisitor &visitor)
173 {
174         visitor.visit(*this);
175 }
176
177
178 FunctionCall::FunctionCall(const FunctionCall &other):
179         Expression(other),
180         name(other.name),
181         constructor(other.constructor),
182         arguments(other.arguments)
183         // Do not copy declaration
184 { }
185
186 void FunctionCall::visit(NodeVisitor &visitor)
187 {
188         visitor.visit(*this);
189 }
190
191
192 void ExpressionStatement::visit(NodeVisitor &visitor)
193 {
194         visitor.visit(*this);
195 }
196
197
198 void Import::visit(NodeVisitor &visitor)
199 {
200         visitor.visit(*this);
201 }
202
203
204 void Precision::visit(NodeVisitor &visitor)
205 {
206         visitor.visit(*this);
207 }
208
209
210 void Layout::visit(NodeVisitor &visitor)
211 {
212         visitor.visit(*this);
213 }
214
215
216 void InterfaceLayout::visit(NodeVisitor &visitor)
217 {
218         visitor.visit(*this);
219 }
220
221
222 BasicTypeDeclaration::BasicTypeDeclaration(const BasicTypeDeclaration &other):
223         TypeDeclaration(other),
224         kind(other.kind),
225         size(other.size),
226         sign(other.sign),
227         extended_alignment(other.extended_alignment),
228         base(other.base)
229         // Do not copy base type
230 { }
231
232 void BasicTypeDeclaration::visit(NodeVisitor &visitor)
233 {
234         visitor.visit(*this);
235 }
236
237
238 void ImageTypeDeclaration::visit(NodeVisitor &visitor)
239 {
240         visitor.visit(*this);
241 }
242
243
244 StructDeclaration::StructDeclaration()
245 {
246         members.use_braces = true;
247 }
248
249 StructDeclaration::StructDeclaration(const StructDeclaration &other):
250         TypeDeclaration(other),
251         members(other.members),
252         extended_alignment(other.extended_alignment)
253         // Do not copy interface block
254 { }
255
256 StructDeclaration::~StructDeclaration()
257 {
258         if(interface_block && interface_block->struct_declaration==this)
259                 interface_block->struct_declaration = 0;
260 }
261
262 void StructDeclaration::visit(NodeVisitor &visitor)
263 {
264         visitor.visit(*this);
265 }
266
267
268 VariableDeclaration::VariableDeclaration(const VariableDeclaration &other):
269         Statement(other),
270         layout(other.layout),
271         constant(other.constant),
272         sampling(other.sampling),
273         interpolation(other.interpolation),
274         interface(other.interface),
275         precision(other.precision),
276         type(other.type),
277         name(other.name),
278         array(other.array),
279         array_size(other.array_size),
280         init_expression(other.init_expression)
281         // Do not copy type and linked declarations
282 { }
283
284 VariableDeclaration::~VariableDeclaration()
285 {
286         if(linked_declaration && linked_declaration->linked_declaration==this)
287                 linked_declaration->linked_declaration = 0;
288 }
289
290 void VariableDeclaration::visit(NodeVisitor &visitor)
291 {
292         visitor.visit(*this);
293 }
294
295
296 InterfaceBlock::InterfaceBlock(const InterfaceBlock &other):
297         Statement(other),
298         layout(other.layout),
299         interface(other.interface),
300         block_name(other.block_name),
301         members(other.members),
302         instance_name(other.instance_name),
303         array(other.array)
304         // Do not copy pointers to other nodes
305 { }
306
307 InterfaceBlock::~InterfaceBlock()
308 {
309         if(linked_block && linked_block->linked_block==this)
310                 linked_block->linked_block = 0;
311         if(struct_declaration && struct_declaration->interface_block==this)
312                 struct_declaration->interface_block = 0;
313 }
314
315 void InterfaceBlock::visit(NodeVisitor &visitor)
316 {
317         visitor.visit(*this);
318 }
319
320
321 FunctionDeclaration::FunctionDeclaration(const FunctionDeclaration &other):
322         Statement(other),
323         return_type(other.return_type),
324         name(other.name),
325         parameters(other.parameters),
326         virtua(other.virtua),
327         overrd(other.overrd),
328         body(other.body),
329         signature(other.signature),
330         definition(other.definition==&other ? this : 0)
331         // Do not copy return type declaration
332 { }
333
334 void FunctionDeclaration::visit(NodeVisitor &visitor)
335 {
336         visitor.visit(*this);
337 }
338
339
340 void Conditional::visit(NodeVisitor &visitor)
341 {
342         visitor.visit(*this);
343 }
344
345
346 void Iteration::visit(NodeVisitor &visitor)
347 {
348         visitor.visit(*this);
349 }
350
351
352 void Passthrough::visit(NodeVisitor &visitor)
353 {
354         visitor.visit(*this);
355 }
356
357
358 void Return::visit(NodeVisitor &visitor)
359 {
360         visitor.visit(*this);
361 }
362
363
364 void Jump::visit(NodeVisitor &visitor)
365 {
366         visitor.visit(*this);
367 }
368
369
370 Stage::Stage(Stage::Type t):
371         type(t)
372 { }
373
374 const char *Stage::get_stage_name(Type type)
375 {
376         static const char *const names[] = { "shared", "vertex", "geometry", "fragment" };
377         return names[type];
378 }
379
380
381 Module::Module():
382         shared(Stage::SHARED)
383 { }
384
385
386 string get_unused_variable_name(const Block &block, const string &base)
387 {
388         string name = base;
389
390         unsigned number = 1;
391         unsigned base_size = name.size();
392         while(1)
393         {
394                 bool unused = true;
395                 for(const Block *b=&block; (unused && b); b=b->parent)
396                         unused = !b->variables.count(name);
397                 if(unused)
398                         return name;
399
400                 name.erase(base_size);
401                 name += format("_%d", number);
402                 ++number;
403         }
404 }
405
406 const TypeDeclaration *get_ultimate_base_type(const TypeDeclaration *type)
407 {
408         if(!type)
409                 return 0;
410         while(const BasicTypeDeclaration *basic = dynamic_cast<const BasicTypeDeclaration *>(type))
411         {
412                 if(!basic->base_type)
413                         break;
414                 type = basic->base_type;
415         }
416         return type;
417 }
418
419 bool has_layout_qualifier(const Layout *layout, const string &name)
420 {
421         if(!layout)
422                 return false;
423         auto i = find_member(layout->qualifiers, name, &Layout::Qualifier::name);
424         return i!=layout->qualifiers.end();
425 }
426
427 int get_layout_value(const Layout *layout, const string &name, int def_value)
428 {
429         if(!layout)
430                 return def_value;
431         auto i = find_member(layout->qualifiers, name, &Layout::Qualifier::name);
432         return (i!=layout->qualifiers.end() ? i->value : def_value);
433 }
434
435 void add_layout_qualifier(RefPtr<Layout> &layout, const Layout::Qualifier &q)
436 {
437         if(!layout)
438                 layout = new Layout;
439         layout->qualifiers.push_back(q);
440 }
441
442 void add_to_chain(Assignment::Target &target, Assignment::Target::ChainType type, unsigned index)
443 {
444         if(target.chain_len<7)
445                 target.chain[target.chain_len] = type | min<unsigned>(index, 0x3F);
446         ++target.chain_len;
447 }
448
449 bool targets_overlap(const Assignment::Target &target1, const Assignment::Target &target2)
450 {
451         bool overlap = (target1.declaration==target2.declaration);
452         for(unsigned i=0; (overlap && i<target1.chain_len && i<target2.chain_len); ++i)
453         {
454                 Assignment::Target::ChainType type1 = static_cast<Assignment::Target::ChainType>(target1.chain[i]&0xC0);
455                 Assignment::Target::ChainType type2 = static_cast<Assignment::Target::ChainType>(target2.chain[i]&0xC0);
456                 unsigned index1 = target1.chain[i]&0x3F;
457                 unsigned index2 = target2.chain[i]&0x3F;
458                 if(type1==Assignment::Target::SWIZZLE || type2==Assignment::Target::SWIZZLE)
459                 {
460                         if(type1==Assignment::Target::SWIZZLE && type2==Assignment::Target::SWIZZLE)
461                                 overlap = index1&index2;
462                         else if(type1==Assignment::Target::ARRAY && index1<4)
463                                 overlap = index2&(1<<index1);
464                         else if(type2==Assignment::Target::ARRAY && index2<4)
465                                 overlap = index1&(1<<index2);
466                         // Treat other combinations as overlapping (shouldn't happen)
467                 }
468                 else
469                         overlap = (type1==type2 && (index1==index2 || index1==0x3F || index2==0x3F));
470         }
471
472         return overlap;
473 }
474
475 } // namespace SL
476 } // namespace GL
477 } // namespace Msp