2 * Copyright © 2008, 2009 Intel Corporation
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:
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
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.
29 #include <sys/types.h>
35 #include "glsl_parser_extras.h"
36 #include "glsl_parser.h"
37 #include "ir_constant_folding.h"
38 #include "ir_print_visitor.h"
41 _mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target
)
44 case vertex_shader
: return "vertex";
45 case fragment_shader
: return "fragment";
46 case geometry_shader
: return "geometry";
49 assert(!"Should not get here.");
54 _mesa_glsl_error(YYLTYPE
*locp
, _mesa_glsl_parse_state
*state
,
63 len
= snprintf(buf
, sizeof(buf
), "%u:%u(%u): error: ",
64 locp
->source
, locp
->first_line
, locp
->first_column
);
67 vsnprintf(buf
+ len
, sizeof(buf
) - len
, fmt
, ap
);
75 _mesa_glsl_warning(const YYLTYPE
*locp
, const _mesa_glsl_parse_state
*state
,
82 len
= snprintf(buf
, sizeof(buf
), "%u:%u(%u): warning: ",
83 locp
->source
, locp
->first_line
, locp
->first_column
);
86 vsnprintf(buf
+ len
, sizeof(buf
) - len
, fmt
, ap
);
94 _mesa_glsl_process_extension(const char *name
, YYLTYPE
*name_locp
,
95 const char *behavior
, YYLTYPE
*behavior_locp
,
96 _mesa_glsl_parse_state
*state
)
106 if (strcmp(behavior
, "warn") == 0) {
107 ext_mode
= extension_warn
;
108 } else if (strcmp(behavior
, "require") == 0) {
109 ext_mode
= extension_require
;
110 } else if (strcmp(behavior
, "enable") == 0) {
111 ext_mode
= extension_enable
;
112 } else if (strcmp(behavior
, "disable") == 0) {
113 ext_mode
= extension_disable
;
115 _mesa_glsl_error(behavior_locp
, state
,
116 "Unknown extension behavior `%s'",
121 if (strcmp(name
, "all") == 0) {
122 if ((ext_mode
== extension_enable
) || (ext_mode
== extension_require
)) {
123 _mesa_glsl_error(name_locp
, state
, "Cannot %s all extensions",
124 (ext_mode
== extension_enable
)
125 ? "enable" : "require");
129 if (ext_mode
== extension_require
) {
130 _mesa_glsl_error(name_locp
, state
, "Unknown extension `%s'",
134 _mesa_glsl_warning(name_locp
, state
, "Unknown extension `%s'",
143 ast_node::~ast_node()
150 _mesa_ast_type_qualifier_print(const struct ast_type_qualifier
*q
)
156 printf("invariant ");
159 printf("attribute ");
182 if (q
->noperspective
)
183 printf("noperspective ");
188 ast_node::print(void) const
190 printf("unhandled node ");
194 ast_node::ast_node(void)
196 make_empty_list(this);
201 ast_opt_array_size_print(bool is_array
, const ast_expression
*array_size
)
215 ast_compound_statement::print(void) const
217 const struct simple_node
*ptr
;
221 foreach(ptr
, & statements
) {
222 ((ast_node
*)ptr
)->print();
229 ast_compound_statement::ast_compound_statement(int new_scope
,
230 ast_node
*statements
)
232 this->new_scope
= new_scope
;
233 make_empty_list(& this->statements
);
235 if (statements
!= NULL
) {
236 /* This seems odd, but it works. The simple_list is,
237 * basically, a circular list. insert_at_tail adds
238 * the specified node to the list before the current
241 insert_at_tail((struct simple_node
*) statements
,
248 ast_expression::print(void) const
262 subexpressions
[0]->print();
263 printf("%s ", operator_string(oper
));
264 subexpressions
[1]->print();
267 case ast_field_selection
:
268 subexpressions
[0]->print();
269 printf(". %s ", primary_expression
.identifier
);
278 printf("%s ", operator_string(oper
));
279 subexpressions
[0]->print();
284 subexpressions
[0]->print();
285 printf("%s ", operator_string(oper
));
288 case ast_conditional
:
289 subexpressions
[0]->print();
291 subexpressions
[1]->print();
293 subexpressions
[1]->print();
296 case ast_array_index
:
297 subexpressions
[0]->print();
299 subexpressions
[1]->print();
303 case ast_function_call
: {
304 ast_expression
*parameters
= subexpressions
[1];
306 subexpressions
[0]->print();
309 if (parameters
!= NULL
) {
310 struct simple_node
*ptr
;
313 foreach (ptr
, (struct simple_node
*) parameters
) {
315 ((ast_node
*)ptr
)->print();
324 printf("%s ", primary_expression
.identifier
);
327 case ast_int_constant
:
328 printf("%d ", primary_expression
.int_constant
);
331 case ast_uint_constant
:
332 printf("%u ", primary_expression
.uint_constant
);
335 case ast_float_constant
:
336 printf("%f ", primary_expression
.float_constant
);
339 case ast_bool_constant
:
341 primary_expression
.bool_constant
346 struct simple_node
*ptr
;
347 struct simple_node
*const head
= first_elem(& expressions
);
350 foreach (ptr
, & expressions
) {
354 ((ast_node
*)ptr
)->print();
366 ast_expression::ast_expression(int oper
,
371 this->oper
= ast_operators(oper
);
372 this->subexpressions
[0] = ex0
;
373 this->subexpressions
[1] = ex1
;
374 this->subexpressions
[2] = ex2
;
375 make_empty_list(& expressions
);
380 ast_expression_statement::print(void) const
389 ast_expression_statement::ast_expression_statement(ast_expression
*ex
) :
397 ast_function::print(void) const
399 struct simple_node
*ptr
;
401 return_type
->print();
402 printf(" %s (", identifier
);
404 foreach(ptr
, & parameters
) {
405 ((ast_node
*)ptr
)->print();
412 ast_function::ast_function(void)
413 : is_definition(false), signature(NULL
)
415 make_empty_list(& parameters
);
420 ast_fully_specified_type::print(void) const
422 _mesa_ast_type_qualifier_print(& qualifier
);
428 ast_parameter_declarator::print(void) const
432 printf("%s ", identifier
);
433 ast_opt_array_size_print(is_array
, array_size
);
438 ast_function_definition::print(void) const
446 ast_declaration::print(void) const
448 printf("%s ", identifier
);
449 ast_opt_array_size_print(is_array
, array_size
);
453 initializer
->print();
458 ast_declaration::ast_declaration(char *identifier
, int is_array
,
459 ast_expression
*array_size
,
460 ast_expression
*initializer
)
462 this->identifier
= identifier
;
463 this->is_array
= is_array
;
464 this->array_size
= array_size
;
465 this->initializer
= initializer
;
470 ast_declarator_list::print(void) const
472 struct simple_node
*head
;
473 struct simple_node
*ptr
;
475 assert(type
|| invariant
);
480 printf("invariant ");
482 head
= first_elem(& declarations
);
483 foreach (ptr
, & declarations
) {
487 ((ast_node
*)ptr
)->print();
494 ast_declarator_list::ast_declarator_list(ast_fully_specified_type
*type
)
497 make_empty_list(& this->declarations
);
501 ast_jump_statement::print(void) const
505 printf("continue; ");
512 if (opt_return_value
)
513 opt_return_value
->print();
524 ast_jump_statement::ast_jump_statement(int mode
, ast_expression
*return_value
)
526 this->mode
= ast_jump_modes(mode
);
528 if (mode
== ast_return
)
529 opt_return_value
= return_value
;
534 ast_selection_statement::print(void) const
540 then_statement
->print();
542 if (else_statement
) {
544 else_statement
->print();
550 ast_selection_statement::ast_selection_statement(ast_expression
*condition
,
551 ast_node
*then_statement
,
552 ast_node
*else_statement
)
554 this->condition
= condition
;
555 this->then_statement
= then_statement
;
556 this->else_statement
= else_statement
;
561 ast_iteration_statement::print(void) const
567 init_statement
->print();
575 rest_expression
->print();
601 ast_iteration_statement::ast_iteration_statement(int mode
,
604 ast_expression
*rest_expression
,
607 this->mode
= ast_iteration_modes(mode
);
608 this->init_statement
= init
;
609 this->condition
= condition
;
610 this->rest_expression
= rest_expression
;
616 ast_struct_specifier::print(void) const
618 struct simple_node
*ptr
;
620 printf("struct %s { ", name
);
621 foreach (ptr
, & declarations
) {
622 ((ast_node
*)ptr
)->print();
628 ast_struct_specifier::ast_struct_specifier(char *identifier
,
629 ast_node
*declarator_list
)
633 /* This seems odd, but it works. The simple_list is,
634 * basically, a circular list. insert_at_tail adds
635 * the specified node to the list before the current
638 insert_at_tail((struct simple_node
*) declarator_list
,
644 load_text_file(const char *file_name
, size_t *size
)
648 ssize_t total_read
= 0;
649 int fd
= open(file_name
, O_RDONLY
);
656 if (fstat(fd
, & st
) == 0) {
657 text
= (char *) malloc(st
.st_size
+ 1);
660 ssize_t bytes
= read(fd
, text
+ total_read
,
661 st
.st_size
- total_read
);
673 } while (total_read
< st
.st_size
);
675 text
[total_read
] = '\0';
687 main(int argc
, char **argv
)
689 struct _mesa_glsl_parse_state state
;
692 struct simple_node
*ptr
;
693 exec_list instructions
;
696 printf("Usage: %s [v|g|f] <shader_file>\n", argv
[0]);
700 switch (argv
[1][0]) {
702 state
.target
= vertex_shader
;
705 state
.target
= geometry_shader
;
708 state
.target
= fragment_shader
;
711 printf("Usage: %s [v|g|f] <shader_file>\n", argv
[0]);
715 shader
= load_text_file(argv
[2], & shader_len
);
717 state
.scanner
= NULL
;
718 make_empty_list(& state
.translation_unit
);
719 state
.symbols
= new glsl_symbol_table
;
721 state
.temp_index
= 0;
722 state
.loop_or_switch_nesting
= NULL
;
724 _mesa_glsl_lexer_ctor(& state
, shader
, shader_len
);
725 _mesa_glsl_parse(& state
);
726 _mesa_glsl_lexer_dtor(& state
);
728 foreach (ptr
, & state
.translation_unit
) {
729 ((ast_node
*)ptr
)->print();
732 _mesa_ast_to_hir(&instructions
, &state
);
734 /* Optimization passes */
736 /* Constant folding */
737 ir_constant_folding_visitor constant_folding
;
738 visit_exec_list(&instructions
, &constant_folding
);
741 /* Print out the resulting IR */
745 foreach_iter(exec_list_iterator
, iter
, instructions
) {
748 ((ir_instruction
*)iter
.get())->accept(& v
);
753 delete state
.symbols
;
755 return state
.error
!= 0;