~ubuntu-branches/ubuntu/jaunty/mesa/jaunty

« back to all changes in this revision

Viewing changes to src/mesa/shader/slang/slang_codegen.c

  • Committer: Bazaar Package Importer
  • Author(s): Timo Aaltonen
  • Date: 2009-01-23 10:20:24 UTC
  • mfrom: (1.2.14 upstream)
  • Revision ID: james.westby@ubuntu.com-20090123102024-1f3kmb3aea7wzk67
Tags: 7.3~rc3-1ubuntu1
* Merge with Debian experimental.
* Drop 102_dont_vblank.patch, since the new drm code in the kernel
  fixes the bugs that it worked around.
* Bump the build-dependency of libdrm to 2.4.4. It's the first version
  with necessary changes to build this.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Mesa 3-D graphics library
3
 
 * Version:  7.1
4
3
 *
5
4
 * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
 
5
 * Copyright (C) 2008 VMware, Inc.  All Rights Reserved.
6
6
 *
7
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
8
 * copy of this software and associated documentation files (the "Software"),
57
57
#include "slang_print.h"
58
58
 
59
59
 
 
60
/** Max iterations to unroll */
 
61
const GLuint MAX_FOR_LOOP_UNROLL_ITERATIONS = 32;
 
62
 
 
63
/** Max for-loop body size (in slang operations) to unroll */
 
64
const GLuint MAX_FOR_LOOP_UNROLL_BODY_SIZE = 50;
 
65
 
 
66
/** Max for-loop body complexity to unroll.
 
67
 * We'll compute complexity as the product of the number of iterations
 
68
 * and the size of the body.  So long-ish loops with very simple bodies
 
69
 * can be unrolled, as well as short loops with larger bodies.
 
70
 */
 
71
const GLuint MAX_FOR_LOOP_UNROLL_COMPLEXITY = 256;
 
72
 
 
73
 
 
74
 
60
75
static slang_ir_node *
61
76
_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper);
62
77
 
63
78
 
 
79
/**
 
80
 * Retrieves type information about an operation.
 
81
 * Returns GL_TRUE on success.
 
82
 * Returns GL_FALSE otherwise.
 
83
 */
 
84
static GLboolean
 
85
typeof_operation(const struct slang_assemble_ctx_ *A,
 
86
                 slang_operation *op,
 
87
                 slang_typeinfo *ti)
 
88
{
 
89
   return _slang_typeof_operation(op, &A->space, ti, A->atoms, A->log);
 
90
}
 
91
 
 
92
 
64
93
static GLboolean
65
94
is_sampler_type(const slang_fully_specified_type *t)
66
95
{
199
228
      break;
200
229
   case SLANG_SPEC_STRUCT:
201
230
      sz = _slang_field_offset(spec, 0); /* special use */
202
 
      if (sz > 4) {
 
231
      if (sz == 1) {
 
232
         /* 1-float structs are actually troublesome to deal with since they
 
233
          * might get placed at R.x, R.y, R.z or R.z.  Return size=2 to
 
234
          * ensure the object is placed at R.x
 
235
          */
 
236
         sz = 2;
 
237
      }
 
238
      else if (sz > 4) {
203
239
         sz = (sz + 3) & ~0x3; /* round up to multiple of four */
204
240
      }
205
241
      break;
220
256
 
221
257
 
222
258
/**
 
259
 * Query variable/array length (number of elements).
 
260
 * This is slightly non-trivial because there are two ways to express
 
261
 * arrays: "float x[3]" vs. "float[3] x".
 
262
 * \return the length of the array for the given variable, or 0 if not an array
 
263
 */
 
264
static GLint
 
265
_slang_array_length(const slang_variable *var)
 
266
{
 
267
   if (var->type.array_len > 0) {
 
268
      /* Ex: float[4] x; */
 
269
      return var->type.array_len;
 
270
   }
 
271
   if (var->array_len > 0) {
 
272
      /* Ex: float x[4]; */
 
273
      return var->array_len;
 
274
   }
 
275
   return 0;
 
276
}
 
277
 
 
278
 
 
279
/**
 
280
 * Compute total size of array give size of element, number of elements.
 
281
 * \return size in floats
 
282
 */
 
283
static GLint
 
284
_slang_array_size(GLint elemSize, GLint arrayLen)
 
285
{
 
286
   GLint total;
 
287
   assert(elemSize > 0);
 
288
   if (arrayLen > 1) {
 
289
      /* round up base type to multiple of 4 */
 
290
      total = ((elemSize + 3) & ~0x3) * MAX2(arrayLen, 1);
 
291
   }
 
292
   else {
 
293
      total = elemSize;
 
294
   }
 
295
   return total;
 
296
}
 
297
 
 
298
 
 
299
 
 
300
/**
223
301
 * Establish the binding between a slang_ir_node and a slang_variable.
224
302
 * Then, allocate/attach a slang_ir_storage object to the IR node if needed.
225
303
 * The IR node must be a IR_VAR or IR_VAR_DECL node.
335
413
   const struct input_info *inputs
336
414
      = (target == GL_VERTEX_PROGRAM_ARB) ? vertInputs : fragInputs;
337
415
 
338
 
   ASSERT(MAX_TEXTURE_UNITS == 8); /* if this fails, fix vertInputs above */
 
416
   ASSERT(MAX_TEXTURE_COORD_UNITS == 8); /* if this fails, fix vertInputs above */
339
417
 
340
418
   for (i = 0; inputs[i].Name; i++) {
341
419
      if (strcmp(inputs[i].Name, name) == 0) {
653
731
 * New IR_VAR node - a reference to a previously declared variable.
654
732
 */
655
733
static slang_ir_node *
656
 
new_var(slang_assemble_ctx *A, slang_operation *oper, slang_atom name)
 
734
new_var(slang_assemble_ctx *A, slang_variable *var)
657
735
{
658
 
   slang_ir_node *n;
659
 
   slang_variable *var = _slang_locate_variable(oper->locals, name, GL_TRUE);
660
 
   if (!var)
661
 
      return NULL;
662
 
 
663
 
   assert(var->declared);
664
 
 
665
 
   assert(!oper->var || oper->var == var);
666
 
 
667
 
   n = new_node0(IR_VAR);
 
736
   slang_ir_node *n = new_node0(IR_VAR);
668
737
   if (n) {
669
738
      _slang_attach_storage(n, var);
670
 
      /*
671
 
      printf("new_var %s store=%p\n", (char*)name, (void*) n->Store);
672
 
      */
673
739
   }
674
740
   return n;
675
741
}
783
849
slang_resolve_variable(slang_operation *oper)
784
850
{
785
851
   if (oper->type == SLANG_OPER_IDENTIFIER && !oper->var) {
786
 
      oper->var = _slang_locate_variable(oper->locals, oper->a_id, GL_TRUE);
 
852
      oper->var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
787
853
   }
788
854
}
789
855
 
799
865
   switch (oper->type) {
800
866
   case SLANG_OPER_VARIABLE_DECL:
801
867
      {
802
 
         slang_variable *v = _slang_locate_variable(oper->locals,
 
868
         slang_variable *v = _slang_variable_locate(oper->locals,
803
869
                                                    oper->a_id, GL_TRUE);
804
870
         assert(v);
805
871
         if (v->initializer && oper->num_children == 0) {
821
887
         slang_atom id = oper->a_id;
822
888
         slang_variable *v;
823
889
         GLuint i;
824
 
         v = _slang_locate_variable(oper->locals, id, GL_TRUE);
 
890
         v = _slang_variable_locate(oper->locals, id, GL_TRUE);
825
891
         if (!v) {
826
892
            _mesa_problem(NULL, "var %s not found!\n", (char *) oper->a_id);
827
893
            return;
1414
1480
 
1415
1481
 
1416
1482
/**
1417
 
 * Return the default swizzle mask for accessing a variable of the
1418
 
 * given size (in floats).  If size = 1, comp is used to identify
1419
 
 * which component [0..3] of the register holds the variable.
1420
 
 */
1421
 
static GLuint
1422
 
_slang_var_swizzle(GLint size, GLint comp)
1423
 
{
1424
 
   switch (size) {
1425
 
   case 1:
1426
 
      return MAKE_SWIZZLE4(comp, comp, comp, comp);
1427
 
   case 2:
1428
 
      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL);
1429
 
   case 3:
1430
 
      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_NIL);
1431
 
   default:
1432
 
      return SWIZZLE_XYZW;
1433
 
   }
1434
 
}
1435
 
 
1436
 
 
1437
 
/**
1438
1483
 * Some write-masked assignments are simple, but others are hard.
1439
1484
 * Simple example:
1440
1485
 *    vec3 v;
1547
1592
}
1548
1593
 
1549
1594
 
 
1595
#if 0 /* not used, but don't remove just yet */
1550
1596
/**
1551
1597
 * Recursively traverse 'oper' to produce a swizzle mask in the event
1552
1598
 * of any vector subscripts and swizzle suffixes.
1600
1646
      return SWIZZLE_XYZW;
1601
1647
   }
1602
1648
}
1603
 
 
1604
 
 
 
1649
#endif
 
1650
 
 
1651
 
 
1652
#if 0
1605
1653
/**
1606
1654
 * Recursively descend through swizzle nodes to find the node's storage info.
1607
1655
 */
1613
1661
   }
1614
1662
   return n->Store;
1615
1663
}
1616
 
 
 
1664
#endif
1617
1665
 
1618
1666
 
1619
1667
/**
1686
1734
}
1687
1735
 
1688
1736
 
 
1737
#if 0
1689
1738
static void
1690
1739
print_funcs(struct slang_function_scope_ *scope, const char *name)
1691
1740
{
1699
1748
   if (scope->outer_scope)
1700
1749
      print_funcs(scope->outer_scope, name);
1701
1750
}
 
1751
#endif
1702
1752
 
1703
1753
 
1704
1754
/**
1760
1810
 * struct type.
1761
1811
 */
1762
1812
static slang_function *
1763
 
_slang_make_constructor(slang_assemble_ctx *A, slang_struct *str)
 
1813
_slang_make_struct_constructor(slang_assemble_ctx *A, slang_struct *str)
1764
1814
{
1765
1815
   const GLint numFields = str->fields->num_variables;
1766
 
 
1767
 
   slang_function *fun = (slang_function *) _mesa_malloc(sizeof(slang_function));
1768
 
   if (!fun)
1769
 
      return NULL;
1770
 
 
1771
 
   slang_function_construct(fun);
 
1816
   slang_function *fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
1772
1817
 
1773
1818
   /* function header (name, return type) */
1774
 
   fun->kind = SLANG_FUNC_CONSTRUCTOR;
1775
1819
   fun->header.a_name = str->a_name;
1776
1820
   fun->header.type.qualifier = SLANG_QUAL_NONE;
1777
1821
   fun->header.type.specifier.type = SLANG_SPEC_STRUCT;
1785
1829
         printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name);
1786
1830
         */
1787
1831
         slang_variable *p = slang_variable_scope_grow(fun->parameters);
1788
 
         *p = *str->fields->variables[i]; /* copy the type */
 
1832
         *p = *str->fields->variables[i]; /* copy the variable and type */
1789
1833
         p->type.qualifier = SLANG_QUAL_CONST;
1790
1834
      }
1791
1835
      fun->param_count = fun->parameters->num_variables;
1890
1934
         ret->children[0].type = SLANG_OPER_IDENTIFIER;
1891
1935
         ret->children[0].a_id = var->a_name;
1892
1936
         ret->children[0].locals = _slang_variable_scope_new(scope);
1893
 
 
1894
1937
      }
1895
1938
   }
1896
1939
   /*
1913
1956
         /* found a structure type that matches the function name */
1914
1957
         if (!str->constructor) {
1915
1958
            /* create the constructor function now */
1916
 
            str->constructor = _slang_make_constructor(A, str);
 
1959
            str->constructor = _slang_make_struct_constructor(A, str);
1917
1960
         }
1918
1961
         return str->constructor;
1919
1962
      }
1922
1965
}
1923
1966
 
