aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp545
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-lex.l656
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-parse.y3
-rw-r--r--mesalib/src/glsl/glsl_parser.yy6
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp2
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.h21
-rw-r--r--mesalib/src/glsl/linker.cpp38
7 files changed, 669 insertions, 602 deletions
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index cde7052b0..c580359fd 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -54,6 +54,7 @@
#include "glsl_parser_extras.h"
#include "ast.h"
#include "glsl_types.h"
+#include "program/hash_table.h"
#include "ir.h"
void
@@ -3405,7 +3406,7 @@ ast_jump_statement::hir(exec_list *instructions,
"continue may only appear in a loop");
} else if (mode == ast_break &&
state->loop_nesting_ast == NULL &&
- state->switch_nesting_ast == NULL) {
+ state->switch_state.switch_nesting_ast == NULL) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(& loc, state,
@@ -3423,11 +3424,11 @@ ast_jump_statement::hir(exec_list *instructions,
state);
}
- if (state->is_switch_innermost &&
+ if (state->switch_state.is_switch_innermost &&
mode == ast_break) {
/* Force break out of switch by setting is_break switch state.
*/
- ir_variable *const is_break_var = state->is_break_var;
+ ir_variable *const is_break_var = state->switch_state.is_break_var;
ir_dereference_variable *const deref_is_break_var =
new(ctx) ir_dereference_variable(is_break_var);
ir_constant *const true_val = new(ctx) ir_constant(true);
@@ -3530,25 +3531,25 @@ ast_switch_statement::hir(exec_list *instructions,
/* Track the switch-statement nesting in a stack-like manner.
*/
- ir_variable *saved_test_var = state->test_var;
- ir_variable *saved_is_fallthru_var = state->is_fallthru_var;
-
- bool save_is_switch_innermost = state->is_switch_innermost;
- ast_switch_statement *saved_nesting_ast = state->switch_nesting_ast;
+ struct glsl_switch_state saved = state->switch_state;
- state->is_switch_innermost = true;
- state->switch_nesting_ast = this;
+ state->switch_state.is_switch_innermost = true;
+ state->switch_state.switch_nesting_ast = this;
+ state->switch_state.labels_ht = hash_table_ctor(0, hash_table_pointer_hash,
+ hash_table_pointer_compare);
+ state->switch_state.previous_default = NULL;
/* Initalize is_fallthru state to false.
*/
ir_rvalue *const is_fallthru_val = new (ctx) ir_constant(false);
- state->is_fallthru_var = new(ctx) ir_variable(glsl_type::bool_type,
- "switch_is_fallthru_tmp",
- ir_var_temporary);
- instructions->push_tail(state->is_fallthru_var);
+ state->switch_state.is_fallthru_var =
+ new(ctx) ir_variable(glsl_type::bool_type,
+ "switch_is_fallthru_tmp",
+ ir_var_temporary);
+ instructions->push_tail(state->switch_state.is_fallthru_var);
ir_dereference_variable *deref_is_fallthru_var =
- new(ctx) ir_dereference_variable(state->is_fallthru_var);
+ new(ctx) ir_dereference_variable(state->switch_state.is_fallthru_var);
instructions->push_tail(new(ctx) ir_assignment(deref_is_fallthru_var,
is_fallthru_val,
NULL));
@@ -3556,13 +3557,13 @@ ast_switch_statement::hir(exec_list *instructions,
/* Initalize is_break state to false.
*/
ir_rvalue *const is_break_val = new (ctx) ir_constant(false);
- state->is_break_var = new(ctx) ir_variable(glsl_type::bool_type,
- "switch_is_break_tmp",
- ir_var_temporary);
- instructions->push_tail(state->is_break_var);
+ state->switch_state.is_break_var = new(ctx) ir_variable(glsl_type::bool_type,
+ "switch_is_break_tmp",
+ ir_var_temporary);
+ instructions->push_tail(state->switch_state.is_break_var);
ir_dereference_variable *deref_is_break_var =
- new(ctx) ir_dereference_variable(state->is_break_var);
+ new(ctx) ir_dereference_variable(state->switch_state.is_break_var);
instructions->push_tail(new(ctx) ir_assignment(deref_is_break_var,
is_break_val,
NULL));
@@ -3575,254 +3576,294 @@ ast_switch_statement::hir(exec_list *instructions,
*/
body->hir(instructions, state);
- /* Restore previous nesting before returning.
- */
- state->switch_nesting_ast = saved_nesting_ast;
- state->is_switch_innermost = save_is_switch_innermost;
+ hash_table_dtor(state->switch_state.labels_ht);
- state->test_var = saved_test_var;
- state->is_fallthru_var = saved_is_fallthru_var;
+ state->switch_state = saved;
- /* Switch statements do not have r-values.
- */
- return NULL;
-}
+ /* Switch statements do not have r-values.
+ */
+ return NULL;
+ }
-void
-ast_switch_statement::test_to_hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
-
- /* Cache value of test expression.
- */
- ir_rvalue *const test_val =
- test_expression->hir(instructions,
- state);
+ void
+ ast_switch_statement::test_to_hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+ {
+ void *ctx = state;
- state->test_var = new(ctx) ir_variable(glsl_type::int_type,
- "switch_test_tmp",
- ir_var_temporary);
- ir_dereference_variable *deref_test_var =
- new(ctx) ir_dereference_variable(state->test_var);
+ /* Cache value of test expression.
+ */
+ ir_rvalue *const test_val =
+ test_expression->hir(instructions,
+ state);
- instructions->push_tail(state->test_var);
- instructions->push_tail(new(ctx) ir_assignment(deref_test_var,
- test_val,
- NULL));
-}
+ state->switch_state.test_var = new(ctx) ir_variable(glsl_type::int_type,
+ "switch_test_tmp",
+ ir_var_temporary);
+ ir_dereference_variable *deref_test_var =
+ new(ctx) ir_dereference_variable(state->switch_state.test_var);
+ instructions->push_tail(state->switch_state.test_var);
+ instructions->push_tail(new(ctx) ir_assignment(deref_test_var,
+ test_val,
+ NULL));
+ }
-ir_rvalue *
-ast_switch_body::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- if (stmts != NULL)
- stmts->hir(instructions, state);
-
- /* Switch bodies do not have r-values.
- */
- return NULL;
-}
+ ir_rvalue *
+ ast_switch_body::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+ {
+ if (stmts != NULL)
+ stmts->hir(instructions, state);
-ir_rvalue *
-ast_case_statement_list::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- foreach_list_typed (ast_case_statement, case_stmt, link, & this->cases)
- case_stmt->hir(instructions, state);
-
- /* Case statements do not have r-values.
- */
- return NULL;
-}
+ /* Switch bodies do not have r-values.
+ */
+ return NULL;
+ }
-ir_rvalue *
-ast_case_statement::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- labels->hir(instructions, state);
-
- /* Conditionally set fallthru state based on break state.
- */
- ir_constant *const false_val = new(state) ir_constant(false);
- ir_dereference_variable *const deref_is_fallthru_var =
- new(state) ir_dereference_variable(state->is_fallthru_var);
- ir_dereference_variable *const deref_is_break_var =
- new(state) ir_dereference_variable(state->is_break_var);
- ir_assignment *const reset_fallthru_on_break =
- new(state) ir_assignment(deref_is_fallthru_var,
- false_val,
- deref_is_break_var);
- instructions->push_tail(reset_fallthru_on_break);
-
- /* Guard case statements depending on fallthru state.
- */
- ir_dereference_variable *const deref_fallthru_guard =
- new(state) ir_dereference_variable(state->is_fallthru_var);
- ir_if *const test_fallthru = new(state) ir_if(deref_fallthru_guard);
-
- foreach_list_typed (ast_node, stmt, link, & this->stmts)
- stmt->hir(& test_fallthru->then_instructions, state);
-
- instructions->push_tail(test_fallthru);
-
- /* Case statements do not have r-values.
- */
- return NULL;
-}
-
-
-ir_rvalue *
-ast_case_label_list::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- foreach_list_typed (ast_case_label, label, link, & this->labels)
- label->hir(instructions, state);
-
- /* Case labels do not have r-values.
- */
- return NULL;
-}
-
-
-ir_rvalue *
-ast_case_label::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
-
- ir_dereference_variable *deref_fallthru_var =
- new(ctx) ir_dereference_variable(state->is_fallthru_var);
-
- ir_rvalue *const true_val = new(ctx) ir_constant(true);
-
- /* If not default case, ...
- */
- if (this->test_value != NULL) {
- /* Conditionally set fallthru state based on
- * comparison of cached test expression value to case label.
- */
- ir_rvalue *const test_val = this->test_value->hir(instructions, state);
+ ir_rvalue *
+ ast_case_statement_list::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+ {
+ foreach_list_typed (ast_case_statement, case_stmt, link, & this->cases)
+ case_stmt->hir(instructions, state);
- ir_dereference_variable *deref_test_var =
- new(ctx) ir_dereference_variable(state->test_var);
+ /* Case statements do not have r-values.
+ */
+ return NULL;
+ }
- ir_rvalue *const test_cond = new(ctx) ir_expression(ir_binop_all_equal,
- glsl_type::bool_type,
- test_val,
- deref_test_var);
- ir_assignment *set_fallthru_on_test =
- new(ctx) ir_assignment(deref_fallthru_var,
- true_val,
- test_cond);
-
- instructions->push_tail(set_fallthru_on_test);
- } else { /* default case */
- /* Set falltrhu state.
- */
- ir_assignment *set_fallthru =
- new(ctx) ir_assignment(deref_fallthru_var,
- true_val,
- NULL);
-
- instructions->push_tail(set_fallthru);
- }
-
- /* Case statements do not have r-values.
- */
- return NULL;
-}
-
-
-void
-ast_iteration_statement::condition_to_hir(ir_loop *stmt,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
-
- if (condition != NULL) {
- ir_rvalue *const cond =
- condition->hir(& stmt->body_instructions, state);
-
- if ((cond == NULL)
- || !cond->type->is_boolean() || !cond->type->is_scalar()) {
- YYLTYPE loc = condition->get_location();
-
- _mesa_glsl_error(& loc, state,
- "loop condition must be scalar boolean");
- } else {
- /* As the first code in the loop body, generate a block that looks
- * like 'if (!condition) break;' as the loop termination condition.
- */
- ir_rvalue *const not_cond =
- new(ctx) ir_expression(ir_unop_logic_not, glsl_type::bool_type, cond,
- NULL);
-
- ir_if *const if_stmt = new(ctx) ir_if(not_cond);
-
- ir_jump *const break_stmt =
- new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
-
- if_stmt->then_instructions.push_tail(break_stmt);
- stmt->body_instructions.push_tail(if_stmt);
- }
- }
-}
-
-
-ir_rvalue *
-ast_iteration_statement::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
-
- /* For-loops and while-loops start a new scope, but do-while loops do not.
- */
- if (mode != ast_do_while)
- state->symbols->push_scope();
-
- if (init_statement != NULL)
- init_statement->hir(instructions, state);
-
- ir_loop *const stmt = new(ctx) ir_loop();
- instructions->push_tail(stmt);
-
- /* Track the current loop nesting.
- */
- ast_iteration_statement *nesting_ast = state->loop_nesting_ast;
-
- state->loop_nesting_ast = this;
-
- /* Likewise, indicate that following code is closest to a loop,
- * NOT closest to a switch.
- */
- bool saved_is_switch_innermost = state->is_switch_innermost;
- state->is_switch_innermost = false;
-
- if (mode != ast_do_while)
- condition_to_hir(stmt, state);
-
- if (body != NULL)
- body->hir(& stmt->body_instructions, state);
-
- if (rest_expression != NULL)
- rest_expression->hir(& stmt->body_instructions, state);
-
- if (mode == ast_do_while)
- condition_to_hir(stmt, state);
-
- if (mode != ast_do_while)
- state->symbols->pop_scope();
+ ir_rvalue *
+ ast_case_statement::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+ {
+ labels->hir(instructions, state);
+
+ /* Conditionally set fallthru state based on break state.
+ */
+ ir_constant *const false_val = new(state) ir_constant(false);
+ ir_dereference_variable *const deref_is_fallthru_var =
+ new(state) ir_dereference_variable(state->switch_state.is_fallthru_var);
+ ir_dereference_variable *const deref_is_break_var =
+ new(state) ir_dereference_variable(state->switch_state.is_break_var);
+ ir_assignment *const reset_fallthru_on_break =
+ new(state) ir_assignment(deref_is_fallthru_var,
+ false_val,
+ deref_is_break_var);
+ instructions->push_tail(reset_fallthru_on_break);
+
+ /* Guard case statements depending on fallthru state.
+ */
+ ir_dereference_variable *const deref_fallthru_guard =
+ new(state) ir_dereference_variable(state->switch_state.is_fallthru_var);
+ ir_if *const test_fallthru = new(state) ir_if(deref_fallthru_guard);
+
+ foreach_list_typed (ast_node, stmt, link, & this->stmts)
+ stmt->hir(& test_fallthru->then_instructions, state);
+
+ instructions->push_tail(test_fallthru);
+
+ /* Case statements do not have r-values.
+ */
+ return NULL;
+ }
+
+
+ ir_rvalue *
+ ast_case_label_list::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+ {
+ foreach_list_typed (ast_case_label, label, link, & this->labels)
+ label->hir(instructions, state);
+
+ /* Case labels do not have r-values.
+ */
+ return NULL;
+ }
+
+
+ ir_rvalue *
+ ast_case_label::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+ {
+ void *ctx = state;
+
+ ir_dereference_variable *deref_fallthru_var =
+ new(ctx) ir_dereference_variable(state->switch_state.is_fallthru_var);
+
+ ir_rvalue *const true_val = new(ctx) ir_constant(true);
+
+ /* If not default case, ...
+ */
+ if (this->test_value != NULL) {
+ /* Conditionally set fallthru state based on
+ * comparison of cached test expression value to case label.
+ */
+ ir_rvalue *const label_rval = this->test_value->hir(instructions, state);
+ ir_constant *label_const = label_rval->constant_expression_value();
+
+ if (!label_const) {
+ YYLTYPE loc = this->test_value->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "switch statement case label must be a "
+ "constant expression");
+
+ /* Stuff a dummy value in to allow processing to continue. */
+ label_const = new(ctx) ir_constant(0);
+ } else {
+ ast_expression *previous_label = (ast_expression *)
+ hash_table_find(state->switch_state.labels_ht,
+ (void *)(uintptr_t)label_const->value.u[0]);
+
+ if (previous_label) {
+ YYLTYPE loc = this->test_value->get_location();
+ _mesa_glsl_error(& loc, state,
+ "duplicate case value");
+
+ loc = previous_label->get_location();
+ _mesa_glsl_error(& loc, state,
+ "this is the previous case label");
+ } else {
+ hash_table_insert(state->switch_state.labels_ht,
+ this->test_value,
+ (void *)(uintptr_t)label_const->value.u[0]);
+ }
+ }
+
+ ir_dereference_variable *deref_test_var =
+ new(ctx) ir_dereference_variable(state->switch_state.test_var);
+
+ ir_rvalue *const test_cond = new(ctx) ir_expression(ir_binop_all_equal,
+ glsl_type::bool_type,
+ label_const,
+ deref_test_var);
+
+ ir_assignment *set_fallthru_on_test =
+ new(ctx) ir_assignment(deref_fallthru_var,
+ true_val,
+ test_cond);
+
+ instructions->push_tail(set_fallthru_on_test);
+ } else { /* default case */
+ if (state->switch_state.previous_default) {
+ printf("a\n");
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(& loc, state,
+ "multiple default labels in one switch");
+
+ printf("b\n");
+
+ loc = state->switch_state.previous_default->get_location();
+ _mesa_glsl_error(& loc, state,
+ "this is the first default label");
+ }
+ state->switch_state.previous_default = this;
+
+ /* Set falltrhu state.
+ */
+ ir_assignment *set_fallthru =
+ new(ctx) ir_assignment(deref_fallthru_var,
+ true_val,
+ NULL);
+
+ instructions->push_tail(set_fallthru);
+ }
+
+ /* Case statements do not have r-values.
+ */
+ return NULL;
+ }
+
+
+ void
+ ast_iteration_statement::condition_to_hir(ir_loop *stmt,
+ struct _mesa_glsl_parse_state *state)
+ {
+ void *ctx = state;
+
+ if (condition != NULL) {
+ ir_rvalue *const cond =
+ condition->hir(& stmt->body_instructions, state);
+
+ if ((cond == NULL)
+ || !cond->type->is_boolean() || !cond->type->is_scalar()) {
+ YYLTYPE loc = condition->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "loop condition must be scalar boolean");
+ } else {
+ /* As the first code in the loop body, generate a block that looks
+ * like 'if (!condition) break;' as the loop termination condition.
+ */
+ ir_rvalue *const not_cond =
+ new(ctx) ir_expression(ir_unop_logic_not, glsl_type::bool_type, cond,
+ NULL);
+
+ ir_if *const if_stmt = new(ctx) ir_if(not_cond);
+
+ ir_jump *const break_stmt =
+ new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
+
+ if_stmt->then_instructions.push_tail(break_stmt);
+ stmt->body_instructions.push_tail(if_stmt);
+ }
+ }
+ }
+
+
+ ir_rvalue *
+ ast_iteration_statement::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+ {
+ void *ctx = state;
+
+ /* For-loops and while-loops start a new scope, but do-while loops do not.
+ */
+ if (mode != ast_do_while)
+ state->symbols->push_scope();
+
+ if (init_statement != NULL)
+ init_statement->hir(instructions, state);
+
+ ir_loop *const stmt = new(ctx) ir_loop();
+ instructions->push_tail(stmt);
+
+ /* Track the current loop nesting.
+ */
+ ast_iteration_statement *nesting_ast = state->loop_nesting_ast;
+
+ state->loop_nesting_ast = this;
+
+ /* Likewise, indicate that following code is closest to a loop,
+ * NOT closest to a switch.
+ */
+ bool saved_is_switch_innermost = state->switch_state.is_switch_innermost;
+ state->switch_state.is_switch_innermost = false;
+
+ if (mode != ast_do_while)
+ condition_to_hir(stmt, state);
+
+ if (body != NULL)
+ body->hir(& stmt->body_instructions, state);
+
+ if (rest_expression != NULL)
+ rest_expression->hir(& stmt->body_instructions, state);
- /* Restore previous nesting before returning.
- */
- state->loop_nesting_ast = nesting_ast;
- state->is_switch_innermost = saved_is_switch_innermost;
+ if (mode == ast_do_while)
+ condition_to_hir(stmt, state);
+
+ if (mode != ast_do_while)
+ state->symbols->pop_scope();
+
+ /* Restore previous nesting before returning.
+ */
+ state->loop_nesting_ast = nesting_ast;
+ state->switch_state.is_switch_innermost = saved_is_switch_innermost;
/* Loops do not have r-values.
*/
diff --git a/mesalib/src/glsl/glcpp/glcpp-lex.l b/mesalib/src/glsl/glcpp/glcpp-lex.l
index 596c6db70..b34f2c0e9 100644
--- a/mesalib/src/glsl/glcpp/glcpp-lex.l
+++ b/mesalib/src/glsl/glcpp/glcpp-lex.l
@@ -1,324 +1,332 @@
-%{
-/*
- * 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 <string.h>
-#include <ctype.h>
-
-#include "glcpp.h"
-#include "glcpp-parse.h"
-
-/* Flex annoyingly generates some functions without making them
- * static. Let's declare them here. */
-int glcpp_get_column (yyscan_t yyscanner);
-void glcpp_set_column (int column_no , yyscan_t yyscanner);
-
-#ifdef _MSC_VER
-#define YY_NO_UNISTD_H
-#endif
-
-#define YY_NO_INPUT
-
-#define YY_USER_ACTION \
- do { \
- yylloc->first_column = yycolumn + 1; \
- yylloc->first_line = yylineno; \
- yycolumn += yyleng; \
- } while(0);
-
-#define YY_USER_INIT \
- do { \
- yylineno = 1; \
- yycolumn = 1; \
- yylloc->source = 0; \
- } while(0)
-%}
-
-%option bison-bridge bison-locations reentrant noyywrap
-%option extra-type="glcpp_parser_t *"
-%option prefix="glcpp_"
-%option stack
-%option never-interactive
-
-%x DONE COMMENT UNREACHABLE SKIP
-
-SPACE [[:space:]]
-NONSPACE [^[:space:]]
-NEWLINE [\n]
-HSPACE [ \t]
-HASH ^{HSPACE}*#{HSPACE}*
-IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]*
-PUNCTUATION [][(){}.&*~!/%<>^|;,=+-]
-OTHER [^][(){}.&*~!/%<>^|;,=#[:space:]+-]+
-
-DIGITS [0-9][0-9]*
-DECIMAL_INTEGER [1-9][0-9]*[uU]?
-OCTAL_INTEGER 0[0-7]*[uU]?
-HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
-
-%%
- /* Implicitly switch between SKIP and INITIAL (non-skipping);
- * don't switch if some other state was explicitly set.
- */
- glcpp_parser_t *parser = yyextra;
- if (YY_START == 0 || YY_START == SKIP) {
- if (parser->lexing_if || parser->skip_stack == NULL || parser->skip_stack->type == SKIP_NO_SKIP) {
- BEGIN 0;
- } else {
- BEGIN SKIP;
- }
- }
-
- /* Single-line comments */
-"//"[^\n]* {
-}
-
- /* Multi-line comments */
-"/*" { yy_push_state(COMMENT, yyscanner); }
-<COMMENT>[^*\n]*
-<COMMENT>[^*\n]*\n { yylineno++; yycolumn = 0; return NEWLINE; }
-<COMMENT>"*"+[^*/\n]*
-<COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; return NEWLINE; }
-<COMMENT>"*"+"/" {
- yy_pop_state(yyscanner);
- if (yyextra->space_tokens)
- return SPACE;
-}
-
-{HASH}version {
- yylval->str = ralloc_strdup (yyextra, yytext);
- yyextra->space_tokens = 0;
- return HASH_VERSION;
-}
-
- /* glcpp doesn't handle #extension, #version, or #pragma directives.
- * Simply pass them through to the main compiler's lexer/parser. */
-{HASH}(extension|pragma)[^\n]+ {
- yylval->str = ralloc_strdup (yyextra, yytext);
- yylineno++;
- yycolumn = 0;
- return OTHER;
-}
-
-{HASH}line{HSPACE}+{DIGITS}{HSPACE}+{DIGITS}{HSPACE}*$ {
- /* Eat characters until the first digit is
- * encountered
- */
- char *ptr = yytext;
- while (!isdigit(*ptr))
- ptr++;
-
- /* Subtract one from the line number because
- * yylineno is zero-based instead of
- * one-based.
- */
- yylineno = strtol(ptr, &ptr, 0) - 1;
- yylloc->source = strtol(ptr, NULL, 0);
-}
-
-{HASH}line{HSPACE}+{DIGITS}{HSPACE}*$ {
- /* Eat characters until the first digit is
- * encountered
- */
- char *ptr = yytext;
- while (!isdigit(*ptr))
- ptr++;
-
- /* Subtract one from the line number because
- * yylineno is zero-based instead of
- * one-based.
- */
- yylineno = strtol(ptr, &ptr, 0) - 1;
-}
-
-<SKIP,INITIAL>{
-{HASH}ifdef {
- yyextra->lexing_if = 1;
- yyextra->space_tokens = 0;
- return HASH_IFDEF;
-}
-
-{HASH}ifndef {
- yyextra->lexing_if = 1;
- yyextra->space_tokens = 0;
- return HASH_IFNDEF;
-}
-
-{HASH}if/[^_a-zA-Z0-9] {
- yyextra->lexing_if = 1;
- yyextra->space_tokens = 0;
- return HASH_IF;
-}
-
-{HASH}elif {
- yyextra->lexing_if = 1;
- yyextra->space_tokens = 0;
- return HASH_ELIF;
-}
-
-{HASH}else {
- yyextra->space_tokens = 0;
- return HASH_ELSE;
-}
-
-{HASH}endif {
- yyextra->space_tokens = 0;
- return HASH_ENDIF;
-}
-}
-
-<SKIP>[^\n] ;
-
-{HASH}error.* {
- char *p;
- for (p = yytext; !isalpha(p[0]); p++); /* skip " # " */
- p += 5; /* skip "error" */
- glcpp_error(yylloc, yyextra, "#error%s", p);
-}
-
-{HASH}define{HSPACE}+/{IDENTIFIER}"(" {
- yyextra->space_tokens = 0;
- return HASH_DEFINE_FUNC;
-}
-
-{HASH}define {
- yyextra->space_tokens = 0;
- return HASH_DEFINE_OBJ;
-}
-
-{HASH}undef {
- yyextra->space_tokens = 0;
- return HASH_UNDEF;
-}
-
-{HASH} {
- yyextra->space_tokens = 0;
- return HASH;
-}
-
-{DECIMAL_INTEGER} {
- yylval->str = ralloc_strdup (yyextra, yytext);
- return INTEGER_STRING;
-}
-
-{OCTAL_INTEGER} {
- yylval->str = ralloc_strdup (yyextra, yytext);
- return INTEGER_STRING;
-}
-
-{HEXADECIMAL_INTEGER} {
- yylval->str = ralloc_strdup (yyextra, yytext);
- return INTEGER_STRING;
-}
-
-"<<" {
- return LEFT_SHIFT;
-}
-
-">>" {
- return RIGHT_SHIFT;
-}
-
-"<=" {
- return LESS_OR_EQUAL;
-}
-
-">=" {
- return GREATER_OR_EQUAL;
-}
-
-"==" {
- return EQUAL;
-}
-
-"!=" {
- return NOT_EQUAL;
-}
-
-"&&" {
- return AND;
-}
-
-"||" {
- return OR;
-}
-
-"##" {
- return PASTE;
-}
-
-"defined" {
- return DEFINED;
-}
-
-{IDENTIFIER} {
- yylval->str = ralloc_strdup (yyextra, yytext);
- return IDENTIFIER;
-}
-
-{PUNCTUATION} {
- return yytext[0];
-}
-
-{OTHER}+ {
- yylval->str = ralloc_strdup (yyextra, yytext);
- return OTHER;
-}
-
-{HSPACE}+ {
- if (yyextra->space_tokens) {
- return SPACE;
- }
-}
-
-<SKIP,INITIAL>\n {
- yyextra->lexing_if = 0;
- yylineno++;
- yycolumn = 0;
- return NEWLINE;
-}
-
- /* Handle missing newline at EOF. */
-<INITIAL><<EOF>> {
- BEGIN DONE; /* Don't keep matching this rule forever. */
- yyextra->lexing_if = 0;
- return NEWLINE;
-}
-
- /* We don't actually use the UNREACHABLE start condition. We
- only have this action here so that we can pretend to call some
- generated functions, (to avoid "defined but not used"
- warnings. */
-<UNREACHABLE>. {
- unput('.');
- yy_top_state(yyextra);
-}
-
-%%
-
-void
-glcpp_lex_set_source_string(glcpp_parser_t *parser, const char *shader)
-{
- yy_scan_string(shader, parser->scanner);
-}
+%{
+/*
+ * 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 <string.h>
+#include <ctype.h>
+
+#include "glcpp.h"
+#include "glcpp-parse.h"
+
+/* Flex annoyingly generates some functions without making them
+ * static. Let's declare them here. */
+int glcpp_get_column (yyscan_t yyscanner);
+void glcpp_set_column (int column_no , yyscan_t yyscanner);
+
+#ifdef _MSC_VER
+#define YY_NO_UNISTD_H
+#endif
+
+#define YY_NO_INPUT
+
+#define YY_USER_ACTION \
+ do { \
+ yylloc->first_column = yycolumn + 1; \
+ yylloc->first_line = yylineno; \
+ yycolumn += yyleng; \
+ } while(0);
+
+#define YY_USER_INIT \
+ do { \
+ yylineno = 1; \
+ yycolumn = 1; \
+ yylloc->source = 0; \
+ } while(0)
+%}
+
+%option bison-bridge bison-locations reentrant noyywrap
+%option extra-type="glcpp_parser_t *"
+%option prefix="glcpp_"
+%option stack
+%option never-interactive
+
+%x DONE COMMENT UNREACHABLE SKIP
+
+SPACE [[:space:]]
+NONSPACE [^[:space:]]
+NEWLINE [\n]
+HSPACE [ \t]
+HASH ^{HSPACE}*#{HSPACE}*
+IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]*
+PUNCTUATION [][(){}.&*~!/%<>^|;,=+-]
+
+/* The OTHER class is simply a catch-all for things that the CPP
+parser just doesn't care about. Since flex regular expressions that
+match longer strings take priority over those matching shorter
+strings, we have to be careful to avoid OTHER matching and hiding
+something that CPP does care about. So we simply exclude all
+characters that appear in any other expressions. */
+
+OTHER [^][_#[:space:]#a-zA-Z0-9(){}.&*~!/%<>^|;,=+-]
+
+DIGITS [0-9][0-9]*
+DECIMAL_INTEGER [1-9][0-9]*[uU]?
+OCTAL_INTEGER 0[0-7]*[uU]?
+HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
+
+%%
+ /* Implicitly switch between SKIP and INITIAL (non-skipping);
+ * don't switch if some other state was explicitly set.
+ */
+ glcpp_parser_t *parser = yyextra;
+ if (YY_START == 0 || YY_START == SKIP) {
+ if (parser->lexing_if || parser->skip_stack == NULL || parser->skip_stack->type == SKIP_NO_SKIP) {
+ BEGIN 0;
+ } else {
+ BEGIN SKIP;
+ }
+ }
+
+ /* Single-line comments */
+"//"[^\n]* {
+}
+
+ /* Multi-line comments */
+"/*" { yy_push_state(COMMENT, yyscanner); }
+<COMMENT>[^*\n]*
+<COMMENT>[^*\n]*\n { yylineno++; yycolumn = 0; return NEWLINE; }
+<COMMENT>"*"+[^*/\n]*
+<COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; return NEWLINE; }
+<COMMENT>"*"+"/" {
+ yy_pop_state(yyscanner);
+ if (yyextra->space_tokens)
+ return SPACE;
+}
+
+{HASH}version {
+ yylval->str = ralloc_strdup (yyextra, yytext);
+ yyextra->space_tokens = 0;
+ return HASH_VERSION;
+}
+
+ /* glcpp doesn't handle #extension, #version, or #pragma directives.
+ * Simply pass them through to the main compiler's lexer/parser. */
+{HASH}(extension|pragma)[^\n]+ {
+ yylval->str = ralloc_strdup (yyextra, yytext);
+ yylineno++;
+ yycolumn = 0;
+ return OTHER;
+}
+
+{HASH}line{HSPACE}+{DIGITS}{HSPACE}+{DIGITS}{HSPACE}*$ {
+ /* Eat characters until the first digit is
+ * encountered
+ */
+ char *ptr = yytext;
+ while (!isdigit(*ptr))
+ ptr++;
+
+ /* Subtract one from the line number because
+ * yylineno is zero-based instead of
+ * one-based.
+ */
+ yylineno = strtol(ptr, &ptr, 0) - 1;
+ yylloc->source = strtol(ptr, NULL, 0);
+}
+
+{HASH}line{HSPACE}+{DIGITS}{HSPACE}*$ {
+ /* Eat characters until the first digit is
+ * encountered
+ */
+ char *ptr = yytext;
+ while (!isdigit(*ptr))
+ ptr++;
+
+ /* Subtract one from the line number because
+ * yylineno is zero-based instead of
+ * one-based.
+ */
+ yylineno = strtol(ptr, &ptr, 0) - 1;
+}
+
+<SKIP,INITIAL>{
+{HASH}ifdef {
+ yyextra->lexing_if = 1;
+ yyextra->space_tokens = 0;
+ return HASH_IFDEF;
+}
+
+{HASH}ifndef {
+ yyextra->lexing_if = 1;
+ yyextra->space_tokens = 0;
+ return HASH_IFNDEF;
+}
+
+{HASH}if/[^_a-zA-Z0-9] {
+ yyextra->lexing_if = 1;
+ yyextra->space_tokens = 0;
+ return HASH_IF;
+}
+
+{HASH}elif {
+ yyextra->lexing_if = 1;
+ yyextra->space_tokens = 0;
+ return HASH_ELIF;
+}
+
+{HASH}else {
+ yyextra->space_tokens = 0;
+ return HASH_ELSE;
+}
+
+{HASH}endif {
+ yyextra->space_tokens = 0;
+ return HASH_ENDIF;
+}
+}
+
+<SKIP>[^\n] ;
+
+{HASH}error.* {
+ char *p;
+ for (p = yytext; !isalpha(p[0]); p++); /* skip " # " */
+ p += 5; /* skip "error" */
+ glcpp_error(yylloc, yyextra, "#error%s", p);
+}
+
+{HASH}define{HSPACE}+/{IDENTIFIER}"(" {
+ yyextra->space_tokens = 0;
+ return HASH_DEFINE_FUNC;
+}
+
+{HASH}define {
+ yyextra->space_tokens = 0;
+ return HASH_DEFINE_OBJ;
+}
+
+{HASH}undef {
+ yyextra->space_tokens = 0;
+ return HASH_UNDEF;
+}
+
+{HASH} {
+ yyextra->space_tokens = 0;
+ return HASH;
+}
+
+{DECIMAL_INTEGER} {
+ yylval->str = ralloc_strdup (yyextra, yytext);
+ return INTEGER_STRING;
+}
+
+{OCTAL_INTEGER} {
+ yylval->str = ralloc_strdup (yyextra, yytext);
+ return INTEGER_STRING;
+}
+
+{HEXADECIMAL_INTEGER} {
+ yylval->str = ralloc_strdup (yyextra, yytext);
+ return INTEGER_STRING;
+}
+
+"<<" {
+ return LEFT_SHIFT;
+}
+
+">>" {
+ return RIGHT_SHIFT;
+}
+
+"<=" {
+ return LESS_OR_EQUAL;
+}
+
+">=" {
+ return GREATER_OR_EQUAL;
+}
+
+"==" {
+ return EQUAL;
+}
+
+"!=" {
+ return NOT_EQUAL;
+}
+
+"&&" {
+ return AND;
+}
+
+"||" {
+ return OR;
+}
+
+"##" {
+ return PASTE;
+}
+
+"defined" {
+ return DEFINED;
+}
+
+{IDENTIFIER} {
+ yylval->str = ralloc_strdup (yyextra, yytext);
+ return IDENTIFIER;
+}
+
+{PUNCTUATION} {
+ return yytext[0];
+}
+
+{OTHER}+ {
+ yylval->str = ralloc_strdup (yyextra, yytext);
+ return OTHER;
+}
+
+{HSPACE}+ {
+ if (yyextra->space_tokens) {
+ return SPACE;
+ }
+}
+
+<SKIP,INITIAL>\n {
+ yyextra->lexing_if = 0;
+ yylineno++;
+ yycolumn = 0;
+ return NEWLINE;
+}
+
+ /* Handle missing newline at EOF. */
+<INITIAL><<EOF>> {
+ BEGIN DONE; /* Don't keep matching this rule forever. */
+ yyextra->lexing_if = 0;
+ return NEWLINE;
+}
+
+ /* We don't actually use the UNREACHABLE start condition. We
+ only have this action here so that we can pretend to call some
+ generated functions, (to avoid "defined but not used"
+ warnings. */
+<UNREACHABLE>. {
+ unput('.');
+ yy_top_state(yyextra);
+}
+
+%%
+
+void
+glcpp_lex_set_source_string(glcpp_parser_t *parser, const char *shader)
+{
+ yy_scan_string(shader, parser->scanner);
+}
diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y
index 2b7e65cd4..efcc205c2 100644
--- a/mesalib/src/glsl/glcpp/glcpp-parse.y
+++ b/mesalib/src/glsl/glcpp/glcpp-parse.y
@@ -85,7 +85,6 @@ _token_create_ival (void *ctx, int type, int ival);
static token_list_t *
_token_list_create (void *ctx);
-/* Note: This function calls ralloc_steal on token. */
static void
_token_list_append (token_list_t *list, token_t *token);
@@ -763,8 +762,6 @@ _token_list_append (token_list_t *list, token_t *token)
node->token = token;
node->next = NULL;
- ralloc_steal (list, token);
-
if (list->head == NULL) {
list->head = node;
} else {
diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy
index e774b4697..d5e85abc0 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -1671,6 +1671,7 @@ switch_statement:
SWITCH '(' expression ')' switch_body
{
$$ = new(state) ast_switch_statement($3, $5);
+ $$->set_location(yylloc);
}
;
@@ -1691,10 +1692,12 @@ case_label:
CASE expression ':'
{
$$ = new(state) ast_case_label($2);
+ $$->set_location(yylloc);
}
| DEFAULT ':'
{
$$ = new(state) ast_case_label(NULL);
+ $$->set_location(yylloc);
}
;
@@ -1705,6 +1708,7 @@ case_label_list:
labels->labels.push_tail(& $1->link);
$$ = labels;
+ $$->set_location(yylloc);
}
| case_label_list case_label
{
@@ -1717,6 +1721,7 @@ case_statement:
case_label_list statement
{
ast_case_statement *stmts = new(state) ast_case_statement($1);
+ stmts->set_location(yylloc);
stmts->stmts.push_tail(& $2->link);
$$ = stmts;
@@ -1732,6 +1737,7 @@ case_statement_list:
case_statement
{
ast_case_statement_list *cases= new(state) ast_case_statement_list();
+ cases->set_location(yylloc);
cases->cases.push_tail(& $1->link);
$$ = cases;
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index 7f8d47ce9..2a72ba1f6 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -51,7 +51,7 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *ctx,
this->info_log = ralloc_strdup(mem_ctx, "");
this->error = false;
this->loop_nesting_ast = NULL;
- this->switch_nesting_ast = NULL;
+ this->switch_state.switch_nesting_ast = NULL;
this->num_builtins_to_link = 0;
diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h
index ee714637d..ce207ecda 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -42,6 +42,20 @@ enum _mesa_glsl_parser_targets {
struct gl_context;
+struct glsl_switch_state {
+ /** Temporary variables needed for switch statement. */
+ ir_variable *test_var;
+ ir_variable *is_fallthru_var;
+ ir_variable *is_break_var;
+ class ast_switch_statement *switch_nesting_ast;
+
+ /** Table of constant values already used in case labels */
+ struct hash_table *labels_ht;
+ class ast_case_label *previous_default;
+
+ bool is_switch_innermost; // if switch stmt is closest to break, ...
+};
+
struct _mesa_glsl_parse_state {
_mesa_glsl_parse_state(struct gl_context *ctx, GLenum target,
void *mem_ctx);
@@ -154,13 +168,8 @@ struct _mesa_glsl_parse_state {
/** Loop or switch statement containing the current instructions. */
class ast_iteration_statement *loop_nesting_ast;
- class ast_switch_statement *switch_nesting_ast;
- bool is_switch_innermost; // if switch stmt is closest to break, ...
- /** Temporary variables needed for switch statement. */
- ir_variable *test_var;
- ir_variable *is_fallthru_var;
- ir_variable *is_break_var;
+ struct glsl_switch_state switch_state;
/** List of structures defined in user code. */
const glsl_type **user_structures;
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index 509575192..82bddb003 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -856,6 +856,27 @@ get_main_function_signature(gl_shader *sh)
/**
+ * This class is only used in link_intrastage_shaders() below but declaring
+ * it inside that function leads to compiler warnings with some versions of
+ * gcc.
+ */
+class array_sizing_visitor : public ir_hierarchical_visitor {
+public:
+ virtual ir_visitor_status visit(ir_variable *var)
+ {
+ if (var->type->is_array() && (var->type->length == 0)) {
+ const glsl_type *type =
+ glsl_type::get_array_instance(var->type->fields.array,
+ var->max_array_access + 1);
+ assert(type != NULL);
+ var->type = type;
+ }
+ return visit_continue;
+ }
+};
+
+
+/**
* Combine a group of shaders for a single stage to generate a linked shader
*
* \note
@@ -1005,22 +1026,7 @@ link_intrastage_shaders(void *mem_ctx,
* max_array_access field.
*/
if (linked != NULL) {
- class array_sizing_visitor : public ir_hierarchical_visitor {
- public:
- virtual ir_visitor_status visit(ir_variable *var)
- {
- if (var->type->is_array() && (var->type->length == 0)) {
- const glsl_type *type =
- glsl_type::get_array_instance(var->type->fields.array,
- var->max_array_access + 1);
-
- assert(type != NULL);
- var->type = type;
- }
-
- return visit_continue;
- }
- } v;
+ array_sizing_visitor v;
v.run(linked->ir);
}