Home | History | Annotate | Download | only in glsl
      1 /* -*- c++ -*- */
      2 /*
      3  * Copyright  2010 Intel Corporation
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the "Software"),
      7  * to deal in the Software without restriction, including without limitation
      8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      9  * and/or sell copies of the Software, and to permit persons to whom the
     10  * Software is furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     22  * DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 #include "glsl_symbol_table.h"
     26 
     27 class symbol_table_entry {
     28 public:
     29    /* Callers of this ralloc-based new need not call delete. It's
     30     * easier to just ralloc_free 'ctx' (or any of its ancestors). */
     31    static void* operator new(size_t size, void *ctx)
     32    {
     33       void *entry = ralloc_size(ctx, size);
     34       assert(entry != NULL);
     35       return entry;
     36    }
     37 
     38    /* If the user *does* call delete, that's OK, we will just ralloc_free. */
     39    static void operator delete(void *entry)
     40    {
     41       ralloc_free(entry);
     42    }
     43 
     44    symbol_table_entry(ir_variable *v)               : v(v), f(0), t(0), u(0) {}
     45    symbol_table_entry(ir_function *f)               : v(0), f(f), t(0), u(0) {}
     46    symbol_table_entry(const glsl_type *t)           : v(0), f(0), t(t), u(0) {}
     47    symbol_table_entry(struct gl_uniform_block *u)   : v(0), f(0), t(0), u(u) {}
     48 
     49    ir_variable *v;
     50    ir_function *f;
     51    const glsl_type *t;
     52    struct gl_uniform_block *u;
     53 };
     54 
     55 glsl_symbol_table::glsl_symbol_table()
     56 {
     57    this->language_version = 120;
     58    this->table = _mesa_symbol_table_ctor();
     59    this->mem_ctx = ralloc_context(NULL);
     60 }
     61 
     62 glsl_symbol_table::~glsl_symbol_table()
     63 {
     64    _mesa_symbol_table_dtor(table);
     65    ralloc_free(mem_ctx);
     66 }
     67 
     68 void glsl_symbol_table::push_scope()
     69 {
     70    _mesa_symbol_table_push_scope(table);
     71 }
     72 
     73 void glsl_symbol_table::pop_scope()
     74 {
     75    _mesa_symbol_table_pop_scope(table);
     76 }
     77 
     78 bool glsl_symbol_table::name_declared_this_scope(const char *name)
     79 {
     80    return _mesa_symbol_table_symbol_scope(table, -1, name) == 0;
     81 }
     82 
     83 bool glsl_symbol_table::add_variable(ir_variable *v)
     84 {
     85    if (this->language_version == 110) {
     86       /* In 1.10, functions and variables have separate namespaces. */
     87       symbol_table_entry *existing = get_entry(v->name);
     88       if (name_declared_this_scope(v->name)) {
     89 	 /* If there's already an existing function (not a constructor!) in
     90 	  * the current scope, just update the existing entry to include 'v'.
     91 	  */
     92 	 if (existing->v == NULL && existing->t == NULL) {
     93 	    existing->v = v;
     94 	    return true;
     95 	 }
     96       } else {
     97 	 /* If not declared at this scope, add a new entry.  But if an existing
     98 	  * entry includes a function, propagate that to this block - otherwise
     99 	  * the new variable declaration would shadow the function.
    100 	  */
    101 	 symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(v);
    102 	 if (existing != NULL)
    103 	    entry->f = existing->f;
    104 	 int added = _mesa_symbol_table_add_symbol(table, -1, v->name, entry);
    105 	 assert(added == 0);
    106 	 (void)added;
    107 	 return true;
    108       }
    109       return false;
    110    }
    111 
    112    /* 1.20+ rules: */
    113    symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(v);
    114    return _mesa_symbol_table_add_symbol(table, -1, v->name, entry) == 0;
    115 }
    116 
    117 bool glsl_symbol_table::add_type(const char *name, const glsl_type *t)
    118 {
    119    symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(t);
    120    return _mesa_symbol_table_add_symbol(table, -1, name, entry) == 0;
    121 }
    122 
    123 bool glsl_symbol_table::add_function(ir_function *f)
    124 {
    125    if (this->language_version == 110 && name_declared_this_scope(f->name)) {
    126       /* In 1.10, functions and variables have separate namespaces. */
    127       symbol_table_entry *existing = get_entry(f->name);
    128       if ((existing->f == NULL) && (existing->t == NULL)) {
    129 	 existing->f = f;
    130 	 return true;
    131       }
    132    }
    133    symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(f);
    134    return _mesa_symbol_table_add_symbol(table, -1, f->name, entry) == 0;
    135 }
    136 
    137 bool glsl_symbol_table::add_uniform_block(struct gl_uniform_block *u)
    138 {
    139    symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(u);
    140    return _mesa_symbol_table_add_symbol(table, -1, u->Name, entry) == 0;
    141 }
    142 
    143 void glsl_symbol_table::add_global_function(ir_function *f)
    144 {
    145    symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(f);
    146    int added = _mesa_symbol_table_add_global_symbol(table, -1, f->name, entry);
    147    assert(added == 0);
    148    (void)added;
    149 }
    150 
    151 ir_variable *glsl_symbol_table::get_variable(const char *name)
    152 {
    153    symbol_table_entry *entry = get_entry(name);
    154    return entry != NULL ? entry->v : NULL;
    155 }
    156 
    157 const glsl_type *glsl_symbol_table::get_type(const char *name)
    158 {
    159    symbol_table_entry *entry = get_entry(name);
    160    return entry != NULL ? entry->t : NULL;
    161 }
    162 
    163 ir_function *glsl_symbol_table::get_function(const char *name)
    164 {
    165    symbol_table_entry *entry = get_entry(name);
    166    return entry != NULL ? entry->f : NULL;
    167 }
    168 
    169 symbol_table_entry *glsl_symbol_table::get_entry(const char *name)
    170 {
    171    return (symbol_table_entry *)
    172       _mesa_symbol_table_find_symbol(table, -1, name);
    173 }
    174