1924
1967
 
 
1968
/**
 
1969
 * Generate a new slang_function to satisfy a call to an array constructor.
 
1970
 * Ex:  float[3](1., 2., 3.)
 
1971
 */
 
1972
static slang_function *
 
1973
_slang_make_array_constructor(slang_assemble_ctx *A, slang_operation *oper)
 
1974
{
 
1975
   slang_type_specifier_type baseType;
 
1976
   slang_function *fun;
 
1977
   int num_elements;
 
1978
 
 
1979
   fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
 
1980
   if (!fun)
 
1981
      return NULL;
 
1982
 
 
1983
   baseType = slang_type_specifier_type_from_string((char *) oper->a_id);
 
1984
 
 
1985
   num_elements = oper->num_children;
 
1986
 
 
1987
   /* function header, return type */
 
1988
   {
 
1989
      fun->header.a_name = oper->a_id;
 
1990
      fun->header.type.qualifier = SLANG_QUAL_NONE;
 
1991
      fun->header.type.specifier.type = SLANG_SPEC_ARRAY;
 
1992
      fun->header.type.specifier._array =
 
1993
         slang_type_specifier_new(baseType, NULL, NULL);
 
1994
      fun->header.type.array_len = num_elements;
 
1995
   }
 
1996
 
 
1997
   /* function parameters (= number of elements) */
 
1998
   {
 
1999
      GLint i;
 
2000
      for (i = 0; i < num_elements; i++) {
 
2001
         /*
 
2002
         printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name);
 
2003
         */
 
2004
         slang_variable *p = slang_variable_scope_grow(fun->parameters);
 
2005
         char name[10];
 
2006
         _mesa_snprintf(name, sizeof(name), "p%d", i);
 
2007
         p->a_name = slang_atom_pool_atom(A->atoms, name);
 
2008
         p->type.qualifier = SLANG_QUAL_CONST;
 
2009
         p->type.specifier.type = baseType;
 
2010
      }
 
2011
      fun->param_count = fun->parameters->num_variables;
 
2012
   }
 
2013
 
 
2014
   /* Add __retVal to params */
 
2015
   {
 
2016
      slang_variable *p = slang_variable_scope_grow(fun->parameters);
 
2017
      slang_atom a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
 
2018
      assert(a_retVal);
 
2019
      p->a_name = a_retVal;
 
2020
      p->type = fun->header.type;
 
2021
      p->type.qualifier = SLANG_QUAL_OUT;
 
2022
      p->type.specifier.type = baseType;
 
2023
      fun->param_count++;
 
2024
   }
 
2025
 
 
2026
   /* function body is:
 
2027
    *    block:
 
2028
    *       declare T;
 
2029
    *       T[0] = p0;
 
2030
    *       T[1] = p1;
 
2031
    *       ...
 
2032
    *       T[n] = pn;
 
2033
    *       return T;
 
2034
    */
 
2035
   {
 
2036
      slang_variable_scope *scope;
 
2037
      slang_variable *var;
 
2038
      GLint i;
 
2039
 
 
2040
      fun->body = slang_operation_new(1);
 
2041
      fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE;
 
2042
      fun->body->num_children = num_elements + 2;
 
2043
      fun->body->children = slang_operation_new(num_elements + 2);
 
2044
 
 
2045
      scope = fun->body->locals;
 
2046
      scope->outer_scope = fun->parameters;
 
2047
 
 
2048
      /* create local var 't' */
 
2049
      var = slang_variable_scope_grow(scope);
 
2050
      var->a_name = slang_atom_pool_atom(A->atoms, "ttt");
 
2051
      var->type = fun->header.type;/*XXX copy*/
 
2052
 
 
2053
      /* declare t */
 
2054
      {
 
2055
         slang_operation *decl;
 
2056
 
 
2057
         decl = &fun->body->children[0];
 
2058
         decl->type = SLANG_OPER_VARIABLE_DECL;
 
2059
         decl->locals = _slang_variable_scope_new(scope);
 
2060
         decl->a_id = var->a_name;
 
2061
      }
 
2062
 
 
2063
      /* assign params to elements of t */
 
2064
      for (i = 0; i < num_elements; i++) {
 
2065
         slang_operation *assign = &fun->body->children[1 + i];
 
2066
 
 
2067
         assign->type = SLANG_OPER_ASSIGN;
 
2068
         assign->locals = _slang_variable_scope_new(scope);
 
2069
         assign->num_children = 2;
 
2070
         assign->children = slang_operation_new(2);
 
2071
         
 
2072
         {
 
2073
            slang_operation *lhs = &assign->children[0];
 
2074
 
 
2075
            lhs->type = SLANG_OPER_SUBSCRIPT;
 
2076
            lhs->locals = _slang_variable_scope_new(scope);
 
2077
            lhs->num_children = 2;
 
2078
            lhs->children = slang_operation_new(2);
 
2079
 
 
2080
            lhs->children[0].type = SLANG_OPER_IDENTIFIER;
 
2081
            lhs->children[0].a_id = var->a_name;
 
2082
            lhs->children[0].locals = _slang_variable_scope_new(scope);
 
2083
 
 
2084
            lhs->children[1].type = SLANG_OPER_LITERAL_INT;
 
2085
            lhs->children[1].literal[0] = (GLfloat) i;
 
2086
         }
 
2087
 
 
2088
         {
 
2089
            slang_operation *rhs = &assign->children[1];
 
2090
 
 
2091
            rhs->type = SLANG_OPER_IDENTIFIER;
 
2092
            rhs->locals = _slang_variable_scope_new(scope);
 
2093
            rhs->a_id = fun->parameters->variables[i]->a_name;
 
2094
         }         
 
2095
      }
 
2096
 
 
2097
      /* return t; */
 
2098
      {
 
2099
         slang_operation *ret = &fun->body->children[num_elements + 1];
 
2100
 
 
2101
         ret->type = SLANG_OPER_RETURN;
 
2102
         ret->locals = _slang_variable_scope_new(scope);
 
2103
         ret->num_children = 1;
 
2104
         ret->children = slang_operation_new(1);
 
2105
         ret->children[0].type = SLANG_OPER_IDENTIFIER;
 
2106
         ret->children[0].a_id = var->a_name;
 
2107
         ret->children[0].locals = _slang_variable_scope_new(scope);
 
2108
      }
 
2109
   }
 
2110
 
 
2111
   /*
 
2112
   slang_print_function(fun, 1);
 
2113
   */
 
2114
 
 
2115
   return fun;
 
2116
}
 
