summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2010-03-19 15:32:57 -0700
committerEric Anholt <eric@anholt.net>2010-06-24 14:56:26 -0700
commit84341f4b2014810b2964230384fe76338be1d78e (patch)
treec1434f4b61d6a26d8fea5e397c264b531764fd30
parentb5e381d9783f17c9a527ac38122444eac6807566 (diff)
Make sure that symbols aren't multiply defined in the same scope.
The assembly parser is already checking this, but we're relying on the symbol table handling it in glsl2.
-rw-r--r--src/mesa/shader/symbol_table.c52
-rw-r--r--src/mesa/shader/symbol_table.h3
2 files changed, 54 insertions, 1 deletions
diff --git a/src/mesa/shader/symbol_table.c b/src/mesa/shader/symbol_table.c
index 6a5d686897..3fea5ee1f1 100644
--- a/src/mesa/shader/symbol_table.c
+++ b/src/mesa/shader/symbol_table.c
@@ -58,7 +58,9 @@ struct symbol {
*/
int name_space;
-
+ /** Scope depth where this symbol was defined. */
+ unsigned depth;
+
/**
* Arbitrary user supplied data.
*/
@@ -104,6 +106,9 @@ struct _mesa_symbol_table {
/** List of all symbol headers in the table. */
struct symbol_header *hdr;
+
+ /** Current scope depth. */
+ unsigned depth;
};
@@ -157,6 +162,7 @@ _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table)
struct symbol *sym = scope->symbols;
table->current_scope = scope->next;
+ table->depth--;
free(scope);
@@ -184,6 +190,7 @@ _mesa_symbol_table_push_scope(struct _mesa_symbol_table *table)
scope->next = table->current_scope;
table->current_scope = scope;
+ table->depth++;
}
@@ -261,6 +268,36 @@ _mesa_symbol_table_iterator_next(struct _mesa_symbol_table_iterator *iter)
}
+/**
+ * Determine the scope "distance" of a symbol from the current scope
+ *
+ * \return
+ * A non-negative number for the number of scopes between the current scope
+ * and the scope where a symbol was defined. A value of zero means the current
+ * scope. A negative number if the symbol does not exist.
+ */
+int
+_mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table,
+ int name_space, const char *name)
+{
+ struct symbol_header *const hdr = find_symbol(table, name);
+ struct symbol *sym;
+
+ if (hdr != NULL) {
+ 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)) {
+ assert(sym->depth <= table->depth);
+ return sym->depth - table->depth;
+ }
+ }
+ }
+
+ return -1;
+}
+
+
void *
_mesa_symbol_table_find_symbol(struct _mesa_symbol_table *table,
int name_space, const char *name)
@@ -309,12 +346,25 @@ _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
check_symbol_table(table);
+ /* If the symbol already exists in this namespace at this scope, it cannot
+ * be added to the table.
+ */
+ for (sym = hdr->symbols
+ ; (sym != NULL) && (sym->name_space != name_space)
+ ; sym = sym->next_with_same_name) {
+ /* empty */
+ }
+
+ if (sym && (sym->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);
diff --git a/src/mesa/shader/symbol_table.h b/src/mesa/shader/symbol_table.h
index 0c054ef139..1d570fc1a0 100644
--- a/src/mesa/shader/symbol_table.h
+++ b/src/mesa/shader/symbol_table.h
@@ -33,6 +33,9 @@ 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 int _mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table,
+ int name_space, const char *name);
+
extern void *_mesa_symbol_table_find_symbol(
struct _mesa_symbol_table *symtab, int name_space, const char *name);