summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2010-03-19 15:32:57 -0700
committerEric Anholt <[email protected]>2010-06-24 14:56:26 -0700
commit84341f4b2014810b2964230384fe76338be1d78e (patch)
treec1434f4b61d6a26d8fea5e397c264b531764fd30 /src/mesa
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.
Diffstat (limited to 'src/mesa')
-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 6a5d6868974..3fea5ee1f1f 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 0c054ef1396..1d570fc1a09 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);