2117
 
1925
2118
 
1926
2119
static GLboolean
1927
2120
_slang_is_vec_mat_type(const char *name)
1955
2148
   const GLuint param_count = oper->num_children;
1956
2149
   slang_atom atom;
1957
2150
   slang_function *fun;
1958
 
   GLboolean error;
1959
2151
   slang_ir_node *n;
1960
2152
 
1961
2153
   atom = slang_atom_pool_atom(A->atoms, name);
1962
2154
   if (atom == SLANG_ATOM_NULL)
1963
2155
      return NULL;
1964
2156
 
1965
 
   /*
1966
 
    * First, try to find function by name and exact argument type matching.
1967
 
    */
1968
 
   fun = _slang_locate_function(A->space.funcs, atom, params, param_count,
1969
 
                                &A->space, A->atoms, A->log, &error);
1970
 
 
1971
 
   if (error) {
1972
 
      slang_info_log_error(A->log,
1973
 
                           "Function '%s' not found (check argument types)",
1974
 
                           name);
1975
 
      return NULL;
 
2157
   if (oper->array_constructor) {
 
2158
      /* this needs special handling */
 
2159
      fun = _slang_make_array_constructor(A, oper);
 
2160
   }
 
2161
   else {
 
2162
      /* Try to find function by name and exact argument type matching */
 
2163
      GLboolean error = GL_FALSE;
 
2164
      fun = _slang_function_locate(A->space.funcs, atom, params, param_count,
 
2165
                                   &A->space, A->atoms, A->log, &error);
 
2166
      if (error) {
 
2167
         slang_info_log_error(A->log,
 
2168
                              "Function '%s' not found (check argument types)",
 
2169
                              name);
 
2170
         return NULL;
 
2171
      }
1976
2172
   }
1977
2173
 
1978
2174
   if (!fun) {
2033
2229
      slang_typeinfo t0;
2034
2230
 
2035
2231
      slang_typeinfo_construct(&t0);
2036
 
      _slang_typeof_operation(A, dest, &t0);
 
2232
      typeof_operation(A, dest, &t0);
2037
2233
 
2038
2234
      if (!slang_type_specifier_equal(&t0.spec, &fun->header.type.specifier)) {
2039
2235
         slang_info_log_error(A->log,
2053
2249
      /*printf("Alloc storage for function result, size %d \n", size);*/
2054
2250
   }
2055
2251
 
 
2252
   if (oper->array_constructor) {
 
2253
      /* free the temporary array constructor function now */
 
2254
      slang_function_destruct(fun);
 
2255
   }
 
2256
 
2056
2257
   return n;
2057
2258
}
2058
2259
 
2080
2281
   }
2081
2282
 
2082
2283
   /* lookup the object/variable */
2083
 
   var = _slang_locate_variable(oper->locals, oper->a_obj, GL_TRUE);
 
2284
   var = _slang_variable_locate(oper->locals, oper->a_obj, GL_TRUE);
2084
2285
   if (!var || var->type.specifier.type != SLANG_SPEC_ARRAY) {
2085
2286
      slang_info_log_error(A->log,
2086
2287
                           "Undefined object '%s'", (char *) oper->a_obj);
2090
2291
   /* Create a float/literal IR node encoding the array length */
2091
2292
   n = new_node0(IR_FLOAT);
2092
2293
   if (n) {
2093
 
      n->Value[0] = (float) var->array_len;
 
2294
      n->Value[0] = (float) _slang_array_length(var);
2094
2295
      n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, 1);
2095
2296
   }
2096
2297
   return n;
2127
2328
   GLint size;
2128
2329
 
2129
2330
   slang_typeinfo_construct(&type);
2130
 
   _slang_typeof_operation(A, oper, &type);
 
2331
   typeof_operation(A, oper, &type);
2131
2332
   size = _slang_sizeof_type_specifier(&type.spec);
2132
2333
   slang_typeinfo_destruct(&type);
2133
2334
   return size == 1;
2144
2345
   GLboolean isBool;
2145
2346
 
2146
2347
   slang_typeinfo_construct(&type);
2147
 
   _slang_typeof_operation(A, oper, &type);
 
2348
   typeof_operation(A, oper, &type);
2148
2349
   isBool = (type.spec.type == SLANG_SPEC_BOOL);
2149
2350
   slang_typeinfo_destruct(&type);
2150
2351
   return isBool;
2265
2466
 
2266
2467
 
2267
2468
/**
2268
 
 * Generate for-loop using high-level IR_LOOP instruction.
 
2469
 * Recursively count the number of operations rooted at 'oper'.
 
2470
 * This gives some kind of indication of the size/complexity of an operation.
 
2471
 */
 
2472
static GLuint
 
2473
sizeof_operation(const slang_operation *oper)
 
2474
{
 
2475
   if (oper) {
 
2476
      GLuint count = 1; /* me */
 
2477
      GLuint i;
 
2478
      for (i = 0; i < oper->num_children; i++) {
 
2479
         count += sizeof_operation(&oper->children[i]);
 
2480
      }
 
2481
      return count;
 
2482
   }
 
2483
   else {
 
2484
      return 0;
 
2485
   }
 
2486
}
 
2487
 
 
2488
 
 
2489
/**
 
2490
 * Determine if a for-loop can be unrolled.
 
2491
 * At this time, only a rather narrow class of for loops can be unrolled.
 
2492
 * See code for details.
 
2493
 * When a loop can't be unrolled because it's too large we'll emit a
 
2494
 * message to the log.
 
2495
 */
 
2496
static GLboolean
 
2497
_slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
 
2498
{
 
2499
   GLuint bodySize;
 
2500
   GLint start, end;
 
2501
   const char *varName;
 
2502
   slang_atom varId;
 
2503
 
 
2504
   assert(oper->type == SLANG_OPER_FOR);
 
2505
   assert(oper->num_children == 4);
 
2506
 
 
2507
   /* children[0] must be either "int i=constant" or "i=constant" */
 
2508
   if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
 
2509
      slang_variable *var;
 
2510
 
 
2511
      if (oper->children[0].children[0].type != SLANG_OPER_VARIABLE_DECL)
 
2512
         return GL_FALSE;
 
2513
 
 
2514
      varId = oper->children[0].children[0].a_id;
 
2515
 
 
2516
      var = _slang_variable_locate(oper->children[0].children[0].locals,
 
2517
                                   varId, GL_TRUE);
 
2518
      if (!var)
 
2519
         return GL_FALSE;
 
2520
      if (!var->initializer)
 
2521
         return GL_FALSE;
 
2522
      if (var->initializer->type != SLANG_OPER_LITERAL_INT)
 
2523
         return GL_FALSE;
 
2524
      start = (GLint) var->initializer->literal[0];
 
2525
   }
 
2526
   else if (oper->children[0].type == SLANG_OPER_EXPRESSION) {
 
2527
      if (oper->children[0].children[0].type != SLANG_OPER_ASSIGN)
 
2528
         return GL_FALSE;
 
2529
      if (oper->children[0].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
 
2530
         return GL_FALSE;
 
2531
      if (oper->children[0].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
 
2532
         return GL_FALSE;
 
2533
 
 
2534
      varId = oper->children[0].children[0].children[0].a_id;
 
2535
 
 
2536
      start = (GLint) oper->children[0].children[0].children[1].literal[0];
 
2537
   }
 
2538
   else {
 
2539
      return GL_FALSE;
 
2540
   }
 
2541
 
 
2542
   /* children[1] must be "i<constant" */
 
2543
   if (oper->children[1].type != SLANG_OPER_EXPRESSION)
 
2544
      return GL_FALSE;
 
2545
   if (oper->children[1].children[0].type != SLANG_OPER_LESS)
 
2546
      return GL_FALSE;
 
2547
   if (oper->children[1].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
 
2548
      return GL_FALSE;
 
2549
   if (oper->children[1].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
 
2550
      return GL_FALSE;
 
2551
 
 
2552
   end = (GLint) oper->children[1].children[0].children[1].literal[0];
 
2553
 
 
2554
   /* children[2] must be "i++" or "++i" */
 
2555
   if (oper->children[2].type != SLANG_OPER_POSTINCREMENT &&
 
2556
       oper->children[2].type != SLANG_OPER_PREINCREMENT)
 
2557
      return GL_FALSE;
 
2558
   if (oper->children[2].children[0].type != SLANG_OPER_IDENTIFIER)
 
2559
      return GL_FALSE;
 
2560
 
 
2561
   /* make sure the same variable name is used in all places */
 
2562
   if ((oper->children[1].children[0].children[0].a_id != varId) ||
 
2563
       (oper->children[2].children[0].a_id != varId))
 
2564
      return GL_FALSE;
 
2565
 
 
2566
   varName = (const char *) varId;
 
2567
 
 
2568
   /* children[3], the loop body, can't be too large */
 
2569
   bodySize = sizeof_operation(&oper->children[3]);
 
2570
   if (bodySize > MAX_FOR_LOOP_UNROLL_BODY_SIZE) {
 
2571
      slang_info_log_print(A->log,
 
2572
                           "Note: 'for (%s ... )' body is too large/complex"
 
2573
                           " to unroll",
 
2574
                           varName);
 
2575
      return GL_FALSE;
 
2576
   }
 
2577
 
 
2578
   if (start >= end)
 
2579
      return GL_FALSE; /* degenerate case */
 
2580
 
 
2581
   if (end - start > MAX_FOR_LOOP_UNROLL_ITERATIONS) {
 
2582
      slang_info_log_print(A->log,
 
2583
                           "Note: 'for (%s=%d; %s<%d; ++%s)' is too"
 
2584
                           " many iterations to unroll",
 
2585
                           varName, start, varName, end, varName);
 
2586
      return GL_FALSE;
 
2587
   }
 
2588
 
 
2589
   if ((end - start) * bodySize > MAX_FOR_LOOP_UNROLL_COMPLEXITY) {
 
2590
      slang_info_log_print(A->log,
 
2591
                           "Note: 'for (%s=%d; %s<%d; ++%s)' will generate"
 
2592
                           " too much code to unroll",
 
2593
                           varName, start, varName, end, varName);
 
2594
      return GL_FALSE;
 
2595
   }
 
2596
 
 
2597
   return GL_TRUE; /* we can unroll the loop */
 
2598
}
 
2599
 
 
2600
 
 
2601
/**
 
2602
 * Unroll a for-loop.
 
2603
 * First we determine the number of iterations to unroll.
 
2604
 * Then for each iteration:
 
2605
 *   make a copy of the loop body
 
2606
 *   replace instances of the loop variable with the current iteration value
 
2607
 *   generate IR code for the body
 
2608
 * \return pointer to generated IR code or NULL if error, out of memory, etc.
 
2609
 */
 
2610
static slang_ir_node *
 
2611
_slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
 
2612
{
 
2613
   GLint start, end, iter;
 
2614
   slang_ir_node *n, *root = NULL;
 
2615
   slang_atom varId;
 
2616
 
 
2617
   if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
 
2618
      /* for (int i=0; ... */
 
2619
      slang_variable *var;
 
2620
 
 
2621
      varId = oper->children[0].children[0].a_id;
 
2622
      var = _slang_variable_locate(oper->children[0].children[0].locals,
 
2623
                                   varId, GL_TRUE);
 
2624
      start = (GLint) var->initializer->literal[0];
 
2625
   }
 
2626
   else {
 
2627
      /* for (i=0; ... */
 
2628
      varId = oper->children[0].children[0].children[0].a_id;
 
2629
      start = (GLint) oper->children[0].children[0].children[1].literal[0];
 
2630
   }
 
2631
 
 
2632
   end = (GLint) oper->children[1].children[0].children[1].literal[0];
 
2633
 
 
2634
   for (iter = start; iter < end; iter++) {
 
2635
      slang_operation *body;
 
2636
 
 
2637
      /* make a copy of the loop body */
 
2638
      body = slang_operation_new(1);
 
2639
      if (!body)
 
2640
         return NULL;
 
2641
 
 
2642
      if (!slang_operation_copy(body, &oper->children[3]))
 
2643
         return NULL;
 
2644
 
 
2645
      /* in body, replace instances of 'varId' with literal 'iter' */
 
2646
      {
 
2647
         slang_variable *oldVar;
 
2648
         slang_operation *newOper;
 
2649
 
 
2650
         oldVar = _slang_variable_locate(oper->locals, varId, GL_TRUE);
 
2651
         if (!oldVar) {
 
2652
            /* undeclared loop variable */
 
2653
            slang_operation_delete(body);
 
2654
            return NULL;
 
2655
         }
 
2656
 
 
2657
         newOper = slang_operation_new(1);
 
2658
         newOper->type = SLANG_OPER_LITERAL_INT;
 
2659
         newOper->literal_size = 1;
 
2660
         newOper->literal[0] = iter;
 
2661
 
 
2662
         /* replace instances of the loop variable with newOper */
 
2663
         slang_substitute(A, body, 1, &oldVar, &newOper, GL_FALSE);
 
2664
      }
 
2665
 
 
2666
      /* do IR codegen for body */
 
2667
      n = _slang_gen_operation(A, body);
 
2668
      root = new_seq(root, n);
 
2669
 
 
2670
      slang_operation_delete(body);
 
2671
   }
 
2672
 
 
2673
   return root;
 
2674
}
 
2675
 
 
2676
 
 
2677
/**
 
2678
 * Generate IR for a for-loop.  Unrolling will be done when possible.
2269
2679
 */
2270
2680
static slang_ir_node *
2271
2681
_slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
2272
2682
{
2273
 
   /*
2274
 
    * init code (child[0])
2275
 
    * LOOP:
2276
 
    *    BREAK if !expr (child[1])
2277
 
    *    body code (child[3])
2278
 
    *    tail code:
2279
 
    *       incr code (child[2])   // XXX continue here
2280
 
    */
2281
 
   slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body, *init, *incr;
2282
 
 
2283
 
   init = _slang_gen_operation(A, &oper->children[0]);
2284
 
   loop = new_loop(NULL);
2285
 
 
2286
 
   /* save old, push new loop */
2287
 
   prevLoop = A->CurLoop;
2288
 
   A->CurLoop = loop;
2289
 
 
2290
 
   cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
2291
 
   breakIf = new_break_if_true(A->CurLoop, cond);
2292
 
   body = _slang_gen_operation(A, &oper->children[3]);
2293
 
   incr = _slang_gen_operation(A, &oper->children[2]);
2294
 
 
2295
 
   loop->Children[0] = new_seq(breakIf, body);
2296
 
   loop->Children[1] = incr;  /* tail code */
2297
 
 
2298
 
   /* pop loop, restore prev */
2299
 
   A->CurLoop = prevLoop;
2300
 
 
2301
 
   return new_seq(init, loop);
 
2683
   GLboolean unroll = _slang_can_unroll_for_loop(A, oper);
 
2684
 
 
2685
   if (unroll) {
 
2686
      slang_ir_node *code = _slang_unroll_for_loop(A, oper);
 
2687
      if (code)
 
2688
         return code;
 
2689
   }
 
2690
 
 
2691
   /* conventional for-loop code generation */
 
2692
   {
 
2693
      /*
 
2694
       * init code (child[0])
 
2695
       * LOOP:
 
2696
       *    BREAK if !expr (child[1])
 
2697
       *    body code (child[3])
 
2698
       *    tail code:
 
2699
       *       incr code (child[2])   // XXX continue here
 
2700
       */
 
2701
      slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body, *init, *incr;
 
2702
      init = _slang_gen_operation(A, &oper->children[0]);
 
2703
      loop = new_loop(NULL);
 
2704
 
 
2705
      /* save old, push new loop */
 
2706
      prevLoop = A->CurLoop;
 
2707
      A->CurLoop = loop;
 
2708
 
 
2709
      cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
 
2710
      breakIf = new_break_if_true(A->CurLoop, cond);
 
2711
      body = _slang_gen_operation(A, &oper->children[3]);
 
2712
      incr = _slang_gen_operation(A, &oper->children[2]);
 
2713
 
 
2714
      loop->Children[0] = new_seq(breakIf, body);
 
2715
      loop->Children[1] = incr;  /* tail code */
 
2716
 
 
2717
      /* pop loop, restore prev */
 
2718
      A->CurLoop = prevLoop;
 
2719
 
 
2720
      return new_seq(init, loop);
 
2721
   }
2302
2722
}
2303
2723
 
2304
2724
 
2479
2899
 
2480
2900
 
2481
2901
/**
2482
 
 * Generate IR node for allocating/declaring a variable.
 
2902
 * Generate program constants for an array.
 
2903
 * Ex: const vec2[3] v = vec2[3](vec2(1,1), vec2(2,2), vec2(3,3));
 
2904
 * This will allocate and initialize three vector constants, storing
 
2905
 * the array in constant memory, not temporaries like a non-const array.
 
2906
 * This can also be used for uniform array initializers.
 
2907
 * \return GL_TRUE for success, GL_FALSE if failure (semantic error, etc).
 
2908
 */
 
2909
static GLboolean
 
2910
make_constant_array(slang_assemble_ctx *A,
 
2911
                    slang_variable *var,
 
2912
                    slang_operation *initializer)
 
2913
{
 
2914
   struct gl_program *prog = A->program;
 
2915
   const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
 
2916
   const char *varName = (char *) var->a_name;
 
2917
   const GLuint numElements = initializer->num_children;
 
2918
   GLint size;
 
2919
   GLuint i, j;
 
2920
   GLfloat *values;
 
2921
 
 
2922
   if (!var->store) {
 
2923
      var->store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -6, -6);
 
2924
   }
 
2925
   size = var->store->Size;
 
2926
 
 
2927
   assert(var->type.qualifier == SLANG_QUAL_CONST ||
 
2928
          var->type.qualifier == SLANG_QUAL_UNIFORM);
 
2929
   assert(initializer->type == SLANG_OPER_CALL);
 
2930
   assert(initializer->array_constructor);
 
2931
 
 
2932
   values = (GLfloat *) _mesa_malloc(numElements * 4 * sizeof(GLfloat));
 
2933
 
 
2934
   /* convert constructor params into ordinary floats */
 
2935
   for (i = 0; i < numElements; i++) {
 
2936
      const slang_operation *op = &initializer->children[i];
 
2937
      if (op->type != SLANG_OPER_LITERAL_FLOAT) {
 
2938
         /* unsupported type for this optimization */
 
2939
         free(values);
 
2940
         return GL_FALSE;
 
2941
      }
 
2942
      for (j = 0; j < op->literal_size; j++) {
 
2943
         values[i * 4 + j] = op->literal[j];
 
2944
      }
 
2945
      for ( ; j < 4; j++) {
 
2946
         values[i * 4 + j] = 0.0f;
 
2947
      }
 
2948
   }
 
2949
 
 
2950
   /* slightly different paths for constants vs. uniforms */
 
2951
   if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
 
2952
      var->store->File = PROGRAM_UNIFORM;
 
2953
      var->store->Index = _mesa_add_uniform(prog->Parameters, varName,
 
2954
                                            size, datatype, values);
 
2955
   }
 
2956
   else {
 
2957
      var->store->File = PROGRAM_CONSTANT;
 
2958
      var->store->Index = _mesa_add_named_constant(prog->Parameters, varName,
 
2959
                                                   values, size);
 
2960
   }
 
2961
   assert(var->store->Size == size);
 
2962
 
 
2963
   _mesa_free(values);
 
2964
 
 
2965
   return GL_TRUE;
 
2966
}
 
2967
 
 
2968
 
 
2969
 
 
2970
/**
 
2971
 * Generate IR node for allocating/declaring a variable (either a local or
 
2972
 * a global).
 
2973
 * Generally, this involves allocating an slang_ir_storage instance for the
 
2974
 * variable, choosing a register file (temporary, constant, etc).
 
2975
 * For ordinary variables we do not yet allocate storage though.  We do that
 
2976
 * when we find the first actual use of the variable to avoid allocating temp
 
2977
 * regs that will never get used.
 
2978
 * At this time, uniforms are always allocated space in this function.
 
2979
 *
 
2980
 * \param initializer  Optional initializer expression for the variable.
2483
2981
 */
2484
2982
static slang_ir_node *
2485
 
_slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var)
 
