19d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org/* -*- c++ -*- */
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright © 2010 Intel Corporation
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Permission is hereby granted, free of charge, to any person obtaining a
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * copy of this software and associated documentation files (the "Software"),
79d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org * to deal in the Software without restriction, including without limitation
89d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * and/or sell copies of the Software, and to permit persons to whom the
109d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org * Software is furnished to do so, subject to the following conditions:
119d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org *
1269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * The above copyright notice and this permission notice (including the next
139d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org * paragraph) shall be included in all copies or substantial portions of the
14181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com * Software.
15383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com *
16383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com * DEALINGS IN THE SOFTWARE.
23383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com */
24383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com
25383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com#include "glsl_symbol_table.h"
26383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com
27383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.comclass symbol_table_entry {
28383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.compublic:
29383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com   /* Callers of this ralloc-based new need not call delete. It's
30383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    * easier to just ralloc_free 'ctx' (or any of its ancestors). */
31383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com   static void* operator new(size_t size, void *ctx)
32181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com   {
33181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com      void *entry = ralloc_size(ctx, size);
34181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com      assert(entry != NULL);
35181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com      return entry;
36181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com   }
37b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
38181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com   /* If the user *does* call delete, that's OK, we will just ralloc_free. */
399d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   static void operator delete(void *entry)
409d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   {
41c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com      ralloc_free(entry);
42c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com   }
43afec7ba75962517b17293799d3fc70d39fa7dbf2tomhudson@google.com
44c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com   symbol_table_entry(ir_variable *v)               : v(v), f(0), t(0), u(0) {}
45c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com   symbol_table_entry(ir_function *f)               : v(0), f(f), t(0), u(0) {}
46c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com   symbol_table_entry(const glsl_type *t)           : v(0), f(0), t(t), u(0) {}
479d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   symbol_table_entry(struct gl_uniform_block *u)   : v(0), f(0), t(0), u(u) {}
48c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com
499d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   ir_variable *v;
509d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   ir_function *f;
519d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   const glsl_type *t;
529d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   struct gl_uniform_block *u;
539d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org};
549d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org
552047f00e4698f83499ab91911999a65c21a951c9epoger@google.comglsl_symbol_table::glsl_symbol_table()
5661f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com{
5761f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com   this->language_version = 120;
5861f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com   this->table = _mesa_symbol_table_ctor();
5961f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com   this->mem_ctx = ralloc_context(NULL);
6061f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com}
6161f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com
6261f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.comglsl_symbol_table::~glsl_symbol_table()
6361f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com{
649d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   _mesa_symbol_table_dtor(table);
659d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   ralloc_free(mem_ctx);
669d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org}
679d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org
68c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.comvoid glsl_symbol_table::push_scope()
69c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com{
70c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com   _mesa_symbol_table_push_scope(table);
71c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com}
72c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com
739d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.orgvoid glsl_symbol_table::pop_scope()
749d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org{
759d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   _mesa_symbol_table_pop_scope(table);
769d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org}
779d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org
789d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.orgbool glsl_symbol_table::name_declared_this_scope(const char *name)
799d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org{
809d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   return _mesa_symbol_table_symbol_scope(table, -1, name) == 0;
817744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com}
827744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com
839d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.orgbool glsl_symbol_table::add_variable(ir_variable *v)
847744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com{
859d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   if (this->language_version == 110) {
869d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org      /* In 1.10, functions and variables have separate namespaces. */
879d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org      symbol_table_entry *existing = get_entry(v->name);
889d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org      if (name_declared_this_scope(v->name)) {
899d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org	 /* If there's already an existing function (not a constructor!) in
909d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org	  * the current scope, just update the existing entry to include 'v'.
919d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org	  */
929d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org	 if (existing->v == NULL && existing->t == NULL) {
939d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org	    existing->v = v;
94c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com	    return true;
95afec7ba75962517b17293799d3fc70d39fa7dbf2tomhudson@google.com	 }
96c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com      } else {
97c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com	 /* If not declared at this scope, add a new entry.  But if an existing
98c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com	  * entry includes a function, propagate that to this block - otherwise
99c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com	  * the new variable declaration would shadow the function.
100c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com	  */
101c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com	 symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(v);
1022047f00e4698f83499ab91911999a65c21a951c9epoger@google.com	 if (existing != NULL)
103c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com	    entry->f = existing->f;
1049d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org	 int added = _mesa_symbol_table_add_symbol(table, -1, v->name, entry);
1059d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org	 assert(added == 0);
1062047f00e4698f83499ab91911999a65c21a951c9epoger@google.com	 (void)added;
10761f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com	 return true;
10861f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com      }
10961f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com      return false;
11061f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com   }
11161f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com
11261f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com   /* 1.20+ rules: */
11361f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com   symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(v);
11461f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com   return _mesa_symbol_table_add_symbol(table, -1, v->name, entry) == 0;
1159d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org}
1169d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org
1179d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.orgbool glsl_symbol_table::add_type(const char *name, const glsl_type *t)
1189d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org{
119c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com   symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(t);
120c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com   return _mesa_symbol_table_add_symbol(table, -1, name, entry) == 0;
121c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com}
122c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com
123c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.combool glsl_symbol_table::add_function(ir_function *f)
124c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com{
1259d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   if (this->language_version == 110 && name_declared_this_scope(f->name)) {
1269d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org      /* In 1.10, functions and variables have separate namespaces. */
1279d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org      symbol_table_entry *existing = get_entry(f->name);
1289d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org      if ((existing->f == NULL) && (existing->t == NULL)) {
1299d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org	 existing->f = f;
1309d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org	 return true;
1319d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org      }
1329d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   }
1337744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com   symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(f);
1347744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com   return _mesa_symbol_table_add_symbol(table, -1, f->name, entry) == 0;
1357744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com}
1369d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org
1379d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.orgbool glsl_symbol_table::add_uniform_block(struct gl_uniform_block *u)
1387744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com{
1397744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com   symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(u);
1409d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   return _mesa_symbol_table_add_symbol(table, -1, u->Name, entry) == 0;
1417744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com}
1429d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org
1439d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.orgvoid glsl_symbol_table::add_global_function(ir_function *f)
1449d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org{
1459d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(f);
1469d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   int added = _mesa_symbol_table_add_global_symbol(table, -1, f->name, entry);
1479d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   assert(added == 0);
14807f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.com   (void)added;
14907f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.com}
150c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com
151afec7ba75962517b17293799d3fc70d39fa7dbf2tomhudson@google.comir_variable *glsl_symbol_table::get_variable(const char *name)
152c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com{
153c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com   symbol_table_entry *entry = get_entry(name);
154c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com   return entry != NULL ? entry->v : NULL;
1559d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org}
1569d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org
1579d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.orgconst glsl_type *glsl_symbol_table::get_type(const char *name)
1589d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org{
1599d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   symbol_table_entry *entry = get_entry(name);
160129b8e3237b80b9d258a8f48e8f54c0073cafbdcsenorblanco@chromium.org   return entry != NULL ? entry->t : NULL;
1619d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org}
1629d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org
1639d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.orgir_function *glsl_symbol_table::get_function(const char *name)
16407f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.com{
1659d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   symbol_table_entry *entry = get_entry(name);
1669d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   return entry != NULL ? entry->f : NULL;
1679d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org}
1689d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org
1699d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.orgsymbol_table_entry *glsl_symbol_table::get_entry(const char *name)
1709d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org{
1719d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org   return (symbol_table_entry *)
1729d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org      _mesa_symbol_table_find_symbol(table, -1, name);
1739d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org}
1749d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org