101e04c3fSmrg/* -*- c++ -*- */ 201e04c3fSmrg/* 301e04c3fSmrg * Copyright © 2010 Intel Corporation 401e04c3fSmrg * 501e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 601e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 701e04c3fSmrg * to deal in the Software without restriction, including without limitation 801e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 901e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 1001e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1101e04c3fSmrg * 1201e04c3fSmrg * The above copyright notice and this permission notice (including the next 1301e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1401e04c3fSmrg * Software. 1501e04c3fSmrg * 1601e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1701e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1801e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1901e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2001e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2101e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2201e04c3fSmrg * DEALINGS IN THE SOFTWARE. 2301e04c3fSmrg */ 2401e04c3fSmrg 2501e04c3fSmrg#include "glsl_symbol_table.h" 2601e04c3fSmrg#include "ast.h" 2701e04c3fSmrg 2801e04c3fSmrgclass symbol_table_entry { 2901e04c3fSmrgpublic: 3001e04c3fSmrg DECLARE_LINEAR_ALLOC_CXX_OPERATORS(symbol_table_entry); 3101e04c3fSmrg 3201e04c3fSmrg bool add_interface(const glsl_type *i, enum ir_variable_mode mode) 3301e04c3fSmrg { 3401e04c3fSmrg const glsl_type **dest; 3501e04c3fSmrg 3601e04c3fSmrg switch (mode) { 3701e04c3fSmrg case ir_var_uniform: 3801e04c3fSmrg dest = &ibu; 3901e04c3fSmrg break; 4001e04c3fSmrg case ir_var_shader_storage: 4101e04c3fSmrg dest = &iss; 4201e04c3fSmrg break; 4301e04c3fSmrg case ir_var_shader_in: 4401e04c3fSmrg dest = &ibi; 4501e04c3fSmrg break; 4601e04c3fSmrg case ir_var_shader_out: 4701e04c3fSmrg dest = &ibo; 4801e04c3fSmrg break; 4901e04c3fSmrg default: 5001e04c3fSmrg assert(!"Unsupported interface variable mode!"); 5101e04c3fSmrg return false; 5201e04c3fSmrg } 5301e04c3fSmrg 5401e04c3fSmrg if (*dest != NULL) { 5501e04c3fSmrg return false; 5601e04c3fSmrg } else { 5701e04c3fSmrg *dest = i; 5801e04c3fSmrg return true; 5901e04c3fSmrg } 6001e04c3fSmrg } 6101e04c3fSmrg 6201e04c3fSmrg const glsl_type *get_interface(enum ir_variable_mode mode) 6301e04c3fSmrg { 6401e04c3fSmrg switch (mode) { 6501e04c3fSmrg case ir_var_uniform: 6601e04c3fSmrg return ibu; 6701e04c3fSmrg case ir_var_shader_storage: 6801e04c3fSmrg return iss; 6901e04c3fSmrg case ir_var_shader_in: 7001e04c3fSmrg return ibi; 7101e04c3fSmrg case ir_var_shader_out: 7201e04c3fSmrg return ibo; 7301e04c3fSmrg default: 7401e04c3fSmrg assert(!"Unsupported interface variable mode!"); 7501e04c3fSmrg return NULL; 7601e04c3fSmrg } 7701e04c3fSmrg } 7801e04c3fSmrg 7901e04c3fSmrg symbol_table_entry(ir_variable *v) : 8001e04c3fSmrg v(v), f(0), t(0), ibu(0), iss(0), ibi(0), ibo(0), a(0) {} 8101e04c3fSmrg symbol_table_entry(ir_function *f) : 8201e04c3fSmrg v(0), f(f), t(0), ibu(0), iss(0), ibi(0), ibo(0), a(0) {} 8301e04c3fSmrg symbol_table_entry(const glsl_type *t) : 8401e04c3fSmrg v(0), f(0), t(t), ibu(0), iss(0), ibi(0), ibo(0), a(0) {} 8501e04c3fSmrg symbol_table_entry(const glsl_type *t, enum ir_variable_mode mode) : 8601e04c3fSmrg v(0), f(0), t(0), ibu(0), iss(0), ibi(0), ibo(0), a(0) 8701e04c3fSmrg { 8801e04c3fSmrg assert(t->is_interface()); 8901e04c3fSmrg add_interface(t, mode); 9001e04c3fSmrg } 9101e04c3fSmrg symbol_table_entry(const class ast_type_specifier *a): 9201e04c3fSmrg v(0), f(0), t(0), ibu(0), iss(0), ibi(0), ibo(0), a(a) {} 9301e04c3fSmrg 9401e04c3fSmrg ir_variable *v; 9501e04c3fSmrg ir_function *f; 9601e04c3fSmrg const glsl_type *t; 9701e04c3fSmrg const glsl_type *ibu; 9801e04c3fSmrg const glsl_type *iss; 9901e04c3fSmrg const glsl_type *ibi; 10001e04c3fSmrg const glsl_type *ibo; 10101e04c3fSmrg const class ast_type_specifier *a; 10201e04c3fSmrg}; 10301e04c3fSmrg 10401e04c3fSmrgglsl_symbol_table::glsl_symbol_table() 10501e04c3fSmrg{ 10601e04c3fSmrg this->separate_function_namespace = false; 10701e04c3fSmrg this->table = _mesa_symbol_table_ctor(); 10801e04c3fSmrg this->mem_ctx = ralloc_context(NULL); 10901e04c3fSmrg this->linalloc = linear_alloc_parent(this->mem_ctx, 0); 11001e04c3fSmrg} 11101e04c3fSmrg 11201e04c3fSmrgglsl_symbol_table::~glsl_symbol_table() 11301e04c3fSmrg{ 11401e04c3fSmrg _mesa_symbol_table_dtor(table); 11501e04c3fSmrg ralloc_free(mem_ctx); 11601e04c3fSmrg} 11701e04c3fSmrg 11801e04c3fSmrgvoid glsl_symbol_table::push_scope() 11901e04c3fSmrg{ 12001e04c3fSmrg _mesa_symbol_table_push_scope(table); 12101e04c3fSmrg} 12201e04c3fSmrg 12301e04c3fSmrgvoid glsl_symbol_table::pop_scope() 12401e04c3fSmrg{ 12501e04c3fSmrg _mesa_symbol_table_pop_scope(table); 12601e04c3fSmrg} 12701e04c3fSmrg 12801e04c3fSmrgbool glsl_symbol_table::name_declared_this_scope(const char *name) 12901e04c3fSmrg{ 13001e04c3fSmrg return _mesa_symbol_table_symbol_scope(table, name) == 0; 13101e04c3fSmrg} 13201e04c3fSmrg 13301e04c3fSmrgbool glsl_symbol_table::add_variable(ir_variable *v) 13401e04c3fSmrg{ 13501e04c3fSmrg assert(v->data.mode != ir_var_temporary); 13601e04c3fSmrg 13701e04c3fSmrg if (this->separate_function_namespace) { 13801e04c3fSmrg /* In 1.10, functions and variables have separate namespaces. */ 13901e04c3fSmrg symbol_table_entry *existing = get_entry(v->name); 14001e04c3fSmrg if (name_declared_this_scope(v->name)) { 14101e04c3fSmrg /* If there's already an existing function (not a constructor!) in 14201e04c3fSmrg * the current scope, just update the existing entry to include 'v'. 14301e04c3fSmrg */ 14401e04c3fSmrg if (existing->v == NULL && existing->t == NULL) { 14501e04c3fSmrg existing->v = v; 14601e04c3fSmrg return true; 14701e04c3fSmrg } 14801e04c3fSmrg } else { 14901e04c3fSmrg /* If not declared at this scope, add a new entry. But if an existing 15001e04c3fSmrg * entry includes a function, propagate that to this block - otherwise 15101e04c3fSmrg * the new variable declaration would shadow the function. 15201e04c3fSmrg */ 15301e04c3fSmrg symbol_table_entry *entry = new(linalloc) symbol_table_entry(v); 15401e04c3fSmrg if (existing != NULL) 15501e04c3fSmrg entry->f = existing->f; 15601e04c3fSmrg int added = _mesa_symbol_table_add_symbol(table, v->name, entry); 15701e04c3fSmrg assert(added == 0); 15801e04c3fSmrg (void)added; 15901e04c3fSmrg return true; 16001e04c3fSmrg } 16101e04c3fSmrg return false; 16201e04c3fSmrg } 16301e04c3fSmrg 16401e04c3fSmrg /* 1.20+ rules: */ 16501e04c3fSmrg symbol_table_entry *entry = new(linalloc) symbol_table_entry(v); 16601e04c3fSmrg return _mesa_symbol_table_add_symbol(table, v->name, entry) == 0; 16701e04c3fSmrg} 16801e04c3fSmrg 16901e04c3fSmrgbool glsl_symbol_table::add_type(const char *name, const glsl_type *t) 17001e04c3fSmrg{ 17101e04c3fSmrg symbol_table_entry *entry = new(linalloc) symbol_table_entry(t); 17201e04c3fSmrg return _mesa_symbol_table_add_symbol(table, name, entry) == 0; 17301e04c3fSmrg} 17401e04c3fSmrg 17501e04c3fSmrgbool glsl_symbol_table::add_interface(const char *name, const glsl_type *i, 17601e04c3fSmrg enum ir_variable_mode mode) 17701e04c3fSmrg{ 17801e04c3fSmrg assert(i->is_interface()); 17901e04c3fSmrg symbol_table_entry *entry = get_entry(name); 18001e04c3fSmrg if (entry == NULL) { 18101e04c3fSmrg symbol_table_entry *entry = 18201e04c3fSmrg new(linalloc) symbol_table_entry(i, mode); 18301e04c3fSmrg bool add_interface_symbol_result = 18401e04c3fSmrg _mesa_symbol_table_add_symbol(table, name, entry) == 0; 18501e04c3fSmrg assert(add_interface_symbol_result); 18601e04c3fSmrg return add_interface_symbol_result; 18701e04c3fSmrg } else { 18801e04c3fSmrg return entry->add_interface(i, mode); 18901e04c3fSmrg } 19001e04c3fSmrg} 19101e04c3fSmrg 19201e04c3fSmrgbool glsl_symbol_table::add_function(ir_function *f) 19301e04c3fSmrg{ 19401e04c3fSmrg if (this->separate_function_namespace && name_declared_this_scope(f->name)) { 19501e04c3fSmrg /* In 1.10, functions and variables have separate namespaces. */ 19601e04c3fSmrg symbol_table_entry *existing = get_entry(f->name); 19701e04c3fSmrg if ((existing->f == NULL) && (existing->t == NULL)) { 19801e04c3fSmrg existing->f = f; 19901e04c3fSmrg return true; 20001e04c3fSmrg } 20101e04c3fSmrg } 20201e04c3fSmrg symbol_table_entry *entry = new(linalloc) symbol_table_entry(f); 20301e04c3fSmrg return _mesa_symbol_table_add_symbol(table, f->name, entry) == 0; 20401e04c3fSmrg} 20501e04c3fSmrg 20601e04c3fSmrgbool glsl_symbol_table::add_default_precision_qualifier(const char *type_name, 20701e04c3fSmrg int precision) 20801e04c3fSmrg{ 20901e04c3fSmrg char *name = ralloc_asprintf(mem_ctx, "#default_precision_%s", type_name); 21001e04c3fSmrg 21101e04c3fSmrg ast_type_specifier *default_specifier = new(linalloc) ast_type_specifier(name); 21201e04c3fSmrg default_specifier->default_precision = precision; 21301e04c3fSmrg 21401e04c3fSmrg symbol_table_entry *entry = 21501e04c3fSmrg new(linalloc) symbol_table_entry(default_specifier); 21601e04c3fSmrg 21701e04c3fSmrg if (!get_entry(name)) 21801e04c3fSmrg return _mesa_symbol_table_add_symbol(table, name, entry) == 0; 21901e04c3fSmrg 22001e04c3fSmrg return _mesa_symbol_table_replace_symbol(table, name, entry) == 0; 22101e04c3fSmrg} 22201e04c3fSmrg 22301e04c3fSmrgvoid glsl_symbol_table::add_global_function(ir_function *f) 22401e04c3fSmrg{ 22501e04c3fSmrg symbol_table_entry *entry = new(linalloc) symbol_table_entry(f); 22601e04c3fSmrg int added = _mesa_symbol_table_add_global_symbol(table, f->name, entry); 22701e04c3fSmrg assert(added == 0); 22801e04c3fSmrg (void)added; 22901e04c3fSmrg} 23001e04c3fSmrg 23101e04c3fSmrgir_variable *glsl_symbol_table::get_variable(const char *name) 23201e04c3fSmrg{ 23301e04c3fSmrg symbol_table_entry *entry = get_entry(name); 23401e04c3fSmrg return entry != NULL ? entry->v : NULL; 23501e04c3fSmrg} 23601e04c3fSmrg 23701e04c3fSmrgconst glsl_type *glsl_symbol_table::get_type(const char *name) 23801e04c3fSmrg{ 23901e04c3fSmrg symbol_table_entry *entry = get_entry(name); 24001e04c3fSmrg return entry != NULL ? entry->t : NULL; 24101e04c3fSmrg} 24201e04c3fSmrg 24301e04c3fSmrgconst glsl_type *glsl_symbol_table::get_interface(const char *name, 24401e04c3fSmrg enum ir_variable_mode mode) 24501e04c3fSmrg{ 24601e04c3fSmrg symbol_table_entry *entry = get_entry(name); 24701e04c3fSmrg return entry != NULL ? entry->get_interface(mode) : NULL; 24801e04c3fSmrg} 24901e04c3fSmrg 25001e04c3fSmrgir_function *glsl_symbol_table::get_function(const char *name) 25101e04c3fSmrg{ 25201e04c3fSmrg symbol_table_entry *entry = get_entry(name); 25301e04c3fSmrg return entry != NULL ? entry->f : NULL; 25401e04c3fSmrg} 25501e04c3fSmrg 25601e04c3fSmrgint glsl_symbol_table::get_default_precision_qualifier(const char *type_name) 25701e04c3fSmrg{ 25801e04c3fSmrg char *name = ralloc_asprintf(mem_ctx, "#default_precision_%s", type_name); 25901e04c3fSmrg symbol_table_entry *entry = get_entry(name); 26001e04c3fSmrg if (!entry) 26101e04c3fSmrg return ast_precision_none; 26201e04c3fSmrg return entry->a->default_precision; 26301e04c3fSmrg} 26401e04c3fSmrg 26501e04c3fSmrgsymbol_table_entry *glsl_symbol_table::get_entry(const char *name) 26601e04c3fSmrg{ 26701e04c3fSmrg return (symbol_table_entry *) 26801e04c3fSmrg _mesa_symbol_table_find_symbol(table, name); 26901e04c3fSmrg} 27001e04c3fSmrg 27101e04c3fSmrgvoid 27201e04c3fSmrgglsl_symbol_table::disable_variable(const char *name) 27301e04c3fSmrg{ 27401e04c3fSmrg /* Ideally we would remove the variable's entry from the symbol table, but 27501e04c3fSmrg * that would be difficult. Fortunately, since this is only used for 27601e04c3fSmrg * built-in variables, it won't be possible for the shader to re-introduce 27701e04c3fSmrg * the variable later, so all we really need to do is to make sure that 27801e04c3fSmrg * further attempts to access it using get_variable() will return NULL. 27901e04c3fSmrg */ 28001e04c3fSmrg symbol_table_entry *entry = get_entry(name); 28101e04c3fSmrg if (entry != NULL) { 28201e04c3fSmrg entry->v = NULL; 28301e04c3fSmrg } 28401e04c3fSmrg} 28501e04c3fSmrg 28601e04c3fSmrgvoid 28701e04c3fSmrgglsl_symbol_table::replace_variable(const char *name, 28801e04c3fSmrg ir_variable *v) 28901e04c3fSmrg{ 29001e04c3fSmrg symbol_table_entry *entry = get_entry(name); 29101e04c3fSmrg if (entry != NULL) { 29201e04c3fSmrg entry->v = v; 29301e04c3fSmrg } 29401e04c3fSmrg} 295