2983
_slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
 
2984
                    slang_operation *initializer)
2486
2985
{
2487
 
   slang_ir_node *n;
 
2986
   const char *varName = (const char *) var->a_name;
 
2987
   const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
 
2988
   slang_ir_node *varDecl, *n;
 
2989
   slang_ir_storage *store;
 
2990
   GLint arrayLen, size, totalSize;  /* if array then totalSize > size */
 
2991
   enum register_file file;
2488
2992
 
2489
2993
   /*assert(!var->declared);*/
2490
2994
   var->declared = GL_TRUE;
2491
2995
 
2492
 
   n = new_node0(IR_VAR_DECL);
2493
 
   if (n) {
2494
 
      _slang_attach_storage(n, var);
2495
 
      assert(var->store);
2496
 
      assert(n->Store == var->store);
2497
 
      assert(n->Store);
2498
 
      assert(n->Store->Index < 0);
2499
 
 
2500
 
      if (is_sampler_type(&var->type)) {
2501
 
         n->Store->File = PROGRAM_SAMPLER;
2502
 
      }
2503
 
      else {
2504
 
         n->Store->File = PROGRAM_TEMPORARY;
2505
 
      }
2506
 
 
2507
 
      n->Store->Size = _slang_sizeof_type_specifier(&n->Var->type.specifier);
2508
 
 
2509
 
      if (n->Store->Size <= 0) {
2510
 
         slang_info_log_error(A->log, "invalid declaration for '%s'",
2511
 
                              (char*) var->a_name);
2512
 
         return NULL;
2513
 
      }
 
2996
   /* determine GPU register file for simple cases */
 
2997
   if (is_sampler_type(&var->type)) {
 
2998
      file = PROGRAM_SAMPLER;
 
2999
   }
 
3000
   else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
 
3001
      file = PROGRAM_UNIFORM;
 
3002
   }
 
3003
   else {
 
3004
      file = PROGRAM_TEMPORARY;
 
3005
   }
 
3006
 
 
3007
   totalSize = size = _slang_sizeof_type_specifier(&var->type.specifier);
 
3008
   if (size <= 0) {
 
3009
      slang_info_log_error(A->log, "invalid declaration for '%s'", varName);
 
3010
      return NULL;
 
3011
   }
 
3012
 
 
3013
   arrayLen = _slang_array_length(var);
 
3014
   totalSize = _slang_array_size(size, arrayLen);
 
3015
 
 
3016
   /* Allocate IR node for the declaration */
 
3017
   varDecl = new_node0(IR_VAR_DECL);
 
3018
   if (!varDecl)
 
3019
      return NULL;
 
3020
 
 
3021
   _slang_attach_storage(varDecl, var); /* undefined storage at first */
 
3022
   assert(var->store);
 
3023
   assert(varDecl->Store == var->store);
 
3024
   assert(varDecl->Store);
 
3025
   assert(varDecl->Store->Index < 0);
 
3026
   store = var->store;
 
3027
 
 
3028
   assert(store == varDecl->Store);
 
3029
 
 
3030
 
 
3031
   /* Fill in storage fields which we now know.  store->Index/Swizzle may be
 
3032
    * set for some cases below.  Otherwise, store->Index/Swizzle will be set
 
3033
    * during code emit.
 
3034
    */
 
3035
   store->File = file;
 
3036
   store->Size = totalSize;
 
3037
 
 
3038
   /* if there's an initializer, generate IR for the expression */
 
3039
   if (initializer) {
 
3040
      slang_ir_node *varRef, *init;
 
3041
 
 
3042
      if (var->type.qualifier == SLANG_QUAL_CONST) {
 
3043
         /* if the variable is const, the initializer must be a const
 
3044
          * expression as well.
 
3045
          */
2514
3046
#if 0
2515
 
      printf("%s var %p %s  store=%p index=%d size=%d\n",
2516
 
             __FUNCTION__, (void *) var, (char *) var->a_name,
2517
 
             (void *) n->Store, n->Store->Index, n->Store->Size);
2518
 
#endif
2519
 
 
2520
 
      if (var->array_len > 0) {
2521
 
         /* this is an array */
2522
 
         /* cannot be const-qualified */
2523
 
         if (var->type.qualifier == SLANG_QUAL_CONST) {
2524
 
            slang_info_log_error(A->log, "array '%s' cannot be const",
2525
 
                                 (char*) var->a_name);
 
3047
         if (!_slang_is_constant_expr(initializer)) {
 
3048
            slang_info_log_error(A->log,
 
3049
                                 "initializer for %s not constant", varName);
2526
3050
            return NULL;
2527
3051
         }
2528
 
         else {
2529
 
            /* round up element size to mult of 4 */
2530
 
            GLint sz = (n->Store->Size + 3) & ~3;
2531
 
            /* mult by array size */
2532
 
            sz *= var->array_len;
2533
 
            n->Store->Size = sz;
2534
 
         }
2535
 
      }
2536
 
 
2537
 
      assert(n->Store->Size > 0);
2538
 
 
2539
 
      /* setup default swizzle for storing the variable */
2540
 
      switch (n->Store->Size) {
2541
 
      case 2:
2542
 
         n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
2543
 
                                           SWIZZLE_NIL, SWIZZLE_NIL);
2544
 
         break;
2545
 
      case 3:
2546
 
         n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
2547
 
                                           SWIZZLE_Z, SWIZZLE_NIL);
2548
 
         break;
2549
 
      default:
2550
 
         /* Note that float-sized vars may be allocated in any x/y/z/w
2551
 
          * slot, but that won't be determined until code emit time.
2552
 
          */
2553
 
         n->Store->Swizzle = SWIZZLE_NOOP;
2554
 
      }
2555
 
   }
 
3052
#endif
 
3053
      }
 
