scons: Add Haiku build support
[mesa.git] / src / glsl / ir_reader.cpp
1 /*
2 * Copyright © 2010 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "ir_reader.h"
25 #include "glsl_parser_extras.h"
26 #include "glsl_types.h"
27 #include "s_expression.h"
28
29 const static bool debug = false;
30
31 class ir_reader {
32 public:
33 ir_reader(_mesa_glsl_parse_state *);
34
35 void read(exec_list *instructions, const char *src, bool scan_for_protos);
36
37 private:
38 void *mem_ctx;
39 _mesa_glsl_parse_state *state;
40
41 void ir_read_error(s_expression *, const char *fmt, ...);
42
43 const glsl_type *read_type(s_expression *);
44
45 void scan_for_prototypes(exec_list *, s_expression *);
46 ir_function *read_function(s_expression *, bool skip_body);
47 void read_function_sig(ir_function *, s_expression *, bool skip_body);
48
49 void read_instructions(exec_list *, s_expression *, ir_loop *);
50 ir_instruction *read_instruction(s_expression *, ir_loop *);
51 ir_variable *read_declaration(s_expression *);
52 ir_if *read_if(s_expression *, ir_loop *);
53 ir_loop *read_loop(s_expression *);
54 ir_return *read_return(s_expression *);
55 ir_rvalue *read_rvalue(s_expression *);
56 ir_assignment *read_assignment(s_expression *);
57 ir_expression *read_expression(s_expression *);
58 ir_call *read_call(s_expression *);
59 ir_swizzle *read_swizzle(s_expression *);
60 ir_constant *read_constant(s_expression *);
61 ir_texture *read_texture(s_expression *);
62
63 ir_dereference *read_dereference(s_expression *);
64 };
65
66 ir_reader::ir_reader(_mesa_glsl_parse_state *state) : state(state)
67 {
68 this->mem_ctx = state;
69 }
70
71 void
72 _mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions,
73 const char *src, bool scan_for_protos)
74 {
75 ir_reader r(state);
76 r.read(instructions, src, scan_for_protos);
77 }
78
79 void
80 ir_reader::read(exec_list *instructions, const char *src, bool scan_for_protos)
81 {
82 void *sx_mem_ctx = ralloc_context(NULL);
83 s_expression *expr = s_expression::read_expression(sx_mem_ctx, src);
84 if (expr == NULL) {
85 ir_read_error(NULL, "couldn't parse S-Expression.");
86 return;
87 }
88
89 if (scan_for_protos) {
90 scan_for_prototypes(instructions, expr);
91 if (state->error)
92 return;
93 }
94
95 read_instructions(instructions, expr, NULL);
96 ralloc_free(sx_mem_ctx);
97
98 if (debug)
99 validate_ir_tree(instructions);
100 }
101
102 void
103 ir_reader::ir_read_error(s_expression *expr, const char *fmt, ...)
104 {
105 va_list ap;
106
107 state->error = true;
108
109 if (state->current_function != NULL)
110 ralloc_asprintf_append(&state->info_log, "In function %s:\n",
111 state->current_function->function_name());
112 ralloc_strcat(&state->info_log, "error: ");
113
114 va_start(ap, fmt);
115 ralloc_vasprintf_append(&state->info_log, fmt, ap);
116 va_end(ap);
117 ralloc_strcat(&state->info_log, "\n");
118
119 if (expr != NULL) {
120 ralloc_strcat(&state->info_log, "...in this context:\n ");
121 expr->print();
122 ralloc_strcat(&state->info_log, "\n\n");
123 }
124 }
125
126 const glsl_type *
127 ir_reader::read_type(s_expression *expr)
128 {
129 s_expression *s_base_type;
130 s_int *s_size;
131
132 s_pattern pat[] = { "array", s_base_type, s_size };
133 if (MATCH(expr, pat)) {
134 const glsl_type *base_type = read_type(s_base_type);
135 if (base_type == NULL) {
136 ir_read_error(NULL, "when reading base type of array type");
137 return NULL;
138 }
139
140 return glsl_type::get_array_instance(base_type, s_size->value());
141 }
142
143 s_symbol *type_sym = SX_AS_SYMBOL(expr);
144 if (type_sym == NULL) {
145 ir_read_error(expr, "expected <type>");
146 return NULL;
147 }
148
149 const glsl_type *type = state->symbols->get_type(type_sym->value());
150 if (type == NULL)
151 ir_read_error(expr, "invalid type: %s", type_sym->value());
152
153 return type;
154 }
155
156
157 void
158 ir_reader::scan_for_prototypes(exec_list *instructions, s_expression *expr)
159 {
160 s_list *list = SX_AS_LIST(expr);
161 if (list == NULL) {
162 ir_read_error(expr, "Expected (<instruction> ...); found an atom.");
163 return;
164 }
165
166 foreach_iter(exec_list_iterator, it, list->subexpressions) {
167 s_list *sub = SX_AS_LIST(it.get());
168 if (sub == NULL)
169 continue; // not a (function ...); ignore it.
170
171 s_symbol *tag = SX_AS_SYMBOL(sub->subexpressions.get_head());
172 if (tag == NULL || strcmp(tag->value(), "function") != 0)
173 continue; // not a (function ...); ignore it.
174
175 ir_function *f = read_function(sub, true);
176 if (f == NULL)
177 return;
178 instructions->push_tail(f);
179 }
180 }
181
182 ir_function *
183 ir_reader::read_function(s_expression *expr, bool skip_body)
184 {
185 bool added = false;
186 s_symbol *name;
187
188 s_pattern pat[] = { "function", name };
189 if (!PARTIAL_MATCH(expr, pat)) {
190 ir_read_error(expr, "Expected (function <name> (signature ...) ...)");
191 return NULL;
192 }
193
194 ir_function *f = state->symbols->get_function(name->value());
195 if (f == NULL) {
196 f = new(mem_ctx) ir_function(name->value());
197 added = state->symbols->add_function(f);
198 assert(added);
199 }
200
201 exec_list_iterator it = ((s_list *) expr)->subexpressions.iterator();
202 it.next(); // skip "function" tag
203 it.next(); // skip function name
204 for (/* nothing */; it.has_next(); it.next()) {
205 s_expression *s_sig = (s_expression *) it.get();
206 read_function_sig(f, s_sig, skip_body);
207 }
208 return added ? f : NULL;
209 }
210
211 void
212 ir_reader::read_function_sig(ir_function *f, s_expression *expr, bool skip_body)
213 {
214 s_expression *type_expr;
215 s_list *paramlist;
216 s_list *body_list;
217
218 s_pattern pat[] = { "signature", type_expr, paramlist, body_list };
219 if (!MATCH(expr, pat)) {
220 ir_read_error(expr, "Expected (signature <type> (parameters ...) "
221 "(<instruction> ...))");
222 return;
223 }
224
225 const glsl_type *return_type = read_type(type_expr);
226 if (return_type == NULL)
227 return;
228
229 s_symbol *paramtag = SX_AS_SYMBOL(paramlist->subexpressions.get_head());
230 if (paramtag == NULL || strcmp(paramtag->value(), "parameters") != 0) {
231 ir_read_error(paramlist, "Expected (parameters ...)");
232 return;
233 }
234
235 // Read the parameters list into a temporary place.
236 exec_list hir_parameters;
237 state->symbols->push_scope();
238
239 exec_list_iterator it = paramlist->subexpressions.iterator();
240 for (it.next() /* skip "parameters" */; it.has_next(); it.next()) {
241 ir_variable *var = read_declaration((s_expression *) it.get());
242 if (var == NULL)
243 return;
244
245 hir_parameters.push_tail(var);
246 }
247
248 ir_function_signature *sig = f->exact_matching_signature(&hir_parameters);
249 if (sig == NULL && skip_body) {
250 /* If scanning for prototypes, generate a new signature. */
251 sig = new(mem_ctx) ir_function_signature(return_type);
252 sig->is_builtin = true;
253 f->add_signature(sig);
254 } else if (sig != NULL) {
255 const char *badvar = sig->qualifiers_match(&hir_parameters);
256 if (badvar != NULL) {
257 ir_read_error(expr, "function `%s' parameter `%s' qualifiers "
258 "don't match prototype", f->name, badvar);
259 return;
260 }
261
262 if (sig->return_type != return_type) {
263 ir_read_error(expr, "function `%s' return type doesn't "
264 "match prototype", f->name);
265 return;
266 }
267 } else {
268 /* No prototype for this body exists - skip it. */
269 state->symbols->pop_scope();
270 return;
271 }
272 assert(sig != NULL);
273
274 sig->replace_parameters(&hir_parameters);
275
276 if (!skip_body && !body_list->subexpressions.is_empty()) {
277 if (sig->is_defined) {
278 ir_read_error(expr, "function %s redefined", f->name);
279 return;
280 }
281 state->current_function = sig;
282 read_instructions(&sig->body, body_list, NULL);
283 state->current_function = NULL;
284 sig->is_defined = true;
285 }
286
287 state->symbols->pop_scope();
288 }
289
290 void
291 ir_reader::read_instructions(exec_list *instructions, s_expression *expr,
292 ir_loop *loop_ctx)
293 {
294 // Read in a list of instructions
295 s_list *list = SX_AS_LIST(expr);
296 if (list == NULL) {
297 ir_read_error(expr, "Expected (<instruction> ...); found an atom.");
298 return;
299 }
300
301 foreach_iter(exec_list_iterator, it, list->subexpressions) {
302 s_expression *sub = (s_expression*) it.get();
303 ir_instruction *ir = read_instruction(sub, loop_ctx);
304 if (ir != NULL) {
305 /* Global variable declarations should be moved to the top, before
306 * any functions that might use them. Functions are added to the
307 * instruction stream when scanning for prototypes, so without this
308 * hack, they always appear before variable declarations.
309 */
310 if (state->current_function == NULL && ir->as_variable() != NULL)
311 instructions->push_head(ir);
312 else
313 instructions->push_tail(ir);
314 }
315 }
316 }
317
318
319 ir_instruction *
320 ir_reader::read_instruction(s_expression *expr, ir_loop *loop_ctx)
321 {
322 s_symbol *symbol = SX_AS_SYMBOL(expr);
323 if (symbol != NULL) {
324 if (strcmp(symbol->value(), "break") == 0 && loop_ctx != NULL)
325 return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break);
326 if (strcmp(symbol->value(), "continue") == 0 && loop_ctx != NULL)
327 return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue);
328 }
329
330 s_list *list = SX_AS_LIST(expr);
331 if (list == NULL || list->subexpressions.is_empty()) {
332 ir_read_error(expr, "Invalid instruction.\n");
333 return NULL;
334 }
335
336 s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
337 if (tag == NULL) {
338 ir_read_error(expr, "expected instruction tag");
339 return NULL;
340 }
341
342 ir_instruction *inst = NULL;
343 if (strcmp(tag->value(), "declare") == 0) {
344 inst = read_declaration(list);
345 } else if (strcmp(tag->value(), "assign") == 0) {
346 inst = read_assignment(list);
347 } else if (strcmp(tag->value(), "if") == 0) {
348 inst = read_if(list, loop_ctx);
349 } else if (strcmp(tag->value(), "loop") == 0) {
350 inst = read_loop(list);
351 } else if (strcmp(tag->value(), "return") == 0) {
352 inst = read_return(list);
353 } else if (strcmp(tag->value(), "function") == 0) {
354 inst = read_function(list, false);
355 } else {
356 inst = read_rvalue(list);
357 if (inst == NULL)
358 ir_read_error(NULL, "when reading instruction");
359 }
360 return inst;
361 }
362
363 ir_variable *
364 ir_reader::read_declaration(s_expression *expr)
365 {
366 s_list *s_quals;
367 s_expression *s_type;
368 s_symbol *s_name;
369
370 s_pattern pat[] = { "declare", s_quals, s_type, s_name };
371 if (!MATCH(expr, pat)) {
372 ir_read_error(expr, "expected (declare (<qualifiers>) <type> <name>)");
373 return NULL;
374 }
375
376 const glsl_type *type = read_type(s_type);
377 if (type == NULL)
378 return NULL;
379
380 ir_variable *var = new(mem_ctx) ir_variable(type, s_name->value(),
381 ir_var_auto);
382
383 foreach_iter(exec_list_iterator, it, s_quals->subexpressions) {
384 s_symbol *qualifier = SX_AS_SYMBOL(it.get());
385 if (qualifier == NULL) {
386 ir_read_error(expr, "qualifier list must contain only symbols");
387 return NULL;
388 }
389
390 // FINISHME: Check for duplicate/conflicting qualifiers.
391 if (strcmp(qualifier->value(), "centroid") == 0) {
392 var->centroid = 1;
393 } else if (strcmp(qualifier->value(), "invariant") == 0) {
394 var->invariant = 1;
395 } else if (strcmp(qualifier->value(), "uniform") == 0) {
396 var->mode = ir_var_uniform;
397 } else if (strcmp(qualifier->value(), "auto") == 0) {
398 var->mode = ir_var_auto;
399 } else if (strcmp(qualifier->value(), "in") == 0) {
400 var->mode = ir_var_in;
401 } else if (strcmp(qualifier->value(), "const_in") == 0) {
402 var->mode = ir_var_const_in;
403 } else if (strcmp(qualifier->value(), "out") == 0) {
404 var->mode = ir_var_out;
405 } else if (strcmp(qualifier->value(), "inout") == 0) {
406 var->mode = ir_var_inout;
407 } else if (strcmp(qualifier->value(), "smooth") == 0) {
408 var->interpolation = INTERP_QUALIFIER_SMOOTH;
409 } else if (strcmp(qualifier->value(), "flat") == 0) {
410 var->interpolation = INTERP_QUALIFIER_FLAT;
411 } else if (strcmp(qualifier->value(), "noperspective") == 0) {
412 var->interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
413 } else {
414 ir_read_error(expr, "unknown qualifier: %s", qualifier->value());
415 return NULL;
416 }
417 }
418
419 // Add the variable to the symbol table
420 state->symbols->add_variable(var);
421
422 return var;
423 }
424
425
426 ir_if *
427 ir_reader::read_if(s_expression *expr, ir_loop *loop_ctx)
428 {
429 s_expression *s_cond;
430 s_expression *s_then;
431 s_expression *s_else;
432
433 s_pattern pat[] = { "if", s_cond, s_then, s_else };
434 if (!MATCH(expr, pat)) {
435 ir_read_error(expr, "expected (if <condition> (<then>...) (<else>...))");
436 return NULL;
437 }
438
439 ir_rvalue *condition = read_rvalue(s_cond);
440 if (condition == NULL) {
441 ir_read_error(NULL, "when reading condition of (if ...)");
442 return NULL;
443 }
444
445 ir_if *iff = new(mem_ctx) ir_if(condition);
446
447 read_instructions(&iff->then_instructions, s_then, loop_ctx);
448 read_instructions(&iff->else_instructions, s_else, loop_ctx);
449 if (state->error) {
450 delete iff;
451 iff = NULL;
452 }
453 return iff;
454 }
455
456
457 ir_loop *
458 ir_reader::read_loop(s_expression *expr)
459 {
460 s_expression *s_counter, *s_from, *s_to, *s_inc, *s_body;
461
462 s_pattern pat[] = { "loop", s_counter, s_from, s_to, s_inc, s_body };
463 if (!MATCH(expr, pat)) {
464 ir_read_error(expr, "expected (loop <counter> <from> <to> "
465 "<increment> <body>)");
466 return NULL;
467 }
468
469 // FINISHME: actually read the count/from/to fields.
470
471 ir_loop *loop = new(mem_ctx) ir_loop;
472 read_instructions(&loop->body_instructions, s_body, loop);
473 if (state->error) {
474 delete loop;
475 loop = NULL;
476 }
477 return loop;
478 }
479
480
481 ir_return *
482 ir_reader::read_return(s_expression *expr)
483 {
484 s_expression *s_retval;
485
486 s_pattern return_value_pat[] = { "return", s_retval};
487 s_pattern return_void_pat[] = { "return" };
488 if (MATCH(expr, return_value_pat)) {
489 ir_rvalue *retval = read_rvalue(s_retval);
490 if (retval == NULL) {
491 ir_read_error(NULL, "when reading return value");
492 return NULL;
493 }
494 return new(mem_ctx) ir_return(retval);
495 } else if (MATCH(expr, return_void_pat)) {
496 return new(mem_ctx) ir_return;
497 } else {
498 ir_read_error(expr, "expected (return <rvalue>) or (return)");
499 return NULL;
500 }
501 }
502
503
504 ir_rvalue *
505 ir_reader::read_rvalue(s_expression *expr)
506 {
507 s_list *list = SX_AS_LIST(expr);
508 if (list == NULL || list->subexpressions.is_empty())
509 return NULL;
510
511 s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
512 if (tag == NULL) {
513 ir_read_error(expr, "expected rvalue tag");
514 return NULL;
515 }
516
517 ir_rvalue *rvalue = read_dereference(list);
518 if (rvalue != NULL || state->error)
519 return rvalue;
520 else if (strcmp(tag->value(), "swiz") == 0) {
521 rvalue = read_swizzle(list);
522 } else if (strcmp(tag->value(), "expression") == 0) {
523 rvalue = read_expression(list);
524 } else if (strcmp(tag->value(), "call") == 0) {
525 rvalue = read_call(list);
526 } else if (strcmp(tag->value(), "constant") == 0) {
527 rvalue = read_constant(list);
528 } else {
529 rvalue = read_texture(list);
530 if (rvalue == NULL && !state->error)
531 ir_read_error(expr, "unrecognized rvalue tag: %s", tag->value());
532 }
533
534 return rvalue;
535 }
536
537 ir_assignment *
538 ir_reader::read_assignment(s_expression *expr)
539 {
540 s_expression *cond_expr = NULL;
541 s_expression *lhs_expr, *rhs_expr;
542 s_list *mask_list;
543
544 s_pattern pat4[] = { "assign", mask_list, lhs_expr, rhs_expr };
545 s_pattern pat5[] = { "assign", cond_expr, mask_list, lhs_expr, rhs_expr };
546 if (!MATCH(expr, pat4) && !MATCH(expr, pat5)) {
547 ir_read_error(expr, "expected (assign [<condition>] (<write mask>) "
548 "<lhs> <rhs>)");
549 return NULL;
550 }
551
552 ir_rvalue *condition = NULL;
553 if (cond_expr != NULL) {
554 condition = read_rvalue(cond_expr);
555 if (condition == NULL) {
556 ir_read_error(NULL, "when reading condition of assignment");
557 return NULL;
558 }
559 }
560
561 unsigned mask = 0;
562
563 s_symbol *mask_symbol;
564 s_pattern mask_pat[] = { mask_symbol };
565 if (MATCH(mask_list, mask_pat)) {
566 const char *mask_str = mask_symbol->value();
567 unsigned mask_length = strlen(mask_str);
568 if (mask_length > 4) {
569 ir_read_error(expr, "invalid write mask: %s", mask_str);
570 return NULL;
571 }
572
573 const unsigned idx_map[] = { 3, 0, 1, 2 }; /* w=bit 3, x=0, y=1, z=2 */
574
575 for (unsigned i = 0; i < mask_length; i++) {
576 if (mask_str[i] < 'w' || mask_str[i] > 'z') {
577 ir_read_error(expr, "write mask contains invalid character: %c",
578 mask_str[i]);
579 return NULL;
580 }
581 mask |= 1 << idx_map[mask_str[i] - 'w'];
582 }
583 } else if (!mask_list->subexpressions.is_empty()) {
584 ir_read_error(mask_list, "expected () or (<write mask>)");
585 return NULL;
586 }
587
588 ir_dereference *lhs = read_dereference(lhs_expr);
589 if (lhs == NULL) {
590 ir_read_error(NULL, "when reading left-hand side of assignment");
591 return NULL;
592 }
593
594 ir_rvalue *rhs = read_rvalue(rhs_expr);
595 if (rhs == NULL) {
596 ir_read_error(NULL, "when reading right-hand side of assignment");
597 return NULL;
598 }
599
600 if (mask == 0 && (lhs->type->is_vector() || lhs->type->is_scalar())) {
601 ir_read_error(expr, "non-zero write mask required.");
602 return NULL;
603 }
604
605 return new(mem_ctx) ir_assignment(lhs, rhs, condition, mask);
606 }
607
608 ir_call *
609 ir_reader::read_call(s_expression *expr)
610 {
611 s_symbol *name;
612 s_list *params;
613
614 s_pattern pat[] = { "call", name, params };
615 if (!MATCH(expr, pat)) {
616 ir_read_error(expr, "expected (call <name> (<param> ...))");
617 return NULL;
618 }
619
620 exec_list parameters;
621
622 foreach_iter(exec_list_iterator, it, params->subexpressions) {
623 s_expression *expr = (s_expression*) it.get();
624 ir_rvalue *param = read_rvalue(expr);
625 if (param == NULL) {
626 ir_read_error(expr, "when reading parameter to function call");
627 return NULL;
628 }
629 parameters.push_tail(param);
630 }
631
632 ir_function *f = state->symbols->get_function(name->value());
633 if (f == NULL) {
634 ir_read_error(expr, "found call to undefined function %s",
635 name->value());
636 return NULL;
637 }
638
639 ir_function_signature *callee = f->matching_signature(&parameters);
640 if (callee == NULL) {
641 ir_read_error(expr, "couldn't find matching signature for function "
642 "%s", name->value());
643 return NULL;
644 }
645
646 return new(mem_ctx) ir_call(callee, &parameters);
647 }
648
649 ir_expression *
650 ir_reader::read_expression(s_expression *expr)
651 {
652 s_expression *s_type;
653 s_symbol *s_op;
654 s_expression *s_arg1;
655
656 s_pattern pat[] = { "expression", s_type, s_op, s_arg1 };
657 if (!PARTIAL_MATCH(expr, pat)) {
658 ir_read_error(expr, "expected (expression <type> <operator> "
659 "<operand> [<operand>])");
660 return NULL;
661 }
662 s_expression *s_arg2 = (s_expression *) s_arg1->next; // may be tail sentinel
663
664 const glsl_type *type = read_type(s_type);
665 if (type == NULL)
666 return NULL;
667
668 /* Read the operator */
669 ir_expression_operation op = ir_expression::get_operator(s_op->value());
670 if (op == (ir_expression_operation) -1) {
671 ir_read_error(expr, "invalid operator: %s", s_op->value());
672 return NULL;
673 }
674
675 unsigned num_operands = ir_expression::get_num_operands(op);
676 if (num_operands == 1 && !s_arg1->next->is_tail_sentinel()) {
677 ir_read_error(expr, "expected (expression <type> %s <operand>)",
678 s_op->value());
679 return NULL;
680 }
681
682 ir_rvalue *arg1 = read_rvalue(s_arg1);
683 ir_rvalue *arg2 = NULL;
684 if (arg1 == NULL) {
685 ir_read_error(NULL, "when reading first operand of %s", s_op->value());
686 return NULL;
687 }
688
689 if (num_operands == 2) {
690 if (s_arg2->is_tail_sentinel() || !s_arg2->next->is_tail_sentinel()) {
691 ir_read_error(expr, "expected (expression <type> %s <operand> "
692 "<operand>)", s_op->value());
693 return NULL;
694 }
695 arg2 = read_rvalue(s_arg2);
696 if (arg2 == NULL) {
697 ir_read_error(NULL, "when reading second operand of %s",
698 s_op->value());
699 return NULL;
700 }
701 }
702
703 return new(mem_ctx) ir_expression(op, type, arg1, arg2);
704 }
705
706 ir_swizzle *
707 ir_reader::read_swizzle(s_expression *expr)
708 {
709 s_symbol *swiz;
710 s_expression *sub;
711
712 s_pattern pat[] = { "swiz", swiz, sub };
713 if (!MATCH(expr, pat)) {
714 ir_read_error(expr, "expected (swiz <swizzle> <rvalue>)");
715 return NULL;
716 }
717
718 if (strlen(swiz->value()) > 4) {
719 ir_read_error(expr, "expected a valid swizzle; found %s", swiz->value());
720 return NULL;
721 }
722
723 ir_rvalue *rvalue = read_rvalue(sub);
724 if (rvalue == NULL)
725 return NULL;
726
727 ir_swizzle *ir = ir_swizzle::create(rvalue, swiz->value(),
728 rvalue->type->vector_elements);
729 if (ir == NULL)
730 ir_read_error(expr, "invalid swizzle");
731
732 return ir;
733 }
734
735 ir_constant *
736 ir_reader::read_constant(s_expression *expr)
737 {
738 s_expression *type_expr;
739 s_list *values;
740
741 s_pattern pat[] = { "constant", type_expr, values };
742 if (!MATCH(expr, pat)) {
743 ir_read_error(expr, "expected (constant <type> (...))");
744 return NULL;
745 }
746
747 const glsl_type *type = read_type(type_expr);
748 if (type == NULL)
749 return NULL;
750
751 if (values == NULL) {
752 ir_read_error(expr, "expected (constant <type> (...))");
753 return NULL;
754 }
755
756 if (type->is_array()) {
757 unsigned elements_supplied = 0;
758 exec_list elements;
759 foreach_iter(exec_list_iterator, it, values->subexpressions) {
760 s_expression *elt = (s_expression *) it.get();
761 ir_constant *ir_elt = read_constant(elt);
762 if (ir_elt == NULL)
763 return NULL;
764 elements.push_tail(ir_elt);
765 elements_supplied++;
766 }
767
768 if (elements_supplied != type->length) {
769 ir_read_error(values, "expected exactly %u array elements, "
770 "given %u", type->length, elements_supplied);
771 return NULL;
772 }
773 return new(mem_ctx) ir_constant(type, &elements);
774 }
775
776 ir_constant_data data = { { 0 } };
777
778 // Read in list of values (at most 16).
779 unsigned k = 0;
780 foreach_iter(exec_list_iterator, it, values->subexpressions) {
781 if (k >= 16) {
782 ir_read_error(values, "expected at most 16 numbers");
783 return NULL;
784 }
785
786 s_expression *expr = (s_expression*) it.get();
787
788 if (type->base_type == GLSL_TYPE_FLOAT) {
789 s_number *value = SX_AS_NUMBER(expr);
790 if (value == NULL) {
791 ir_read_error(values, "expected numbers");
792 return NULL;
793 }
794 data.f[k] = value->fvalue();
795 } else {
796 s_int *value = SX_AS_INT(expr);
797 if (value == NULL) {
798 ir_read_error(values, "expected integers");
799 return NULL;
800 }
801
802 switch (type->base_type) {
803 case GLSL_TYPE_UINT: {
804 data.u[k] = value->value();
805 break;
806 }
807 case GLSL_TYPE_INT: {
808 data.i[k] = value->value();
809 break;
810 }
811 case GLSL_TYPE_BOOL: {
812 data.b[k] = value->value();
813 break;
814 }
815 default:
816 ir_read_error(values, "unsupported constant type");
817 return NULL;
818 }
819 }
820 ++k;
821 }
822 if (k != type->components()) {
823 ir_read_error(values, "expected %u constant values, found %u",
824 type->components(), k);
825 return NULL;
826 }
827
828 return new(mem_ctx) ir_constant(type, &data);
829 }
830
831 ir_dereference *
832 ir_reader::read_dereference(s_expression *expr)
833 {
834 s_symbol *s_var;
835 s_expression *s_subject;
836 s_expression *s_index;
837 s_symbol *s_field;
838
839 s_pattern var_pat[] = { "var_ref", s_var };
840 s_pattern array_pat[] = { "array_ref", s_subject, s_index };
841 s_pattern record_pat[] = { "record_ref", s_subject, s_field };
842
843 if (MATCH(expr, var_pat)) {
844 ir_variable *var = state->symbols->get_variable(s_var->value());
845 if (var == NULL) {
846 ir_read_error(expr, "undeclared variable: %s", s_var->value());
847 return NULL;
848 }
849 return new(mem_ctx) ir_dereference_variable(var);
850 } else if (MATCH(expr, array_pat)) {
851 ir_rvalue *subject = read_rvalue(s_subject);
852 if (subject == NULL) {
853 ir_read_error(NULL, "when reading the subject of an array_ref");
854 return NULL;
855 }
856
857 ir_rvalue *idx = read_rvalue(s_index);
858 if (subject == NULL) {
859 ir_read_error(NULL, "when reading the index of an array_ref");
860 return NULL;
861 }
862 return new(mem_ctx) ir_dereference_array(subject, idx);
863 } else if (MATCH(expr, record_pat)) {
864 ir_rvalue *subject = read_rvalue(s_subject);
865 if (subject == NULL) {
866 ir_read_error(NULL, "when reading the subject of a record_ref");
867 return NULL;
868 }
869 return new(mem_ctx) ir_dereference_record(subject, s_field->value());
870 }
871 return NULL;
872 }
873
874 ir_texture *
875 ir_reader::read_texture(s_expression *expr)
876 {
877 s_symbol *tag = NULL;
878 s_expression *s_type = NULL;
879 s_expression *s_sampler = NULL;
880 s_expression *s_coord = NULL;
881 s_expression *s_offset = NULL;
882 s_expression *s_proj = NULL;
883 s_list *s_shadow = NULL;
884 s_expression *s_lod = NULL;
885
886 ir_texture_opcode op = ir_tex; /* silence warning */
887
888 s_pattern tex_pattern[] =
889 { "tex", s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow };
890 s_pattern txf_pattern[] =
891 { "txf", s_type, s_sampler, s_coord, s_offset, s_lod };
892 s_pattern txs_pattern[] =
893 { "txs", s_type, s_sampler, s_lod };
894 s_pattern other_pattern[] =
895 { tag, s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod };
896
897 if (MATCH(expr, tex_pattern)) {
898 op = ir_tex;
899 } else if (MATCH(expr, txf_pattern)) {
900 op = ir_txf;
901 } else if (MATCH(expr, txs_pattern)) {
902 op = ir_txs;
903 } else if (MATCH(expr, other_pattern)) {
904 op = ir_texture::get_opcode(tag->value());
905 if (op == -1)
906 return NULL;
907 } else {
908 ir_read_error(NULL, "unexpected texture pattern");
909 return NULL;
910 }
911
912 ir_texture *tex = new(mem_ctx) ir_texture(op);
913
914 // Read return type
915 const glsl_type *type = read_type(s_type);
916 if (type == NULL) {
917 ir_read_error(NULL, "when reading type in (%s ...)",
918 tex->opcode_string());
919 return NULL;
920 }
921
922 // Read sampler (must be a deref)
923 ir_dereference *sampler = read_dereference(s_sampler);
924 if (sampler == NULL) {
925 ir_read_error(NULL, "when reading sampler in (%s ...)",
926 tex->opcode_string());
927 return NULL;
928 }
929 tex->set_sampler(sampler, type);
930
931 if (op != ir_txs) {
932 // Read coordinate (any rvalue)
933 tex->coordinate = read_rvalue(s_coord);
934 if (tex->coordinate == NULL) {
935 ir_read_error(NULL, "when reading coordinate in (%s ...)",
936 tex->opcode_string());
937 return NULL;
938 }
939
940 // Read texel offset - either 0 or an rvalue.
941 s_int *si_offset = SX_AS_INT(s_offset);
942 if (si_offset == NULL || si_offset->value() != 0) {
943 tex->offset = read_rvalue(s_offset);
944 if (tex->offset == NULL) {
945 ir_read_error(s_offset, "expected 0 or an expression");
946 return NULL;
947 }
948 }
949 }
950
951 if (op != ir_txf && op != ir_txs) {
952 s_int *proj_as_int = SX_AS_INT(s_proj);
953 if (proj_as_int && proj_as_int->value() == 1) {
954 tex->projector = NULL;
955 } else {
956 tex->projector = read_rvalue(s_proj);
957 if (tex->projector == NULL) {
958 ir_read_error(NULL, "when reading projective divide in (%s ..)",
959 tex->opcode_string());
960 return NULL;
961 }
962 }
963
964 if (s_shadow->subexpressions.is_empty()) {
965 tex->shadow_comparitor = NULL;
966 } else {
967 tex->shadow_comparitor = read_rvalue(s_shadow);
968 if (tex->shadow_comparitor == NULL) {
969 ir_read_error(NULL, "when reading shadow comparitor in (%s ..)",
970 tex->opcode_string());
971 return NULL;
972 }
973 }
974 }
975
976 switch (op) {
977 case ir_txb:
978 tex->lod_info.bias = read_rvalue(s_lod);
979 if (tex->lod_info.bias == NULL) {
980 ir_read_error(NULL, "when reading LOD bias in (txb ...)");
981 return NULL;
982 }
983 break;
984 case ir_txl:
985 case ir_txf:
986 case ir_txs:
987 tex->lod_info.lod = read_rvalue(s_lod);
988 if (tex->lod_info.lod == NULL) {
989 ir_read_error(NULL, "when reading LOD in (%s ...)",
990 tex->opcode_string());
991 return NULL;
992 }
993 break;
994 case ir_txd: {
995 s_expression *s_dx, *s_dy;
996 s_pattern dxdy_pat[] = { s_dx, s_dy };
997 if (!MATCH(s_lod, dxdy_pat)) {
998 ir_read_error(s_lod, "expected (dPdx dPdy) in (txd ...)");
999 return NULL;
1000 }
1001 tex->lod_info.grad.dPdx = read_rvalue(s_dx);
1002 if (tex->lod_info.grad.dPdx == NULL) {
1003 ir_read_error(NULL, "when reading dPdx in (txd ...)");
1004 return NULL;
1005 }
1006 tex->lod_info.grad.dPdy = read_rvalue(s_dy);
1007 if (tex->lod_info.grad.dPdy == NULL) {
1008 ir_read_error(NULL, "when reading dPdy in (txd ...)");
1009 return NULL;
1010 }
1011 break;
1012 }
1013 default:
1014 // tex doesn't have any extra parameters.
1015 break;
1016 };
1017 return tex;
1018 }