]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/syntax.cpp
Align staging memory with an alignment suitable for image transfers
[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 MemberAccess::MemberAccess(const MemberAccess &other):
108         Expression(other),
109         left(other.left),
110         member(other.member)
111         // Do not copy declaration
112 { }
113
114 void MemberAccess::visit(NodeVisitor &visitor)
115 {
116         visitor.visit(*this);
117 }
118
119
120 void Swizzle::visit(NodeVisitor &visitor)
121 {
122         visitor.visit(*this);
123 }
124
125
126 void UnaryExpression::visit(NodeVisitor &visitor)
127 {
128         visitor.visit(*this);
129 }
130
131
132 void BinaryExpression::visit(NodeVisitor &visitor)
133 {
134         visitor.visit(*this);
135 }
136
137
138 Assignment::Assignment(const Assignment &other):
139         BinaryExpression(other),
140         self_referencing(other.self_referencing)
141         // Do not copy target
142 { }
143
144 void Assignment::visit(NodeVisitor &visitor)
145 {
146         visitor.visit(*this);
147 }
148
149
150 bool Assignment::Target::operator<(const Target &other) const
151 {
152         if(declaration!=other.declaration)
153                 return declaration<other.declaration;
154         for(unsigned i=0; (i<7 && i<chain_len && i<other.chain_len); ++i)
155                 if(chain[i]!=other.chain[i])
156                         return chain[i]<other.chain[i];
157         return chain_len<other.chain_len;
158 }
159
160
161 void TernaryExpression::visit(NodeVisitor &visitor)
162 {
163         visitor.visit(*this);
164 }
165
166
167 FunctionCall::FunctionCall(const FunctionCall &other):
168         Expression(other),
169         name(other.name),
170         constructor(other.constructor),
171         arguments(other.arguments)
172         // Do not copy declaration
173 { }
174
175 void FunctionCall::visit(NodeVisitor &visitor)
176 {
177         visitor.visit(*this);
178 }
179
180
181 void ExpressionStatement::visit(NodeVisitor &visitor)
182 {
183         visitor.visit(*this);
184 }
185
186
187 void Import::visit(NodeVisitor &visitor)
188 {
189         visitor.visit(*this);
190 }
191
192
193 void Precision::visit(NodeVisitor &visitor)
194 {
195         visitor.visit(*this);
196 }
197
198
199 void Layout::visit(NodeVisitor &visitor)
200 {
201         visitor.visit(*this);
202 }
203
204
205 void InterfaceLayout::visit(NodeVisitor &visitor)
206 {
207         visitor.visit(*this);
208 }
209
210
211 BasicTypeDeclaration::BasicTypeDeclaration(const BasicTypeDeclaration &other):
212         TypeDeclaration(other),
213         kind(other.kind),
214         size(other.size),
215         sign(other.sign),
216         extended_alignment(other.extended_alignment),
217         base(other.base)
218         // Do not copy base type
219 { }
220
221 void BasicTypeDeclaration::visit(NodeVisitor &visitor)
222 {
223         visitor.visit(*this);
224 }
225
226
227 void ImageTypeDeclaration::visit(NodeVisitor &visitor)
228 {
229         visitor.visit(*this);
230 }
231
232
233 StructDeclaration::StructDeclaration()
234 {
235         members.use_braces = true;
236 }
237
238 StructDeclaration::StructDeclaration(const StructDeclaration &other):
239         TypeDeclaration(other),
240         members(other.members),
241         block_name(other.block_name),
242         extended_alignment(other.extended_alignment)
243         // Do not copy block declaration
244 { }
245
246 void StructDeclaration::visit(NodeVisitor &visitor)
247 {
248         visitor.visit(*this);
249 }
250
251
252 VariableDeclaration::VariableDeclaration(const VariableDeclaration &other):
253         Statement(other),
254         layout(other.layout),
255         constant(other.constant),
256         sampling(other.sampling),
257         interpolation(other.interpolation),
258         interface(other.interface),
259         precision(other.precision),
260         type(other.type),
261         name(other.name),
262         array(other.array),
263         array_size(other.array_size),
264         init_expression(other.init_expression)
265         // Do not copy pointers to other nodes
266 { }
267
268 VariableDeclaration::~VariableDeclaration()
269 {
270         if(linked_declaration && linked_declaration->linked_declaration==this)
271                 linked_declaration->linked_declaration = 0;
272 }
273
274 void VariableDeclaration::visit(NodeVisitor &visitor)
275 {
276         visitor.visit(*this);
277 }
278
279
280 FunctionDeclaration::FunctionDeclaration(const FunctionDeclaration &other):
281         Statement(other),
282         return_type(other.return_type),
283         name(other.name),
284         parameters(other.parameters),
285         virtua(other.virtua),
286         overrd(other.overrd),
287         body(other.body),
288         signature(other.signature),
289         definition(other.definition==&other ? this : 0)
290         // Do not copy return type declaration
291 { }
292
293 void FunctionDeclaration::visit(NodeVisitor &visitor)
294 {
295         visitor.visit(*this);
296 }
297
298
299 void Conditional::visit(NodeVisitor &visitor)
300 {
301         visitor.visit(*this);
302 }
303
304
305 void Iteration::visit(NodeVisitor &visitor)
306 {
307         visitor.visit(*this);
308 }
309
310
311 void Passthrough::visit(NodeVisitor &visitor)
312 {
313         visitor.visit(*this);
314 }
315
316
317 void Return::visit(NodeVisitor &visitor)
318 {
319         visitor.visit(*this);
320 }
321
322
323 void Jump::visit(NodeVisitor &visitor)
324 {
325         visitor.visit(*this);
326 }
327
328
329 Stage::Stage(Stage::Type t):
330         type(t)
331 { }
332
333 const char *Stage::get_stage_name(Type type)
334 {
335         static const char *const names[] = { "shared", "vertex", "geometry", "fragment" };
336         return names[type];
337 }
338
339
340 Module::Module():
341         shared(Stage::SHARED)
342 { }
343
344
345 string get_unused_variable_name(const Block &block, const string &base)
346 {
347         string name = base;
348
349         unsigned number = 1;
350         unsigned base_size = name.size();
351         while(1)
352         {
353                 bool unused = true;
354                 for(const Block *b=&block; (unused && b); b=b->parent)
355                         unused = !b->variables.count(name);
356                 if(unused)
357                         return name;
358
359                 name.erase(base_size);
360                 name += format("_%d", number);
361                 ++number;
362         }
363 }
364
365 TypeDeclaration *get_ultimate_base_type(TypeDeclaration *type)
366 {
367         if(!type)
368                 return 0;
369         while(const BasicTypeDeclaration *basic = dynamic_cast<const BasicTypeDeclaration *>(type))
370         {
371                 if(!basic->base_type)
372                         break;
373                 type = basic->base_type;
374         }
375         return type;
376 }
377
378 bool has_layout_qualifier(const Layout *layout, const string &name)
379 {
380         if(!layout)
381                 return false;
382         auto i = find_member(layout->qualifiers, name, &Layout::Qualifier::name);
383         return i!=layout->qualifiers.end();
384 }
385
386 int get_layout_value(const Layout *layout, const string &name, int def_value)
387 {
388         if(!layout)
389                 return def_value;
390         auto i = find_member(layout->qualifiers, name, &Layout::Qualifier::name);
391         return (i!=layout->qualifiers.end() ? i->value : def_value);
392 }
393
394 void add_layout_qualifier(RefPtr<Layout> &layout, const Layout::Qualifier &q)
395 {
396         if(!layout)
397                 layout = new Layout;
398         layout->qualifiers.push_back(q);
399 }
400
401 void add_to_chain(Assignment::Target &target, Assignment::Target::ChainType type, unsigned index)
402 {
403         if(target.chain_len<7)
404                 target.chain[target.chain_len] = type | min<unsigned>(index, 0x3F);
405         ++target.chain_len;
406 }
407
408 bool targets_overlap(const Assignment::Target &target1, const Assignment::Target &target2)
409 {
410         bool overlap = (target1.declaration==target2.declaration);
411         for(unsigned i=0; (overlap && i<target1.chain_len && i<target2.chain_len); ++i)
412         {
413                 Assignment::Target::ChainType type1 = static_cast<Assignment::Target::ChainType>(target1.chain[i]&0xC0);
414                 Assignment::Target::ChainType type2 = static_cast<Assignment::Target::ChainType>(target2.chain[i]&0xC0);
415                 unsigned index1 = target1.chain[i]&0x3F;
416                 unsigned index2 = target2.chain[i]&0x3F;
417                 if(type1==Assignment::Target::SWIZZLE || type2==Assignment::Target::SWIZZLE)
418                 {
419                         if(type1==Assignment::Target::SWIZZLE && type2==Assignment::Target::SWIZZLE)
420                                 overlap = index1&index2;
421                         else if(type1==Assignment::Target::ARRAY && index1<4)
422                                 overlap = index2&(1<<index1);
423                         else if(type2==Assignment::Target::ARRAY && index2<4)
424                                 overlap = index1&(1<<index2);
425                         // Treat other combinations as overlapping (shouldn't happen)
426                 }
427                 else
428                         overlap = (type1==type2 && (index1==index2 || index1==0x3F || index2==0x3F));
429         }
430
431         return overlap;
432 }
433
434 } // namespace SL
435 } // namespace GL
436 } // namespace Msp