3054
 
 
3055
      /* IR for the variable we're initializing */
 
3056
      varRef = new_var(A, var);
 
3057
      if (!varRef) {
 
3058
         slang_info_log_error(A->log, "out of memory");
 
3059
         return NULL;
 
3060
      }
 
3061
 
 
3062
      /* constant-folding, etc here */
 
3063
      _slang_simplify(initializer, &A->space, A->atoms); 
 
3064
 
 
3065
      /* look for simple constant-valued variables and uniforms */
 
3066
      if (var->type.qualifier == SLANG_QUAL_CONST ||
 
3067
          var->type.qualifier == SLANG_QUAL_UNIFORM) {
 
3068
 
 
3069
         if (initializer->type == SLANG_OPER_CALL &&
 
3070
             initializer->array_constructor) {
 
3071
            /* array initializer */
 
3072
            if (make_constant_array(A, var, initializer))
 
3073
               return varRef;
 
3074
         }
 
3075
         else if (initializer->type == SLANG_OPER_LITERAL_FLOAT ||
 
3076
                  initializer->type == SLANG_OPER_LITERAL_INT) {
 
3077
            /* simple float/vector initializer */
 
3078
            if (store->File == PROGRAM_UNIFORM) {
 
3079
               store->Index = _mesa_add_uniform(A->program->Parameters,
 
3080
                                                varName,
 
3081
                                                totalSize, datatype,
 
3082
                                                initializer->literal);
 
3083
               store->Swizzle = _slang_var_swizzle(size, 0);
 
3084
               return varRef;
 
3085
            }
 
3086
#if 0
 
3087
            else {
 
3088
               store->File = PROGRAM_CONSTANT;
 
3089
               store->Index = _mesa_add_named_constant(A->program->Parameters,
 
3090
                                                       varName,
 
3091
                                                       initializer->literal,
 
3092
                                                       totalSize);
 
3093
               store->Swizzle = _slang_var_swizzle(size, 0);
 
3094
               return varRef;
 
3095
            }
 
3096
#endif
 
3097
         }
 
3098
      }
 
