OSDN Git Service

Fix unused variable warning.
[android-x86/external-mesa.git] / glsl_parser_extras.cpp
1 /*
2  * Copyright © 2008, 2009 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 #include <stdio.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28     
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33
34 #include "ast.h"
35 #include "glsl_parser_extras.h"
36 #include "glsl_parser.h"
37 #include "ir_print_visitor.h"
38
39 void
40 _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
41                  const char *fmt, ...)
42 {
43    char buf[1024];
44    int len;
45    va_list ap;
46
47    state->error = true;
48
49    len = snprintf(buf, sizeof(buf), "%u:%u(%u): error: ",
50                   locp->source, locp->first_line, locp->first_column);
51
52    va_start(ap, fmt);
53    vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
54    va_end(ap);
55
56    printf("%s\n", buf);
57 }
58
59
60 ast_node::~ast_node()
61 {
62    /* empty */
63 }
64
65
66 void
67 _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
68 {
69    if (q->constant)
70       printf("const ");
71
72    if (q->invariant)
73       printf("invariant ");
74
75    if (q->attribute)
76       printf("attribute ");
77
78    if (q->varying)
79       printf("varying ");
80
81    if (q->in && q->out) 
82       printf("inout ");
83    else {
84       if (q->in)
85          printf("in ");
86
87       if (q->out)
88          printf("out ");
89    }
90
91    if (q->centroid)
92       printf("centroid ");
93    if (q->uniform)
94       printf("uniform ");
95    if (q->smooth)
96       printf("smooth ");
97    if (q->flat)
98       printf("flat ");
99    if (q->noperspective)
100       printf("noperspective ");
101 }
102
103
104 void
105 ast_node::print(void) const
106 {
107    printf("node_%d ", type);
108 }
109
110
111 ast_node::ast_node(void)
112 {
113    make_empty_list(this);
114 }
115
116
117 static void
118 ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
119 {
120    if (is_array) {
121       printf("[ ");
122
123       if (array_size)
124          array_size->print();
125
126       printf("] ");
127    }
128 }
129
130
131 void
132 ast_compound_statement::print(void) const
133 {
134    const struct simple_node *ptr;
135
136    printf("{\n");
137    
138    foreach(ptr, & statements) {
139       ((ast_node *)ptr)->print();
140    }
141
142    printf("}\n");
143 }
144
145
146 ast_compound_statement::ast_compound_statement(int new_scope,
147                                                ast_node *statements)
148 {
149    this->new_scope = new_scope;
150    make_empty_list(& this->statements);
151
152    if (statements != NULL) {
153       /* This seems odd, but it works.  The simple_list is,
154        * basically, a circular list.  insert_at_tail adds
155        * the specified node to the list before the current
156        * head.
157        */
158       insert_at_tail((struct simple_node *) statements,
159                      & this->statements);
160    }
161 }
162
163
164 void
165 ast_expression::print(void) const
166 {
167    switch (oper) {
168    case ast_assign:
169    case ast_mul_assign:
170    case ast_div_assign:
171    case ast_mod_assign:
172    case ast_add_assign:
173    case ast_sub_assign:
174    case ast_ls_assign:
175    case ast_rs_assign:
176    case ast_and_assign:
177    case ast_xor_assign:
178    case ast_or_assign:
179       subexpressions[0]->print();
180       printf("%s ", operator_string(oper));
181       subexpressions[1]->print();
182       break;
183
184    case ast_field_selection:
185       subexpressions[0]->print();
186       printf(". %s ", primary_expression.identifier);
187       break;
188
189    case ast_plus:
190    case ast_neg:
191    case ast_bit_not:
192    case ast_logic_not:
193    case ast_pre_inc:
194    case ast_pre_dec:
195       printf("%s ", operator_string(oper));
196       subexpressions[0]->print();
197       break;
198
199    case ast_post_inc:
200    case ast_post_dec:
201       subexpressions[0]->print();
202       printf("%s ", operator_string(oper));
203       break;
204
205    case ast_conditional:
206       subexpressions[0]->print();
207       printf("? ");
208       subexpressions[1]->print();
209       printf(": ");
210       subexpressions[1]->print();
211       break;
212
213    case ast_array_index:
214       subexpressions[0]->print();
215       printf("[ ");
216       subexpressions[1]->print();
217       printf("] ");
218       break;
219
220    case ast_function_call: {
221       ast_expression *parameters = subexpressions[1];
222
223       subexpressions[0]->print();
224       printf("( ");
225
226       if (parameters != NULL) {
227          struct simple_node *ptr;
228
229          parameters->print();
230          foreach (ptr, (struct simple_node *) parameters) {
231             printf(", ");
232             ((ast_node *)ptr)->print();
233          }
234       }
235
236       printf(") ");
237       break;
238    }
239
240    case ast_identifier:
241       printf("%s ", primary_expression.identifier);
242       break;
243
244    case ast_int_constant:
245       printf("%d ", primary_expression.int_constant);
246       break;
247
248    case ast_uint_constant:
249       printf("%u ", primary_expression.uint_constant);
250       break;
251
252    case ast_float_constant:
253       printf("%f ", primary_expression.float_constant);
254       break;
255
256    case ast_bool_constant:
257       printf("%s ",
258              primary_expression.bool_constant
259              ? "true" : "false");
260       break;
261
262    case ast_sequence: {
263       struct simple_node *ptr;
264       struct simple_node *const head = first_elem(& expressions);
265       
266       printf("( ");
267       foreach (ptr, & expressions) {
268          if (ptr != head)
269             printf(", ");
270
271          ((ast_node *)ptr)->print();
272       }
273       printf(") ");
274       break;
275    }
276
277    default:
278       assert(0);
279       break;
280    }
281 }
282
283 ast_expression::ast_expression(int oper,
284                                ast_expression *ex0,
285                                ast_expression *ex1,
286                                ast_expression *ex2)
287 {
288    this->oper = ast_operators(oper);
289    this->subexpressions[0] = ex0;
290    this->subexpressions[1] = ex1;
291    this->subexpressions[2] = ex2;
292    make_empty_list(& expressions);
293 }
294
295
296 void
297 ast_expression_statement::print(void) const
298 {
299    if (expression)
300       expression->print();
301
302    printf("; ");
303 }
304
305
306 ast_expression_statement::ast_expression_statement(ast_expression *ex) :
307    expression(ex)
308 {
309    /* empty */
310 }
311
312
313 void
314 ast_function::print(void) const
315 {
316    struct simple_node *ptr;
317
318    return_type->print();
319    printf(" %s (", identifier);
320
321    foreach(ptr, & parameters) {
322       ((ast_node *)ptr)->print();
323    }
324
325    printf(")");
326 }
327
328
329 ast_function::ast_function(void)
330 {
331    make_empty_list(& parameters);
332 }
333
334
335 void
336 ast_fully_specified_type::print(void) const
337 {
338    _mesa_ast_type_qualifier_print(& qualifier);
339    specifier->print();
340 }
341
342
343 void
344 ast_parameter_declarator::print(void) const
345 {
346    type->print();
347    if (identifier)
348       printf("%s ", identifier);
349    ast_opt_array_size_print(is_array, array_size);
350 }
351
352
353 void
354 ast_function_definition::print(void) const
355 {
356    prototype->print();
357    body->print();
358 }
359
360
361 void
362 ast_declaration::print(void) const
363 {
364    printf("%s ", identifier);
365    ast_opt_array_size_print(is_array, array_size);
366
367    if (initializer) {
368       printf("= ");
369       initializer->print();
370    }
371 }
372
373
374 ast_declaration::ast_declaration(char *identifier, int is_array,
375                                  ast_expression *array_size,
376                                  ast_expression *initializer)
377 {
378    this->identifier = identifier;
379    this->is_array = is_array;
380    this->array_size = array_size;
381    this->initializer = initializer;
382 }
383
384
385 void
386 ast_declarator_list::print(void) const
387 {
388    struct simple_node *head;
389    struct simple_node *ptr;
390
391    assert(type || invariant);
392
393    if (type)
394       type->print();
395    else
396       printf("invariant ");
397
398    head = first_elem(& declarations);
399    foreach (ptr, & declarations) {
400       if (ptr != head)
401          printf(", ");
402
403       ((ast_node *)ptr)->print();
404    }
405
406    printf("; ");
407 }
408
409
410 ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
411 {
412    this->type = type;
413    make_empty_list(& this->declarations);
414 }
415
416 void
417 ast_jump_statement::print(void) const
418 {
419    switch (mode) {
420    case ast_continue:
421       printf("continue; ");
422       break;
423    case ast_break:
424       printf("break; ");
425       break;
426    case ast_return:
427       printf("return ");
428       if (opt_return_value)
429          opt_return_value->print();
430
431       printf("; ");
432       break;
433    case ast_discard:
434       printf("discard; ");
435       break;
436    }
437 }
438
439
440 ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
441 {
442    this->mode = ast_jump_modes(mode);
443
444    if (mode == ast_return)
445       opt_return_value = return_value;
446 }
447
448
449 void
450 ast_selection_statement::print(void) const
451 {
452    printf("if ( ");
453    condition->print();
454    printf(") ");
455
456    then_statement->print();
457
458    if (else_statement) {
459       printf("else ");
460       else_statement->print();
461    }
462    
463 }
464
465
466 ast_selection_statement::ast_selection_statement(ast_expression *condition,
467                                                  ast_node *then_statement,
468                                                  ast_node *else_statement)
469 {
470    this->condition = condition;
471    this->then_statement = then_statement;
472    this->else_statement = else_statement;
473 }
474
475
476 void
477 ast_iteration_statement::print(void) const
478 {
479    switch (mode) {
480    case ast_for:
481       printf("for( ");
482       if (init_statement)
483          init_statement->print();
484       printf("; ");
485
486       if (condition)
487          condition->print();
488       printf("; ");
489
490       if (rest_expression)
491          rest_expression->print();
492       printf(") ");
493
494       body->print();
495       break;
496
497    case ast_while:
498       printf("while ( ");
499       if (condition)
500          condition->print();
501       printf(") ");
502       body->print();
503       break;
504
505    case ast_do_while:
506       printf("do ");
507       body->print();
508       printf("while ( ");
509       if (condition)
510          condition->print();
511       printf("); ");
512       break;
513    }
514 }
515
516
517 ast_iteration_statement::ast_iteration_statement(int mode,
518                                                  ast_node *init,
519                                                  ast_node *condition,
520                                                  ast_expression *rest_expression,
521                                                  ast_node *body)
522 {
523    this->mode = ast_iteration_modes(mode);
524    this->init_statement = init;
525    this->condition = condition;
526    this->rest_expression = rest_expression;
527    this->body = body;
528 }
529
530
531 void
532 ast_struct_specifier::print(void) const
533 {
534    struct simple_node *ptr;
535
536    printf("struct %s { ", name);
537    foreach (ptr, & declarations) {
538       ((ast_node *)ptr)->print();
539    }
540    printf("} ");
541 }
542
543
544 ast_struct_specifier::ast_struct_specifier(char *identifier,
545                                            ast_node *declarator_list)
546 {
547    name = identifier;
548
549    /* This seems odd, but it works.  The simple_list is,
550     * basically, a circular list.  insert_at_tail adds
551     * the specified node to the list before the current
552     * head.
553     */
554    insert_at_tail((struct simple_node *) declarator_list,
555                   & declarations);
556 }
557
558
559 static char *
560 load_text_file(const char *file_name, size_t *size)
561 {
562         char *text = NULL;
563         struct stat st;
564         ssize_t total_read = 0;
565         int fd = open(file_name, O_RDONLY);
566
567         *size = 0;
568         if (fd < 0) {
569                 return NULL;
570         }
571
572         if (fstat(fd, & st) == 0) {
573            text = (char *) malloc(st.st_size + 1);
574                 if (text != NULL) {
575                         do {
576                                 ssize_t bytes = read(fd, text + total_read,
577                                                      st.st_size - total_read);
578                                 if (bytes < 0) {
579                                         free(text);
580                                         text = NULL;
581                                         break;
582                                 }
583
584                                 if (bytes == 0) {
585                                         break;
586                                 }
587
588                                 total_read += bytes;
589                         } while (total_read < st.st_size);
590
591                         text[total_read] = '\0';
592                         *size = total_read;
593                 }
594         }
595
596         close(fd);
597
598         return text;
599 }
600
601
602 int
603 main(int argc, char **argv)
604 {
605    struct _mesa_glsl_parse_state state;
606    char *shader;
607    size_t shader_len;
608    struct simple_node *ptr;
609    exec_list instructions;
610
611    if (argc < 3) {
612       printf("Usage: %s [v|g|f] <shader_file>\n", argv[0]);
613       return EXIT_FAILURE;
614    }
615
616    switch (argv[1][0]) {
617    case 'v':
618       state.target = vertex_shader;
619       break;
620    case 'g':
621       state.target = geometry_shader;
622       break;
623    case 'f':
624       state.target = fragment_shader;
625       break;
626    default:
627       printf("Usage: %s [v|g|f] <shader_file>\n", argv[0]);
628       return EXIT_FAILURE;
629    }
630
631    shader = load_text_file(argv[2], & shader_len);
632
633    state.scanner = NULL;
634    make_empty_list(& state.translation_unit);
635    state.symbols = new glsl_symbol_table;
636    state.error = false;
637    state.temp_index = 0;
638
639    _mesa_glsl_lexer_ctor(& state, shader, shader_len);
640    _mesa_glsl_parse(& state);
641    _mesa_glsl_lexer_dtor(& state);
642
643    foreach (ptr, & state.translation_unit) {
644       ((ast_node *)ptr)->print();
645    }
646
647    _mesa_ast_to_hir(&instructions, &state);
648
649    printf("\n\n");
650
651    if (!state.error) {
652       foreach_iter(exec_list_iterator, iter, instructions) {
653          ir_print_visitor v;
654
655          ((ir_instruction *)iter.get())->accept(& v);
656          printf("\n");
657       }
658    }
659
660    delete state.symbols;
661
662    return state.error != 0;
663 }