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 hieralloc-based new need not call delete. It's
     30     * easier to just hieralloc_free 'ctx' (or any of its ancestors). */
     31    static void* operator new(size_t size, void *ctx)
     32    {
     33       void *entry = hieralloc_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
     39     * hieralloc_free in that case. Here, C++ will have already called the
     40     * destructor so tell hieralloc not to do that again. */
     41    static void operator delete(void *table)
     42    {
     43       hieralloc_set_destructor(table, NULL);
     44       hieralloc_free(table);
     45    }
     46 
     47    symbol_table_entry(ir_variable *v)                     : v(v), f(0), t(0) {}
     48    symbol_table_entry(ir_function *f)                     : v(0), f(f), t(0) {}
     49    symbol_table_entry(const glsl_type *t)                 : v(0), f(0), t(t) {}
     50 
     51    ir_variable *v;
     52    ir_function *f;
     53    const glsl_type *t;
     54 };
     55 
     56 glsl_symbol_table::glsl_symbol_table(void * ctx)
     57 {
     58    this->language_version = 120;
     59    this->table = _mesa_symbol_table_ctor();
     60    this->mem_ctx = hieralloc_allocate(ctx, 0, "symbol table entries");
     61 }
     62 
     63 glsl_symbol_table::~glsl_symbol_table()
     64 {
     65    _mesa_symbol_table_dtor(table);
     66    //hieralloc_free(mem_ctx); parent context free will free this
     67 }
     68 
     69 void glsl_symbol_table::push_scope()
     70 {
     71    _mesa_symbol_table_push_scope(table);
     72 }
     73 
     74 void glsl_symbol_table::pop_scope()
     75 {
     76    _mesa_symbol_table_pop_scope(table);
     77 }
     78 
     79 bool glsl_symbol_table::name_declared_this_scope(const char *name)
     80 {
     81    return _mesa_symbol_table_symbol_scope(table, -1, name) == 0;
     82 }
     83 
     84 bool glsl_symbol_table::add_variable(ir_variable *v)
     85 {
     86    if (this->language_version == 110) {
     87       /* In 1.10, functions and variables have separate namespaces. */
     88       symbol_table_entry *existing = get_entry(v->name);
     89       if (name_declared_this_scope(v->name)) {
     90 	 /* If there's already an existing function (not a constructor!) in
     91 	  * the current scope, just update the existing entry to include 'v'.
     92 	  */
     93 	 if (existing->v == NULL && existing->t == NULL) {
     94 	    existing->v = v;
     95 	    return true;
     96 	 }
     97       } else {
     98 	 /* If not declared at this scope, add a new entry.  But if an existing
     99 	  * entry includes a function, propagate that to this block - otherwise
    100 	  * the new variable declaration would shadow the function.
    101 	  */
    102 	 symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(v);
    103 	 if (existing != NULL)
    104 	    entry->f = existing->f;
    105 	 int added = _mesa_symbol_table_add_symbol(table, -1, v->name, entry);
    106 	 assert(added == 0);
    107 	 (void)added;
    108 	 return true;
    109       }
    110       return false;
    111    }
    112 
    113    /* 1.20+ rules: */
    114    symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(v);
    115    return _mesa_symbol_table_add_symbol(table, -1, v->name, entry) == 0;
    116 }
    117 
    118 bool glsl_symbol_table::add_type(const char *name, const glsl_type *t)
    119 {
    120    symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(t);
    121    return _mesa_symbol_table_add_symbol(table, -1, name, entry) == 0;
    122 }
    123 
    124 bool glsl_symbol_table::add_function(ir_function *f)
    125 {
    126    if (this->language_version == 110 && name_declared_this_scope(f->name)) {
    127       /* In 1.10, functions and variables have separate namespaces. */
    128       symbol_table_entry *existing = get_entry(f->name);
    129       if ((existing->f == NULL) && (existing->t == NULL)) {
    130 	 existing->f = f;
    131 	 return true;
    132       }
    133    }
    134    symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(f);
    135    return _mesa_symbol_table_add_symbol(table, -1, f->name, entry) == 0;
    136 }
    137 
    138 void glsl_symbol_table::add_global_function(ir_function *f)
    139 {
    140    symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(f);
    141    int added = _mesa_symbol_table_add_global_symbol(table, -1, f->name, entry);
    142    assert(added == 0);
    143 }
    144 
    145 ir_variable *glsl_symbol_table::get_variable(const char *name)
    146 {
    147    symbol_table_entry *entry = get_entry(name);
    148    return entry != NULL ? entry->v : NULL;
    149 }
    150 
    151 const glsl_type *glsl_symbol_table::get_type(const char *name)
    152 {
    153    symbol_table_entry *entry = get_entry(name);
    154    return entry != NULL ? entry->t : NULL;
    155 }
    156 
    157 ir_function *glsl_symbol_table::get_function(const char *name)
    158 {
    159    symbol_table_entry *entry = get_entry(name);
    160    return entry != NULL ? entry->f : NULL;
    161 }
    162 
    163 symbol_table_entry *glsl_symbol_table::get_entry(const char *name)
    164 {
    165    return (symbol_table_entry *)
    166       _mesa_symbol_table_find_symbol(table, -1, name);
    167 }
    168