3099
 
 
3100
      /* IR for initializer */
 
3101
      init = _slang_gen_operation(A, initializer);
 
3102
      if (!init)
 
3103
         return NULL;
 
3104
 
 
3105
      /* XXX remove this when type checking is added above */
 
3106
      if (init->Store && init->Store->Size != totalSize) {
 
3107
         slang_info_log_error(A->log, "invalid assignment (wrong types)");
 
3108
         return NULL;
 
3109
      }
 
3110
 
 
3111
      /* assign RHS to LHS */
 
3112
      n = new_node2(IR_COPY, varRef, init);
 
3113
      n = new_seq(varDecl, n);
 
3114
   }
 
3115
   else {
 
3116
      /* no initializer */
 
3117
      n = varDecl;
 
3118
   }
 
3119
 
 
3120
   if (store->File == PROGRAM_UNIFORM && store->Index < 0) {
 
3121
      /* always need to allocate storage for uniforms at this point */
 
3122
      store->Index = _mesa_add_uniform(A->program->Parameters, varName,
 
3123
                                       totalSize, datatype, NULL);
 
3124
      store->Swizzle = _slang_var_swizzle(size, 0);
 
3125
   }
 
3126
 
 
3127
#if 0
 
3128
   printf("%s var %p %s  store=%p index=%d size=%d\n",
 
3129
          __FUNCTION__, (void *) var, (char *) varName,
 
3130
          (void *) store, store->Index, store->Size);
 
3131
#endif
 
3132
 
2556
3133
   return n;
2557
3134
}
2558
3135
 
2576
3153
 
2577
3154
   /* type of children[0] must be boolean */
2578
3155
   slang_typeinfo_construct(&type0);
2579
 
   _slang_typeof_operation(A, &oper->children[0], &type0);
 
3156
   typeof_operation(A, &oper->children[0], &type0);
2580
3157
   isBool = (type0.spec.type == SLANG_SPEC_BOOL);
2581
3158
   slang_typeinfo_destruct(&type0);
