| @@ -0,0 +1 @@ | |||
| ((c-mode . ((c-basic-offset . 3)))) | |||
| @@ -0,0 +1,40 @@ | |||
| CSRCS = symbol_table.c hash_table.c glsl_types.c | |||
| CCSRCS = glsl_parser.tab.cc glsl_lexer.cc glsl_parser_extras.cc | |||
| # ast_to_hir.cc ir.cc hir_field_selection.cc | |||
| OBJS = $(CSRCS:.c=.o) $(CCSRCS:.cc=.o) | |||
| CC = gcc | |||
| CXX = g++ | |||
| WARN = -Wall -Wextra -Wunsafe-loop-optimizations -Wstack-protector \ | |||
| -Wunreachable-code | |||
| CPPFLAGS = -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE | |||
| CFLAGS = -O0 -ggdb3 -fstack-protector $(CPPFLAGS) $(WARN) -std=c89 -ansi -pedantic | |||
| CXXFLAGS = -O0 -ggdb3 -fstack-protector $(CPPFLAGS) $(WARN) | |||
| LDLAGS = -ggdb3 | |||
| glsl: $(OBJS) | |||
| $(CXX) $(LDLAGS) $(OBJS) -o glsl | |||
| glsl_parser.tab.cc glsl_parser.tab.h: glsl_parser.y | |||
| bison --report-file=glsl_parser.output -v -d \ | |||
| --output=glsl_parser.tab.cc \ | |||
| --name-prefix=_mesa_glsl_ $< && \ | |||
| mv glsl_parser.tab.hh glsl_parser.tab.h | |||
| glsl_lexer.cc: glsl_lexer.l | |||
| flex --outfile="glsl_lexer.cc" $< | |||
| glsl_parser_tab.o: glsl_parser.tab.cc | |||
| glsl_types.o: glsl_types.c glsl_types.h builtin_types.h | |||
| glsl_lexer.o: glsl_lexer.cc glsl_parser.tab.h glsl_parser_extras.h ast.h | |||
| glsl_parser.o: glsl_parser_extras.h ast.h | |||
| ast_to_hir.o: ast_to_hir.cc symbol_table.h glsl_parser_extras.h ast.h glsl_types.h ir.h | |||
| builtin_types.h: builtin_types.sh | |||
| ./builtin_types.sh > builtin_types.h | |||
| clean: | |||
| rm -f $(OBJS) glsl | |||
| rm -f glsl_lexer.cc glsl_parser.tab.{cc,h,hh} glsl_parser.output | |||
| rm -f builtin_types.h | |||
| rm -f *~ | |||
| @@ -0,0 +1,511 @@ | |||
| /* | |||
| * Copyright © 2009 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #pragma once | |||
| #ifndef AST_H | |||
| #define AST_H | |||
| #include "main/simple_list.h" | |||
| #include "glsl_parser_extras.h" | |||
| struct ir_instruction; | |||
| struct _mesa_glsl_parse_state; | |||
| struct YYLTYPE; | |||
| #define _mesa_ast_print(n) \ | |||
| ((ast_node *) n)->print() | |||
| #define _mesa_ast_to_hir(n, instr, s) \ | |||
| ((struct ast_node *) n)->vtbl->to_hir((struct ast_node *) n, instr, s) | |||
| #define _mesa_ast_function_call_to_hir(n, p, s) \ | |||
| ((struct ast_node *) n)->vtbl->function_call_to_hir( \ | |||
| (struct ast_node *) n, \ | |||
| (struct ast_node *) p, \ | |||
| s) | |||
| class ast_node : public simple_node { | |||
| public: | |||
| virtual ~ast_node(); | |||
| virtual void print(void) const; | |||
| /** | |||
| * Retrieve the source location of an AST node | |||
| * | |||
| * This function is primarily used to get the source position of an AST node | |||
| * into a form that can be passed to \c _mesa_glsl_error. | |||
| * | |||
| * \sa _mesa_glsl_error, ast_node::set_location | |||
| */ | |||
| struct YYLTYPE get_location(void) const | |||
| { | |||
| struct YYLTYPE locp; | |||
| locp.source = this->location.source; | |||
| locp.first_line = this->location.line; | |||
| locp.first_column = this->location.column; | |||
| locp.last_line = locp.first_line; | |||
| locp.last_column = locp.first_column; | |||
| return locp; | |||
| } | |||
| /** | |||
| * Set the source location of an AST node from a parser location | |||
| * | |||
| * \sa ast_node::get_location | |||
| */ | |||
| void set_location(const struct YYLTYPE *locp) | |||
| { | |||
| this->location.source = locp->source; | |||
| this->location.line = locp->first_line; | |||
| this->location.column = locp->first_column; | |||
| } | |||
| int type; | |||
| struct { | |||
| unsigned source; | |||
| unsigned line; | |||
| unsigned column; | |||
| } location; | |||
| protected: | |||
| ast_node(void); | |||
| }; | |||
| enum ast_operators { | |||
| ast_assign, | |||
| ast_plus, /**< Unary + operator. */ | |||
| ast_neg, | |||
| ast_add, | |||
| ast_sub, | |||
| ast_mul, | |||
| ast_div, | |||
| ast_mod, | |||
| ast_lshift, | |||
| ast_rshift, | |||
| ast_less, | |||
| ast_greater, | |||
| ast_lequal, | |||
| ast_gequal, | |||
| ast_equal, | |||
| ast_nequal, | |||
| ast_bit_and, | |||
| ast_bit_xor, | |||
| ast_bit_or, | |||
| ast_bit_not, | |||
| ast_logic_and, | |||
| ast_logic_xor, | |||
| ast_logic_or, | |||
| ast_logic_not, | |||
| ast_mul_assign, | |||
| ast_div_assign, | |||
| ast_mod_assign, | |||
| ast_add_assign, | |||
| ast_sub_assign, | |||
| ast_ls_assign, | |||
| ast_rs_assign, | |||
| ast_and_assign, | |||
| ast_xor_assign, | |||
| ast_or_assign, | |||
| ast_conditional, | |||
| ast_pre_inc, | |||
| ast_pre_dec, | |||
| ast_post_inc, | |||
| ast_post_dec, | |||
| ast_field_selection, | |||
| ast_array_index, | |||
| ast_function_call, | |||
| ast_identifier, | |||
| ast_int_constant, | |||
| ast_uint_constant, | |||
| ast_float_constant, | |||
| ast_bool_constant, | |||
| ast_sequence | |||
| }; | |||
| class ast_expression : public ast_node { | |||
| public: | |||
| ast_expression(int oper, ast_expression *, | |||
| ast_expression *, ast_expression *); | |||
| virtual void print(void) const; | |||
| enum ast_operators oper; | |||
| ast_expression *subexpressions[3]; | |||
| union { | |||
| char *identifier; | |||
| int int_constant; | |||
| float float_constant; | |||
| unsigned uint_constant; | |||
| int bool_constant; | |||
| } primary_expression; | |||
| /** | |||
| * List of expressions for an \c ast_sequence. | |||
| */ | |||
| struct simple_node expressions; | |||
| }; | |||
| /** | |||
| * Number of possible operators for an ast_expression | |||
| * | |||
| * This is done as a define instead of as an additional value in the enum so | |||
| * that the compiler won't generate spurious messages like "warning: | |||
| * enumeration value ‘ast_num_operators’ not handled in switch" | |||
| */ | |||
| #define AST_NUM_OPERATORS (ast_sequence + 1) | |||
| class ast_compound_statement : public ast_node { | |||
| public: | |||
| ast_compound_statement(int new_scope, ast_node *statements); | |||
| virtual void print(void) const; | |||
| int new_scope; | |||
| struct simple_node statements; | |||
| }; | |||
| class ast_declaration : public ast_node { | |||
| public: | |||
| ast_declaration(char *identifier, int is_array, ast_expression *array_size, | |||
| ast_expression *initializer); | |||
| virtual void print(void) const; | |||
| char *identifier; | |||
| int is_array; | |||
| ast_expression *array_size; | |||
| ast_expression *initializer; | |||
| }; | |||
| enum { | |||
| ast_precision_high = 0, /**< Default precision. */ | |||
| ast_precision_medium, | |||
| ast_precision_low | |||
| }; | |||
| struct ast_type_qualifier { | |||
| unsigned invariant:1; | |||
| unsigned constant:1; | |||
| unsigned attribute:1; | |||
| unsigned varying:1; | |||
| unsigned in:1; | |||
| unsigned out:1; | |||
| unsigned centroid:1; | |||
| unsigned uniform:1; | |||
| unsigned smooth:1; | |||
| unsigned flat:1; | |||
| unsigned noperspective:1; | |||
| }; | |||
| class ast_struct_specifier : public ast_node { | |||
| public: | |||
| ast_struct_specifier(char *identifier, ast_node *declarator_list); | |||
| virtual void print(void) const; | |||
| char *name; | |||
| struct simple_node declarations; | |||
| }; | |||
| enum ast_types { | |||
| ast_void, | |||
| ast_float, | |||
| ast_int, | |||
| ast_uint, | |||
| ast_bool, | |||
| ast_vec2, | |||
| ast_vec3, | |||
| ast_vec4, | |||
| ast_bvec2, | |||
| ast_bvec3, | |||
| ast_bvec4, | |||
| ast_ivec2, | |||
| ast_ivec3, | |||
| ast_ivec4, | |||
| ast_uvec2, | |||
| ast_uvec3, | |||
| ast_uvec4, | |||
| ast_mat2, | |||
| ast_mat2x3, | |||
| ast_mat2x4, | |||
| ast_mat3x2, | |||
| ast_mat3, | |||
| ast_mat3x4, | |||
| ast_mat4x2, | |||
| ast_mat4x3, | |||
| ast_mat4, | |||
| ast_sampler1d, | |||
| ast_sampler2d, | |||
| ast_sampler3d, | |||
| ast_samplercube, | |||
| ast_sampler1dshadow, | |||
| ast_sampler2dshadow, | |||
| ast_samplercubeshadow, | |||
| ast_sampler1darray, | |||
| ast_sampler2darray, | |||
| ast_sampler1darrayshadow, | |||
| ast_sampler2darrayshadow, | |||
| ast_isampler1d, | |||
| ast_isampler2d, | |||
| ast_isampler3d, | |||
| ast_isamplercube, | |||
| ast_isampler1darray, | |||
| ast_isampler2darray, | |||
| ast_usampler1d, | |||
| ast_usampler2d, | |||
| ast_usampler3d, | |||
| ast_usamplercube, | |||
| ast_usampler1darray, | |||
| ast_usampler2darray, | |||
| ast_struct, | |||
| ast_type_name | |||
| }; | |||
| class ast_type_specifier : public ast_node { | |||
| public: | |||
| ast_type_specifier(int specifier); | |||
| virtual void print(void) const; | |||
| enum ast_types type_specifier; | |||
| char *type_name; | |||
| ast_struct_specifier *structure; | |||
| int is_array; | |||
| ast_expression *array_size; | |||
| unsigned precision:2; | |||
| }; | |||
| class ast_fully_specified_type : public ast_node { | |||
| public: | |||
| virtual void print(void) const; | |||
| ast_type_qualifier qualifier; | |||
| ast_type_specifier *specifier; | |||
| }; | |||
| class ast_declarator_list : public ast_node { | |||
| public: | |||
| ast_declarator_list(ast_fully_specified_type *); | |||
| virtual void print(void) const; | |||
| ast_fully_specified_type *type; | |||
| struct simple_node declarations; | |||
| /** | |||
| * Special flag for vertex shader "invariant" declarations. | |||
| * | |||
| * Vertex shaders can contain "invariant" variable redeclarations that do | |||
| * not include a type. For example, "invariant gl_Position;". This flag | |||
| * is used to note these cases when no type is specified. | |||
| */ | |||
| int invariant; | |||
| }; | |||
| class ast_parameter_declarator : public ast_node { | |||
| public: | |||
| virtual void print(void) const; | |||
| ast_fully_specified_type *type; | |||
| char *identifier; | |||
| int is_array; | |||
| ast_expression *array_size; | |||
| }; | |||
| class ast_function : public ast_node { | |||
| public: | |||
| ast_function(void); | |||
| virtual void print(void) const; | |||
| ast_fully_specified_type *return_type; | |||
| char *identifier; | |||
| struct simple_node parameters; | |||
| }; | |||
| class ast_declaration_statement : public ast_node { | |||
| public: | |||
| ast_declaration_statement(void); | |||
| enum { | |||
| ast_function, | |||
| ast_declaration, | |||
| ast_precision | |||
| } mode; | |||
| union { | |||
| class ast_function *function; | |||
| ast_declarator_list *declarator; | |||
| ast_type_specifier *type; | |||
| ast_node *node; | |||
| } declaration; | |||
| }; | |||
| class ast_expression_statement : public ast_node { | |||
| public: | |||
| ast_expression_statement(ast_expression *); | |||
| virtual void print(void) const; | |||
| ast_expression *expression; | |||
| }; | |||
| class ast_case_label : public ast_node { | |||
| public: | |||
| /** | |||
| * An expression of NULL means 'default'. | |||
| */ | |||
| ast_expression *expression; | |||
| }; | |||
| class ast_selection_statement : public ast_node { | |||
| public: | |||
| ast_selection_statement(ast_expression *condition, | |||
| ast_node *then_statement, | |||
| ast_node *else_statement); | |||
| virtual void print(void) const; | |||
| ast_expression *condition; | |||
| ast_node *then_statement; | |||
| ast_node *else_statement; | |||
| }; | |||
| class ast_switch_statement : public ast_node { | |||
| public: | |||
| ast_expression *expression; | |||
| struct simple_node statements; | |||
| }; | |||
| class ast_iteration_statement : public ast_node { | |||
| public: | |||
| ast_iteration_statement(int mode, ast_node *init, ast_node *condition, | |||
| ast_expression *rest_expression, ast_node *body); | |||
| virtual void print(void) const; | |||
| enum ast_iteration_modes { | |||
| ast_for, | |||
| ast_while, | |||
| ast_do_while | |||
| } mode; | |||
| ast_node *init_statement; | |||
| ast_node *condition; | |||
| ast_expression *rest_expression; | |||
| ast_node *body; | |||
| }; | |||
| class ast_jump_statement : public ast_node { | |||
| public: | |||
| ast_jump_statement(int mode, ast_expression *return_value); | |||
| virtual void print(void) const; | |||
| enum ast_jump_modes { | |||
| ast_continue, | |||
| ast_break, | |||
| ast_return, | |||
| ast_discard | |||
| } mode; | |||
| ast_expression *opt_return_value; | |||
| }; | |||
| class ast_function_definition : public ast_node { | |||
| public: | |||
| virtual void print(void) const; | |||
| ast_function *prototype; | |||
| ast_compound_statement *body; | |||
| }; | |||
| extern struct ir_instruction * | |||
| ast_expression_to_hir(const ast_node *ast, | |||
| struct simple_node *instructions, | |||
| struct _mesa_glsl_parse_state *state); | |||
| extern struct ir_instruction * | |||
| ast_expression_statement_to_hir(const struct ast_node *ast, | |||
| struct simple_node *instructions, | |||
| struct _mesa_glsl_parse_state *state); | |||
| extern struct ir_instruction * | |||
| ast_compound_statement_to_hir(const struct ast_node *ast, | |||
| struct simple_node *instructions, | |||
| struct _mesa_glsl_parse_state *state); | |||
| extern struct ir_instruction * | |||
| ast_function_definition_to_hir(const struct ast_node *ast, | |||
| struct simple_node *instructions, | |||
| struct _mesa_glsl_parse_state *state); | |||
| extern struct ir_instruction * | |||
| ast_declarator_list_to_hir(const struct ast_node *ast, | |||
| struct simple_node *instructions, | |||
| struct _mesa_glsl_parse_state *state); | |||
| extern struct ir_instruction * | |||
| ast_parameter_declarator_to_hir(const struct ast_node *ast, | |||
| struct simple_node *instructions, | |||
| struct _mesa_glsl_parse_state *state); | |||
| extern struct ir_instruction * | |||
| _mesa_ast_field_selection_to_hir(const struct ast_expression *expr, | |||
| struct simple_node *instructions, | |||
| struct _mesa_glsl_parse_state *state); | |||
| #endif /* AST_H */ | |||
| @@ -0,0 +1,328 @@ | |||
| #!/bin/sh | |||
| # | |||
| # Copyright © 2009 Intel Corporation | |||
| # | |||
| # Permission is hereby granted, free of charge, to any person obtaining a | |||
| # copy of this software and associated documentation files (the "Software"), | |||
| # to deal in the Software without restriction, including without limitation | |||
| # the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| # and/or sell copies of the Software, and to permit persons to whom the | |||
| # Software is furnished to do so, subject to the following conditions: | |||
| # | |||
| # The above copyright notice and this permission notice (including the next | |||
| # paragraph) shall be included in all copies or substantial portions of the | |||
| # Software. | |||
| # | |||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| # DEALINGS IN THE SOFTWARE. | |||
| # gen_integral_type <name> <base_type> <vector elements> <matrix rows> | |||
| function gen_integral_type | |||
| { | |||
| printf ' { %17s, 0, 0, 0, 0, %u, %u, "%s", 0, {NULL} },\n' $2 $3 $4 $1 | |||
| index=$((index + 1)) | |||
| } | |||
| # gen_struct_type <name> | |||
| function gen_struct_type | |||
| { | |||
| elements=$(printf "%s_fields" $1) | |||
| printf ' {\n GLSL_TYPE_STRUCT, 0, 0, 0, 0, 0, 0, "%s",\n Elements(%s),\n {(void *) %s}\n },\n' \ | |||
| $1 $elements $elements | |||
| } | |||
| # gen_sampler_type <name> <dimensions> <shadow> <array> <type> | |||
| function gen_sampler_type | |||
| { | |||
| name=$(printf "sampler%s" $1) | |||
| if [ $4 -eq 1 ]; then | |||
| name=$(printf "%sArray" $name) | |||
| fi | |||
| if [ $3 -eq 1 ]; then | |||
| name=$(printf "%sShadow" $name) | |||
| fi | |||
| if [ $5 == GLSL_TYPE_INT ]; then | |||
| name=$(printf "i%s" $name) | |||
| elif [ $5 == GLSL_TYPE_UINT ]; then | |||
| name=$(printf "u%s" $name) | |||
| fi | |||
| printf ' { GLSL_TYPE_SAMPLER, %21s, %u, %u, %15s, 0, 0,\n "%s", 0, {NULL} },\n' \ | |||
| $2 $3 $4 $5 $name | |||
| } | |||
| function gen_header | |||
| { | |||
| if [ x$1 == x ]; then | |||
| name="builtin_types" | |||
| else | |||
| name="builtin_${1}_types" | |||
| fi | |||
| printf "\nstatic const struct glsl_type %s[] = {\n" $name | |||
| } | |||
| function gen_footer | |||
| { | |||
| printf "};\n" | |||
| } | |||
| function gen_struct_field_header | |||
| { | |||
| printf "\nstatic const struct glsl_struct_field %s_fields[] = {\n" $1 | |||
| } | |||
| function gen_struct_field_footer | |||
| { | |||
| printf "};\n" | |||
| } | |||
| function gen_struct_field | |||
| { | |||
| printf ' { & %s[%2u], "%s" },\n' $1 $2 "$3" | |||
| } | |||
| cat <<EOF | |||
| /* THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! See builtin_types.sh. */ | |||
| /* | |||
| * Copyright © 2009 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #ifndef Elements | |||
| #define Elements(x) (sizeof(x)/sizeof(*(x))) | |||
| #endif | |||
| static const struct glsl_type error_type = { | |||
| GLSL_TYPE_ERROR, 0, 0, 0, 0, 0, 0, "", 0, {NULL} | |||
| }; | |||
| const struct glsl_type *const glsl_error_type = & error_type; | |||
| EOF | |||
| echo '/** \name Core built-in types' | |||
| echo ' *' | |||
| echo ' * These types exist in all versions of GLSL.' | |||
| echo ' */' | |||
| echo '/*@{*/' | |||
| gen_header "core" | |||
| index=0; | |||
| bool_index=$index | |||
| gen_integral_type "bool" "GLSL_TYPE_BOOL" 0 0 | |||
| for i in 2 3 4; do | |||
| gen_integral_type "bvec$i" "GLSL_TYPE_BOOL" $i 0 | |||
| done | |||
| int_index=$index | |||
| gen_integral_type "int" "GLSL_TYPE_INT" 0 0 | |||
| for i in 2 3 4; do | |||
| gen_integral_type "ivec$i" "GLSL_TYPE_INT" $i 0 | |||
| done | |||
| float_index=$index | |||
| gen_integral_type "float" "GLSL_TYPE_FLOAT" 0 0 | |||
| for i in 2 3 4; do | |||
| gen_integral_type "vec$i" "GLSL_TYPE_FLOAT" $i 0 | |||
| done | |||
| for i in 2 3 4; do | |||
| gen_integral_type "mat$i" "GLSL_TYPE_FLOAT" $i $i | |||
| done | |||
| for i in "1D" "2D"; do | |||
| gen_sampler_type $i "GLSL_SAMPLER_DIM_$i" 0 0 "GLSL_TYPE_FLOAT" | |||
| gen_sampler_type $i "GLSL_SAMPLER_DIM_$i" 1 0 "GLSL_TYPE_FLOAT" | |||
| done | |||
| gen_sampler_type "3D" "GLSL_SAMPLER_DIM_3D" 0 0 "GLSL_TYPE_FLOAT" | |||
| gen_sampler_type "Cube" "GLSL_SAMPLER_DIM_CUBE" 0 0 "GLSL_TYPE_FLOAT" | |||
| gen_sampler_type "2DRect" "GLSL_SAMPLER_DIM_RECT" 0 0 "GLSL_TYPE_FLOAT" | |||
| gen_sampler_type "2DRect" "GLSL_SAMPLER_DIM_RECT" 1 0 "GLSL_TYPE_FLOAT" | |||
| gen_footer | |||
| echo | |||
| echo 'const struct glsl_type *const glsl_bool_type = & builtin_core_types['$bool_index'];' | |||
| echo 'const struct glsl_type *const glsl_int_type = & builtin_core_types['$int_index'];' | |||
| echo 'const struct glsl_type *const glsl_float_type = & builtin_core_types['$float_index'];' | |||
| echo '/*@}*/' | |||
| echo | |||
| echo '/** \name GLSL structures that have not been deprecated.' | |||
| echo ' */' | |||
| echo '/*@{*/' | |||
| gen_struct_field_header gl_DepthRangeParameters | |||
| gen_struct_field builtin_core_types 8 "near" | |||
| gen_struct_field builtin_core_types 8 "far" | |||
| gen_struct_field builtin_core_types 8 "diff" | |||
| gen_struct_field_footer | |||
| gen_header "structure" | |||
| gen_struct_type gl_DepthRangeParameters | |||
| gen_footer | |||
| echo '/*@}*/' | |||
| echo | |||
| echo '/** \name GLSL 1.00 / 1.10 structures that are deprecated in GLSL 1.30' | |||
| echo ' */' | |||
| echo '/*@{*/' | |||
| gen_struct_field_header gl_PointParameters | |||
| gen_struct_field builtin_core_types 8 "size" | |||
| gen_struct_field builtin_core_types 8 "sizeMin" | |||
| gen_struct_field builtin_core_types 8 "sizeMax" | |||
| gen_struct_field builtin_core_types 8 "fadeThresholdSize" | |||
| gen_struct_field builtin_core_types 8 "distanceConstantAttenuation" | |||
| gen_struct_field builtin_core_types 8 "distanceLinearAttenuation" | |||
| gen_struct_field builtin_core_types 8 "distanceQuadraticAttenuation" | |||
| gen_struct_field_footer | |||
| gen_struct_field_header gl_MaterialParameters | |||
| gen_struct_field builtin_core_types 11 "emission" | |||
| gen_struct_field builtin_core_types 11 "ambient" | |||
| gen_struct_field builtin_core_types 11 "diffuse" | |||
| gen_struct_field builtin_core_types 11 "specular" | |||
| gen_struct_field builtin_core_types 8 "shininess" | |||
| gen_struct_field_footer | |||
| gen_struct_field_header gl_LightSourceParameters | |||
| gen_struct_field builtin_core_types 11 "ambient" | |||
| gen_struct_field builtin_core_types 11 "diffuse" | |||
| gen_struct_field builtin_core_types 11 "specular" | |||
| gen_struct_field builtin_core_types 11 "position" | |||
| gen_struct_field builtin_core_types 11 "halfVector" | |||
| gen_struct_field builtin_core_types 10 "spotDirection" | |||
| gen_struct_field builtin_core_types 8 "spotExponent" | |||
| gen_struct_field builtin_core_types 8 "spotCutoff" | |||
| gen_struct_field builtin_core_types 8 "spotCosCutoff" | |||
| gen_struct_field builtin_core_types 8 "constantAttenuation" | |||
| gen_struct_field builtin_core_types 8 "linearAttenuation" | |||
| gen_struct_field builtin_core_types 8 "quadraticAttenuation" | |||
| gen_struct_field_footer | |||
| gen_struct_field_header gl_LightModelParameters | |||
| gen_struct_field builtin_core_types 11 "ambient" | |||
| gen_struct_field_footer | |||
| gen_struct_field_header gl_LightModelProducts | |||
| gen_struct_field builtin_core_types 11 "sceneColor" | |||
| gen_struct_field_footer | |||
| gen_struct_field_header gl_LightProducts | |||
| gen_struct_field builtin_core_types 11 "ambient" | |||
| gen_struct_field builtin_core_types 11 "diffuse" | |||
| gen_struct_field builtin_core_types 11 "specular" | |||
| gen_struct_field_footer | |||
| gen_struct_field_header gl_FogParameters | |||
| gen_struct_field builtin_core_types 11 "color" | |||
| gen_struct_field builtin_core_types 8 "density" | |||
| gen_struct_field builtin_core_types 8 "start" | |||
| gen_struct_field builtin_core_types 8 "end" | |||
| gen_struct_field builtin_core_types 8 "scalre" | |||
| gen_struct_field_footer | |||
| gen_header "110_deprecated_structure" | |||
| gen_struct_type gl_PointParameters | |||
| gen_struct_type gl_MaterialParameters | |||
| gen_struct_type gl_LightSourceParameters | |||
| gen_struct_type gl_LightModelParameters | |||
| gen_struct_type gl_LightModelProducts | |||
| gen_struct_type gl_LightProducts | |||
| gen_struct_type gl_FogParameters | |||
| gen_footer | |||
| echo '/*@}*/' | |||
| echo | |||
| echo '/** \name Types added in GLSL 1.20' | |||
| echo ' */' | |||
| echo '/*@{*/' | |||
| gen_header "120" | |||
| for i in 2 3 4; do | |||
| for j in 2 3 4; do | |||
| if [ $i -ne $j ]; then | |||
| gen_integral_type "mat${i}x${j}" "GLSL_TYPE_FLOAT" $i $j | |||
| fi | |||
| done | |||
| done | |||
| gen_footer | |||
| echo '/*@}*/' | |||
| echo | |||
| echo '/** \name Types added in GLSL 1.30' | |||
| echo ' */' | |||
| echo '/*@{*/' | |||
| gen_header "130" | |||
| index=0; | |||
| uint_index=$index | |||
| gen_integral_type "uint" "GLSL_TYPE_UINT" 0 0 | |||
| for i in 2 3 4; do | |||
| gen_integral_type "uvec$i" "GLSL_TYPE_UINT" $i 0 | |||
| done | |||
| echo | |||
| echo " /* 1D and 2D texture arrays */" | |||
| for i in "1D" "2D"; do | |||
| gen_sampler_type $i "GLSL_SAMPLER_DIM_$i" 0 1 "GLSL_TYPE_FLOAT" | |||
| gen_sampler_type $i "GLSL_SAMPLER_DIM_$i" 0 1 "GLSL_TYPE_INT" | |||
| gen_sampler_type $i "GLSL_SAMPLER_DIM_$i" 0 1 "GLSL_TYPE_UINT" | |||
| gen_sampler_type $i "GLSL_SAMPLER_DIM_$i" 1 1 "GLSL_TYPE_FLOAT" | |||
| done | |||
| echo | |||
| echo " /* cube shadow samplers */" | |||
| gen_sampler_type "Cube" "GLSL_SAMPLER_DIM_CUBE" 1 0 "GLSL_TYPE_FLOAT" | |||
| echo | |||
| echo " /* signed and unsigned integer samplers */" | |||
| for i in "1D" "2D" "3D"; do | |||
| gen_sampler_type $i "GLSL_SAMPLER_DIM_$i" 0 0 "GLSL_TYPE_INT" | |||
| gen_sampler_type $i "GLSL_SAMPLER_DIM_$i" 0 0 "GLSL_TYPE_UINT" | |||
| done | |||
| gen_sampler_type "Cube" "GLSL_SAMPLER_DIM_CUBE" 0 0 "GLSL_TYPE_INT" | |||
| gen_sampler_type "Cube" "GLSL_SAMPLER_DIM_CUBE" 0 0 "GLSL_TYPE_UINT" | |||
| gen_footer | |||
| echo '' | |||
| echo 'const struct glsl_type *const glsl_uint_type = & builtin_130_types['$uint_index'];' | |||
| echo '/*@}*/' | |||
| echo | |||
| echo '/** \name Sampler types added by GL_EXT_texture_buffer_object' | |||
| echo ' */' | |||
| echo '/*@{*/' | |||
| gen_header "EXT_texture_buffer_object" | |||
| gen_sampler_type "Buffer" "GLSL_SAMPLER_DIM_BUF" 0 0 "GLSL_TYPE_FLOAT" | |||
| gen_sampler_type "Buffer" "GLSL_SAMPLER_DIM_BUF" 0 0 "GLSL_TYPE_INT" | |||
| gen_sampler_type "Buffer" "GLSL_SAMPLER_DIM_BUF" 0 0 "GLSL_TYPE_UINT" | |||
| gen_footer | |||
| echo '/*@}*/' | |||
| @@ -0,0 +1,273 @@ | |||
| %{ | |||
| /* | |||
| * Copyright © 2008, 2009 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #include "ast.h" | |||
| #include "glsl_parser_extras.h" | |||
| #include "glsl_parser.tab.h" | |||
| #include "symbol_table.h" | |||
| #define YY_USER_ACTION \ | |||
| do { \ | |||
| yylloc->source = 0; \ | |||
| yylloc->first_column = yycolumn + 1; \ | |||
| yylloc->first_line = yylineno + 1; \ | |||
| yycolumn += yyleng; \ | |||
| } while(0); | |||
| %} | |||
| %option bison-bridge bison-locations reentrant noyywrap | |||
| %option never-interactive | |||
| %option prefix="_mesa_glsl_" | |||
| %option extra-type="struct _mesa_glsl_parse_state *" | |||
| %option stack | |||
| %x PP COMMENT | |||
| %% | |||
| "/*" { yy_push_state(COMMENT, yyscanner); } | |||
| <COMMENT>[^*\n]* | |||
| <COMMENT>[^*\n]*\n { yylineno++; yycolumn = 0; } | |||
| <COMMENT>"*"+[^*/\n]* | |||
| <COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; } | |||
| <COMMENT>"*"+"/" { yy_pop_state(yyscanner); } | |||
| \/\/.*\n { yylineno++; yycolumn = 0; } | |||
| [ \r\t]+ ; | |||
| /* Preprocessor tokens. */ | |||
| ^[ \t]*#[ \t]*$ ; | |||
| ^[ \t]*#[ \t]*version { BEGIN PP; return VERSION; } | |||
| ^[ \t]*#[ \t]*extension { BEGIN PP; return EXTENSION; } | |||
| ^[ \t]*#[ \t]*line { BEGIN PP; return LINE; } | |||
| ^[ \t]*#[ \t]*pragma { BEGIN PP; return PRAGMA; } | |||
| <PP>: return COLON; | |||
| <PP>[_a-zA-Z][_a-zA-Z0-9]* { | |||
| yylval->identifier = strdup(yytext); | |||
| return IDENTIFIER; | |||
| } | |||
| <PP>[1-9][0-9]* { | |||
| yylval->n = strtol(yytext, NULL, 10); | |||
| return INTCONSTANT; | |||
| } | |||
| <PP>\n { BEGIN 0; yylineno++; yycolumn = 0; return EOL; } | |||
| \n { yylineno++; yycolumn = 0; } | |||
| attribute return ATTRIBUTE; | |||
| const return CONST; | |||
| bool return BOOL; | |||
| float return FLOAT; | |||
| int return INT; | |||
| break return BREAK; | |||
| continue return CONTINUE; | |||
| do return DO; | |||
| while return WHILE; | |||
| else return ELSE; | |||
| for return FOR; | |||
| if return IF; | |||
| discard return DISCARD; | |||
| return return RETURN; | |||
| bvec2 return BVEC2; | |||
| bvec3 return BVEC3; | |||
| bvec4 return BVEC4; | |||
| ivec2 return IVEC2; | |||
| ivec3 return IVEC3; | |||
| ivec4 return IVEC4; | |||
| vec2 return VEC2; | |||
| vec3 return VEC3; | |||
| vec4 return VEC4; | |||
| mat2 return MAT2; | |||
| mat3 return MAT3; | |||
| mat4 return MAT4; | |||
| mat2x2 return MAT2X2; | |||
| mat2x3 return MAT2X3; | |||
| mat2x4 return MAT2X4; | |||
| mat3x2 return MAT3X2; | |||
| mat3x3 return MAT3X3; | |||
| mat3x4 return MAT3X4; | |||
| mat4x2 return MAT4X2; | |||
| mat4x3 return MAT4X3; | |||
| mat4x4 return MAT4X4; | |||
| in return IN; | |||
| out return OUT; | |||
| inout return INOUT; | |||
| uniform return UNIFORM; | |||
| varying return VARYING; | |||
| centroid return CENTROID; | |||
| invariant return INVARIANT; | |||
| sampler1D return SAMPLER1D; | |||
| sampler2D return SAMPLER2D; | |||
| sampler3D return SAMPLER3D; | |||
| samplerCube return SAMPLERCUBE; | |||
| sampler1DShadow return SAMPLER1DSHADOW; | |||
| sampler2DShadow return SAMPLER2DSHADOW; | |||
| struct return STRUCT; | |||
| void return VOID; | |||
| \+\+ return INC_OP; | |||
| -- return DEC_OP; | |||
| \<= return LE_OP; | |||
| >= return GE_OP; | |||
| == return EQ_OP; | |||
| != return NE_OP; | |||
| && return AND_OP; | |||
| \|\| return OR_OP; | |||
| "^^" return XOR_OP; | |||
| \*= return MUL_ASSIGN; | |||
| \/= return DIV_ASSIGN; | |||
| \+= return ADD_ASSIGN; | |||
| \%= return MOD_ASSIGN; | |||
| \<\<= return LEFT_ASSIGN; | |||
| >>= return RIGHT_ASSIGN; | |||
| &= return AND_ASSIGN; | |||
| ^= return XOR_ASSIGN; | |||
| \|= return OR_ASSIGN; | |||
| -= return SUB_ASSIGN; | |||
| [1-9][0-9]* { | |||
| yylval->n = strtol(yytext, NULL, 10); | |||
| return INTCONSTANT; | |||
| } | |||
| 0[xX][0-9a-fA-F]+ { | |||
| yylval->n = strtol(yytext + 2, NULL, 16); | |||
| return INTCONSTANT; | |||
| } | |||
| 0[0-7]* { | |||
| yylval->n = strtol(yytext + 2, NULL, 8); | |||
| return INTCONSTANT; | |||
| } | |||
| [0-9]+\.[0-9]+([eE][+-]?[0-9]+)?[fF]? { | |||
| yylval->real = strtod(yytext, NULL); | |||
| return FLOATCONSTANT; | |||
| } | |||
| \.[0-9]+([eE][+-]?[0-9]+)?[fF]? { | |||
| yylval->real = strtod(yytext, NULL); | |||
| return FLOATCONSTANT; | |||
| } | |||
| [0-9]+\.([eE][+-]?[0-9]+)?[fF]? { | |||
| yylval->real = strtod(yytext, NULL); | |||
| return FLOATCONSTANT; | |||
| } | |||
| [0-9]+[eE][+-]?[0-9]+[fF]? { | |||
| yylval->real = strtod(yytext, NULL); | |||
| return FLOATCONSTANT; | |||
| } | |||
| true { | |||
| yylval->n = 1; | |||
| return BOOLCONSTANT; | |||
| } | |||
| false { | |||
| yylval->n = 0; | |||
| return BOOLCONSTANT; | |||
| } | |||
| /* Reserved words in GLSL 1.10. */ | |||
| asm return ASM; | |||
| class return CLASS; | |||
| union return UNION; | |||
| enum return ENUM; | |||
| typedef return TYPEDEF; | |||
| template return TEMPLATE; | |||
| this return THIS; | |||
| packed return PACKED; | |||
| goto return GOTO; | |||
| switch return SWITCH; | |||
| default return DEFAULT; | |||
| inline return INLINE; | |||
| noinline return NOINLINE; | |||
| volatile return VOLATILE; | |||
| public return PUBLIC; | |||
| static return STATIC; | |||
| extern return EXTERN; | |||
| external return EXTERNAL; | |||
| interface return INTERFACE; | |||
| long return LONG; | |||
| short return SHORT; | |||
| double return DOUBLE; | |||
| half return HALF; | |||
| fixed return FIXED; | |||
| unsigned return UNSIGNED; | |||
| input return INPUT; | |||
| output return OUTPUT; | |||
| hvec2 return HVEC2; | |||
| hvec3 return HVEC3; | |||
| hvec4 return HVEC4; | |||
| dvec2 return DVEC2; | |||
| dvec3 return DVEC3; | |||
| dvec4 return DVEC4; | |||
| fvec2 return FVEC2; | |||
| fvec3 return FVEC3; | |||
| fvec4 return FVEC4; | |||
| sampler2DRect return SAMPLER2DRECT; | |||
| sampler3DRect return SAMPLER3DRECT; | |||
| sampler2DRectShadow return SAMPLER2DRECTSHADOW; | |||
| sizeof return SIZEOF; | |||
| cast return CAST; | |||
| namespace return NAMESPACE; | |||
| using return USING; | |||
| /* Additional reserved words in GLSL 1.20. */ | |||
| lowp return LOWP; | |||
| mediump return MEDIUMP; | |||
| highp return HIGHP; | |||
| precision return PRECISION; | |||
| [_a-zA-Z][_a-zA-Z0-9]* { | |||
| yylval->identifier = strdup(yytext); | |||
| if (_mesa_symbol_table_find_symbol(yyextra->symbols, | |||
| 0, | |||
| yylval->identifier)) | |||
| return TYPE_NAME; | |||
| else | |||
| return IDENTIFIER; | |||
| } | |||
| . { return yytext[0]; } | |||
| %% | |||
| void | |||
| _mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, | |||
| const char *string, size_t len) | |||
| { | |||
| yylex_init_extra(state, & state->scanner); | |||
| yy_scan_bytes(string, len, state->scanner); | |||
| } | |||
| void | |||
| _mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state) | |||
| { | |||
| yylex_destroy(state->scanner); | |||
| } | |||
| @@ -0,0 +1,771 @@ | |||
| /* | |||
| * Copyright © 2008, 2009 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #include <stdio.h> | |||
| #include <stdarg.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <assert.h> | |||
| #include <sys/types.h> | |||
| #include <sys/stat.h> | |||
| #include <fcntl.h> | |||
| #include <unistd.h> | |||
| #include "ast.h" | |||
| #include "glsl_parser_extras.h" | |||
| #include "glsl_parser.tab.h" | |||
| #include "symbol_table.h" | |||
| void | |||
| _mesa_glsl_error(YYLTYPE *locp, void *state, const char *fmt, ...) | |||
| { | |||
| char buf[1024]; | |||
| int len; | |||
| va_list ap; | |||
| (void) state; | |||
| len = snprintf(buf, sizeof(buf), "%u:%u(%u): error: ", | |||
| locp->source, locp->first_line, locp->first_column); | |||
| va_start(ap, fmt); | |||
| vsnprintf(buf + len, sizeof(buf) - len, fmt, ap); | |||
| va_end(ap); | |||
| printf("%s\n", buf); | |||
| } | |||
| ast_node::~ast_node() | |||
| { | |||
| /* empty */ | |||
| } | |||
| void | |||
| _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q) | |||
| { | |||
| if (q->constant) | |||
| printf("const "); | |||
| if (q->invariant) | |||
| printf("invariant "); | |||
| if (q->attribute) | |||
| printf("attribute "); | |||
| if (q->varying) | |||
| printf("varying "); | |||
| if (q->in && q->out) | |||
| printf("inout "); | |||
| else { | |||
| if (q->in) | |||
| printf("in "); | |||
| if (q->out) | |||
| printf("out "); | |||
| } | |||
| if (q->centroid) | |||
| printf("centroid "); | |||
| if (q->uniform) | |||
| printf("uniform "); | |||
| if (q->smooth) | |||
| printf("smooth "); | |||
| if (q->flat) | |||
| printf("flat "); | |||
| if (q->noperspective) | |||
| printf("noperspective "); | |||
| } | |||
| void | |||
| ast_node::print(void) const | |||
| { | |||
| printf("node_%d ", type); | |||
| } | |||
| ast_node::ast_node(void) | |||
| { | |||
| // make_empty_list(& ast->node); | |||
| } | |||
| void | |||
| ast_type_specifier::print(void) const | |||
| { | |||
| switch (type_specifier) { | |||
| case ast_void: printf("void "); break; | |||
| case ast_float: printf("float "); break; | |||
| case ast_int: printf("int "); break; | |||
| case ast_uint: printf("uint "); break; | |||
| case ast_bool: printf("bool "); break; | |||
| case ast_vec2: printf("vec2 "); break; | |||
| case ast_vec3: printf("vec3 "); break; | |||
| case ast_vec4: printf("vec4 "); break; | |||
| case ast_bvec2: printf("bvec2 "); break; | |||
| case ast_bvec3: printf("bvec3 "); break; | |||
| case ast_bvec4: printf("bvec4 "); break; | |||
| case ast_ivec2: printf("ivec2 "); break; | |||
| case ast_ivec3: printf("ivec3 "); break; | |||
| case ast_ivec4: printf("ivec4 "); break; | |||
| case ast_uvec2: printf("uvec2 "); break; | |||
| case ast_uvec3: printf("uvec3 "); break; | |||
| case ast_uvec4: printf("uvec4 "); break; | |||
| case ast_mat2: printf("mat2 "); break; | |||
| case ast_mat2x3: printf("mat2x3 "); break; | |||
| case ast_mat2x4: printf("mat2x4 "); break; | |||
| case ast_mat3x2: printf("mat3x2 "); break; | |||
| case ast_mat3: printf("mat3 "); break; | |||
| case ast_mat3x4: printf("mat3x4 "); break; | |||
| case ast_mat4x2: printf("mat4x2 "); break; | |||
| case ast_mat4x3: printf("mat4x3 "); break; | |||
| case ast_mat4: printf("mat4 "); break; | |||
| case ast_sampler1d: printf("sampler1d "); break; | |||
| case ast_sampler2d: printf("sampler2d "); break; | |||
| case ast_sampler3d: printf("sampler3d "); break; | |||
| case ast_samplercube: printf("samplercube "); break; | |||
| case ast_sampler1dshadow: printf("sampler1dshadow "); break; | |||
| case ast_sampler2dshadow: printf("sampler2dshadow "); break; | |||
| case ast_samplercubeshadow: printf("samplercubeshadow "); break; | |||
| case ast_sampler1darray: printf("sampler1darray "); break; | |||
| case ast_sampler2darray: printf("sampler2darray "); break; | |||
| case ast_sampler1darrayshadow: printf("sampler1darrayshadow "); break; | |||
| case ast_sampler2darrayshadow: printf("sampler2darrayshadow "); break; | |||
| case ast_isampler1d: printf("isampler1d "); break; | |||
| case ast_isampler2d: printf("isampler2d "); break; | |||
| case ast_isampler3d: printf("isampler3d "); break; | |||
| case ast_isamplercube: printf("isamplercube "); break; | |||
| case ast_isampler1darray: printf("isampler1darray "); break; | |||
| case ast_isampler2darray: printf("isampler2darray "); break; | |||
| case ast_usampler1d: printf("usampler1d "); break; | |||
| case ast_usampler2d: printf("usampler2d "); break; | |||
| case ast_usampler3d: printf("usampler3d "); break; | |||
| case ast_usamplercube: printf("usamplercube "); break; | |||
| case ast_usampler1darray: printf("usampler1darray "); break; | |||
| case ast_usampler2darray: printf("usampler2darray "); break; | |||
| case ast_struct: | |||
| structure->print(); | |||
| break; | |||
| case ast_type_name: printf("%s ", type_name); break; | |||
| } | |||
| if (is_array) { | |||
| printf("[ "); | |||
| if (array_size) { | |||
| array_size->print(); | |||
| } | |||
| printf("] "); | |||
| } | |||
| } | |||
| static void | |||
| ast_opt_array_size_print(bool is_array, const ast_expression *array_size) | |||
| { | |||
| if (is_array) { | |||
| printf("[ "); | |||
| if (array_size) | |||
| array_size->print(); | |||
| printf("] "); | |||
| } | |||
| } | |||
| ast_type_specifier::ast_type_specifier(int specifier) | |||
| { | |||
| type_specifier = ast_types(specifier); | |||
| } | |||
| void | |||
| ast_compound_statement::print(void) const | |||
| { | |||
| const struct simple_node *ptr; | |||
| printf("{\n"); | |||
| foreach(ptr, & statements) { | |||
| _mesa_ast_print(ptr); | |||
| } | |||
| printf("}\n"); | |||
| } | |||
| ast_compound_statement::ast_compound_statement(int new_scope, | |||
| ast_node *statements) | |||
| { | |||
| this->new_scope = new_scope; | |||
| make_empty_list(& this->statements); | |||
| if (statements != NULL) { | |||
| /* This seems odd, but it works. The simple_list is, | |||
| * basically, a circular list. insert_at_tail adds | |||
| * the specified node to the list before the current | |||
| * head. | |||
| */ | |||
| insert_at_tail((struct simple_node *) statements, | |||
| & this->statements); | |||
| } | |||
| } | |||
| void | |||
| ast_expression::print(void) const | |||
| { | |||
| static const char *const operators[] = { | |||
| "=", | |||
| "+", | |||
| "-", | |||
| "+", | |||
| "-", | |||
| "*", | |||
| "/", | |||
| "%", | |||
| "<<", | |||
| ">>", | |||
| "<", | |||
| ">", | |||
| "<=", | |||
| ">=", | |||
| "==", | |||
| "!=", | |||
| "&", | |||
| "^", | |||
| "|", | |||
| "~", | |||
| "&&", | |||
| "^^", | |||
| "!", | |||
| "*=", | |||
| "/=", | |||
| "%=", | |||
| "+=", | |||
| "-=", | |||
| "<<=", | |||
| ">>=", | |||
| "&=", | |||
| "^=", | |||
| "|=", | |||
| "?:", | |||
| "++", | |||
| "--", | |||
| "++", | |||
| "--", | |||
| ".", | |||
| }; | |||
| switch (oper) { | |||
| case ast_assign: | |||
| case ast_add: | |||
| case ast_sub: | |||
| case ast_mul: | |||
| case ast_div: | |||
| case ast_mod: | |||
| case ast_lshift: | |||
| case ast_rshift: | |||
| case ast_less: | |||
| case ast_greater: | |||
| case ast_lequal: | |||
| case ast_gequal: | |||
| case ast_equal: | |||
| case ast_nequal: | |||
| case ast_bit_and: | |||
| case ast_bit_xor: | |||
| case ast_bit_or: | |||
| case ast_logic_and: | |||
| case ast_logic_xor: | |||
| case ast_logic_or: | |||
| case ast_mul_assign: | |||
| case ast_div_assign: | |||
| case ast_mod_assign: | |||
| case ast_add_assign: | |||
| case ast_sub_assign: | |||
| case ast_ls_assign: | |||
| case ast_rs_assign: | |||
| case ast_and_assign: | |||
| case ast_xor_assign: | |||
| case ast_or_assign: | |||
| subexpressions[0]->print(); | |||
| printf("%s ", operators[oper]); | |||
| subexpressions[1]->print(); | |||
| break; | |||
| case ast_field_selection: | |||
| subexpressions[0]->print(); | |||
| printf(". %s ", primary_expression.identifier); | |||
| break; | |||
| case ast_plus: | |||
| case ast_neg: | |||
| case ast_bit_not: | |||
| case ast_logic_not: | |||
| case ast_pre_inc: | |||
| case ast_pre_dec: | |||
| printf("%s ", operators[oper]); | |||
| subexpressions[0]->print(); | |||
| break; | |||
| case ast_post_inc: | |||
| case ast_post_dec: | |||
| subexpressions[0]->print(); | |||
| printf("%s ", operators[oper]); | |||
| break; | |||
| case ast_conditional: | |||
| subexpressions[0]->print(); | |||
| printf("? "); | |||
| subexpressions[1]->print(); | |||
| printf(": "); | |||
| subexpressions[1]->print(); | |||
| break; | |||
| case ast_array_index: | |||
| subexpressions[0]->print(); | |||
| printf("[ "); | |||
| subexpressions[1]->print(); | |||
| printf("] "); | |||
| break; | |||
| case ast_function_call: { | |||
| ast_expression *parameters = subexpressions[1]; | |||
| subexpressions[0]->print(); | |||
| printf("( "); | |||
| if (parameters != NULL) { | |||
| struct simple_node *ptr; | |||
| parameters->print(); | |||
| foreach (ptr, (struct simple_node *) parameters) { | |||
| printf(", "); | |||
| _mesa_ast_print(ptr); | |||
| } | |||
| } | |||
| printf(") "); | |||
| break; | |||
| } | |||
| case ast_identifier: | |||
| printf("%s ", primary_expression.identifier); | |||
| break; | |||
| case ast_int_constant: | |||
| printf("%d ", primary_expression.int_constant); | |||
| break; | |||
| case ast_uint_constant: | |||
| printf("%u ", primary_expression.uint_constant); | |||
| break; | |||
| case ast_float_constant: | |||
| printf("%f ", primary_expression.float_constant); | |||
| break; | |||
| case ast_bool_constant: | |||
| printf("%s ", | |||
| primary_expression.bool_constant | |||
| ? "true" : "false"); | |||
| break; | |||
| case ast_sequence: { | |||
| struct simple_node *ptr; | |||
| struct simple_node *const head = first_elem(& expressions); | |||
| printf("( "); | |||
| foreach (ptr, & expressions) { | |||
| if (ptr != head) | |||
| printf(", "); | |||
| _mesa_ast_print(ptr); | |||
| } | |||
| printf(") "); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| ast_expression::ast_expression(int oper, | |||
| ast_expression *ex0, | |||
| ast_expression *ex1, | |||
| ast_expression *ex2) | |||
| { | |||
| this->oper = ast_operators(oper); | |||
| this->subexpressions[0] = ex0; | |||
| this->subexpressions[1] = ex1; | |||
| this->subexpressions[2] = ex2; | |||
| make_empty_list(& expressions); | |||
| } | |||
| void | |||
| ast_expression_statement::print(void) const | |||
| { | |||
| if (expression) | |||
| expression->print(); | |||
| printf("; "); | |||
| } | |||
| ast_expression_statement::ast_expression_statement(ast_expression *ex) : | |||
| expression(ex) | |||
| { | |||
| /* empty */ | |||
| } | |||
| void | |||
| ast_function::print(void) const | |||
| { | |||
| struct simple_node *ptr; | |||
| return_type->print(); | |||
| printf(" %s (", identifier); | |||
| foreach(ptr, & parameters) { | |||
| _mesa_ast_print(ptr); | |||
| } | |||
| printf(")"); | |||
| } | |||
| ast_function::ast_function(void) | |||
| { | |||
| make_empty_list(& parameters); | |||
| } | |||
| void | |||
| ast_fully_specified_type::print(void) const | |||
| { | |||
| _mesa_ast_type_qualifier_print(& qualifier); | |||
| specifier->print(); | |||
| } | |||
| void | |||
| ast_parameter_declarator::print(void) const | |||
| { | |||
| type->print(); | |||
| if (identifier) | |||
| printf("%s ", identifier); | |||
| ast_opt_array_size_print(is_array, array_size); | |||
| } | |||
| void | |||
| ast_function_definition::print(void) const | |||
| { | |||
| prototype->print(); | |||
| body->print(); | |||
| } | |||
| void | |||
| ast_declaration::print(void) const | |||
| { | |||
| printf("%s ", identifier); | |||
| ast_opt_array_size_print(is_array, array_size); | |||
| if (initializer) { | |||
| printf("= "); | |||
| initializer->print(); | |||
| } | |||
| } | |||
| ast_declaration::ast_declaration(char *identifier, int is_array, | |||
| ast_expression *array_size, | |||
| ast_expression *initializer) | |||
| { | |||
| this->identifier = identifier; | |||
| this->is_array = is_array; | |||
| this->array_size = array_size; | |||
| this->initializer = initializer; | |||
| } | |||
| void | |||
| ast_declarator_list::print(void) const | |||
| { | |||
| struct simple_node *head; | |||
| struct simple_node *ptr; | |||
| assert(type || invariant); | |||
| if (type) | |||
| type->print(); | |||
| else | |||
| printf("invariant "); | |||
| head = first_elem(& declarations); | |||
| foreach (ptr, & declarations) { | |||
| if (ptr != head) | |||
| printf(", "); | |||
| _mesa_ast_print(ptr); | |||
| } | |||
| printf("; "); | |||
| } | |||
| ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type) | |||
| { | |||
| this->type = type; | |||
| make_empty_list(& this->declarations); | |||
| } | |||
| void | |||
| ast_jump_statement::print(void) const | |||
| { | |||
| switch (mode) { | |||
| case ast_continue: | |||
| printf("continue; "); | |||
| break; | |||
| case ast_break: | |||
| printf("break; "); | |||
| break; | |||
| case ast_return: | |||
| printf("return "); | |||
| if (opt_return_value) | |||
| opt_return_value->print(); | |||
| printf("; "); | |||
| break; | |||
| case ast_discard: | |||
| printf("discard; "); | |||
| break; | |||
| } | |||
| } | |||
| ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value) | |||
| { | |||
| this->mode = ast_jump_modes(mode); | |||
| if (mode == ast_return) | |||
| opt_return_value = return_value; | |||
| } | |||
| void | |||
| ast_selection_statement::print(void) const | |||
| { | |||
| printf("if ( "); | |||
| condition->print(); | |||
| printf(") "); | |||
| then_statement->print(); | |||
| if (else_statement) { | |||
| printf("else "); | |||
| else_statement->print(); | |||
| } | |||
| } | |||
| ast_selection_statement::ast_selection_statement(ast_expression *condition, | |||
| ast_node *then_statement, | |||
| ast_node *else_statement) | |||
| { | |||
| this->condition = condition; | |||
| this->then_statement = then_statement; | |||
| this->else_statement = else_statement; | |||
| } | |||
| void | |||
| ast_iteration_statement::print(void) const | |||
| { | |||
| switch (mode) { | |||
| case ast_for: | |||
| printf("for( "); | |||
| if (init_statement) | |||
| init_statement->print(); | |||
| printf("; "); | |||
| if (condition) | |||
| condition->print(); | |||
| printf("; "); | |||
| if (rest_expression) | |||
| rest_expression->print(); | |||
| printf(") "); | |||
| body->print(); | |||
| break; | |||
| case ast_while: | |||
| printf("while ( "); | |||
| if (condition) | |||
| condition->print(); | |||
| printf(") "); | |||
| body->print(); | |||
| break; | |||
| case ast_do_while: | |||
| printf("do "); | |||
| body->print(); | |||
| printf("while ( "); | |||
| if (condition) | |||
| condition->print(); | |||
| printf("); "); | |||
| break; | |||
| } | |||
| } | |||
| ast_iteration_statement::ast_iteration_statement(int mode, | |||
| ast_node *init, | |||
| ast_node *condition, | |||
| ast_expression *rest_expression, | |||
| ast_node *body) | |||
| { | |||
| this->mode = ast_iteration_modes(mode); | |||
| this->init_statement = init; | |||
| this->condition = condition; | |||
| this->rest_expression = rest_expression; | |||
| this->body = body; | |||
| } | |||
| void | |||
| ast_struct_specifier::print(void) const | |||
| { | |||
| struct simple_node *ptr; | |||
| printf("struct %s { ", name); | |||
| foreach (ptr, & declarations) { | |||
| _mesa_ast_print(ptr); | |||
| } | |||
| printf("} "); | |||
| } | |||
| ast_struct_specifier::ast_struct_specifier(char *identifier, | |||
| ast_node *declarator_list) | |||
| { | |||
| name = identifier; | |||
| /* This seems odd, but it works. The simple_list is, | |||
| * basically, a circular list. insert_at_tail adds | |||
| * the specified node to the list before the current | |||
| * head. | |||
| */ | |||
| insert_at_tail((struct simple_node *) declarator_list, | |||
| & declarations); | |||
| } | |||
| static char * | |||
| load_text_file(const char *file_name, size_t *size) | |||
| { | |||
| char *text = NULL; | |||
| struct stat st; | |||
| ssize_t total_read = 0; | |||
| int fd = open(file_name, O_RDONLY); | |||
| *size = 0; | |||
| if (fd < 0) { | |||
| return NULL; | |||
| } | |||
| if (fstat(fd, & st) == 0) { | |||
| text = (char *) malloc(st.st_size + 1); | |||
| if (text != NULL) { | |||
| do { | |||
| ssize_t bytes = read(fd, text + total_read, | |||
| st.st_size - total_read); | |||
| if (bytes < 0) { | |||
| free(text); | |||
| text = NULL; | |||
| break; | |||
| } | |||
| if (bytes == 0) { | |||
| break; | |||
| } | |||
| total_read += bytes; | |||
| } while (total_read < st.st_size); | |||
| text[total_read] = '\0'; | |||
| *size = total_read; | |||
| } | |||
| } | |||
| close(fd); | |||
| return text; | |||
| } | |||
| int | |||
| main(int argc, char **argv) | |||
| { | |||
| struct _mesa_glsl_parse_state state; | |||
| char *shader; | |||
| size_t shader_len; | |||
| struct simple_node *ptr; | |||
| struct simple_node instructions; | |||
| (void) argc; | |||
| shader = load_text_file(argv[1], & shader_len); | |||
| state.scanner = NULL; | |||
| make_empty_list(& state.translation_unit); | |||
| state.symbols = _mesa_symbol_table_ctor(); | |||
| _mesa_glsl_lexer_ctor(& state, shader, shader_len); | |||
| _mesa_glsl_parse(& state); | |||
| _mesa_glsl_lexer_dtor(& state); | |||
| foreach (ptr, & state.translation_unit) { | |||
| _mesa_ast_print(ptr); | |||
| } | |||
| #if 0 | |||
| make_empty_list(& instructions); | |||
| foreach (ptr, & state.translation_unit) { | |||
| _mesa_ast_to_hir(ptr, &instructions, &state); | |||
| } | |||
| #endif | |||
| _mesa_symbol_table_dtor(state.symbols); | |||
| return 0; | |||
| } | |||
| @@ -0,0 +1,68 @@ | |||
| /* | |||
| * Copyright © 2010 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #pragma once | |||
| #ifndef GLSL_PARSER_EXTRAS_H | |||
| #define GLSL_PARSER_EXTRAS_H | |||
| #include "main/simple_list.h" | |||
| enum _mesa_glsl_parser_targets { | |||
| vertex_shader, | |||
| geometry_shader, | |||
| fragment_shader | |||
| }; | |||
| struct _mesa_glsl_parse_state { | |||
| void *scanner; | |||
| struct simple_node translation_unit; | |||
| struct _mesa_symbol_table *symbols; | |||
| unsigned language_version; | |||
| enum _mesa_glsl_parser_targets target; | |||
| }; | |||
| typedef struct YYLTYPE { | |||
| int first_line; | |||
| int first_column; | |||
| int last_line; | |||
| int last_column; | |||
| unsigned source; | |||
| } YYLTYPE; | |||
| # define YYLTYPE_IS_DECLARED 1 | |||
| # define YYLTYPE_IS_TRIVIAL 1 | |||
| extern void _mesa_glsl_error(YYLTYPE *locp, void *state, const char *fmt, ...); | |||
| extern void _mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, | |||
| const char *string, size_t len); | |||
| extern void _mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state); | |||
| union YYSTYPE; | |||
| extern int _mesa_glsl_lex(union YYSTYPE *yylval, YYLTYPE *yylloc, | |||
| void *scanner); | |||
| extern int _mesa_glsl_parse(struct _mesa_glsl_parse_state *); | |||
| #endif /* GLSL_PARSER_EXTRAS_H */ | |||
| @@ -0,0 +1,159 @@ | |||
| /* | |||
| * Copyright © 2009 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #include <stdlib.h> | |||
| #include "symbol_table.h" | |||
| #include "glsl_parser_extras.h" | |||
| #include "glsl_types.h" | |||
| #include "builtin_types.h" | |||
| struct glsl_type * | |||
| _mesa_glsl_array_type_ctor(struct glsl_type *base, unsigned length, | |||
| const char *name) | |||
| { | |||
| struct glsl_type *type = calloc(1, sizeof(*type)); | |||
| type->base_type = GLSL_TYPE_ARRAY; | |||
| type->name = name; | |||
| type->length = length; | |||
| type->fields.array = base; | |||
| return type; | |||
| } | |||
| static void | |||
| add_types_to_symbol_table(struct _mesa_symbol_table *symtab, | |||
| const struct glsl_type *types, | |||
| unsigned num_types) | |||
| { | |||
| unsigned i; | |||
| for (i = 0; i < num_types; i++) { | |||
| _mesa_symbol_table_add_symbol(symtab, 0, types[i].name, | |||
| (void *) & types[i]); | |||
| } | |||
| } | |||
| static void | |||
| generate_110_types(struct _mesa_symbol_table *symtab) | |||
| { | |||
| add_types_to_symbol_table(symtab, builtin_core_types, | |||
| Elements(builtin_core_types)); | |||
| add_types_to_symbol_table(symtab, builtin_structure_types, | |||
| Elements(builtin_structure_types)); | |||
| add_types_to_symbol_table(symtab, builtin_110_deprecated_structure_types, | |||
| Elements(builtin_110_deprecated_structure_types)); | |||
| } | |||
| static void | |||
| generate_120_types(struct _mesa_symbol_table *symtab) | |||
| { | |||
| generate_110_types(symtab); | |||
| add_types_to_symbol_table(symtab, builtin_120_types, | |||
| Elements(builtin_120_types)); | |||
| } | |||
| static void | |||
| generate_130_types(struct _mesa_symbol_table *symtab) | |||
| { | |||
| generate_120_types(symtab); | |||
| add_types_to_symbol_table(symtab, builtin_130_types, | |||
| Elements(builtin_130_types)); | |||
| } | |||
| void | |||
| _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state) | |||
| { | |||
| switch (state->language_version) { | |||
| case 110: | |||
| generate_110_types(state->symbols); | |||
| break; | |||
| case 120: | |||
| generate_120_types(state->symbols); | |||
| break; | |||
| case 130: | |||
| generate_130_types(state->symbols); | |||
| break; | |||
| default: | |||
| /* error */ | |||
| break; | |||
| } | |||
| } | |||
| const struct glsl_type * | |||
| _mesa_glsl_get_vector_type(unsigned base_type, unsigned vector_length) | |||
| { | |||
| switch (base_type) { | |||
| case GLSL_TYPE_UINT: | |||
| switch (vector_length) { | |||
| case 1: | |||
| case 2: | |||
| case 3: | |||
| case 4: | |||
| return glsl_uint_type + (vector_length - 1); | |||
| default: | |||
| return glsl_error_type; | |||
| } | |||
| case GLSL_TYPE_INT: | |||
| switch (vector_length) { | |||
| case 1: | |||
| case 2: | |||
| case 3: | |||
| case 4: | |||
| return glsl_int_type + (vector_length - 1); | |||
| default: | |||
| return glsl_error_type; | |||
| } | |||
| case GLSL_TYPE_FLOAT: | |||
| switch (vector_length) { | |||
| case 1: | |||
| case 2: | |||
| case 3: | |||
| case 4: | |||
| return glsl_float_type + (vector_length - 1); | |||
| default: | |||
| return glsl_error_type; | |||
| } | |||
| case GLSL_TYPE_BOOL: | |||
| switch (vector_length) { | |||
| case 1: | |||
| case 2: | |||
| case 3: | |||
| case 4: | |||
| return glsl_bool_type + (vector_length - 1); | |||
| default: | |||
| return glsl_error_type; | |||
| } | |||
| default: | |||
| return glsl_error_type; | |||
| } | |||
| } | |||
| @@ -0,0 +1,141 @@ | |||
| /* | |||
| * Copyright © 2009 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #pragma once | |||
| #ifndef GLSL_TYPES_H | |||
| #define GLSL_TYPES_H | |||
| #define GLSL_TYPE_UINT 0 | |||
| #define GLSL_TYPE_INT 1 | |||
| #define GLSL_TYPE_FLOAT 2 | |||
| #define GLSL_TYPE_BOOL 3 | |||
| #define GLSL_TYPE_SAMPLER 4 | |||
| #define GLSL_TYPE_STRUCT 5 | |||
| #define GLSL_TYPE_ARRAY 6 | |||
| #define GLSL_TYPE_FUNCTION 7 | |||
| #define GLSL_TYPE_VOID 8 | |||
| #define GLSL_TYPE_ERROR 9 | |||
| #define is_numeric_base_type(b) \ | |||
| (((b) >= GLSL_TYPE_UINT) && ((b) <= GLSL_TYPE_FLOAT)) | |||
| #define is_integer_base_type(b) \ | |||
| (((b) == GLSL_TYPE_UINT) || ((b) == GLSL_TYPE_INT)) | |||
| #define is_error_type(t) ((t)->base_type == GLSL_TYPE_ERROR) | |||
| #define GLSL_SAMPLER_DIM_1D 0 | |||
| #define GLSL_SAMPLER_DIM_2D 1 | |||
| #define GLSL_SAMPLER_DIM_3D 2 | |||
| #define GLSL_SAMPLER_DIM_CUBE 3 | |||
| #define GLSL_SAMPLER_DIM_RECT 4 | |||
| #define GLSL_SAMPLER_DIM_BUF 5 | |||
| struct glsl_type { | |||
| unsigned base_type:4; | |||
| unsigned sampler_dimensionality:3; | |||
| unsigned sampler_shadow:1; | |||
| unsigned sampler_array:1; | |||
| unsigned sampler_type:2; /**< Type of data returned using this sampler. | |||
| * only \c GLSL_TYPE_FLOAT, \c GLSL_TYPE_INT, | |||
| * and \c GLSL_TYPE_UINT are valid. | |||
| */ | |||
| unsigned vector_elements:3; /**< 0, 2, 3, or 4 vector elements. */ | |||
| unsigned matrix_rows:3; /**< 0, 2, 3, or 4 matrix rows. */ | |||
| /** | |||
| * Name of the data type | |||
| * | |||
| * This may be \c NULL for anonymous structures, for arrays, or for | |||
| * function types. | |||
| */ | |||
| const char *name; | |||
| /** | |||
| * For \c GLSL_TYPE_ARRAY, this is the length of the array. For | |||
| * \c GLSL_TYPE_STRUCT, it is the number of elements in the structure and | |||
| * the number of values pointed to by \c fields.structure (below). | |||
| * | |||
| * For \c GLSL_TYPE_FUNCTION, it is the number of parameters to the | |||
| * function. The return value from a function is implicitly the first | |||
| * parameter. The types of the parameters are stored in | |||
| * \c fields.parameters (below). | |||
| */ | |||
| unsigned length; | |||
| /** | |||
| * Subtype of composite data types. | |||
| */ | |||
| union { | |||
| const struct glsl_type *array; /**< Type of array elements. */ | |||
| const struct glsl_type *parameters; /**< Parameters to function. */ | |||
| const struct glsl_struct_field *structure;/**< List of struct fields. */ | |||
| } fields; | |||
| }; | |||
| #define is_glsl_type_scalar(t) \ | |||
| (((t)->vector_elements == 0) \ | |||
| && ((t)->base_type >= GLSL_TYPE_UINT) \ | |||
| && ((t)->base_type <= GLSL_TYPE_BOOL)) | |||
| #define is_glsl_type_vector(t) \ | |||
| (((t)->vector_elements > 0) \ | |||
| && ((t)->matrix_rows == 0) \ | |||
| && ((t)->base_type >= GLSL_TYPE_UINT) \ | |||
| && ((t)->base_type <= GLSL_TYPE_BOOL)) | |||
| #define is_glsl_type_matrix(t) \ | |||
| (((t)->matrix_rows > 0) \ | |||
| && ((t)->base_type == GLSL_TYPE_FLOAT)) /* GLSL only has float matrices. */ | |||
| struct glsl_struct_field { | |||
| const struct glsl_type *type; | |||
| const char *name; | |||
| }; | |||
| struct _mesa_glsl_parse_state; | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| extern void | |||
| _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state); | |||
| extern const struct glsl_type * | |||
| _mesa_glsl_get_vector_type(unsigned base_type, unsigned vector_length); | |||
| extern const struct glsl_type *const glsl_error_type; | |||
| extern const struct glsl_type *const glsl_int_type; | |||
| extern const struct glsl_type *const glsl_uint_type; | |||
| extern const struct glsl_type *const glsl_float_type; | |||
| extern const struct glsl_type *const glsl_bool_type; | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* GLSL_TYPES_H */ | |||
| @@ -0,0 +1,159 @@ | |||
| /* | |||
| * Copyright © 2008 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /** | |||
| * \file hash_table.c | |||
| * \brief Implementation of a generic, opaque hash table data type. | |||
| * | |||
| * \author Ian Romanick <ian.d.romanick@intel.com> | |||
| */ | |||
| #include "main/imports.h" | |||
| #include "main/simple_list.h" | |||
| #include "hash_table.h" | |||
| struct node { | |||
| struct node *next; | |||
| struct node *prev; | |||
| }; | |||
| struct hash_table { | |||
| hash_func_t hash; | |||
| hash_compare_func_t compare; | |||
| unsigned num_buckets; | |||
| struct node buckets[1]; | |||
| }; | |||
| struct hash_node { | |||
| struct node link; | |||
| const void *key; | |||
| void *data; | |||
| }; | |||
| struct hash_table * | |||
| hash_table_ctor(unsigned num_buckets, hash_func_t hash, | |||
| hash_compare_func_t compare) | |||
| { | |||
| struct hash_table *ht; | |||
| unsigned i; | |||
| if (num_buckets < 16) { | |||
| num_buckets = 16; | |||
| } | |||
| ht = _mesa_malloc(sizeof(*ht) + ((num_buckets - 1) | |||
| * sizeof(ht->buckets[0]))); | |||
| if (ht != NULL) { | |||
| ht->hash = hash; | |||
| ht->compare = compare; | |||
| ht->num_buckets = num_buckets; | |||
| for (i = 0; i < num_buckets; i++) { | |||
| make_empty_list(& ht->buckets[i]); | |||
| } | |||
| } | |||
| return ht; | |||
| } | |||
| void | |||
| hash_table_dtor(struct hash_table *ht) | |||
| { | |||
| hash_table_clear(ht); | |||
| _mesa_free(ht); | |||
| } | |||
| void | |||
| hash_table_clear(struct hash_table *ht) | |||
| { | |||
| struct node *node; | |||
| struct node *temp; | |||
| unsigned i; | |||
| for (i = 0; i < ht->num_buckets; i++) { | |||
| foreach_s(node, temp, & ht->buckets[i]) { | |||
| remove_from_list(node); | |||
| _mesa_free(node); | |||
| } | |||
| assert(is_empty_list(& ht->buckets[i])); | |||
| } | |||
| } | |||
| void * | |||
| hash_table_find(struct hash_table *ht, const void *key) | |||
| { | |||
| const unsigned hash_value = (*ht->hash)(key); | |||
| const unsigned bucket = hash_value % ht->num_buckets; | |||
| struct node *node; | |||
| foreach(node, & ht->buckets[bucket]) { | |||
| struct hash_node *hn = (struct hash_node *) node; | |||
| if ((*ht->compare)(hn->key, key) == 0) { | |||
| return hn->data; | |||
| } | |||
| } | |||
| return NULL; | |||
| } | |||
| void | |||
| hash_table_insert(struct hash_table *ht, void *data, const void *key) | |||
| { | |||
| const unsigned hash_value = (*ht->hash)(key); | |||
| const unsigned bucket = hash_value % ht->num_buckets; | |||
| struct hash_node *node; | |||
| node = _mesa_calloc(sizeof(*node)); | |||
| node->data = data; | |||
| node->key = key; | |||
| insert_at_head(& ht->buckets[bucket], & node->link); | |||
| } | |||
| unsigned | |||
| hash_table_string_hash(const void *key) | |||
| { | |||
| const char *str = (const char *) key; | |||
| unsigned hash = 5381; | |||
| while (*str != '\0') { | |||
| hash = (hash * 33) + *str; | |||
| str++; | |||
| } | |||
| return hash; | |||
| } | |||
| @@ -0,0 +1,117 @@ | |||
| /* | |||
| * Copyright © 2008 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /** | |||
| * \file hash_table.h | |||
| * \brief Implementation of a generic, opaque hash table data type. | |||
| * | |||
| * \author Ian Romanick <ian.d.romanick@intel.com> | |||
| */ | |||
| #ifndef HASH_TABLE_H | |||
| #define HASH_TABLE_H | |||
| #include <string.h> | |||
| struct hash_table; | |||
| typedef unsigned (*hash_func_t)(const void *key); | |||
| typedef int (*hash_compare_func_t)(const void *key1, const void *key2); | |||
| /** | |||
| * Hash table constructor | |||
| * | |||
| * Creates a hash table with the specified number of buckets. The supplied | |||
| * \c hash and \c compare routines are used when adding elements to the table | |||
| * and when searching for elements in the table. | |||
| * | |||
| * \param num_buckets Number of buckets (bins) in the hash table. | |||
| * \param hash Function used to compute hash value of input keys. | |||
| * \param compare Function used to compare keys. | |||
| */ | |||
| extern struct hash_table *hash_table_ctor(unsigned num_buckets, | |||
| hash_func_t hash, hash_compare_func_t compare); | |||
| /** | |||
| * Release all memory associated with a hash table | |||
| * | |||
| * \warning | |||
| * This function cannot release memory occupied either by keys or data. | |||
| */ | |||
| extern void hash_table_dtor(struct hash_table *ht); | |||
| /** | |||
| * Flush all entries from a hash table | |||
| * | |||
| * \param ht Table to be cleared of its entries. | |||
| */ | |||
| extern void hash_table_clear(struct hash_table *ht); | |||
| /** | |||
| * Search a hash table for a specific element | |||
| * | |||
| * \param ht Table to be searched | |||
| * \param key Key of the desired element | |||
| * | |||
| * \return | |||
| * The \c data value supplied to \c hash_table_insert when the element with | |||
| * the matching key was added. If no matching key exists in the table, | |||
| * \c NULL is returned. | |||
| */ | |||
| extern void *hash_table_find(struct hash_table *ht, const void *key); | |||
| /** | |||
| * Add an element to a hash table | |||
| */ | |||
| extern void hash_table_insert(struct hash_table *ht, void *data, | |||
| const void *key); | |||
| /** | |||
| * Compute hash value of a string | |||
| * | |||
| * Computes the hash value of a string using the DJB2 algorithm developed by | |||
| * Professor Daniel J. Bernstein. It was published on comp.lang.c once upon | |||
| * a time. I was unable to find the original posting in the archives. | |||
| * | |||
| * \param key Pointer to a NUL terminated string to be hashed. | |||
| * | |||
| * \sa hash_table_string_compare | |||
| */ | |||
| extern unsigned hash_table_string_hash(const void *key); | |||
| /** | |||
| * Compare two strings used as keys | |||
| * | |||
| * This is just a macro wrapper around \c strcmp. | |||
| * | |||
| * \sa hash_table_string_hash | |||
| */ | |||
| #define hash_table_string_compare ((hash_compare_func_t) strcmp) | |||
| #endif /* HASH_TABLE_H */ | |||
| @@ -0,0 +1,187 @@ | |||
| /* | |||
| * Copyright © 2010 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #include <stdio.h> | |||
| #include "main/imports.h" | |||
| #include "symbol_table.h" | |||
| #include "glsl_parser_extras.h" | |||
| #include "ast.h" | |||
| #include "glsl_types.h" | |||
| #include "ir.h" | |||
| #define X 1 | |||
| #define R 5 | |||
| #define S 9 | |||
| #define I 13 | |||
| static bool | |||
| generate_swizzle(const char *str, struct ir_swizzle_mask *swiz, | |||
| unsigned vector_length) | |||
| { | |||
| /* For each possible swizzle character, this table encodes the value in | |||
| * \c idx_map that represents the 0th element of the vector. For invalid | |||
| * swizzle characters (e.g., 'k'), a special value is used that will allow | |||
| * detection of errors. | |||
| */ | |||
| unsigned char base_idx[26] = { | |||
| /* a b c d e f g h i j k l m */ | |||
| R, R, I, I, I, I, R, I, I, I, I, I, I, | |||
| /* n o p q r s t u v w x y z */ | |||
| I, I, S, S, R, S, S, I, I, X, X, X, X | |||
| }; | |||
| /* Each valid swizzle character has an entry in the previous table. This | |||
| * table encodes the base index encoded in the previous table plus the actual | |||
| * index of the swizzle character. When processing swizzles, the first | |||
| * character in the string is indexed in the previous table. Each character | |||
| * in the string is indexed in this table, and the value found there has the | |||
| * value form the first table subtracted. The result must be on the range | |||
| * [0,3]. | |||
| * | |||
| * For example, the string "wzyx" will get X from the first table. Each of | |||
| * the charcaters will get X+3, X+2, X+1, and X+0 from this table. After | |||
| * subtraction, the swizzle values are { 3, 2, 1, 0 }. | |||
| * | |||
| * The string "wzrg" will get X from the first table. Each of the characters | |||
| * will get X+3, X+2, R+0, and R+1 from this table. After subtraction, the | |||
| * swizzle values are { 3, 2, 4, 5 }. Since 4 and 5 are outside the range | |||
| * [0,3], the error is detected. | |||
| */ | |||
| unsigned char idx_map[26] = { | |||
| /* a b c d e f g h i j k l m */ | |||
| R+3, R+2, 0, 0, 0, 0, R+1, 0, 0, 0, 0, 0, 0, | |||
| /* n o p q r s t u v w x y z */ | |||
| 0, 0, S+2, S+3, R+0, S+0, S+1, 0, 0, X+3, X+0, X+1, X+2 | |||
| }; | |||
| int swiz_idx[4] = { 0, 0, 0, 0 }; | |||
| unsigned base; | |||
| unsigned dup_mask = 0; | |||
| unsigned seen_mask = 0; | |||
| unsigned i; | |||
| /* Validate the first character in the swizzle string and look up the base | |||
| * index value as described above. | |||
| */ | |||
| if ((str[0] < 'a') || (str[0] > 'z')) | |||
| return FALSE; | |||
| base = base_idx[str[0] - 'a']; | |||
| for (i = 0; (i < 4) && (str[i] != '\0'); i++) { | |||
| unsigned bit; | |||
| /* Validate the next character, and, as described above, convert it to a | |||
| * swizzle index. | |||
| */ | |||
| if ((str[i] < 'a') || (str[i] > 'z')) | |||
| return FALSE; | |||
| swiz_idx[i] = idx_map[str[0] - 'a'] - base; | |||
| if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length)) | |||
| return FALSE; | |||
| /* Track a bit-mask of the swizzle index values that have been seen. If | |||
| * a value is seen more than once, set the "duplicate" flag. | |||
| */ | |||
| bit = (1U << swiz_idx[i]); | |||
| dup_mask |= seen_mask & bit; | |||
| seen_mask |= bit; | |||
| } | |||
| if (str[i] != '\0') | |||
| return FALSE; | |||
| swiz->x = swiz_idx[0]; | |||
| swiz->y = swiz_idx[1]; | |||
| swiz->z = swiz_idx[2]; | |||
| swiz->w = swiz_idx[3]; | |||
| swiz->num_components = i; | |||
| swiz->has_duplicates = (dup_mask != 0); | |||
| return TRUE; | |||
| } | |||
| struct ir_instruction * | |||
| _mesa_ast_field_selection_to_hir(const ast_expression *expr, | |||
| simple_node *instructions, | |||
| struct _mesa_glsl_parse_state *state) | |||
| { | |||
| ir_instruction *op; | |||
| ir_dereference *deref; | |||
| YYLTYPE loc; | |||
| op = _mesa_ast_to_hir(expr->subexpressions[0], instructions, state); | |||
| deref = new ir_dereference(op); | |||
| /* Initially assume that the resulting type of the field selection is an | |||
| * error. This make the error paths below a bit easier to follow. | |||
| */ | |||
| deref->type = glsl_error_type; | |||
| /* If processing the thing being dereferenced generated an error, bail out | |||
| * now. Doing so prevents spurious error messages from being logged below. | |||
| */ | |||
| if (is_error_type(op->type)) | |||
| return (struct ir_instruction *) deref; | |||
| /* There are two kinds of field selection. There is the selection of a | |||
| * specific field from a structure, and there is the selection of a | |||
| * swizzle / mask from a vector. Which is which is determined entirely | |||
| * by the base type of the thing to which the field selection operator is | |||
| * being applied. | |||
| */ | |||
| _mesa_ast_get_location(expr, & loc); | |||
| if (is_glsl_type_vector(op->type)) { | |||
| if (generate_swizzle(expr->primary_expression.identifier, | |||
| & deref->selector.swizzle, | |||
| op->type->vector_elements)) { | |||
| /* Based on the number of elements in the swizzle and the base type | |||
| * (i.e., float, int, unsigned, or bool) of the vector being swizzled, | |||
| * generate the type of the resulting value. | |||
| */ | |||
| deref->type = | |||
| _mesa_glsl_get_vector_type(op->type->base_type, | |||
| deref->selector.swizzle.num_components); | |||
| } else { | |||
| /* FINISHME: Logging of error messages should be moved into | |||
| * FINISHME: generate_swizzle. This allows the generation of more | |||
| * FINISHME: specific error messages. | |||
| */ | |||
| _mesa_glsl_error(& loc, state, "Invalid swizzle / mask `%s'", | |||
| expr->primary_expression.identifier); | |||
| } | |||
| } else if (op->type->base_type == GLSL_TYPE_STRUCT) { | |||
| /* FINISHME: Handle field selection from structures. */ | |||
| } else { | |||
| _mesa_glsl_error(& loc, state, "Cannot access field `%s' of " | |||
| "non-structure / non-vector.", | |||
| expr->primary_expression.identifier); | |||
| } | |||
| return (struct ir_instruction *) deref; | |||
| } | |||
| @@ -0,0 +1,41 @@ | |||
| struct ir_instruction * | |||
| _mesa_ast_constructor_to_hir(const struct ast_node *n, | |||
| const struct ast_node *parameters, | |||
| struct _mesa_glsl_parse_state *state) | |||
| { | |||
| const struct ast_type_specifier *type = (struct ast_type_specifier *) n; | |||
| /* There are effectively three kinds of constructors. Each has its own set | |||
| * of rules. | |||
| * | |||
| * * Built-in scalar, vector, and matrix types: For each of these the only | |||
| * matching requirement is that the number of values supplied is | |||
| * sufficient to initialize all of the fields of the type. | |||
| * * Array types: The number of initializers must match the size of the | |||
| * array, if a size is specified. Each of the initializers must | |||
| * exactly match the base type of the array. | |||
| * * Structure types: These initializers must exactly match the fields of | |||
| * the structure in order. This is the most restrictive type. | |||
| * | |||
| * In all cases the built-in promotions from integer to floating-point types | |||
| * are applied. | |||
| */ | |||
| if (type->is_array) { | |||
| /* FINISHME */ | |||
| } else if ((type->type_specifier == ast_struct) | |||
| || (type->type_specifier == ast_type_name)) { | |||
| /* FINISHME */ | |||
| } else { | |||
| const struct glsl_type *ctor_type; | |||
| /* Look-up the type, by name, in the symbol table. | |||
| */ | |||
| /* Generate a series of assignments of constructor parameters to fields | |||
| * of the object being initialized. | |||
| */ | |||
| } | |||
| } | |||
| @@ -0,0 +1,116 @@ | |||
| /* | |||
| * Copyright © 2010 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #include <string.h> | |||
| #include "main/imports.h" | |||
| #include "main/simple_list.h" | |||
| #include "ir.h" | |||
| #include "glsl_types.h" | |||
| ir_instruction::ir_instruction(int mode) | |||
| { | |||
| this->mode = mode; | |||
| make_empty_list(this); | |||
| } | |||
| ir_assignment::ir_assignment(ir_instruction *lhs, ir_instruction *rhs, | |||
| ir_expression *condition) | |||
| : ir_instruction(ir_op_assign) | |||
| { | |||
| this->lhs = (ir_dereference *) lhs; | |||
| this->rhs = rhs; | |||
| this->condition = condition; | |||
| } | |||
| ir_expression::ir_expression(int op, const struct glsl_type *type, | |||
| ir_instruction *op0, ir_instruction *op1) | |||
| : ir_instruction(ir_op_expression) | |||
| { | |||
| this->type = type; | |||
| this->operation = ir_expression_operation(op); | |||
| this->operands[0] = op0; | |||
| this->operands[1] = op1; | |||
| } | |||
| ir_label::ir_label(const char *label) | |||
| : ir_instruction(ir_op_label), label(label) | |||
| { | |||
| /* empty */ | |||
| } | |||
| ir_constant::ir_constant(const struct glsl_type *type, const void *data) | |||
| : ir_instruction(ir_op_constant) | |||
| { | |||
| const unsigned elements = | |||
| ((type->vector_elements == 0) ? 1 : type->vector_elements) | |||
| * ((type->matrix_rows == 0) ? 1 : type->matrix_rows); | |||
| unsigned size = 0; | |||
| this->type = type; | |||
| switch (type->base_type) { | |||
| case GLSL_TYPE_UINT: size = sizeof(this->value.u[0]); break; | |||
| case GLSL_TYPE_INT: size = sizeof(this->value.i[0]); break; | |||
| case GLSL_TYPE_FLOAT: size = sizeof(this->value.f[0]); break; | |||
| case GLSL_TYPE_BOOL: size = sizeof(this->value.b[0]); break; | |||
| default: | |||
| /* FINISHME: What to do? Exceptions are not the answer. | |||
| */ | |||
| break; | |||
| } | |||
| memcpy(& this->value, data, size * elements); | |||
| } | |||
| ir_dereference::ir_dereference(ir_instruction *var) | |||
| : ir_instruction(ir_op_dereference) | |||
| { | |||
| this->mode = ir_reference_variable; | |||
| this->var = var; | |||
| this->type = (var != NULL) ? var->type : glsl_error_type; | |||
| } | |||
| ir_variable::ir_variable(const struct glsl_type *type, const char *name) | |||
| : ir_instruction(ir_op_var_decl) | |||
| { | |||
| this->type = type; | |||
| this->name = name; | |||
| } | |||
| ir_function_signature::ir_function_signature(void) | |||
| : ir_instruction(ir_op_func_sig) | |||
| { | |||
| make_empty_list(& parameters); | |||
| } | |||
| ir_function::ir_function(void) | |||
| : ir_instruction(ir_op_func) | |||
| { | |||
| make_empty_list(& signatures); | |||
| } | |||
| @@ -0,0 +1,302 @@ | |||
| /* | |||
| * Copyright © 2010 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| struct ir_program { | |||
| void *bong_hits; | |||
| }; | |||
| enum ir_opcodes { | |||
| ir_op_var_decl, | |||
| ir_op_assign, | |||
| ir_op_expression, | |||
| ir_op_dereference, | |||
| ir_op_jump, | |||
| ir_op_label, | |||
| ir_op_constant, | |||
| ir_op_func_sig, | |||
| ir_op_func | |||
| }; | |||
| /** | |||
| * Base class of all IR instructions | |||
| */ | |||
| class ir_instruction : public simple_node { | |||
| public: | |||
| unsigned mode; | |||
| const struct glsl_type *type; | |||
| protected: | |||
| ir_instruction(int mode); | |||
| private: | |||
| /** | |||
| * Dummy constructor to catch bad constructors in derived classes. | |||
| * | |||
| * Every derived must use the constructor that sets the instructions | |||
| * mode. Having the \c void constructor private prevents derived classes | |||
| * from accidentally doing the wrong thing. | |||
| */ | |||
| ir_instruction(void); | |||
| }; | |||
| enum ir_variable_mode { | |||
| ir_var_auto = 0, | |||
| ir_var_uniform, | |||
| ir_var_in, | |||
| ir_var_out, | |||
| ir_var_inout | |||
| }; | |||
| enum ir_varaible_interpolation { | |||
| ir_var_smooth = 0, | |||
| ir_var_flat, | |||
| ir_var_noperspective | |||
| }; | |||
| class ir_variable : public ir_instruction { | |||
| public: | |||
| ir_variable(const struct glsl_type *, const char *); | |||
| const char *name; | |||
| unsigned read_only:1; | |||
| unsigned centroid:1; | |||
| unsigned invariant:1; | |||
| unsigned mode:3; | |||
| unsigned interpolation:2; | |||
| }; | |||
| class ir_label : public ir_instruction { | |||
| public: | |||
| ir_label(const char *label); | |||
| const char *label; | |||
| }; | |||
| /*@{*/ | |||
| class ir_function_signature : public ir_instruction { | |||
| public: | |||
| ir_function_signature(void); | |||
| /** | |||
| * Function return type. | |||
| * | |||
| * \note This discards the optional precision qualifier. | |||
| */ | |||
| const struct glsl_type *return_type; | |||
| /** | |||
| * List of function parameters stored as ir_variable objects. | |||
| */ | |||
| struct simple_node parameters; | |||
| /** | |||
| * Pointer to the label that begins the function definition. | |||
| */ | |||
| ir_label *definition; | |||
| }; | |||
| /** | |||
| * Header for tracking functions in the symbol table | |||
| */ | |||
| class ir_function : public ir_instruction { | |||
| public: | |||
| ir_function(void); | |||
| /** | |||
| * Name of the function. | |||
| */ | |||
| const char *name; | |||
| struct simple_node signatures; | |||
| }; | |||
| /*@}*/ | |||
| class ir_expression; | |||
| class ir_dereference; | |||
| class ir_assignment : public ir_instruction { | |||
| public: | |||
| ir_assignment(ir_instruction *lhs, ir_instruction *rhs, | |||
| ir_expression *condition); | |||
| /** | |||
| * Left-hand side of the assignment. | |||
| */ | |||
| ir_dereference *lhs; | |||
| /** | |||
| * Value being assigned | |||
| * | |||
| * This should be either \c ir_op_expression or \c ir_op_deference. | |||
| */ | |||
| ir_instruction *rhs; | |||
| /** | |||
| * Optional condition for the assignment. | |||
| */ | |||
| ir_expression *condition; | |||
| }; | |||
| enum ir_expression_operation { | |||
| ir_unop_bit_not, | |||
| ir_unop_logic_not, | |||
| ir_unop_neg, | |||
| ir_unop_abs, | |||
| ir_unop_rcp, | |||
| ir_unop_rsq, | |||
| ir_unop_exp, | |||
| ir_unop_log, | |||
| ir_unop_f2i, /**< Float-to-integer conversion. */ | |||
| ir_unop_i2f, /**< Integer-to-float conversion. */ | |||
| /** | |||
| * \name Unary floating-point rounding operations. | |||
| */ | |||
| /*@{*/ | |||
| ir_unop_trunc, | |||
| ir_unop_ceil, | |||
| ir_unop_floor, | |||
| /*@}*/ | |||
| ir_binop_add, | |||
| ir_binop_sub, | |||
| ir_binop_mul, | |||
| ir_binop_div, | |||
| ir_binop_mod, | |||
| /** | |||
| * \name Binary comparison operators | |||
| */ | |||
| /*@{*/ | |||
| ir_binop_less, | |||
| ir_binop_greater, | |||
| ir_binop_lequal, | |||
| ir_binop_gequal, | |||
| ir_binop_equal, | |||
| ir_binop_nequal, | |||
| /*@}*/ | |||
| /** | |||
| * \name Bit-wise binary operations. | |||
| */ | |||
| /*@{*/ | |||
| ir_binop_lshift, | |||
| ir_binop_rshift, | |||
| ir_binop_bit_and, | |||
| ir_binop_bit_xor, | |||
| ir_binop_bit_or, | |||
| /*@}*/ | |||
| ir_binop_logic_and, | |||
| ir_binop_logic_xor, | |||
| ir_binop_logic_or, | |||
| ir_binop_logic_not, | |||
| ir_binop_dot, | |||
| ir_binop_min, | |||
| ir_binop_max, | |||
| ir_binop_pow | |||
| }; | |||
| class ir_expression : public ir_instruction { | |||
| public: | |||
| ir_expression(int op, const struct glsl_type *type, | |||
| ir_instruction *, ir_instruction *); | |||
| ir_expression_operation operation; | |||
| ir_instruction *operands[2]; | |||
| }; | |||
| struct ir_swizzle_mask { | |||
| unsigned x:2; | |||
| unsigned y:2; | |||
| unsigned z:2; | |||
| unsigned w:2; | |||
| /** | |||
| * Number of components in the swizzle. | |||
| */ | |||
| unsigned num_components:2; | |||
| /** | |||
| * Does the swizzle contain duplicate components? | |||
| * | |||
| * L-value swizzles cannot contain duplicate components. | |||
| */ | |||
| unsigned has_duplicates:1; | |||
| }; | |||
| class ir_dereference : public ir_instruction { | |||
| public: | |||
| ir_dereference(struct ir_instruction *); | |||
| enum { | |||
| ir_reference_variable, | |||
| ir_reference_array, | |||
| ir_reference_record | |||
| } mode; | |||
| /** | |||
| * Object being dereferenced. | |||
| * | |||
| * Must be either an \c ir_variable or an \c ir_deference. | |||
| */ | |||
| ir_instruction *var; | |||
| union { | |||
| ir_expression *array_index; | |||
| const char *field; | |||
| struct ir_swizzle_mask swizzle; | |||
| } selector; | |||
| }; | |||
| class ir_constant : public ir_instruction { | |||
| public: | |||
| ir_constant(const struct glsl_type *type, const void *data); | |||
| /** | |||
| * Value of the constant. | |||
| * | |||
| * The field used to back the values supplied by the constant is determined | |||
| * by the type associated with the \c ir_instruction. Constants may be | |||
| * scalars, vectors, or matrices. | |||
| */ | |||
| union { | |||
| unsigned u[16]; | |||
| int i[16]; | |||
| float f[16]; | |||
| bool b[16]; | |||
| } value; | |||
| }; | |||
| @@ -0,0 +1,6 @@ | |||
| #include <assert.h> | |||
| #include <stdlib.h> | |||
| #define _mesa_malloc(x) malloc(x) | |||
| #define _mesa_free(x) free(x) | |||
| #define _mesa_calloc(x) calloc(1,x) | |||
| @@ -0,0 +1,235 @@ | |||
| /** | |||
| * \file simple_list.h | |||
| * Simple macros for type-safe, intrusive lists. | |||
| * | |||
| * Intended to work with a list sentinal which is created as an empty | |||
| * list. Insert & delete are O(1). | |||
| * | |||
| * \author | |||
| * (C) 1997, Keith Whitwell | |||
| */ | |||
| /* | |||
| * Mesa 3-D graphics library | |||
| * Version: 3.5 | |||
| * | |||
| * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included | |||
| * in all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||
| * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #ifndef _SIMPLE_LIST_H | |||
| #define _SIMPLE_LIST_H | |||
| struct simple_node { | |||
| struct simple_node *next; | |||
| struct simple_node *prev; | |||
| }; | |||
| /** | |||
| * Remove an element from list. | |||
| * | |||
| * \param elem element to remove. | |||
| */ | |||
| #define remove_from_list(elem) \ | |||
| do { \ | |||
| (elem)->next->prev = (elem)->prev; \ | |||
| (elem)->prev->next = (elem)->next; \ | |||
| } while (0) | |||
| /** | |||
| * Insert an element to the list head. | |||
| * | |||
| * \param list list. | |||
| * \param elem element to insert. | |||
| */ | |||
| #define insert_at_head(list, elem) \ | |||
| do { \ | |||
| (elem)->prev = list; \ | |||
| (elem)->next = (list)->next; \ | |||
| (list)->next->prev = elem; \ | |||
| (list)->next = elem; \ | |||
| } while(0) | |||
| /** | |||
| * Insert an element to the list tail. | |||
| * | |||
| * \param list list. | |||
| * \param elem element to insert. | |||
| */ | |||
| #define insert_at_tail(list, elem) \ | |||
| do { \ | |||
| (elem)->next = list; \ | |||
| (elem)->prev = (list)->prev; \ | |||
| (list)->prev->next = elem; \ | |||
| (list)->prev = elem; \ | |||
| } while(0) | |||
| /** | |||
| * Move an element to the list head. | |||
| * | |||
| * \param list list. | |||
| * \param elem element to move. | |||
| */ | |||
| #define move_to_head(list, elem) \ | |||
| do { \ | |||
| remove_from_list(elem); \ | |||
| insert_at_head(list, elem); \ | |||
| } while (0) | |||
| /** | |||
| * Move an element to the list tail. | |||
| * | |||
| * \param list list. | |||
| * \param elem element to move. | |||
| */ | |||
| #define move_to_tail(list, elem) \ | |||
| do { \ | |||
| remove_from_list(elem); \ | |||
| insert_at_tail(list, elem); \ | |||
| } while (0) | |||
| /** | |||
| * Consatinate a cyclic list to a list | |||
| * | |||
| * Appends the sequence of nodes starting with \c tail to the list \c head. | |||
| * A "cyclic list" is a list that does not have a sentinal node. This means | |||
| * that the data pointed to by \c tail is an actual node, not a dataless | |||
| * sentinal. Note that if \c tail constist of a single node, this macro | |||
| * behaves identically to \c insert_at_tail | |||
| * | |||
| * \param head Head of the list to be appended to. This may or may not | |||
| * be a cyclic list. | |||
| * \param tail Head of the cyclic list to be appended to \c head. | |||
| * \param temp Temporary \c simple_list used by the macro | |||
| * | |||
| * \sa insert_at_tail | |||
| */ | |||
| #define concat_list_and_cycle(head, tail, temp) \ | |||
| do { \ | |||
| (head)->prev->next = (tail); \ | |||
| (tail)->prev->next = (head); \ | |||
| (temp) = (head)->prev; \ | |||
| (head)->prev = (tail)->prev; \ | |||
| (tail)->prev = (temp); \ | |||
| } while (0) | |||
| #define concat_list(head, next_list) \ | |||
| do { \ | |||
| (next_list)->next->prev = (head)->prev; \ | |||
| (next_list)->prev->next = (head); \ | |||
| (head)->prev->next = (next_list)->next; \ | |||
| (head)->prev = (next_list)->prev; \ | |||
| } while (0) | |||
| /** | |||
| * Make a empty list empty. | |||
| * | |||
| * \param sentinal list (sentinal element). | |||
| */ | |||
| #define make_empty_list(sentinal) \ | |||
| do { \ | |||
| (sentinal)->next = sentinal; \ | |||
| (sentinal)->prev = sentinal; \ | |||
| } while (0) | |||
| /** | |||
| * Get list first element. | |||
| * | |||
| * \param list list. | |||
| * | |||
| * \return pointer to first element. | |||
| */ | |||
| #define first_elem(list) ((list)->next) | |||
| /** | |||
| * Get list last element. | |||
| * | |||
| * \param list list. | |||
| * | |||
| * \return pointer to last element. | |||
| */ | |||
| #define last_elem(list) ((list)->prev) | |||
| /** | |||
| * Get next element. | |||
| * | |||
| * \param elem element. | |||
| * | |||
| * \return pointer to next element. | |||
| */ | |||
| #define next_elem(elem) ((elem)->next) | |||
| /** | |||
| * Get previous element. | |||
| * | |||
| * \param elem element. | |||
| * | |||
| * \return pointer to previous element. | |||
| */ | |||
| #define prev_elem(elem) ((elem)->prev) | |||
| /** | |||
| * Test whether element is at end of the list. | |||
| * | |||
| * \param list list. | |||
| * \param elem element. | |||
| * | |||
| * \return non-zero if element is at end of list, or zero otherwise. | |||
| */ | |||
| #define at_end(list, elem) ((elem) == (list)) | |||
| /** | |||
| * Test if a list is empty. | |||
| * | |||
| * \param list list. | |||
| * | |||
| * \return non-zero if list empty, or zero otherwise. | |||
| */ | |||
| #define is_empty_list(list) ((list)->next == (list)) | |||
| /** | |||
| * Walk through the elements of a list. | |||
| * | |||
| * \param ptr pointer to the current element. | |||
| * \param list list. | |||
| * | |||
| * \note It should be followed by a { } block or a single statement, as in a \c | |||
| * for loop. | |||
| */ | |||
| #define foreach(ptr, list) \ | |||
| for( ptr=(list)->next ; ptr!=list ; ptr=(ptr)->next ) | |||
| /** | |||
| * Walk through the elements of a list. | |||
| * | |||
| * Same as #foreach but lets you unlink the current value during a list | |||
| * traversal. Useful for freeing a list, element by element. | |||
| * | |||
| * \param ptr pointer to the current element. | |||
| * \param t temporary pointer. | |||
| * \param list list. | |||
| * | |||
| * \note It should be followed by a { } block or a single statement, as in a \c | |||
| * for loop. | |||
| */ | |||
| #define foreach_s(ptr, t, list) \ | |||
| for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next) | |||
| #endif | |||
| @@ -0,0 +1,377 @@ | |||
| /* | |||
| * Copyright © 2008 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #include "main/imports.h" | |||
| #include "symbol_table.h" | |||
| #include "hash_table.h" | |||
| struct symbol { | |||
| /** | |||
| * Link to the next symbol in the table with the same name | |||
| * | |||
| * The linked list of symbols with the same name is ordered by scope | |||
| * from inner-most to outer-most. | |||
| */ | |||
| struct symbol *next_with_same_name; | |||
| /** | |||
| * Link to the next symbol in the table with the same scope | |||
| * | |||
| * The linked list of symbols with the same scope is unordered. Symbols | |||
| * in this list my have unique names. | |||
| */ | |||
| struct symbol *next_with_same_scope; | |||
| /** | |||
| * Header information for the list of symbols with the same name. | |||
| */ | |||
| struct symbol_header *hdr; | |||
| /** | |||
| * Name space of the symbol | |||
| * | |||
| * Name space are arbitrary user assigned integers. No two symbols can | |||
| * exist in the same name space at the same scope level. | |||
| */ | |||
| int name_space; | |||
| /** | |||
| * Arbitrary user supplied data. | |||
| */ | |||
| void *data; | |||
| /** Scope depth where this symbol was defined. */ | |||
| unsigned depth; | |||
| }; | |||
| /** | |||
| */ | |||
| struct symbol_header { | |||
| /** Linkage in list of all headers in a given symbol table. */ | |||
| struct symbol_header *next; | |||
| /** Symbol name. */ | |||
| const char *name; | |||
| /** Linked list of symbols with the same name. */ | |||
| struct symbol *symbols; | |||
| }; | |||
| /** | |||
| * Element of the scope stack. | |||
| */ | |||
| struct scope_level { | |||
| /** Link to next (inner) scope level. */ | |||
| struct scope_level *next; | |||
| /** Linked list of symbols with the same scope. */ | |||
| struct symbol *symbols; | |||
| }; | |||
| /** | |||
| * | |||
| */ | |||
| struct _mesa_symbol_table { | |||
| /** Hash table containing all symbols in the symbol table. */ | |||
| struct hash_table *ht; | |||
| /** Top of scope stack. */ | |||
| struct scope_level *current_scope; | |||
| /** List of all symbol headers in the table. */ | |||
| struct symbol_header *hdr; | |||
| /** Current scope depth. */ | |||
| unsigned depth; | |||
| }; | |||
| struct _mesa_symbol_table_iterator { | |||
| /** | |||
| * Name space of symbols returned by this iterator. | |||
| */ | |||
| int name_space; | |||
| /** | |||
| * Currently iterated symbol | |||
| * | |||
| * The next call to \c _mesa_symbol_table_iterator_get will return this | |||
| * value. It will also update this value to the value that should be | |||
| * returned by the next call. | |||
| */ | |||
| struct symbol *curr; | |||
| }; | |||
| static void | |||
| check_symbol_table(struct _mesa_symbol_table *table) | |||
| { | |||
| #if 1 | |||
| struct scope_level *scope; | |||
| for (scope = table->current_scope; scope != NULL; scope = scope->next) { | |||
| struct symbol *sym; | |||
| for (sym = scope->symbols | |||
| ; sym != NULL | |||
| ; sym = sym->next_with_same_name) { | |||
| const struct symbol_header *const hdr = sym->hdr; | |||
| struct symbol *sym2; | |||
| for (sym2 = hdr->symbols | |||
| ; sym2 != NULL | |||
| ; sym2 = sym2->next_with_same_name) { | |||
| assert(sym2->hdr == hdr); | |||
| } | |||
| } | |||
| } | |||
| #endif | |||
| } | |||
| void | |||
| _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table) | |||
| { | |||
| struct scope_level *const scope = table->current_scope; | |||
| struct symbol *sym = scope->symbols; | |||
| table->current_scope = scope->next; | |||
| table->depth--; | |||
| free(scope); | |||
| while (sym != NULL) { | |||
| struct symbol *const next = sym->next_with_same_scope; | |||
| struct symbol_header *const hdr = sym->hdr; | |||
| assert(hdr->symbols == sym); | |||
| hdr->symbols = sym->next_with_same_name; | |||
| free(sym); | |||
| sym = next; | |||
| } | |||
| check_symbol_table(table); | |||
| } | |||
| void | |||
| _mesa_symbol_table_push_scope(struct _mesa_symbol_table *table) | |||
| { | |||
| struct scope_level *const scope = calloc(1, sizeof(*scope)); | |||
| scope->next = table->current_scope; | |||
| table->current_scope = scope; | |||
| table->depth++; | |||
| } | |||
| static struct symbol_header * | |||
| find_symbol(struct _mesa_symbol_table *table, const char *name) | |||
| { | |||
| return (struct symbol_header *) hash_table_find(table->ht, name); | |||
| } | |||
| struct _mesa_symbol_table_iterator * | |||
| _mesa_symbol_table_iterator_ctor(struct _mesa_symbol_table *table, | |||
| int name_space, const char *name) | |||
| { | |||
| struct _mesa_symbol_table_iterator *iter = calloc(1, sizeof(*iter)); | |||
| struct symbol_header *const hdr = find_symbol(table, name); | |||
| iter->name_space = name_space; | |||
| if (hdr != NULL) { | |||
| struct symbol *sym; | |||
| for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) { | |||
| assert(sym->hdr == hdr); | |||
| if ((name_space == -1) || (sym->name_space == name_space)) { | |||
| iter->curr = sym; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| return iter; | |||
| } | |||
| void | |||
| _mesa_symbol_table_iterator_dtor(struct _mesa_symbol_table_iterator *iter) | |||
| { | |||
| free(iter); | |||
| } | |||
| void * | |||
| _mesa_symbol_table_iterator_get(struct _mesa_symbol_table_iterator *iter) | |||
| { | |||
| return (iter->curr == NULL) ? NULL : iter->curr->data; | |||
| } | |||
| int | |||
| _mesa_symbol_table_iterator_next(struct _mesa_symbol_table_iterator *iter) | |||
| { | |||
| struct symbol_header *hdr; | |||
| if (iter->curr == NULL) { | |||
| return 0; | |||
| } | |||
| hdr = iter->curr->hdr; | |||
| iter->curr = iter->curr->next_with_same_name; | |||
| while (iter->curr != NULL) { | |||
| assert(iter->curr->hdr == hdr); | |||
| if ((iter->name_space == -1) | |||
| || (iter->curr->name_space == iter->name_space)) { | |||
| return 1; | |||
| } | |||
| iter->curr = iter->curr->next_with_same_name; | |||
| } | |||
| return 0; | |||
| } | |||
| void * | |||
| _mesa_symbol_table_find_symbol(struct _mesa_symbol_table *table, | |||
| int name_space, const char *name) | |||
| { | |||
| struct symbol_header *const hdr = find_symbol(table, name); | |||
| if (hdr != NULL) { | |||
| struct symbol *sym; | |||
| for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) { | |||
| assert(sym->hdr == hdr); | |||
| if ((name_space == -1) || (sym->name_space == name_space)) { | |||
| return sym->data; | |||
| } | |||
| } | |||
| } | |||
| return NULL; | |||
| } | |||
| int | |||
| _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table, | |||
| int name_space, const char *name, | |||
| void *declaration) | |||
| { | |||
| struct symbol_header *hdr; | |||
| struct symbol *sym; | |||
| check_symbol_table(table); | |||
| hdr = find_symbol(table, name); | |||
| check_symbol_table(table); | |||
| if (hdr == NULL) { | |||
| hdr = calloc(1, sizeof(*hdr)); | |||
| hdr->name = name; | |||
| hash_table_insert(table->ht, hdr, name); | |||
| hdr->next = table->hdr; | |||
| table->hdr = hdr; | |||
| } | |||
| check_symbol_table(table); | |||
| /* If the symbol already exists at this scope, it cannot be added to the | |||
| * table. | |||
| */ | |||
| if (hdr->symbols && (hdr->symbols->depth == table->depth)) | |||
| return -1; | |||
| sym = calloc(1, sizeof(*sym)); | |||
| sym->next_with_same_name = hdr->symbols; | |||
| sym->next_with_same_scope = table->current_scope->symbols; | |||
| sym->hdr = hdr; | |||
| sym->name_space = name_space; | |||
| sym->data = declaration; | |||
| sym->depth = table->depth; | |||
| assert(sym->hdr == hdr); | |||
| hdr->symbols = sym; | |||
| table->current_scope->symbols = sym; | |||
| check_symbol_table(table); | |||
| return 0; | |||
| } | |||
| struct _mesa_symbol_table * | |||
| _mesa_symbol_table_ctor(void) | |||
| { | |||
| struct _mesa_symbol_table *table = calloc(1, sizeof(*table)); | |||
| if (table != NULL) { | |||
| table->ht = hash_table_ctor(32, hash_table_string_hash, | |||
| hash_table_string_compare); | |||
| _mesa_symbol_table_push_scope(table); | |||
| } | |||
| return table; | |||
| } | |||
| void | |||
| _mesa_symbol_table_dtor(struct _mesa_symbol_table *table) | |||
| { | |||
| struct symbol_header *hdr; | |||
| struct symbol_header *next; | |||
| while (table->current_scope != NULL) { | |||
| _mesa_symbol_table_pop_scope(table); | |||
| } | |||
| for (hdr = table->hdr; hdr != NULL; hdr = next) { | |||
| next = hdr->next; | |||
| _mesa_free(hdr); | |||
| } | |||
| hash_table_dtor(table->ht); | |||
| free(table); | |||
| } | |||
| @@ -0,0 +1,63 @@ | |||
| /* | |||
| * Copyright © 2008 Intel Corporation | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice (including the next | |||
| * paragraph) shall be included in all copies or substantial portions of the | |||
| * Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| #ifndef MESA_SYMBOL_TABLE_H | |||
| #define MESA_SYMBOL_TABLE_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| struct _mesa_symbol_table; | |||
| struct _mesa_symbol_table_iterator; | |||
| extern void _mesa_symbol_table_push_scope(struct _mesa_symbol_table *table); | |||
| extern void _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table); | |||
| extern int _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *symtab, | |||
| int name_space, const char *name, void *declaration); | |||
| extern void *_mesa_symbol_table_find_symbol( | |||
| struct _mesa_symbol_table *symtab, int name_space, const char *name); | |||
| extern struct _mesa_symbol_table *_mesa_symbol_table_ctor(void); | |||
| extern void _mesa_symbol_table_dtor(struct _mesa_symbol_table *); | |||
| extern struct _mesa_symbol_table_iterator *_mesa_symbol_table_iterator_ctor( | |||
| struct _mesa_symbol_table *table, int name_space, const char *name); | |||
| extern void _mesa_symbol_table_iterator_dtor( | |||
| struct _mesa_symbol_table_iterator *); | |||
| extern void *_mesa_symbol_table_iterator_get( | |||
| struct _mesa_symbol_table_iterator *iter); | |||
| extern int _mesa_symbol_table_iterator_next( | |||
| struct _mesa_symbol_table_iterator *iter); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* MESA_SYMBOL_TABLE_H */ | |||
| @@ -0,0 +1,9 @@ | |||
| void a() | |||
| { | |||
| ; | |||
| } | |||
| void a() | |||
| { | |||
| ; | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| void a() | |||
| { | |||
| ; | |||
| } | |||
| void a(float x) | |||
| { | |||
| ; | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| /* FAIL - x is redeclared in the function body at the same scope as the | |||
| * parameter | |||
| */ | |||
| void a(float x, float y) | |||
| { | |||
| float x; | |||
| x = y; | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| #version 120 | |||
| void main() | |||
| { | |||
| float a; | |||
| vec4 b; | |||
| b.x = 6.0; | |||
| a = b.x; | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| #version 120 | |||
| void main() | |||
| { | |||
| float a; | |||
| vec4 b; | |||
| b.x = 6.0; | |||
| a = b.xy; | |||
| } | |||