OSDN Git Service

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