2582
3159
   if (!isBool) {
2586
3163
 
2587
3164
   slang_typeinfo_construct(&type1);
2588
3165
   slang_typeinfo_construct(&type2);
2589
 
   _slang_typeof_operation(A, &oper->children[1], &type1);
2590
 
   _slang_typeof_operation(A, &oper->children[2], &type2);
 
3166
   typeof_operation(A, &oper->children[1], &type1);
 
3167
   typeof_operation(A, &oper->children[2], &type2);
2591
3168
   isEqual = slang_type_specifier_equal(&type1.spec, &type2.spec);
2592
3169
   slang_typeinfo_destruct(&type1);
2593
3170
   slang_typeinfo_destruct(&type2);
2727
3304
 
2728
3305
#if 1 /* DEBUG */
2729
3306
      {
2730
 
         slang_variable *v
2731
 
            = _slang_locate_variable(oper->locals, a_retVal, GL_TRUE);
 
3307
         slang_variable *v =
 
3308
            _slang_variable_locate(oper->locals, a_retVal, GL_TRUE);
2732
3309
         if (!v) {
2733
3310
            /* trying to return a value in a void-valued function */
2734
3311
            return NULL;
2758
3335
}
2759
3336
 
2760
3337
 
 
3338
#if 0
2761
3339
/**
2762
3340
 * Determine if the given operation/expression is const-valued.
2763
3341
 */
2769
3347
 
2770
3348
   switch (oper->type) {
2771
3349
   case SLANG_OPER_IDENTIFIER:
2772
 
      var = _slang_locate_variable(oper->locals, oper->a_id, GL_TRUE);
 
3350
      var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
2773
3351
      if (var && var->type.qualifier == SLANG_QUAL_CONST)
2774
3352
         return GL_TRUE;
2775
3353
      return GL_FALSE;
2781
3359
      return GL_TRUE;
2782
3360
   }
2783
3361
}
 
3362
#endif
2784
3363
 
2785
3364
 
2786
3365
/**
2801
3380
   }
2802
3381
 
2803
3382
   slang_typeinfo_construct(&t0);
2804
 
   _slang_typeof_operation(A, op0, &t0);
 
3383
   typeof_operation(A, op0, &t0);
2805
3384
 
2806
3385
   slang_typeinfo_construct(&t1);
2807
 
   _slang_typeof_operation(A, op1, &t1);
 
3386
   typeof_operation(A, op1, &t1);
2808
3387
 
2809
3388
   sz0 = _slang_sizeof_type_specifier(&t0.spec);
2810
3389
   sz1 = _slang_sizeof_type_specifier(&t1.spec);
2843
3422
}
2844
3423
 
2845
3424
 
2846
 
 
2847
3425
/**
2848
 
 * Generate IR tree for a variable declaration.
 
3426
 * Generate IR tree for a local variable declaration.
 
3427
 * Basically do some error checking and call _slang_gen_var_decl().
2849
3428
 */
2850
3429
static slang_ir_node *
2851
3430
_slang_gen_declaration(slang_assemble_ctx *A, slang_operation *oper)
2852
3431
{
2853
 
   slang_ir_node *n;
 
3432
   const char *varName = (char *) oper->a_id;
 
3433
   slang_variable *var;
2854
3434
   slang_ir_node *varDecl;
2855
 
   slang_variable *v;
2856
 
   const char *varName = (char *) oper->a_id;
2857
3435
   slang_operation *initializer;
2858
3436
 
2859
3437
   assert(oper->type == SLANG_OPER_VARIABLE_DECL);
2860
3438
   assert(oper->num_children <= 1);
2861
3439
 
2862
 
   v = _slang_locate_variable(oper->locals, oper->a_id, GL_TRUE);
2863
 
   if (!v)
 
3440
   /* lookup the variable by name */
 
3441
   var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
 
3442
   if (!var)
2864
3443
      return NULL;  /* "shouldn't happen" */
2865
3444
 
2866
 
   if (v->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
2867
 
       v->type.qualifier == SLANG_QUAL_VARYING ||
2868
 
       v->type.qualifier == SLANG_QUAL_UNIFORM) {
 
3445
   if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
 
3446
       var->type.qualifier == SLANG_QUAL_VARYING ||
 
3447
       var->type.qualifier == SLANG_QUAL_UNIFORM) {
2869
3448
      /* can't declare attribute/uniform vars inside functions */
2870
3449
      slang_info_log_error(A->log,
2871
3450
                "local variable '%s' cannot be an attribute/uniform/varying",
2880
3459
   }
2881
3460
#endif
2882
3461
 
2883
 
   varDecl = _slang_gen_var_decl(A, v);
2884
 
   if (!varDecl)
2885
 
      return NULL;
2886
 
 
2887
3462
   /* check if the var has an initializer */
2888
3463
   if (oper->num_children > 0) {
2889
3464
      assert(oper->num_children == 1);
2890
3465
      initializer = &oper->children[0];
2891
3466
   }
2892
 
   else if (v->initializer) {
2893
 
      initializer = v->initializer;
 
3467
   else if (var->initializer) {
 
3468
      initializer = var->initializer;
2894
3469
   }
2895
3470
   else {
2896
3471
      initializer = NULL;
2897
3472
   }
2898
3473
 
2899
 
   if (v->type.qualifier == SLANG_QUAL_CONST && !initializer) {
2900
 
      slang_info_log_error(A->log,
2901
 
                           "const-qualified variable '%s' requires initializer",
2902
 
                           varName);
2903
 
      return NULL;
2904
 
   }
2905
 
 
2906
 
 
2907
3474
   if (initializer) {
2908
 
      slang_ir_node *var, *init;
2909
 
 
2910
 
      /* type check/compare var and initializer */
 
3475
      /* check/compare var type and initializer type */
2911
3476
      if (!_slang_assignment_compatible(A, oper, initializer)) {
2912
3477
         slang_info_log_error(A->log, "incompatible types in assignment");
2913
3478
         return NULL;
2914
3479
      }         
2915
 
 
2916
 
      var = new_var(A, oper, oper->a_id);
2917
 
      if (!var) {
2918
 
         slang_info_log_error(A->log, "undefined variable '%s'", varName);
2919
 
         return NULL;
2920
 
      }
2921
 
 
2922
 
      if (v->type.qualifier == SLANG_QUAL_CONST) {
2923
 
         /* if the variable is const, the initializer must be a const
2924
 
          * expression as well.
2925
 
          */
2926
 
#if 0
2927
 
         if (!_slang_is_constant_expr(initializer)) {
2928
 
            slang_info_log_error(A->log,
2929
 
                                 "initializer for %s not constant", varName);
2930
 
            return NULL;
2931
 
         }
2932
 
#endif
2933
 
      }
2934
 
 
2935
 
      _slang_simplify(initializer, &A->space, A->atoms); 
2936
 
 
2937
 
      init = _slang_gen_operation(A, initializer);
2938
 
      if (!init)
2939
 
         return NULL;
2940
 
 
2941
 
      /*assert(init->Store);*/
2942
 
 
2943
 
      /* XXX remove this when type checking is added above */
2944
 
      if (init->Store && var->Store->Size != init->Store->Size) {
2945
 
         slang_info_log_error(A->log, "invalid assignment (wrong types)");
2946
 
         return NULL;
2947
 
      }
2948
 
 
2949
 
      n = new_node2(IR_COPY, var, init);
2950
 
      n = new_seq(varDecl, n);
2951
3480
   }
2952
3481
   else {
2953
 
      n = varDecl;
 
3482
      if (var->type.qualifier == SLANG_QUAL_CONST) {
 
3483
         slang_info_log_error(A->log,
 
3484
                       "const-qualified variable '%s' requires initializer",
 
3485
                       varName);
 
3486
         return NULL;
 
3487
      }
2954
3488
   }
2955
3489
 
2956
 
   return n;
 
3490
   /* Generate IR node */
 
3491
   varDecl = _slang_gen_var_decl(A, var, initializer);
 
3492
   if (!varDecl)
 
3493
      return NULL;
 
3494
 
 
3495
   return varDecl;
2957
3496
}
2958
3497
 
2959
3498
 
2960
3499
/**
2961
 
 * Generate IR tree for a variable (such as in an expression).
 
3500
 * Generate IR tree for a reference to a variable (such as in an expression).
 
3501
 * This is different from a variable declaration.
2962
3502
 */
2963
3503
static slang_ir_node *
2964
3504
_slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper)
2966
3506
   /* If there's a variable associated with this oper (from inlining)
2967
3507
    * use it.  Otherwise, use the oper's var id.
2968
3508
    */
2969
 
   slang_atom aVar = oper->var ? oper->var->a_name : oper->a_id;
2970
 
   slang_ir_node *n = new_var(A, oper, aVar);
2971
 
   if (!n) {
2972
 
      slang_info_log_error(A->log, "undefined variable '%s'", (char *) aVar);
 
3509
   slang_atom name = oper->var ? oper->var->a_name : oper->a_id;
 
3510
   slang_variable *var = _slang_variable_locate(oper->locals, name, GL_TRUE);
 
3511
   slang_ir_node *n;
 
3512
   if (!var) {
 
3513
      slang_info_log_error(A->log, "undefined variable '%s'", (char *) name);
2973
3514
      return NULL;
2974
3515
   }
 
3516
   assert(var->declared);
 
3517
   n = new_var(A, var);
2975
3518
   return n;
2976
3519
}
2977
3520
 
3028
3571
 
3029
3572
 
3030
3573
/**
 
3574
 * Walk up an IR storage path to compute the final swizzle.
 
3575
 * This is used when we find an expression such as "foo.xz.yx".
 
3576
 */
 
3577
static GLuint
 
3578
root_swizzle(const slang_ir_storage *st)
 
3579
{
 
3580
   GLuint swizzle = st->Swizzle;
 
3581
   while (st->Parent) {
 
3582
      st = st->Parent;
 
3583
      swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
 
3584
   }
 
3585
   return swizzle;
 
3586
}
 
3587
 
 
3588
 
 
3589
/**
3031
3590
 * Generate IR tree for an assignment (=).
3032
3591
 */
3033
3592
static slang_ir_node *
3036
3595
   if (oper->children[0].type == SLANG_OPER_IDENTIFIER) {
3037
3596
      /* Check that var is writeable */
3038
3597
      slang_variable *var
3039
 
         = _slang_locate_variable(oper->children[0].locals,
 
3598
         = _slang_variable_locate(oper->children[0].locals,
3040
3599
                                  oper->children[0].a_id, GL_TRUE);
3041
3600
      if (!var) {
3042
3601
         slang_info_log_error(A->log, "undefined variable '%s'",
3102
3661
      rhs = _slang_gen_operation(A, &oper->children[1]);
3103
3662
      if (lhs && rhs) {
3104
3663
         /* convert lhs swizzle into writemask */
 
3664
         const GLuint swizzle = root_swizzle(lhs->Store);
3105
3665
         GLuint writemask, newSwizzle;
3106
 
         if (!swizzle_to_writemask(A, lhs->Store->Swizzle,
3107
 
                                   &writemask, &newSwizzle)) {
 
3666
         if (!swizzle_to_writemask(A, swizzle, &writemask, &newSwizzle)) {
3108
3667
            /* Non-simple writemask, need to swizzle right hand side in
3109
3668
             * order to put components into the right place.
3110
3669
             */
3130
3689
 
3131
3690
   /* type of struct */
3132
3691
   slang_typeinfo_construct(&ti);
3133
 
   _slang_typeof_operation(A, &oper->children[0], &ti);
 
3692
   typeof_operation(A, &oper->children[0], &ti);
3134
3693
 
3135
3694
   if (_slang_type_is_vector(ti.spec.type)) {
3136
3695
      /* the field should be a swizzle */
3182
3741
 
3183
3742
      /* type of field */
3184
3743
      slang_typeinfo_construct(&field_ti);
3185
 
      _slang_typeof_operation(A, oper, &field_ti);
 
3744
      typeof_operation(A, oper, &field_ti);
3186
3745
 
3187
3746
      fieldSize = _slang_sizeof_type_specifier(&field_ti.spec);
3188
3747
      if (fieldSize > 0)
3233
3792
 
3234
3793
   /* get array's type info */
3235
3794
   slang_typeinfo_construct(&array_ti);
3236
 
   _slang_typeof_operation(A, &oper->children[0], &array_ti);
 
3795
   typeof_operation(A, &oper->children[0], &array_ti);
3237
3796
 
3238
3797
   if (_slang_type_is_vector(array_ti.spec.type)) {
3239
3798
      /* indexing a simple vector type: "vec4 v; v[0]=p;" */
3245
3804
      index = (GLint) oper->children[1].literal[0];
3246
3805
      if (oper->children[1].type != SLANG_OPER_LITERAL_INT ||
3247
3806
          index >= (GLint) max) {
 
3807
#if 0
3248
3808
         slang_info_log_error(A->log, "Invalid array index for vector type");
 
3809
         printf("type = %d\n", oper->children[1].type);
 
3810
         printf("index = %d, max = %d\n", index, max);
 
3811
         printf("array = %s\n", (char*)oper->children[0].a_id);
 
3812
         printf("index = %s\n", (char*)oper->children[1].a_id);
3249
3813
         return NULL;
 
3814
#else
 
3815
         index = 0;
 
3816
#endif
3250
3817
      }
3251
3818
 
3252
3819
      n = _slang_gen_operation(A, &oper->children[0]);
3269
3836
 
3270
3837
      /* size of array element */
3271
3838
      slang_typeinfo_construct(&elem_ti);
3272
 
      _slang_typeof_operation(A, oper, &elem_ti);
 
3839
      typeof_operation(A, oper, &elem_ti);
3273
3840
      elemSize = _slang_sizeof_type_specifier(&elem_ti.spec);
3274
3841
 
3275
3842
      if (_slang_type_is_matrix(array_ti.spec.type))
3314
3881
         elem->Store = _slang_new_ir_storage(array->Store->File,
3315
3882
                                             array->Store->Index,
3316
3883
                                             elemSize);
3317
 
 
 
3884
         elem->Store->Swizzle = _slang_var_swizzle(elemSize, 0);
3318
3885
         return elem;
3319
3886
      }
3320
3887
      else {
3334
3901
   slang_ir_node *n;
3335
3902
   
3336
3903
   slang_typeinfo_construct(&t0);
3337
 
   _slang_typeof_operation(A, &oper->children[0], &t0);
 
3904
   typeof_operation(A, &oper->children[0], &t0);
3338
3905
 
3339
3906
   slang_typeinfo_construct(&t1);
3340
 
   _slang_typeof_operation(A, &oper->children[0], &t1);
 
3907
   typeof_operation(A, &oper->children[0], &t1);
3341
3908
 
3342
3909
   if (t0.spec.type == SLANG_SPEC_ARRAY ||
3343
3910
       t1.spec.type == SLANG_SPEC_ARRAY) {
3672
4239
 
3673
4240
 
3674
4241
/**
3675
 
 * Compute total size of array give size of element, number of elements.
 
4242
 * Check if the given type specifier is a rectangular texture sampler.
3676
4243
 */
3677
 
static GLint
3678
 
array_size(GLint baseSize, GLint arrayLen)
 
4244
static GLboolean
 
4245
is_rect_sampler_spec(const slang_type_specifier *spec)
3679
4246
{
3680
 
   GLint total;
3681
 
   if (arrayLen > 1) {
3682
 
      /* round up base type to multiple of 4 */
3683
 
      total = ((baseSize + 3) & ~0x3) * MAX2(arrayLen, 1);
3684
 
   }
3685
 
   else {
3686
 
      total = baseSize;
3687
 
   }
3688
 
   return total;
 
4247
   while (spec->_array) {
 
4248
      spec = spec->_array;
 
4249
   }
 
4250
   return spec->type == SLANG_SPEC_SAMPLER2DRECT ||
 
4251
          spec->type == SLANG_SPEC_SAMPLER2DRECTSHADOW;
3689
4252
}
3690
4253
 
3691
4254
 
 
4255
 
3692
4256
/**
3693
4257
 * Called by compiler when a global variable has been parsed/compiled.
3694
4258
 * Here we examine the variable's type to determine what kind of register
3712
4276
   slang_ir_storage *store = NULL;
3713
4277
   int dbg = 0;
3714
4278
   const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
3715
 
   const GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
3716
4279
   const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
 
4280
   const GLint arrayLen = _slang_array_length(var);
 
4281
   const GLint totalSize = _slang_array_size(size, arrayLen);
 
4282
   GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
 
4283
 
 
4284
   /* check for sampler2D arrays */
 
4285
   if (texIndex == -1 && var->type.specifier._array)
 
4286
      texIndex = sampler_to_texture_index(var->type.specifier._array->type);
3717
4287
 
3718
4288
   if (texIndex != -1) {
3719
4289
      /* This is a texture sampler variable...
3727
4297
      }
3728
4298
#if FEATURE_es2_glsl /* XXX should use FEATURE_texture_rect */
3729
4299
      /* disallow rect samplers */
3730
 
      if (var->type.specifier.type == SLANG_SPEC_SAMPLER2DRECT ||
3731
 
          var->type.specifier.type == SLANG_SPEC_SAMPLER2DRECTSHADOW) {
 
4300
      if (is_rect_sampler_spec(&var->type.specifier)) {
3732
4301
         slang_info_log_error(A->log, "invalid sampler type for '%s'", varName);
3733
4302
         return GL_FALSE;
3734
4303
      }
 
4304
#else
 
4305
      (void) is_rect_sampler_spec; /* silence warning */
3735
4306
#endif
3736
4307
      {
3737
4308
         GLint sampNum = _mesa_add_sampler(prog->Parameters, varName, datatype);
3738
 
         store = _slang_new_ir_storage(PROGRAM_SAMPLER, sampNum, texIndex);
 
4309
         store = _slang_new_ir_storage_sampler(sampNum, texIndex, totalSize);
 
4310
 
 
4311
         /* If we have a sampler array, then we need to allocate the 
 
4312
          * additional samplers to ensure we don't allocate them elsewhere.
 
4313
          * We can't directly use _mesa_add_sampler() as that checks the
 
4314
          * varName and gets a match, so we call _mesa_add_parameter()
 
4315
          * directly and use the last sampler number from the call above.
 
4316
          */
 
4317
         if (arrayLen > 0) {
 
4318
            GLint a = arrayLen - 1;
 
4319
            GLint i;
 
4320
            for (i = 0; i < a; i++) {
 
4321
               GLfloat value = (GLfloat)(i + sampNum + 1);
 
4322
               (void) _mesa_add_parameter(prog->Parameters, PROGRAM_SAMPLER,
 
4323
                                 varName, 1, datatype, &value, NULL, 0x0);
 
4324
            }
 
4325
         }
3739
4326
      }
3740
4327
      if (dbg) printf("SAMPLER ");
3741
4328
   }
3742
4329
   else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
3743
4330
      /* Uniform variable */
3744
 
      const GLint totalSize = array_size(size, var->array_len);
3745
4331
      const GLuint swizzle = _slang_var_swizzle(totalSize, 0);
3746
4332
 
3747
4333
      if (prog) {
3783
4369
            }
3784
4370
         }
3785
4371
         else {
3786
 
            GLint uniformLoc;
3787
 
            const GLfloat *initialValues = NULL;
3788
 
            if (var->initializer) {
3789
 
               _slang_simplify(var->initializer, &A->space, A->atoms);
3790
 
               if (var->initializer->type == SLANG_OPER_LITERAL_FLOAT ||
3791
 
                   var->initializer->type == SLANG_OPER_LITERAL_INT) {
3792
 
                  /* simple float/vector initializer */
3793
 
                  initialValues = var->initializer->literal;
3794
 
               }
3795
 
               else {
3796
 
                  /* complex initializer */
3797
 
                  slang_info_log_error(A->log,
3798
 
                     "unsupported initializer for uniform '%s'", varName);
3799
 
                  return GL_FALSE;
3800
 
               }
3801
 
            }
3802
 
 
3803
 
            uniformLoc = _mesa_add_uniform(prog->Parameters, varName,
3804
 
                                           totalSize, datatype, initialValues);
3805
 
            store = _slang_new_ir_storage_swz(PROGRAM_UNIFORM, uniformLoc,
3806
 
                                              totalSize, swizzle);
 
4372
            /* non-struct uniform */
 
4373
            if (!_slang_gen_var_decl(A, var, var->initializer))
 
4374
               return GL_FALSE;
 
4375
            store = var->store;
3807
4376
         }
3808
4377
      }
3809
4378
      else {
3817
4386
      if (dbg) printf("UNIFORM (sz %d) ", totalSize);
3818
4387
   }
3819
4388
   else if (var->type.qualifier == SLANG_QUAL_VARYING) {
3820
 
      const GLint totalSize = array_size(size, var->array_len);
3821
 
 
3822
4389
      /* varyings must be float, vec or mat */
3823
4390
      if (!_slang_type_is_float_vec_mat(var->type.specifier.type) &&
3824
4391
          var->type.specifier.type != SLANG_SPEC_ARRAY) {
3936
4503
      slang_ir_node *n;
3937
4504
 
3938
4505
      /* IR node to declare the variable */
3939
 
      n = _slang_gen_var_decl(A, var);
3940
 
 
3941
 
      /* IR code for the var's initializer, if present */
3942
 
      if (var->initializer) {
3943
 
         slang_ir_node *lhs, *rhs, *init;
3944
 
 
3945
 
         /* Generate IR_COPY instruction to initialize the variable */
3946
 
         lhs = new_node0(IR_VAR);
3947
 
         lhs->Var = var;
3948
 
         lhs->Store = n->Store;
3949
 
 
3950
 
         /* constant folding, etc */
3951
 
         _slang_simplify(var->initializer, &A->space, A->atoms);
3952
 
 
3953
 
         rhs = _slang_gen_operation(A, var->initializer);
3954
 
         assert(rhs);
3955
 
         init = new_node2(IR_COPY, lhs, rhs);
3956
 
         n = new_seq(n, init);
3957
 
      }
3958
 
 
3959
 
      success = _slang_emit_code(n, A->vartable, A->program, GL_FALSE, A->log);
 
4506
      n = _slang_gen_var_decl(A, var, var->initializer);
 
4507
 
 
4508
      /* emit GPU instructions */
 
4509
      success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_FALSE, A->log);
3960
4510
 
3961
4511
      _slang_free_ir_tree(n);
3962
4512
   }
4066
4616
#endif
4067
4617
 
4068
4618
   /* Emit program instructions */
4069
 
   success = _slang_emit_code(n, A->vartable, A->program, GL_TRUE, A->log);
 
4619
   success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_TRUE, A->log);
4070
4620
   _slang_free_ir_tree(n);
4071
4621
 
4072
4622
   /* free codegen context */