@@ -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; | |||
} |