mesa: move shader/slang/* sources to main/slang/*
authorBrian Paul <brianp@vmware.com>
Fri, 11 Jun 2010 04:48:16 +0000 (22:48 -0600)
committerBrian Paul <brianp@vmware.com>
Fri, 11 Jun 2010 04:48:16 +0000 (22:48 -0600)
Reduce the source tree depth a bit.

103 files changed:
Makefile
src/mesa/Makefile
src/mesa/SConscript
src/mesa/main/shaderapi.c
src/mesa/shader/slang/descrip.mms [deleted file]
src/mesa/shader/slang/library/.gitignore [deleted file]
src/mesa/shader/slang/library/Makefile [deleted file]
src/mesa/shader/slang/library/SConscript [deleted file]
src/mesa/shader/slang/library/slang_120_core.gc [deleted file]
src/mesa/shader/slang/library/slang_builtin_120_common.gc [deleted file]
src/mesa/shader/slang/library/slang_builtin_120_fragment.gc [deleted file]
src/mesa/shader/slang/library/slang_common_builtin.gc [deleted file]
src/mesa/shader/slang/library/slang_core.gc [deleted file]
src/mesa/shader/slang/library/slang_fragment_builtin.gc [deleted file]
src/mesa/shader/slang/library/slang_vertex_builtin.gc [deleted file]
src/mesa/shader/slang/slang_builtin.c [deleted file]
src/mesa/shader/slang/slang_builtin.h [deleted file]
src/mesa/shader/slang/slang_codegen.c [deleted file]
src/mesa/shader/slang/slang_codegen.h [deleted file]
src/mesa/shader/slang/slang_compile.c [deleted file]
src/mesa/shader/slang/slang_compile.h [deleted file]
src/mesa/shader/slang/slang_compile_function.c [deleted file]
src/mesa/shader/slang/slang_compile_function.h [deleted file]
src/mesa/shader/slang/slang_compile_operation.c [deleted file]
src/mesa/shader/slang/slang_compile_operation.h [deleted file]
src/mesa/shader/slang/slang_compile_struct.c [deleted file]
src/mesa/shader/slang/slang_compile_struct.h [deleted file]
src/mesa/shader/slang/slang_compile_variable.c [deleted file]
src/mesa/shader/slang/slang_compile_variable.h [deleted file]
src/mesa/shader/slang/slang_emit.c [deleted file]
src/mesa/shader/slang/slang_emit.h [deleted file]
src/mesa/shader/slang/slang_ir.c [deleted file]
src/mesa/shader/slang/slang_ir.h [deleted file]
src/mesa/shader/slang/slang_label.c [deleted file]
src/mesa/shader/slang/slang_label.h [deleted file]
src/mesa/shader/slang/slang_link.c [deleted file]
src/mesa/shader/slang/slang_link.h [deleted file]
src/mesa/shader/slang/slang_log.c [deleted file]
src/mesa/shader/slang/slang_log.h [deleted file]
src/mesa/shader/slang/slang_mem.c [deleted file]
src/mesa/shader/slang/slang_mem.h [deleted file]
src/mesa/shader/slang/slang_print.c [deleted file]
src/mesa/shader/slang/slang_print.h [deleted file]
src/mesa/shader/slang/slang_simplify.c [deleted file]
src/mesa/shader/slang/slang_simplify.h [deleted file]
src/mesa/shader/slang/slang_storage.c [deleted file]
src/mesa/shader/slang/slang_storage.h [deleted file]
src/mesa/shader/slang/slang_typeinfo.c [deleted file]
src/mesa/shader/slang/slang_typeinfo.h [deleted file]
src/mesa/shader/slang/slang_utility.c [deleted file]
src/mesa/shader/slang/slang_utility.h [deleted file]
src/mesa/shader/slang/slang_vartable.c [deleted file]
src/mesa/shader/slang/slang_vartable.h [deleted file]
src/mesa/slang/descrip.mms [new file with mode: 0644]
src/mesa/slang/library/.gitignore [new file with mode: 0644]
src/mesa/slang/library/Makefile [new file with mode: 0644]
src/mesa/slang/library/SConscript [new file with mode: 0644]
src/mesa/slang/library/slang_120_core.gc [new file with mode: 0644]
src/mesa/slang/library/slang_builtin_120_common.gc [new file with mode: 0644]
src/mesa/slang/library/slang_builtin_120_fragment.gc [new file with mode: 0644]
src/mesa/slang/library/slang_common_builtin.gc [new file with mode: 0644]
src/mesa/slang/library/slang_core.gc [new file with mode: 0644]
src/mesa/slang/library/slang_fragment_builtin.gc [new file with mode: 0644]
src/mesa/slang/library/slang_vertex_builtin.gc [new file with mode: 0644]
src/mesa/slang/slang_builtin.c [new file with mode: 0644]
src/mesa/slang/slang_builtin.h [new file with mode: 0644]
src/mesa/slang/slang_codegen.c [new file with mode: 0644]
src/mesa/slang/slang_codegen.h [new file with mode: 0644]
src/mesa/slang/slang_compile.c [new file with mode: 0644]
src/mesa/slang/slang_compile.h [new file with mode: 0644]
src/mesa/slang/slang_compile_function.c [new file with mode: 0644]
src/mesa/slang/slang_compile_function.h [new file with mode: 0644]
src/mesa/slang/slang_compile_operation.c [new file with mode: 0644]
src/mesa/slang/slang_compile_operation.h [new file with mode: 0644]
src/mesa/slang/slang_compile_struct.c [new file with mode: 0644]
src/mesa/slang/slang_compile_struct.h [new file with mode: 0644]
src/mesa/slang/slang_compile_variable.c [new file with mode: 0644]
src/mesa/slang/slang_compile_variable.h [new file with mode: 0644]
src/mesa/slang/slang_emit.c [new file with mode: 0644]
src/mesa/slang/slang_emit.h [new file with mode: 0644]
src/mesa/slang/slang_ir.c [new file with mode: 0644]
src/mesa/slang/slang_ir.h [new file with mode: 0644]
src/mesa/slang/slang_label.c [new file with mode: 0644]
src/mesa/slang/slang_label.h [new file with mode: 0644]
src/mesa/slang/slang_link.c [new file with mode: 0644]
src/mesa/slang/slang_link.h [new file with mode: 0644]
src/mesa/slang/slang_log.c [new file with mode: 0644]
src/mesa/slang/slang_log.h [new file with mode: 0644]
src/mesa/slang/slang_mem.c [new file with mode: 0644]
src/mesa/slang/slang_mem.h [new file with mode: 0644]
src/mesa/slang/slang_print.c [new file with mode: 0644]
src/mesa/slang/slang_print.h [new file with mode: 0644]
src/mesa/slang/slang_simplify.c [new file with mode: 0644]
src/mesa/slang/slang_simplify.h [new file with mode: 0644]
src/mesa/slang/slang_storage.c [new file with mode: 0644]
src/mesa/slang/slang_storage.h [new file with mode: 0644]
src/mesa/slang/slang_typeinfo.c [new file with mode: 0644]
src/mesa/slang/slang_typeinfo.h [new file with mode: 0644]
src/mesa/slang/slang_utility.c [new file with mode: 0644]
src/mesa/slang/slang_utility.h [new file with mode: 0644]
src/mesa/slang/slang_vartable.c [new file with mode: 0644]
src/mesa/slang/slang_vartable.h [new file with mode: 0644]
src/mesa/sources.mak

index 2f83ce99f198e2724ac8f879199eadc0e8826d36..bf4f2d5218f40227d0e4d9c6c78f121a5b33c4db 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -246,10 +246,10 @@ MAIN_FILES = \
        $(DIRECTORY)/src/mesa/shader/*.[chly]                           \
        $(DIRECTORY)/src/mesa/shader/Makefile                           \
        $(DIRECTORY)/src/mesa/shader/descrip.mms                        \
-       $(DIRECTORY)/src/mesa/shader/slang/*.[ch]                       \
-       $(DIRECTORY)/src/mesa/shader/slang/descrip.mms                  \
-       $(DIRECTORY)/src/mesa/shader/slang/library/*.gc                 \
-       $(DIRECTORY)/src/mesa/shader/slang/library/Makefile             \
+       $(DIRECTORY)/src/mesa/slang/*.[ch]                              \
+       $(DIRECTORY)/src/mesa/slang/descrip.mms                         \
+       $(DIRECTORY)/src/mesa/slang/library/*.gc                        \
+       $(DIRECTORY)/src/mesa/slang/library/Makefile                    \
        $(DIRECTORY)/src/mesa/swrast/*.[ch]                             \
        $(DIRECTORY)/src/mesa/swrast/descrip.mms                        \
        $(DIRECTORY)/src/mesa/swrast_setup/*.[ch]                       \
index 4f81768924a3fbf813ee46d0e92d493c24d8c1d0..3e0f010671ceff6a9ce2ad823fff3fe1b8bddf8f 100644 (file)
@@ -116,7 +116,7 @@ asm_subdirs:
 ######################################################################
 # GLSL built-in library
 glsl_builtin:
-       (cd shader/slang/library && $(MAKE)) || exit 1 ;
+       (cd slang/library && $(MAKE)) || exit 1 ;
 
 
 ######################################################################
@@ -234,7 +234,7 @@ clean: clean-es1 clean-es2
        -rm -f depend depend.bak libmesa.a libmesagallium.a
        -rm -f drivers/*/*.o
        -rm -f *.pc
-       -rm -f shader/slang/library/*_gc.h
+       -rm -f slang/library/*_gc.h
        -@cd drivers/dri && $(MAKE) clean
        -@cd drivers/x11 && $(MAKE) clean
        -@cd drivers/osmesa && $(MAKE) clean
index b65c86da820e7fbb161ac9df55bf2b21312945ed..405b5c8830c1863cfa984e1b2c7ab2a95fb9f0a0 100644 (file)
@@ -221,25 +221,25 @@ if env['platform'] != 'winddk':
        ]
        
        slang_sources = [
-               'shader/slang/slang_builtin.c',
-               'shader/slang/slang_codegen.c',
-               'shader/slang/slang_compile.c',
-               'shader/slang/slang_compile_function.c',
-               'shader/slang/slang_compile_operation.c',
-               'shader/slang/slang_compile_struct.c',
-               'shader/slang/slang_compile_variable.c',
-               'shader/slang/slang_emit.c',
-               'shader/slang/slang_ir.c',
-               'shader/slang/slang_label.c',
-               'shader/slang/slang_link.c',
-               'shader/slang/slang_log.c',
-               'shader/slang/slang_mem.c',
-               'shader/slang/slang_print.c',
-               'shader/slang/slang_simplify.c',
-               'shader/slang/slang_storage.c',
-               'shader/slang/slang_typeinfo.c',
-               'shader/slang/slang_vartable.c',
-               'shader/slang/slang_utility.c',
+               'slang/slang_builtin.c',
+               'slang/slang_codegen.c',
+               'slang/slang_compile.c',
+               'slang/slang_compile_function.c',
+               'slang/slang_compile_operation.c',
+               'slang/slang_compile_struct.c',
+               'slang/slang_compile_variable.c',
+               'slang/slang_emit.c',
+               'slang/slang_ir.c',
+               'slang/slang_label.c',
+               'slang/slang_link.c',
+               'slang/slang_log.c',
+               'slang/slang_mem.c',
+               'slang/slang_print.c',
+               'slang/slang_simplify.c',
+               'slang/slang_storage.c',
+               'slang/slang_typeinfo.c',
+               'slang/slang_vartable.c',
+               'slang/slang_utility.c',
        ]
        
        mesa_sources = (
index 88edb541ac63780594133be0ff7eebdc086f325e..81c3964f9316997aff46e01068f87465ff734072 100644 (file)
@@ -45,8 +45,8 @@
 #include "shader/program.h"
 #include "shader/prog_parameter.h"
 #include "shader/prog_uniform.h"
-#include "shader/slang/slang_compile.h"
-#include "shader/slang/slang_link.h"
+#include "slang/slang_compile.h"
+#include "slang/slang_link.h"
 
 
 /** Define this to enable shader substitution (see below) */
diff --git a/src/mesa/shader/slang/descrip.mms b/src/mesa/shader/slang/descrip.mms
deleted file mode 100644 (file)
index 674b786..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-# Makefile for core library for VMS
-# contributed by Jouk Jansen  joukj@hrem.nano.tudelft.nl
-# Last revision : 3 October 2007
-
-.first
-       define gl [----.include.gl]
-       define math [--.math]
-       define swrast [--.swrast]
-       define array_cache [--.array_cache]
-       define main [--.main]
-       define glapi [--.glapi]
-       define shader [--.shader]
-
-.include [----]mms-config.
-
-##### MACROS #####
-
-VPATH = RCS
-
-INCDIR = [----.include],[--.main],[--.glapi],[-.slang],[-]
-LIBDIR = [----.lib]
-CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
-
-SOURCES = \
-       slang_compile.c
-
-OBJECTS = slang_builtin.obj,slang_codegen.obj,slang_compile.obj,\
-       slang_compile_function.obj,slang_compile_operation.obj,\
-       slang_compile_struct.obj,slang_compile_variable.obj,slang_emit.obj,\
-       slang_ir.obj,slang_label.obj,slang_library_noise.obj,slang_link.obj,\
-       slang_log.obj,slang_mem.obj,slang_preprocess.obj,slang_print.obj,\
-       slang_simplify.obj,slang_storage.obj,slang_typeinfo.obj,\
-       slang_utility.obj,slang_vartable.obj
-
-##### RULES #####
-
-VERSION=Mesa V3.4
-
-##### TARGETS #####
-# Make the library
-$(LIBDIR)$(GL_LIB) : $(OBJECTS)
-  @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
-
-clean :
-       purge
-       delete *.obj;*
-
-slang_builtin.obj : slang_builtin.c
-slang_codegen.obj : slang_codegen.c
-slang_compile.obj : slang_compile.c
-slang_compile_function.obj : slang_compile_function.c
-slang_compile_operation.obj : slang_compile_operation.c
-slang_compile_struct.obj : slang_compile_struct.c
-slang_compile_variable.obj : slang_compile_variable.c
-slang_emit.obj : slang_emit.c
-slang_ir.obj : slang_ir.c
-slang_label.obj : slang_label.c
-slang_library_noise.obj : slang_library_noise.c
-slang_link.obj : slang_link.c
-slang_log.obj : slang_log.c
-slang_mem.obj : slang_mem.c
-slang_print.obj : slang_print.c
-slang_simplify.obj : slang_simplify.c
-slang_storage.obj : slang_storage.c
-slang_typeinfo.obj : slang_typeinfo.c
-slang_utility.obj : slang_utility.c
-slang_vartable.obj : slang_vartable.c
diff --git a/src/mesa/shader/slang/library/.gitignore b/src/mesa/shader/slang/library/.gitignore
deleted file mode 100644 (file)
index 02a89fc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-*_gc.h
diff --git a/src/mesa/shader/slang/library/Makefile b/src/mesa/shader/slang/library/Makefile
deleted file mode 100644 (file)
index c696451..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-# src/mesa/shader/slang/library/Makefile
-
-TOP = ../../../../..
-
-include $(TOP)/configs/current
-
-GLSL_CL = $(TOP)/src/glsl/apps/compile
-
-#
-# targets
-#
-
-.PHONY: default clean
-
-default: builtin
-
-clean:
-       -rm -f *_gc.h
-
-builtin: builtin_110 builtin_120
-
-#
-# builtin library sources
-#
-
-builtin_110: slang_common_builtin_gc.h slang_core_gc.h slang_fragment_builtin_gc.h slang_vertex_builtin_gc.h
-
-builtin_120: slang_120_core_gc.h slang_builtin_120_common_gc.h slang_builtin_120_fragment_gc.h
-
-
-slang_120_core_gc.h: slang_120_core.gc
-       $(GLSL_CL) fragment slang_120_core.gc slang_120_core_gc.h
-
-slang_builtin_120_common_gc.h: slang_builtin_120_common.gc
-       $(GLSL_CL) fragment slang_builtin_120_common.gc slang_builtin_120_common_gc.h
-
-slang_builtin_120_fragment_gc.h: slang_builtin_120_fragment.gc
-       $(GLSL_CL) fragment slang_builtin_120_fragment.gc slang_builtin_120_fragment_gc.h
-
-slang_common_builtin_gc.h: slang_common_builtin.gc
-       $(GLSL_CL) fragment slang_common_builtin.gc slang_common_builtin_gc.h
-
-slang_core_gc.h: slang_core.gc
-       $(GLSL_CL) fragment slang_core.gc slang_core_gc.h
-
-slang_fragment_builtin_gc.h: slang_fragment_builtin.gc
-       $(GLSL_CL) fragment slang_fragment_builtin.gc slang_fragment_builtin_gc.h
-
-slang_vertex_builtin_gc.h: slang_vertex_builtin.gc
-       $(GLSL_CL) vertex slang_vertex_builtin.gc slang_vertex_builtin_gc.h
-
diff --git a/src/mesa/shader/slang/library/SConscript b/src/mesa/shader/slang/library/SConscript
deleted file mode 100644 (file)
index 0b25467..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#######################################################################
-# SConscript for GLSL builtin library
-
-Import('*')
-
-env = env.Clone()
-
-# See also http://www.scons.org/wiki/UsingCodeGenerators
-
-def glsl_compile_emitter(target, source, env):
-       env.Depends(target, glsl_compile)
-       return (target, source)
-bld_frag = Builder(
-       action = Action(glsl_compile[0].abspath + ' fragment $SOURCE $TARGET', '$CODEGENCODESTR'),
-       emitter = glsl_compile_emitter,
-       suffix = '.gc',
-       src_suffix = '_gc.h')
-       
-bld_vert = Builder(
-       action = Action(glsl_compile[0].abspath + ' vertex $SOURCE $TARGET', '$CODEGENCODESTR'),
-       emitter = glsl_compile_emitter,
-       suffix = '.gc',
-       src_suffix = '_gc.h')
-
-env['BUILDERS']['bld_frag'] = bld_frag
-env['BUILDERS']['bld_vert'] = bld_vert
-
-# Generate GLSL builtin library binaries
-env.bld_frag(
-       '#src/mesa/shader/slang/library/slang_core_gc.h',
-       '#src/mesa/shader/slang/library/slang_core.gc')
-env.bld_frag(
-       '#src/mesa/shader/slang/library/slang_common_builtin_gc.h',
-       '#src/mesa/shader/slang/library/slang_common_builtin.gc')
-env.bld_frag(
-       '#src/mesa/shader/slang/library/slang_fragment_builtin_gc.h',
-       '#src/mesa/shader/slang/library/slang_fragment_builtin.gc')
-env.bld_vert(
-       '#src/mesa/shader/slang/library/slang_vertex_builtin_gc.h',
-       '#src/mesa/shader/slang/library/slang_vertex_builtin.gc')
-
-# Generate GLSL 1.20 builtin library binaries
-env.bld_frag(
-       '#src/mesa/shader/slang/library/slang_120_core_gc.h',
-       '#src/mesa/shader/slang/library/slang_120_core.gc')
-env.bld_frag(
-       '#src/mesa/shader/slang/library/slang_builtin_120_common_gc.h',
-       '#src/mesa/shader/slang/library/slang_builtin_120_common.gc')
-env.bld_frag(
-       '#src/mesa/shader/slang/library/slang_builtin_120_fragment_gc.h',
-       '#src/mesa/shader/slang/library/slang_builtin_120_fragment.gc')
diff --git a/src/mesa/shader/slang/library/slang_120_core.gc b/src/mesa/shader/slang/library/slang_120_core.gc
deleted file mode 100644 (file)
index 04c5ec2..0000000
+++ /dev/null
@@ -1,1978 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// Constructors and operators introduced in GLSL 1.20 - mostly on new
-// (non-square) types of matrices.
-//
-// One important change in the language is that when a matrix is used
-// as an argument to a matrix constructor, it must be the only argument
-// for the constructor. The compiler takes care of it by itself and
-// here we only care to re-introduce constructors for old (square)
-// types of matrices.
-//
-
-//
-// From Shader Spec, ver. 1.20, rev. 6
-//
-
-//// mat2x3: 2 columns of vec3
-
-mat2x3 __constructor(const float f00, const float f10, const float f20,
-                     const float f01, const float f11, const float f21)
-{
-   __retVal[0].x = f00;
-   __retVal[0].y = f10;
-   __retVal[0].z = f20;
-   __retVal[1].x = f01;
-   __retVal[1].y = f11;
-   __retVal[1].z = f21;
-}
-
-mat2x3 __constructor(const float f)
-{
-   __retVal = mat2x3(  f, 0.0, 0.0,
-                     0.0,   f, 0.0);
-}
-
-mat2x3 __constructor(const int  i)
-{
-   const float f = float(i);
-   __retVal = mat2x3(f);
-}
-
-mat2x3 __constructor(const bool b)
-{
-   const float f = float(b);
-   __retVal = mat2x3(f);
-}
-
-mat2x3 __constructor(const vec3 c0, const vec3 c1)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-}
-
-
-
-//// mat2x4: 2 columns of vec4
-
-mat2x4 __constructor(const float f00, const float f10, const float f20, const float f30,
-                     const float f01, const float f11, const float f21, const float f31)
-{
-   __retVal[0].x = f00;
-   __retVal[0].y = f10;
-   __retVal[0].z = f20;
-   __retVal[0].w = f30;
-   __retVal[1].x = f01;
-   __retVal[1].y = f11;
-   __retVal[1].z = f21;
-   __retVal[1].w = f31;
-}
-
-mat2x4 __constructor(const float f)
-{
-   __retVal = mat2x4(  f, 0.0, 0.0, 0.0,
-                     0.0,   f, 0.0, 0.0);
-}
-
-mat2x4 __constructor(const int i)
-{
-   const float f = float(i);
-   __retVal = mat2x4(f);
-}
-
-mat2x4 __constructor(const bool b)
-{
-   const float f = float(b);
-   __retVal = mat2x4(f);
-}
-
-mat2x4 __constructor(const vec4 c0, const vec4 c1)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-}
-
-
-
-//// mat3x2: 3 columns of vec2
-
-mat3x2 __constructor(const float f00, const float f10,
-                     const float f01, const float f11,
-                     const float f02, const float f12)
-{
-   __retVal[0].x = f00;
-   __retVal[0].y = f10;
-   __retVal[1].x = f01;
-   __retVal[1].y = f11;
-   __retVal[2].x = f02;
-   __retVal[2].y = f12;
-}
-
-mat3x2 __constructor(const float f)
-{
-   __retVal = mat3x2(  f, 0.0,
-                     0.0,   f,
-                     0.0, 0.0);
-}
-
-mat3x2 __constructor(const int i)
-{
-   const float f = float(i);
-   __retVal = mat3x2(f);
-}
-
-mat3x2 __constructor(const bool b)
-{
-   const float f = float(b);
-   __retVal = mat3x2(f);
-}
-
-mat3x2 __constructor(const vec2 c0, const vec2 c1, const vec2 c2)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-   __retVal[2] = c2;
-}
-
-
-
-//// mat3x4: 3 columns of vec4
-
-mat3x4 __constructor(const float f00, const float f10, const float f20, const float f30,
-                     const float f01, const float f11, const float f21, const float f31,
-                    const float f02, const float f12, const float f22, const float f32)
-{
-   __retVal[0].x = f00;
-   __retVal[0].y = f10;
-   __retVal[0].z = f20;
-   __retVal[0].w = f30;
-   __retVal[1].x = f01;
-   __retVal[1].y = f11;
-   __retVal[1].z = f21;
-   __retVal[1].w = f31;
-   __retVal[2].x = f02;
-   __retVal[2].y = f12;
-   __retVal[2].z = f22;
-   __retVal[2].w = f32;
-}
-
-mat3x4 __constructor(const float f)
-{
-   __retVal = mat3x4(  f, 0.0, 0.0, 0.0,
-                     0.0,   f, 0.0, 0.0,
-                     0.0, 0.0,   f, 0.0);
-}
-
-mat3x4 __constructor(const int i)
-{
-   const float f = float(i);
-   __retVal = mat3x4(f);
-}
-
-mat3x4 __constructor(const bool b)
-{
-   const float f = float(b);
-   __retVal = mat3x4(f);
-}
-
-mat3x4 __constructor(const vec4 c0, const vec4 c1, const vec4 c2)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-   __retVal[2] = c2;
-}
-
-
-
-//// mat4x2: 4 columns of vec2
-
-mat4x2 __constructor(const float f00, const float f10,
-                     const float f01, const float f11,
-                    const float f02, const float f12,
-                    const float f03, const float f13)
-{
-   __retVal[0].x = f00;
-   __retVal[0].y = f10;
-   __retVal[1].x = f01;
-   __retVal[1].y = f11;
-   __retVal[2].x = f02;
-   __retVal[2].y = f12;
-   __retVal[3].x = f03;
-   __retVal[3].y = f13;
-}
-
-mat4x2 __constructor(const float f)
-{
-   __retVal = mat4x2(  f, 0.0,
-                     0.0,   4,
-                     0.0, 0.0,
-                     0.0, 0.0);
-}
-
-mat4x2 __constructor(const int i)
-{
-   const float f = float(i);
-   __retVal = mat4x2(f);
-}
-
-mat4x2 __constructor(const bool b)
-{
-   const float f = float(b);
-   __retVal = mat4x2(f);
-}
-
-mat4x2 __constructor(const vec2 c0, const vec2 c1, const vec2 c2, const vec2 c3)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-   __retVal[2] = c2;
-   __retVal[3] = c3;
-}
-
-
-
-//// mat4x3: 4 columns of vec3
-
-mat4x3 __constructor(const float f00, const float f10, const float f20,
-                     const float f01, const float f11, const float f21,
-                    const float f02, const float f12, const float f22,
-                    const float f03, const float f13, const float f23)
-{
-   __retVal[0].x = f00;
-   __retVal[0].y = f10;
-   __retVal[0].z = f20;
-   __retVal[1].x = f01;
-   __retVal[1].y = f11;
-   __retVal[1].z = f21;
-   __retVal[2].x = f02;
-   __retVal[2].y = f12;
-   __retVal[2].z = f22;
-   __retVal[3].x = f03;
-   __retVal[3].y = f13;
-   __retVal[3].z = f23;
-}
-
-mat4x3 __constructor(const float f)
-{
-   __retVal = mat4x3(  f, 0.0, 0.0,
-                     0.0,   f, 0.0,
-                     0.0, 0.0,   f,
-                     0.0, 0.0, 0.0);
-}
-
-mat4x3 __constructor(const int i)
-{
-   const float f = float(i);
-   __retVal = mat4x3(f);
-}
-
-mat4x3 __constructor(const bool b)
-{
-   const float f = float(b);
-   __retVal = mat4x3(f);
-}
-
-mat4x3 __constructor(const vec3 c0, const vec3 c1, const vec3 c2, const vec3 c3)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-   __retVal[2] = c2;
-   __retVal[3] = c3;
-}
-
-
-
-//// misc assorted matrix constructors
-
-mat2 __constructor(const mat2 m)
-{
-   __retVal = m;
-}
-
-mat2 __constructor(const mat3x2 m)
-{
-   __retVal = mat2(m[0], m[1]);
-}
-
-mat2 __constructor(const mat4x2 m)
-{
-   __retVal = mat2(m[0], m[1]);
-}
-
-mat2 __constructor(const mat2x3 m)
-{
-   __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat2x4 m)
-{
-   __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat3 m)
-{
-   __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat3x4 m)
-{
-   __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat4x3 m)
-{
-   __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat4 m)
-{
-   __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-
-
-mat2x3 __constructor(const mat2x3 m)
-{
-   __retVal = m;
-}
-
-mat2x3 __constructor(const mat3 m)
-{
-   __retVal = mat2x3(m[0], m[1]);
-}
-
-mat2x3 __constructor(const mat4x3 m)
-{
-   __retVal = mat2x3(m[0], m[1]);
-}
-
-mat2x3 __constructor(const mat2x4 m)
-{
-   __retVal = mat2x3(m[0].xyz, m[1].xyz);
-}
-
-mat2x3 __constructor(const mat3x4 m)
-{
-   __retVal = mat2x3(m[0].xyz, m[1].xyz);
-}
-
-mat2x3 __constructor(const mat4 m)
-{
-   __retVal = mat2x3(m[0].xyz, m[1].xyz);
-}
-
-mat2x3 __constructor(const mat2 m)
-{
-   __retVal = mat2x3(m[0].x, m[0].y, 0.0,
-                     m[1].x, m[1].y, 0.0);
-}
-
-mat2x3 __constructor(const mat3x2 m)
-{
-   __retVal = mat2x3(m[0].x, m[0].y, 0.0,
-                     m[1].x, m[1].y, 0.0);
-}
-
-mat2x3 __constructor(const mat4x2 m)
-{
-   __retVal = mat2x3(m[0].x, m[0].y, 0.0,
-                     m[1].x, m[1].y, 0.0);
-}
-
-
-
-mat2x4 __constructor(const mat2x4 m)
-{
-   __retVal = m;
-}
-
-mat2x4 __constructor(const mat3x4 m)
-{
-   __retVal = mat2x4(m[0], m[1]);
-}
-
-mat2x4 __constructor(const mat4 m)
-{
-   __retVal = mat2x4(m[0], m[1]);
-}
-
-mat2x4 __constructor(const mat2x3 m)
-{
-   __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
-                     m[1].x, m[1].y, m[1].z, 0.0);
-}
-
-mat2x4 __constructor(const mat3 m)
-{
-   __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
-                     m[1].x, m[1].y, m[1].z, 0.0);
-}
-
-mat2x4 __constructor(const mat4x3 m)
-{
-   __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
-                     m[1].x, m[1].y, m[1].z, 0.0);
-}
-
-mat2x4 __constructor(const mat2 m)
-{
-   __retVal = mat2x4(m[0].x, m[1].y, 0.0, 0.0,
-                     m[1].x, m[1].y, 0.0, 0.0);
-}
-
-mat2x4 __constructor(const mat3x2 m)
-{
-   __retVal = mat2x4(m[0].x, m[0].y, 0.0, 0.0,
-                     m[1].x, m[1].y, 0.0, 0.0);
-}
-
-mat2x4 __constructor(const mat4x2 m)
-{
-   __retVal = mat2x4(m[0].x, m[0].y, 0.0, 0.0,
-                     m[1].x, m[1].y, 0.0, 0.0);
-}
-
-
-
-mat3x2 __constructor(const mat3x2 m)
-{
-   __retVal = m;
-}
-
-mat3x2 __constructor(const mat4x2 m)
-{
-   __retVal = mat3x2(m[0], m[1], m[2]);
-}
-
-mat3x2 __constructor(const mat3 m)
-{
-   __retVal = mat3x2(m[0], m[1], m[2]);
-}
-
-mat3x2 __constructor(const mat3x4 m)
-{
-   __retVal = mat3x2(m[0].x, m[0].y,
-                     m[1].x, m[1].y,
-                     m[2].x, m[2].y);
-}
-
-mat3x2 __constructor(const mat4x3 m)
-{
-   __retVal = mat3x2(m[0].x, m[0].y,
-                     m[1].x, m[1].y,
-                     m[2].x, m[2].y);
-}
-
-mat3x2 __constructor(const mat4 m)
-{
-   __retVal = mat3x2(m[0].x, m[0].y,
-                     m[1].x, m[1].y,
-                        0.0,    0.0);
-}
-
-mat3x2 __constructor(const mat2 m)
-{
-   __retVal = mat3x2(m[0], m[1], vec2(0.0));
-}
-
-mat3x2 __constructor(const mat2x3 m)
-{
-   __retVal = mat3x2(m[0].x, m[0].y,
-                     m[1].x, m[1].y,
-                        0.0,    0.0);
-}
-
-mat3x2 __constructor(const mat2x4 m)
-{
-   __retVal = mat3x2(m[0].x, m[0].y,
-                     m[1].x, m[1].y,
-                        0.0,    0.0);
-}
-
-
-
-
-mat3 __constructor(const mat3 m)
-{
-   __retVal = m;
-}
-
-mat3 __constructor(const mat4x3 m)
-{
-   __retVal = mat3 (
-        m[0],
-        m[1],
-        m[2]
-    );
-}
-
-mat3 __constructor(const mat3x4 m)
-{
-   __retVal = mat3 (
-        m[0].xyz,
-        m[1].xyz,
-        m[2].xyz
-    );
-}
-
-mat3 __constructor(const mat4 m)
-{
-   __retVal = mat3 (
-        m[0].xyz,
-        m[1].xyz,
-        m[2].xyz
-    );
-}
-
-mat3 __constructor(const mat2x3 m)
-{
-   __retVal = mat3 (
-        m[0],
-        m[1],
-        0., 0., 1.
-    );
-}
-
-mat3 __constructor(const mat2x4 m)
-{
-   __retVal = mat3 (
-        m[0].xyz,
-        m[1].xyz,
-        0., 0., 1.
-    );
-}
-
-mat3 __constructor(const mat3x2 m)
-{
-   __retVal = mat3 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 1.
-    );
-}
-
-mat3 __constructor(const mat4x2 m)
-{
-   __retVal = mat3 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 1.
-    );
-}
-
-mat3 __constructor(const mat2 m)
-{
-   __retVal = mat3 (
-        m[0], 0.,
-        m[1], 0.,
-        0., 0., 1.
-    );
-}
-
-
-mat3x4 __constructor(const mat3x4 m)
-{
-   __retVal = m;
-}
-
-mat3x4 __constructor(const mat4 m)
-{
-   __retVal = mat3x4 (
-        m[0],
-        m[1],
-        m[2]
-    );
-}
-
-mat3x4 __constructor(const mat3 m)
-{
-   __retVal = mat3x4 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 0.
-    );
-}
-
-mat3x4 __constructor(const mat4x3 m)
-{
-   __retVal = mat3x4 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 0.
-    );
-}
-
-mat3x4 __constructor(const mat2x4 m)
-{
-   __retVal = mat3x4 (
-        m[0],
-        m[1],
-        0., 0., 1., 0.
-    );
-}
-
-mat3x4 __constructor(const mat2x3 m)
-{
-   __retVal = mat3x4 (
-        m[0], 0.,
-        m[1], 0.,
-        0., 0., 1., 0.
-    );
-}
-
-mat3x4 __constructor(const mat3x2 m)
-{
-   __retVal = mat3x4 (
-        m[0], 0., 0.,
-        m[1], 0., 0.,
-        m[2], 1., 0.
-    );
-}
-
-mat3x4 __constructor(const mat4x2 m)
-{
-   __retVal = mat3x4 (
-        m[0], 0., 0.,
-        m[1], 0., 0.,
-        m[2], 1., 0.
-    );
-}
-
-mat3x4 __constructor(const mat2 m)
-{
-   __retVal = mat3x4 (
-        m[0], 0., 0.,
-        m[1], 0., 0.,
-        0., 0., 1., 0.
-    );
-}
-
-
-mat4x2 __constructor(const mat4x2 m)
-{
-   __retVal = m;
-}
-
-mat4x2 __constructor(const mat4x3 m)
-{
-   __retVal = mat4x2 (
-        m[0].xy,
-        m[1].xy,
-        m[2].xy,
-        m[3].xy
-    );
-}
-
-mat4x2 __constructor(const mat4 m)
-{
-   __retVal = mat4x2 (
-        m[0].xy,
-        m[1].xy,
-        m[2].xy,
-        m[3].xy
-    );
-}
-
-mat4x2 __constructor(const mat3x2 m)
-{
-   __retVal = mat4x2 (
-        m[0],
-        m[1],
-        0., 0.
-    );
-}
-
-mat4x2 __constructor(const mat3 m)
-{
-   __retVal = mat4x2 (
-        m[0].xy,
-        m[1].xy,
-        m[2].xy,
-        0., 0.
-    );
-}
-
-mat4x2 __constructor(const mat3x4 m)
-{
-   __retVal = mat4x2 (
-        m[0].xy,
-        m[1].xy,
-        m[2].xy,
-        0., 0.
-    );
-}
-
-mat4x2 __constructor(const mat2 m)
-{
-   __retVal = mat4x2 (
-        m[0],
-        m[1],
-        0., 0.,
-        0., 0.
-    );
-}
-
-mat4x2 __constructor(const mat2x3 m)
-{
-   __retVal = mat4x2 (
-        m[0].xy,
-        m[1].xy,
-        0., 0.,
-        0., 0.
-    );
-}
-
-mat4x2 __constructor(const mat2x4 m)
-{
-   __retVal = mat4x2 (
-        m[0].xy,
-        m[1].xy,
-        0., 0.,
-        0., 0.
-    );
-}
-
-
-mat4x3 __constructor(const mat4x3 m)
-{
-   __retVal = m;
-}
-
-mat4x3 __constructor(const mat4 m)
-{
-   __retVal = mat4x3 (
-        m[0].xyz,
-        m[1].xyz,
-        m[2].xyz,
-        m[3].xyz
-    );
-}
-
-mat4x3 __constructor(const mat3 m)
-{
-   __retVal = mat4x3 (
-        m[0],
-        m[1],
-        m[2],
-        0., 0., 0.
-    );
-}
-
-mat4x3 __constructor(const mat3x4 m)
-{
-   __retVal = mat4x3 (
-        m[0].xyz,
-        m[1].xyz,
-        m[2].xyz,
-        0., 0., 0.
-    );
-}
-
-mat4x3 __constructor(const mat4x2 m)
-{
-   __retVal = mat4x3 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 1.,
-        m[3], 0.
-    );
-}
-
-mat4x3 __constructor(const mat2x3 m)
-{
-   __retVal = mat4x3 (
-        m[0],
-        m[1],
-        0., 0., 1.,
-        0., 0., 0.
-    );
-}
-
-mat4x3 __constructor(const mat3x2 m)
-{
-   __retVal = mat4x3 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 1.,
-        0., 0., 0.
-    );
-}
-
-mat4x3 __constructor(const mat2x4 m)
-{
-   __retVal = mat4x3 (
-        m[0].xyz,
-        m[1].xyz,
-        0., 0., 1.,
-        0., 0., 0.
-    );
-}
-
-mat4x3 __constructor(const mat2 m)
-{
-   __retVal = mat4x3 (
-        m[0], 0.,
-        m[1], 0.,
-        0., 0., 1.,
-        0., 0., 0.
-    );
-}
-
-
-mat4 __constructor(const mat4 m)
-{
-   __retVal = m;
-}
-
-mat4 __constructor(const mat3x4 m)
-{
-   __retVal = mat4 (
-        m[0],
-        m[1],
-        m[2],
-        0., 0., 0., 1.
-    );
-}
-
-mat4 __constructor(const mat4x3 m)
-{
-   __retVal = mat4 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 0.,
-        m[3], 1.
-    );
-}
-
-mat4 __constructor(const mat2x4 m)
-{
-   __retVal = mat4 (
-        m[0],
-        m[1],
-        0., 0., 1., 0.,
-        0., 0., 0., 1.
-    );
-}
-
-mat4 __constructor(const mat4x2 m)
-{
-   __retVal = mat4 (
-        m[0], 0., 0.,
-        m[1], 0., 0.,
-        m[2], 1., 0.,
-        m[3], 0., 1.
-    );
-}
-
-mat4 __constructor(const mat3 m)
-{
-   __retVal = mat4 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 0.,
-        0., 0., 0., 1.
-    );
-}
-
-mat4 __constructor(const mat2x3 m)
-{
-   __retVal = mat4 (
-        m[0], 0.,
-        m[1], 0.,
-        0., 0., 1., 0.,
-        0., 0., 0., 1.
-    );
-}
-
-mat4 __constructor(const mat3x2 m)
-{
-   __retVal = mat4 (
-        m[0], 0., 0.,
-        m[1], 0., 0.,
-        m[2], 1., 0.,
-        0., 0., 0., 1.
-    );
-}
-
-mat4 __constructor(const mat2 m)
-{
-   __retVal = mat4 (
-        m[0], 0., 0.,
-        m[1], 0., 0.,
-        0., 0., 1., 0.,
-        0., 0., 0., 1.
-    );
-}
-
-
-void __operator += (inout mat2x3 m, const mat2x3 n) {
-    m[0] += n[0];
-    m[1] += n[1];
-}
-
-void __operator += (inout mat2x4 m, const mat2x4 n) {
-    m[0] += n[0];
-    m[1] += n[1];
-}
-
-void __operator += (inout mat3x2 m, const mat3x2 n) {
-    m[0] += n[0];
-    m[1] += n[1];
-    m[2] += n[2];
-}
-
-void __operator += (inout mat3x4 m, const mat3x4 n) {
-    m[0] += n[0];
-    m[1] += n[1];
-    m[2] += n[2];
-}
-
-void __operator += (inout mat4x2 m, const mat4x2 n) {
-    m[0] += n[0];
-    m[1] += n[1];
-    m[2] += n[2];
-    m[3] += n[3];
-}
-
-void __operator += (inout mat4x3 m, const mat4x3 n) {
-    m[0] += n[0];
-    m[1] += n[1];
-    m[2] += n[2];
-    m[3] += n[3];
-}
-
-
-void __operator -= (inout mat2x3 m, const mat2x3 n) {
-    m[0] -= n[0];
-    m[1] -= n[1];
-}
-
-void __operator -= (inout mat2x4 m, const mat2x4 n) {
-    m[0] -= n[0];
-    m[1] -= n[1];
-}
-
-void __operator -= (inout mat3x2 m, const mat3x2 n) {
-    m[0] -= n[0];
-    m[1] -= n[1];
-    m[2] -= n[2];
-}
-
-void __operator -= (inout mat3x4 m, const mat3x4 n) {
-    m[0] -= n[0];
-    m[1] -= n[1];
-    m[2] -= n[2];
-}
-
-void __operator -= (inout mat4x2 m, const mat4x2 n) {
-    m[0] -= n[0];
-    m[1] -= n[1];
-    m[2] -= n[2];
-    m[3] -= n[3];
-}
-
-void __operator -= (inout mat4x3 m, const mat4x3 n) {
-    m[0] -= n[0];
-    m[1] -= n[1];
-    m[2] -= n[2];
-    m[3] -= n[3];
-}
-
-
-void __operator /= (inout mat2x3 m, const mat2x3 n) {
-    m[0] /= n[0];
-    m[1] /= n[1];
-}
-
-void __operator /= (inout mat2x4 m, const mat2x4 n) {
-    m[0] /= n[0];
-    m[1] /= n[1];
-}
-
-void __operator /= (inout mat3x2 m, const mat3x2 n) {
-    m[0] /= n[0];
-    m[1] /= n[1];
-    m[2] /= n[2];
-}
-
-void __operator /= (inout mat3x4 m, const mat3x4 n) {
-    m[0] /= n[0];
-    m[1] /= n[1];
-    m[2] /= n[2];
-}
-
-void __operator /= (inout mat4x2 m, const mat4x2 n) {
-    m[0] /= n[0];
-    m[1] /= n[1];
-    m[2] /= n[2];
-    m[3] /= n[3];
-}
-
-void __operator /= (inout mat4x3 m, const mat4x3 n) {
-    m[0] /= n[0];
-    m[1] /= n[1];
-    m[2] /= n[2];
-    m[3] /= n[3];
-}
-
-
-vec3 __operator * (const mat2x3 m, const vec2 v)
-{
-   __retVal.x = v.x * m[0].x + v.y * m[1].x;
-   __retVal.y = v.x * m[0].y + v.y * m[1].y;
-   __retVal.z = v.x * m[0].z + v.y * m[1].z;
-}
-
-vec4 __operator * (const mat2x4 m, const vec2 v)
-{
-   __retVal.x = v.x * m[0].x + v.y * m[1].x;
-   __retVal.y = v.x * m[0].y + v.y * m[1].y;
-   __retVal.z = v.x * m[0].z + v.y * m[1].z;
-   __retVal.w = v.x * m[0].w + v.y * m[1].w;
-}
-
-vec2 __operator * (const mat3x2 m, const vec3 v)
-{
-   __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x;
-   __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y;
-}
-
-vec4 __operator * (const mat3x4 m, const vec3 v)
-{
-   __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x;
-   __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y;
-   __retVal.z = v.x * m[0].z + v.y * m[1].z + v.z * m[2].z;
-   __retVal.w = v.x * m[0].w + v.y * m[1].w + v.z * m[2].w;
-}
-
-vec2 __operator * (const mat4x2 m, const vec4 v)
-{
-   __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x;
-   __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y;
-}
-
-vec3 __operator * (const mat4x3 m, const vec4 v)
-{
-   __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x;
-   __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y;
-   __retVal.z = v.x * m[0].z + v.y * m[1].z + v.z * m[2].z + v.w * m[3].z;
-}
-
-
-mat3x2 __operator * (const mat2 m, const mat3x2 n)
-{
-   //return mat3x2 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4x2 __operator * (const mat2 m, const mat4x2 n)
-{
-   //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2x3 __operator * (const mat2x3 m, const mat2 n)
-{
-   //return mat2x3 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3 __operator * (const mat2x3 m, const mat3x2 n)
-{
-   //return mat3 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4x3 __operator * (const mat2x3 m, const mat4x2 n)
-{
-   //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2x4 __operator * (const mat2x4 m, const mat2 n)
-{
-   //return mat2x4 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3x4 __operator * (const mat2x4 m, const mat3x2 n)
-{
-   //return mat3x4 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4 __operator * (const mat2x4 m, const mat4x2 n)
-{
-   //return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2 __operator * (const mat3x2 m, const mat2x3 n)
-{
-   //return mat2 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3x2 __operator * (const mat3x2 m, const mat3 n)
-{
-   //return mat3x2 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4x2 __operator * (const mat3x2 m, const mat4x3 n)
-{
-   //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2x3 __operator * (const mat3 m, const mat2x3 n)
-{
-   //return mat2x3 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat4x3 __operator * (const mat3 m, const mat4x3 n)
-{
-   //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2x4 __operator * (const mat3x4 m, const mat2x3 n)
-{
-   //return mat2x4 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3x4 __operator * (const mat3x4 m, const mat3 n)
-{
-   //return mat3x4 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4 __operator * (const mat3x4 m, const mat4x3 n)
-{
-   //return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2 __operator * (const mat4x2 m, const mat2x4 n)
-{
-   //return = mat2 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3x2 __operator * (const mat4x2 m, const mat3x4 n)
-{
-   //return mat3x2 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4x2 __operator * (const mat4x2 m, const mat4 n)
-{
-   //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2x3 __operator * (const mat4x3 m, const mat2x4 n)
-{
-   //return mat2x3 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3 __operator * (const mat4x3 m, const mat3x4 n)
-{
-   //return mat3 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4x3 __operator * (const mat4x3 m, const mat4 n)
-{
-   //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2x4 __operator * (const mat4 m, const mat2x4 n)
-{
-   //return mat2x4 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3x4 __operator * (const mat4 m, const mat3x4 n)
-{
-   //return mat3x4 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-
-void __operator *= (inout mat2x3 m, const mat2 n) {
-    m = m * n;
-}
-
-void __operator *= (inout mat2x4 m, const mat2 n) {
-    m = m * n;
-}
-
-void __operator *= (inout mat3x2 m, const mat3 n) {
-    m = m * n;
-}
-
-void __operator *= (inout mat3x4 m, const mat3 n) {
-    m = m * n;
-}
-
-void __operator *= (inout mat4x2 m, const mat4 n) {
-    m = m * n;
-}
-
-void __operator *= (inout mat4x3 m, const mat4 n) {
-    m = m * n;
-}
-
-
-vec3 __operator * (const vec2 v, const mat3x2 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-   __retVal.z = dot(v, m[2]);
-}
-
-vec4 __operator * (const vec2 v, const mat4x2 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-   __retVal.z = dot(v, m[2]);
-   __retVal.w = dot(v, m[3]);
-}
-
-vec2 __operator * (const vec3 v, const mat2x3 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-}
-
-vec4 __operator * (const vec3 v, const mat4x3 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-   __retVal.z = dot(v, m[2]);
-   __retVal.w = dot(v, m[3]);
-}
-
-vec2 __operator * (const vec4 v, const mat2x4 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-}
-
-vec3 __operator * (const vec4 v, const mat3x4 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-   __retVal.z = dot(v, m[2]);
-}
-
-
-void __operator += (inout mat2x3 m, const float a) {
-    m[0] += a;
-    m[1] += a;
-}
-
-void __operator += (inout mat2x4 m, const float a) {
-    m[0] += a;
-    m[1] += a;
-}
-
-void __operator += (inout mat3x2 m, const float a) {
-    m[0] += a;
-    m[1] += a;
-    m[2] += a;
-}
-
-void __operator += (inout mat3x4 m, const float a) {
-    m[0] += a;
-    m[1] += a;
-    m[2] += a;
-}
-
-void __operator += (inout mat4x2 m, const float a) {
-    m[0] += a;
-    m[1] += a;
-    m[2] += a;
-    m[3] += a;
-}
-
-void __operator += (inout mat4x3 m, const float a) {
-    m[0] += a;
-    m[1] += a;
-    m[2] += a;
-    m[3] += a;
-}
-
-
-void __operator -= (inout mat2x3 m, const float a) {
-    m[0] -= a;
-    m[1] -= a;
-}
-
-void __operator -= (inout mat2x4 m, const float a) {
-    m[0] -= a;
-    m[1] -= a;
-}
-
-void __operator -= (inout mat3x2 m, const float a) {
-    m[0] -= a;
-    m[1] -= a;
-    m[2] -= a;
-}
-
-void __operator -= (inout mat3x4 m, const float a) {
-    m[0] -= a;
-    m[1] -= a;
-    m[2] -= a;
-}
-
-void __operator -= (inout mat4x2 m, const float a) {
-    m[0] -= a;
-    m[1] -= a;
-    m[2] -= a;
-    m[3] -= a;
-}
-
-void __operator -= (inout mat4x3 m, const float a) {
-    m[0] -= a;
-    m[1] -= a;
-    m[2] -= a;
-    m[3] -= a;
-}
-
-
-void __operator *= (inout mat2x3 m, const float a) {
-    m[0] *= a;
-    m[1] *= a;
-}
-
-void __operator *= (inout mat2x4 m, const float a) {
-    m[0] *= a;
-    m[1] *= a;
-}
-
-void __operator *= (inout mat3x2 m, const float a) {
-    m[0] *= a;
-    m[1] *= a;
-    m[2] *= a;
-}
-
-void __operator *= (inout mat3x4 m, const float a) {
-    m[0] *= a;
-    m[1] *= a;
-    m[2] *= a;
-}
-
-void __operator *= (inout mat4x2 m, const float a) {
-    m[0] *= a;
-    m[1] *= a;
-    m[2] *= a;
-    m[3] *= a;
-}
-
-void __operator *= (inout mat4x3 m, const float a) {
-    m[0] *= a;
-    m[1] *= a;
-    m[2] *= a;
-    m[3] *= a;
-}
-
-
-void __operator /= (inout mat2x3 m, const float a) {
-    m[0] /= a;
-    m[1] /= a;
-}
-
-void __operator /= (inout mat2x4 m, const float a) {
-    m[0] /= a;
-    m[1] /= a;
-}
-
-void __operator /= (inout mat3x2 m, const float a) {
-    m[0] /= a;
-    m[1] /= a;
-    m[2] /= a;
-}
-
-void __operator /= (inout mat3x4 m, const float a) {
-    m[0] /= a;
-    m[1] /= a;
-    m[2] /= a;
-}
-
-void __operator /= (inout mat4x2 m, const float a) {
-    m[0] /= a;
-    m[1] /= a;
-    m[2] /= a;
-    m[3] /= a;
-}
-
-void __operator /= (inout mat4x3 m, const float a) {
-    m[0] /= a;
-    m[1] /= a;
-    m[2] /= a;
-    m[3] /= a;
-}
-
-
-mat2x3 __operator + (const mat2x3 m, const mat2x3 n) {
-    return mat2x3 (m[0] + n[0], m[1] + n[1]);
-}
-
-mat2x4 __operator + (const mat2x4 m, const mat2x4 n) {
-    return mat2x4 (m[0] + n[0], m[1] + n[1]);
-}
-
-mat3x2 __operator + (const mat3x2 m, const mat3x2 n) {
-    return mat3x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2]);
-}
-
-mat3x4 __operator + (const mat3x4 m, const mat3x4 n) {
-    return mat3x4 (m[0] + n[0], m[1] + n[1], m[2] + n[2]);
-}
-
-mat4x2 __operator + (const mat4x2 m, const mat4x2 n) {
-    return mat4x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]);
-}
-
-mat4x3 __operator + (const mat4x3 m, const mat4x3 n) {
-    return mat4x3 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]);
-}
-
-
-mat2x3 __operator - (const mat2x3 m, const mat2x3 n) {
-    return mat2x3 (m[0] - n[0], m[1] - n[1]);
-}
-
-mat2x4 __operator - (const mat2x4 m, const mat2x4 n) {
-    return mat2x4 (m[0] - n[0], m[1] - n[1]);
-}
-
-mat3x2 __operator - (const mat3x2 m, const mat3x2 n) {
-    return mat3x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2]);
-}
-
-mat3x4 __operator - (const mat3x4 m, const mat3x4 n) {
-    return mat3x4 (m[0] - n[0], m[1] - n[1], m[2] - n[2]);
-}
-
-mat4x2 __operator - (const mat4x2 m, const mat4x2 n) {
-    return mat4x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]);
-}
-
-mat4x3 __operator - (const mat4x3 m, const mat4x3 n) {
-    return mat4x3 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]);
-}
-
-
-mat2x3 __operator / (const mat2x3 m, const mat2x3 n) {
-    return mat2x3 (m[0] / n[0], m[1] / n[1]);
-}
-
-mat2x4 __operator / (const mat2x4 m, const mat2x4 n) {
-    return mat2x4 (m[0] / n[0], m[1] / n[1]);
-}
-
-mat3x2 __operator / (const mat3x2 m, const mat3x2 n) {
-    return mat3x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2]);
-}
-
-mat3x4 __operator / (const mat3x4 m, const mat3x4 n) {
-    return mat3x4 (m[0] / n[0], m[1] / n[1], m[2] / n[2]);
-}
-
-mat4x2 __operator / (const mat4x2 m, const mat4x2 n) {
-    return mat4x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]);
-}
-
-mat4x3 __operator / (const mat4x3 m, const mat4x3 n) {
-    return mat4x3 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]);
-}
-
-
-mat2x3 __operator + (const float a, const mat2x3 n) {
-    return mat2x3 (a + n[0], a + n[1]);
-}
-
-mat2x3 __operator + (const mat2x3 m, const float b) {
-    return mat2x3 (m[0] + b, m[1] + b);
-}
-
-mat2x4 __operator + (const float a, const mat2x4 n) {
-    return mat2x4 (a + n[0], a + n[1]);
-}
-
-mat2x4 __operator + (const mat2x4 m, const float b) {
-    return mat2x4 (m[0] + b, m[1] + b);
-}
-
-mat3x2 __operator + (const float a, const mat3x2 n) {
-    return mat3x2 (a + n[0], a + n[1], a + n[2]);
-}
-
-mat3x2 __operator + (const mat3x2 m, const float b) {
-    return mat3x2 (m[0] + b, m[1] + b, m[2] + b);
-}
-
-mat3x4 __operator + (const float a, const mat3x4 n) {
-    return mat3x4 (a + n[0], a + n[1], a + n[2]);
-}
-
-mat3x4 __operator + (const mat3x4 m, const float b) {
-    return mat3x4 (m[0] + b, m[1] + b, m[2] + b);
-}
-
-mat4x2 __operator + (const mat4x2 m, const float b) {
-    return mat4x2 (m[0] + b, m[1] + b, m[2] + b, m[3] + b);
-}
-
-mat4x2 __operator + (const float a, const mat4x2 n) {
-    return mat4x2 (a + n[0], a + n[1], a + n[2], a + n[3]);
-}
-
-mat4x3 __operator + (const mat4x3 m, const float b) {
-    return mat4x3 (m[0] + b, m[1] + b, m[2] + b, m[3] + b);
-}
-
-mat4x3 __operator + (const float a, const mat4x3 n) {
-    return mat4x3 (a + n[0], a + n[1], a + n[2], a + n[3]);
-}
-
-
-mat2x3 __operator - (const float a, const mat2x3 n) {
-    return mat2x3 (a - n[0], a - n[1]);
-}
-
-mat2x3 __operator - (const mat2x3 m, const float b) {
-    return mat2x3 (m[0] - b, m[1] - b);
-}
-
-mat2x4 __operator - (const float a, const mat2x4 n) {
-    return mat2x4 (a - n[0], a - n[1]);
-}
-
-mat2x4 __operator - (const mat2x4 m, const float b) {
-    return mat2x4 (m[0] - b, m[1] - b);
-}
-
-mat3x2 __operator - (const float a, const mat3x2 n) {
-    return mat3x2 (a - n[0], a - n[1], a - n[2]);
-}
-
-mat3x2 __operator - (const mat3x2 m, const float b) {
-    return mat3x2 (m[0] - b, m[1] - b, m[2] - b);
-}
-
-mat3x4 __operator - (const float a, const mat3x4 n) {
-    return mat3x4 (a - n[0], a - n[1], a - n[2]);
-}
-
-mat3x4 __operator - (const mat3x4 m, const float b) {
-    return mat3x4 (m[0] - b, m[1] - b, m[2] - b);
-}
-
-mat4x2 __operator - (const mat4x2 m, const float b) {
-    return mat4x2 (m[0] - b, m[1] - b, m[2] - b, m[3] - b);
-}
-
-mat4x2 __operator - (const float a, const mat4x2 n) {
-    return mat4x2 (a - n[0], a - n[1], a - n[2], a - n[3]);
-}
-
-mat4x3 __operator - (const mat4x3 m, const float b) {
-    return mat4x3 (m[0] - b, m[1] - b, m[2] - b, m[3] - b);
-}
-
-mat4x3 __operator - (const float a, const mat4x3 n) {
-    return mat4x3 (a - n[0], a - n[1], a - n[2], a - n[3]);
-}
-
-
-mat2x3 __operator * (const float a, const mat2x3 n)
-{
-   //return mat2x3 (a * n[0], a * n[1]);
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-}
-
-mat2x3 __operator * (const mat2x3 m, const float b)
-{
-   //return mat2x3 (m[0] * b, m[1] * b);
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-}
-
-mat2x4 __operator * (const float a, const mat2x4 n)
-{
-   //return mat2x4 (a * n[0], a * n[1]);
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-}
-
-mat2x4 __operator * (const mat2x4 m, const float b)
-{
-   //return mat2x4 (m[0] * b, m[1] * b);
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-}
-
-mat3x2 __operator * (const float a, const mat3x2 n)
-{
-   //return mat3x2 (a * n[0], a * n[1], a * n[2]);
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-   __retVal[2] = a * n[2];
-}
-
-mat3x2 __operator * (const mat3x2 m, const float b)
-{
-   //return mat3x2 (m[0] * b, m[1] * b, m[2] * b);
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-   __retVal[2] = m[2] * b;
-}
-
-mat3x4 __operator * (const float a, const mat3x4 n)
-{
-   //return mat3x4 (a * n[0], a * n[1], a * n[2]);
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-   __retVal[2] = a * n[2];
-}
-
-mat3x4 __operator * (const mat3x4 m, const float b)
-{
-   //return mat3x4 (m[0] * b, m[1] * b, m[2] * b);
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-   __retVal[2] = m[2] * b;
-}
-
-mat4x2 __operator * (const mat4x2 m, const float b)
-{
-   //return mat4x2 (m[0] * b, m[1] * b, m[2] * b, m[3] * b);
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-   __retVal[2] = m[2] * b;
-   __retVal[3] = m[3] * b;
-}
-
-mat4x2 __operator * (const float a, const mat4x2 n)
-{
-   //return mat4x2 (a * n[0], a * n[1], a * n[2], a * n[3]);
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-   __retVal[2] = a * n[2];
-   __retVal[3] = a * n[3];
-}
-
-mat4x3 __operator * (const mat4x3 m, const float b)
-{
-   //return mat4x3 (m[0] * b, m[1] * b, m[2] * b, m[3] * b);
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-   __retVal[2] = m[2] * b;
-   __retVal[3] = m[3] * b;
-}
-
-mat4x3 __operator * (const float a, const mat4x3 n)
-{
-   //return mat4x3 (a * n[0], a * n[1], a * n[2], a * n[3]);
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-   __retVal[2] = a * n[2];
-   __retVal[3] = a * n[3];
-}
-
-
-mat2x3 __operator / (const float a, const mat2x3 n)
-{
-   //return mat2x3 (a / n[0], a / n[1]);
-   const float inv = 1.0 / a;
-   __retVal[0] = inv * n[0];
-   __retVal[1] = inv * n[1];
-}
-
-mat2x3 __operator / (const mat2x3 m, const float b)
-{
-   //return mat2x3 (m[0] / b, m[1] / b);
-   const float inv = 1.0 / b;
-   __retVal[0] = m[0] * inv;
-   __retVal[1] = m[1] * inv;
-}
-
-mat2x4 __operator / (const float a, const mat2x4 n)
-{
-   //return mat2x4 (a / n[0], a / n[1]);
-   const float inv = 1.0 / a;
-   __retVal[0] = inv * n[0];
-   __retVal[1] = inv * n[1];
-}
-
-mat2x4 __operator / (const mat2x4 m, const float b)
-{
-   //return mat2x4 (m[0] / b, m[1] / b);
-   const float inv = 1.0 / b;
-   __retVal[0] = m[0] * inv;
-   __retVal[1] = m[1] * inv;
-}
-
-mat3x2 __operator / (const float a, const mat3x2 n)
-{
-   //return mat3x2 (a / n[0], a / n[1], a / n[2]);
-   const float inv = 1.0 / a;
-   __retVal[0] = inv * n[0];
-   __retVal[1] = inv * n[1];
-   __retVal[2] = inv * n[2];
-}
-
-mat3x2 __operator / (const mat3x2 m, const float b)
-{
-   //return mat3x2 (m[0] / b, m[1] / b, m[2] / b);
-   const float inv = 1.0 / b;
-   __retVal[0] = m[0] * inv;
-   __retVal[1] = m[1] * inv;
-   __retVal[2] = m[2] * inv;
-}
-
-mat3x4 __operator / (const float a, const mat3x4 n)
-{
-   //return mat3x4 (a / n[0], a / n[1], a / n[2]);
-   const float inv = 1.0 / a;
-   __retVal[0] = inv * n[0];
-   __retVal[1] = inv * n[1];
-   __retVal[2] = inv * n[2];
-}
-
-mat3x4 __operator / (const mat3x4 m, const float b)
-{
-   //return mat3x4 (m[0] / b, m[1] / b, m[2] / b);
-   const float inv = 1.0 / b;
-   __retVal[0] = m[0] * inv;
-   __retVal[1] = m[1] * inv;
-   __retVal[2] = m[2] * inv;
-}
-
-mat4x2 __operator / (const mat4x2 m, const float b)
-{
-   //return mat4x2 (m[0] / b, m[1] / b, m[2] / b, m[3] / b);
-   const float inv = 1.0 / b;
-   __retVal[0] = m[0] * inv;
-   __retVal[1] = m[1] * inv;
-   __retVal[2] = m[2] * inv;
-   __retVal[3] = m[3] * inv;
-}
-
-mat4x2 __operator / (const float a, const mat4x2 n)
-{
-   //return mat4x2 (a / n[0], a / n[1], a / n[2], a / n[3]);
-   const float inv = 1.0 / a;
-   __retVal[0] = inv * n[0];
-   __retVal[1] = inv * n[1];
-   __retVal[2] = inv * n[2];
-   __retVal[3] = inv * n[3];
-}
-
-mat4x3 __operator / (const mat4x3 m, const float b)
-{
-   //return mat4x3 (m[0] / b, m[1] / b, m[2] / b, m[3] / b);
-   const float inv = 1.0 / b;
-   __retVal[0] = m[0] * inv;
-   __retVal[1] = m[1] * inv;
-   __retVal[2] = m[2] * inv;
-   __retVal[3] = m[3] * inv;
-}
-
-mat4x3 __operator / (const float a, const mat4x3 n)
-{
-   //return mat4x3 (a / n[0], a / n[1], a / n[2], a / n[3]);
-   const float inv = 1.0 / a;
-   __retVal[0] = inv * n[0];
-   __retVal[1] = inv * n[1];
-   __retVal[2] = inv * n[2];
-   __retVal[3] = inv * n[3];
-}
-
-
-mat2x3 __operator - (const mat2x3 m) {
-    return mat2x3 (-m[0], -m[1]);
-}
-
-mat2x4 __operator - (const mat2x4 m) {
-    return mat2x4 (-m[0], -m[1]);
-}
-
-mat3x2 __operator - (const mat3x2 m) {
-    return mat3x2 (-m[0], -m[1], -m[2]);
-}
-
-mat3x4 __operator - (const mat3x4 m) {
-    return mat3x4 (-m[0], -m[1], -m[2]);
-}
-
-mat4x2 __operator - (const mat4x2 m) {
-    return mat4x2 (-m[0], -m[1], -m[2], -m[3]);
-}
-
-mat4x3 __operator - (const mat4x3 m) {
-    return mat4x3 (-m[0], -m[1], -m[2], -m[3]);
-}
-
-
-void __operator -- (inout mat2x3 m) {
-    --m[0];
-    --m[1];
-}
-
-void __operator -- (inout mat2x4 m) {
-    --m[0];
-    --m[1];
-}
-
-void __operator -- (inout mat3x2 m) {
-    --m[0];
-    --m[1];
-    --m[2];
-}
-
-void __operator -- (inout mat3x4 m) {
-    --m[0];
-    --m[1];
-    --m[2];
-}
-
-void __operator -- (inout mat4x2 m) {
-    --m[0];
-    --m[1];
-    --m[2];
-    --m[3];
-}
-
-void __operator -- (inout mat4x3 m) {
-    --m[0];
-    --m[1];
-    --m[2];
-    --m[3];
-}
-
-
-void __operator ++ (inout mat2x3 m) {
-    ++m[0];
-    ++m[1];
-}
-
-void __operator ++ (inout mat2x4 m) {
-    ++m[0];
-    ++m[1];
-}
-
-void __operator ++ (inout mat3x2 m) {
-    ++m[0];
-    ++m[1];
-    ++m[2];
-}
-
-void __operator ++ (inout mat3x4 m) {
-    ++m[0];
-    ++m[1];
-    ++m[2];
-}
-
-void __operator ++ (inout mat4x2 m) {
-    ++m[0];
-    ++m[1];
-    ++m[2];
-    ++m[3];
-}
-
-void __operator ++ (inout mat4x3 m) {
-    ++m[0];
-    ++m[1];
-    ++m[2];
-    ++m[3];
-}
-
diff --git a/src/mesa/shader/slang/library/slang_builtin_120_common.gc b/src/mesa/shader/slang/library/slang_builtin_120_common.gc
deleted file mode 100644 (file)
index c6264c3..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.6
- *
- * Copyright (C) 2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// From Shader Spec, ver. 1.20, rev. 6
-//
-
-//
-// 8.5 Matrix Functions
-//
-
-mat2x3 matrixCompMult (mat2x3 m, mat2x3 n) {
-    return mat2x3 (m[0] * n[0], m[1] * n[1]);
-}
-
-mat2x4 matrixCompMult (mat2x4 m, mat2x4 n) {
-    return mat2x4 (m[0] * n[0], m[1] * n[1]);
-}
-
-mat3x2 matrixCompMult (mat3x2 m, mat3x2 n) {
-    return mat3x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
-}
-
-mat3x4 matrixCompMult (mat3x4 m, mat3x4 n) {
-    return mat3x4 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
-}
-
-mat4x2 matrixCompMult (mat4x2 m, mat4x2 n) {
-    return mat4x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
-}
-
-mat4x3 matrixCompMult (mat4x3 m, mat4x3 n) {
-    return mat4x3 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
-}
-
-mat2 outerProduct (vec2 c, vec2 r) {
-    return mat2 (
-        c.x * r.x, c.y * r.x,
-        c.x * r.y, c.y * r.y
-    );
-}
-
-mat3 outerProduct (vec3 c, vec3 r) {
-    return mat3 (
-        c.x * r.x, c.y * r.x, c.z * r.x,
-        c.x * r.y, c.y * r.y, c.z * r.y,
-        c.x * r.z, c.y * r.z, c.z * r.z
-    );
-}
-
-mat4 outerProduct (vec4 c, vec4 r) {
-    return mat4 (
-        c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
-        c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y,
-        c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z,
-        c.x * r.w, c.y * r.w, c.z * r.w, c.w * r.w
-    );
-}
-
-mat2x3 outerProduct (vec3 c, vec2 r) {
-    return mat2x3 (
-        c.x * r.x, c.y * r.x, c.z * r.x,
-        c.x * r.y, c.y * r.y, c.z * r.y
-    );
-}
-
-mat3x2 outerProduct (vec2 c, vec3 r) {
-    return mat3x2 (
-        c.x * r.x, c.y * r.x,
-        c.x * r.y, c.y * r.y,
-        c.x * r.z, c.y * r.z
-    );
-}
-
-mat2x4 outerProduct (vec4 c, vec2 r) {
-    return mat2x4 (
-        c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
-        c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y
-    );
-}
-
-mat4x2 outerProduct (vec2 c, vec4 r) {
-    return mat4x2 (
-        c.x * r.x, c.y * r.x,
-        c.x * r.y, c.y * r.y,
-        c.x * r.z, c.y * r.z,
-        c.x * r.w, c.y * r.w
-    );
-}
-
-mat3x4 outerProduct (vec4 c, vec3 r) {
-    return mat3x4 (
-        c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
-        c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y,
-        c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z
-    );
-}
-
-mat4x3 outerProduct (vec3 c, vec4 r) {
-    return mat4x3 (
-        c.x * r.x, c.y * r.x, c.z * r.x,
-        c.x * r.y, c.y * r.y, c.z * r.y,
-        c.x * r.z, c.y * r.z, c.z * r.z,
-        c.x * r.w, c.y * r.w, c.z * r.w
-    );
-}
-
-mat2 transpose (mat2 m) {
-    return mat2 (
-        m[0].x, m[1].x,
-        m[0].y, m[1].y
-    );
-}
-
-mat3 transpose (mat3 m) {
-    return mat3 (
-        m[0].x, m[1].x, m[2].x,
-        m[0].y, m[1].y, m[2].y,
-        m[0].z, m[1].z, m[2].z
-    );
-}
-
-mat4 transpose (mat4 m) {
-    return mat4 (
-        m[0].x, m[1].x, m[2].x, m[3].x,
-        m[0].y, m[1].y, m[2].y, m[3].y,
-        m[0].z, m[1].z, m[2].z, m[3].z,
-        m[0].w, m[1].w, m[2].w, m[3].w
-    );
-}
-
-mat2x3 transpose (mat3x2 m) {
-    return mat2x3 (
-        m[0].x, m[1].x, m[2].x,
-        m[0].y, m[1].y, m[2].y
-    );
-}
-
-mat3x2 transpose (mat2x3 m) {
-    return mat3x2 (
-        m[0].x, m[1].x,
-        m[0].y, m[1].y,
-        m[0].z, m[1].z
-    );
-}
-
-mat2x4 transpose (mat4x2 m) {
-    return mat2x4 (
-        m[0].x, m[1].x, m[2].x, m[3].x,
-        m[0].y, m[1].y, m[2].y, m[3].y
-    );
-}
-
-mat4x2 transpose (mat2x4 m) {
-    return mat4x2 (
-        m[0].x, m[1].x,
-        m[0].y, m[1].y,
-        m[0].z, m[1].z,
-        m[0].w, m[1].w
-    );
-}
-
-mat3x4 transpose (mat4x3 m) {
-    return mat3x4 (
-        m[0].x, m[1].x, m[2].x, m[3].x,
-        m[0].y, m[1].y, m[2].y, m[3].y,
-        m[0].z, m[1].z, m[2].z, m[3].z
-    );
-}
-
-mat4x3 transpose (mat3x4 m) {
-    return mat4x3 (
-        m[0].x, m[1].x, m[2].x,
-        m[0].y, m[1].y, m[2].y,
-        m[0].z, m[1].z, m[2].z,
-        m[0].w, m[1].w, m[2].w
-    );
-}
-
diff --git a/src/mesa/shader/slang/library/slang_builtin_120_fragment.gc b/src/mesa/shader/slang/library/slang_builtin_120_fragment.gc
deleted file mode 100644 (file)
index 7d51604..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// From Shader Spec, ver. 1.20, rev. 6
-//
-
-varying vec2 gl_PointCoord;
-
diff --git a/src/mesa/shader/slang/library/slang_common_builtin.gc b/src/mesa/shader/slang/library/slang_common_builtin.gc
deleted file mode 100644 (file)
index d75354d..0000000
+++ /dev/null
@@ -1,1887 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.3
- *
- * Copyright (C) 2006  Brian Paul   All Rights Reserved.
- * Copyright (C) 2008  VMware, Inc.  All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// From Shader Spec, ver. 1.10, rev. 59
-//
-
-// Note: the values assigned to these constants here aren't actually used.
-// They're set by the compiler according to the GL context limits.
-// See slang_simplify.c
-const int gl_MaxLights = 8;
-const int gl_MaxClipPlanes = 6;
-const int gl_MaxTextureUnits = 8;
-const int gl_MaxTextureCoords = 8;
-const int gl_MaxVertexAttribs = 16;
-const int gl_MaxVertexUniformComponents = 512;
-const int gl_MaxVaryingFloats = 32;
-const int gl_MaxVertexTextureImageUnits = 0;
-const int gl_MaxCombinedTextureImageUnits = 2;
-const int gl_MaxTextureImageUnits = 2;
-const int gl_MaxFragmentUniformComponents = 64;
-const int gl_MaxDrawBuffers = 1;
-
-uniform mat4 gl_ModelViewMatrix;
-uniform mat4 gl_ProjectionMatrix;
-uniform mat4 gl_ModelViewProjectionMatrix;
-uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];
-
-uniform mat3 gl_NormalMatrix;
-
-uniform mat4 gl_ModelViewMatrixInverse;
-uniform mat4 gl_ProjectionMatrixInverse;
-uniform mat4 gl_ModelViewProjectionMatrixInverse;
-uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];
-
-uniform mat4 gl_ModelViewMatrixTranspose;
-uniform mat4 gl_ProjectionMatrixTranspose;
-uniform mat4 gl_ModelViewProjectionMatrixTranspose;
-uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];
-
-uniform mat4 gl_ModelViewMatrixInverseTranspose;
-uniform mat4 gl_ProjectionMatrixInverseTranspose;
-uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;
-uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];
-
-uniform float gl_NormalScale;
-
-struct gl_DepthRangeParameters {
-    float near;
-    float far;
-    float diff;
-};
-
-uniform gl_DepthRangeParameters gl_DepthRange;
-
-uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];
-
-struct gl_PointParameters {
-    float size;
-    float sizeMin;
-    float sizeMax;
-    float fadeThresholdSize;
-    float distanceConstantAttenuation;
-    float distanceLinearAttenuation;
-    float distanceQuadraticAttenuation;
-};
-
-uniform gl_PointParameters gl_Point;
-
-struct gl_MaterialParameters {
-    vec4 emission;
-    vec4 ambient;
-    vec4 diffuse;
-    vec4 specular;
-    float shininess;
-};
-
-uniform gl_MaterialParameters gl_FrontMaterial;
-uniform gl_MaterialParameters gl_BackMaterial;
-
-/* NOTE: the order of these fields is significant!
- * See the definition of the lighting state vars such as STATE_SPOT_DIRECTION.
- */
-struct gl_LightSourceParameters {
-    vec4 ambient;
-    vec4 diffuse;
-    vec4 specular;
-    vec4 position;
-    vec4 halfVector;
-    vec3 spotDirection;
-    float spotCosCutoff;
-
-    float constantAttenuation;
-    float linearAttenuation;
-    float quadraticAttenuation;
-    float spotExponent;
-
-    float spotCutoff;
-};
-
-uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];
-
-struct gl_LightModelParameters {
-    vec4 ambient;
-};
-
-uniform gl_LightModelParameters gl_LightModel;
-
-struct gl_LightModelProducts {
-    vec4 sceneColor;
-};
-
-uniform gl_LightModelProducts gl_FrontLightModelProduct;
-uniform gl_LightModelProducts gl_BackLightModelProduct;
-
-struct gl_LightProducts {
-    vec4 ambient;
-    vec4 diffuse;
-    vec4 specular;
-};
-
-uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];
-uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];
-
-uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];
-uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];
-uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];
-uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];
-uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];
-uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];
-uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];
-uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];
-uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];
-
-struct gl_FogParameters {
-    vec4 color;
-    float density;
-    float start;
-    float end;
-    float scale;
-};
-
-uniform gl_FogParameters gl_Fog;
-
-
-
-
-
-//
-// 8.1 Angle and Trigonometry Functions
-//
-
-//// radians
-
-float radians(const float deg)
-{
-   const float c = 3.1415926 / 180.0;
-   __asm vec4_multiply __retVal, deg, c;
-}
-
-vec2 radians(const vec2 deg)
-{
-   const float c = 3.1415926 / 180.0;
-   __asm vec4_multiply __retVal.xy, deg.xy, c.xx;
-}
-
-vec3 radians(const vec3 deg)
-{
-   const float c = 3.1415926 / 180.0;
-   __asm vec4_multiply __retVal.xyz, deg.xyz, c.xxx;
-}
-
-vec4 radians(const vec4 deg)
-{
-   const float c = 3.1415926 / 180.0;
-   __asm vec4_multiply __retVal, deg, c.xxxx;
-}
-
-
-//// degrees
-
-float degrees(const float rad)
-{
-   const float c = 180.0 / 3.1415926;
-   __asm vec4_multiply __retVal, rad, c;
-}
-
-vec2 degrees(const vec2 rad)
-{
-   const float c = 180.0 / 3.1415926;
-   __asm vec4_multiply __retVal.xy, rad.xy, c.xx;
-}
-
-vec3 degrees(const vec3 rad)
-{
-   const float c = 180.0 / 3.1415926;
-   __asm vec4_multiply __retVal.xyz, rad.xyz, c.xxx;
-}
-
-vec4 degrees(const vec4 rad)
-{
-   const float c = 180.0 / 3.1415926;
-   __asm vec4_multiply __retVal, rad, c.xxxx;
-}
-
-
-//// sin
-
-float sin(const float radians)
-{
-   __asm float_sine __retVal, radians;
-}
-
-vec2 sin(const vec2 radians)
-{
-   __asm float_sine __retVal.x, radians.x;
-   __asm float_sine __retVal.y, radians.y;
-}
-
-vec3 sin(const vec3 radians)
-{
-   __asm float_sine __retVal.x, radians.x;
-   __asm float_sine __retVal.y, radians.y;
-   __asm float_sine __retVal.z, radians.z;
-}
-
-vec4 sin(const vec4 radians)
-{
-   __asm float_sine __retVal.x, radians.x;
-   __asm float_sine __retVal.y, radians.y;
-   __asm float_sine __retVal.z, radians.z;
-   __asm float_sine __retVal.w, radians.w;
-}
-
-
-//// cos
-
-float cos(const float radians)
-{
-   __asm float_cosine __retVal, radians;
-}
-
-vec2 cos(const vec2 radians)
-{
-   __asm float_cosine __retVal.x, radians.x;
-   __asm float_cosine __retVal.y, radians.y;
-}
-
-vec3 cos(const vec3 radians)
-{
-   __asm float_cosine __retVal.x, radians.x;
-   __asm float_cosine __retVal.y, radians.y;
-   __asm float_cosine __retVal.z, radians.z;
-}
-
-vec4 cos(const vec4 radians)
-{
-   __asm float_cosine __retVal.x, radians.x;
-   __asm float_cosine __retVal.y, radians.y;
-   __asm float_cosine __retVal.z, radians.z;
-   __asm float_cosine __retVal.w, radians.w;
-}
-
-
-
-//// tan
-
-float tan(const float angle)
-{
-   const float s = sin(angle);
-   const float c = cos(angle);
-   return s / c;
-}
-
-vec2 tan(const vec2 angle)
-{
-   const vec2 s = sin(angle);
-   const vec2 c = cos(angle);
-   return s / c;
-}
-
-vec3 tan(const vec3 angle)
-{
-   const vec3 s = sin(angle);
-   const vec3 c = cos(angle);
-   return s / c;
-}
-
-vec4 tan(const vec4 angle)
-{
-   const vec4 s = sin(angle);
-   const vec4 c = cos(angle);
-   return s / c;
-}
-
-
-
-float asin(const float x)
-{
-   const float a0 = 1.5707288;  // PI/2?
-   const float a1 = -0.2121144;
-   const float a2 = 0.0742610;
-   //const float a3 = -0.0187293;
-   const float halfPi = 3.1415926 * 0.5;
-   const float y = abs(x);
-   // three terms seem to be enough:
-   __retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + a2 * y))) * sign(x);
-   // otherwise, try four:
-   //__retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + y * (a2 + y * a3)))) * sign(x);
-}
-
-vec2 asin(const vec2 v)
-{
-   __retVal.x = asin(v.x);
-   __retVal.y = asin(v.y);
-}
-
-vec3 asin(const vec3 v)
-{
-   __retVal.x = asin(v.x);
-   __retVal.y = asin(v.y);
-   __retVal.z = asin(v.z);
-}
-
-vec4 asin(const vec4 v)
-{
-   __retVal.x = asin(v.x);
-   __retVal.y = asin(v.y);
-   __retVal.z = asin(v.z);
-   __retVal.w = asin(v.w);
-}
-
-float acos(const float x)
-{
-   const float halfPi = 3.1415926 * 0.5;
-   __retVal = halfPi - asin(x);
-}
-
-vec2 acos(const vec2 v)
-{
-   __retVal.x = acos(v.x);
-   __retVal.y = acos(v.y);
-}
-
-vec3 acos(const vec3 v)
-{
-   __retVal.x = acos(v.x);
-   __retVal.y = acos(v.y);
-   __retVal.z = acos(v.z);
-}
-
-vec4 acos(const vec4 v)
-{
-   __retVal.x = acos(v.x);
-   __retVal.y = acos(v.y);
-   __retVal.z = acos(v.z);
-   __retVal.w = acos(v.w);
-}
-
-float atan(const float x)
-{
-   __retVal = asin(x * inversesqrt(x * x + 1.0));
-}
-
-vec2 atan(const vec2 y_over_x)
-{
-   __retVal.x = atan(y_over_x.x);
-   __retVal.y = atan(y_over_x.y);
-}
-
-vec3 atan(const vec3 y_over_x)
-{
-   __retVal.x = atan(y_over_x.x);
-   __retVal.y = atan(y_over_x.y);
-   __retVal.z = atan(y_over_x.z);
-}
-
-vec4 atan(const vec4 y_over_x)
-{
-   __retVal.x = atan(y_over_x.x);
-   __retVal.y = atan(y_over_x.y);
-   __retVal.z = atan(y_over_x.z);
-   __retVal.w = atan(y_over_x.w);
-}
-
-float atan(const float y, const float x)
-{
-   float r;
-   if (abs(x) > 1.0e-4) {
-      r = atan(y / x);
-      if (x < 0.0) {
-         r = r + sign(y) * 3.141593;
-      }
-   }
-   else {
-      r = sign(y) * 1.5707965;  // pi/2
-   }
-   return r;
-}
-
-vec2 atan(const vec2 u, const vec2 v)
-{
-   __retVal.x = atan(u.x, v.x);
-   __retVal.y = atan(u.y, v.y);
-}
-
-vec3 atan(const vec3 u, const vec3 v)
-{
-   __retVal.x = atan(u.x, v.x);
-   __retVal.y = atan(u.y, v.y);
-   __retVal.z = atan(u.z, v.z);
-}
-
-vec4 atan(const vec4 u, const vec4 v)
-{
-   __retVal.x = atan(u.x, v.x);
-   __retVal.y = atan(u.y, v.y);
-   __retVal.z = atan(u.z, v.z);
-   __retVal.w = atan(u.w, v.w);
-}
-
-
-//
-// 8.2 Exponential Functions
-//
-
-//// pow
-
-float pow(const float a, const float b)
-{
-   __asm float_power __retVal, a, b;
-}
-
-vec2 pow(const vec2 a, const vec2 b)
-{
-   __asm float_power __retVal.x, a.x, b.x;
-   __asm float_power __retVal.y, a.y, b.y;
-}
-
-vec3 pow(const vec3 a, const vec3 b)
-{
-   __asm float_power __retVal.x, a.x, b.x;
-   __asm float_power __retVal.y, a.y, b.y;
-   __asm float_power __retVal.z, a.z, b.z;
-}
-
-vec4 pow(const vec4 a, const vec4 b)
-{
-   __asm float_power __retVal.x, a.x, b.x;
-   __asm float_power __retVal.y, a.y, b.y;
-   __asm float_power __retVal.z, a.z, b.z;
-   __asm float_power __retVal.w, a.w, b.w;
-}
-
-
-//// exp
-
-float exp(const float a)
-{
-   // NOTE: log2(e) = 1.44269502
-   float t = a * 1.44269502;
-   __asm float_exp2 __retVal, t;
-}
-
-vec2 exp(const vec2 a)
-{
-   vec2 t = a * 1.44269502;
-   __asm float_exp2 __retVal.x, t.x;
-   __asm float_exp2 __retVal.y, t.y;
-}
-
-vec3 exp(const vec3 a)
-{
-   vec3 t = a * 1.44269502;
-   __asm float_exp2 __retVal.x, t.x;
-   __asm float_exp2 __retVal.y, t.y;
-   __asm float_exp2 __retVal.z, t.z;
-}
-
-vec4 exp(const vec4 a)
-{
-   vec4 t = a * 1.44269502;
-   __asm float_exp2 __retVal.x, t.x;
-   __asm float_exp2 __retVal.y, t.y;
-   __asm float_exp2 __retVal.z, t.z;
-   __asm float_exp2 __retVal.w, t.w;
-}
-
-
-
-//// log2
-
-float log2(const float x)
-{
-   __asm float_log2 __retVal, x;
-}
-
-vec2 log2(const vec2 v)
-{
-   __asm float_log2 __retVal.x, v.x;
-   __asm float_log2 __retVal.y, v.y;
-}
-
-vec3 log2(const vec3 v)
-{
-   __asm float_log2 __retVal.x, v.x;
-   __asm float_log2 __retVal.y, v.y;
-   __asm float_log2 __retVal.z, v.z;
-}
-
-vec4 log2(const vec4 v)
-{
-   __asm float_log2 __retVal.x, v.x;
-   __asm float_log2 __retVal.y, v.y;
-   __asm float_log2 __retVal.z, v.z;
-   __asm float_log2 __retVal.w, v.w;
-}
-
-
-//// log  (natural log)
-
-float log(const float x)
-{
-   // note:  logBaseB(x) = logBaseN(x) / logBaseN(B)
-   // compute log(x) = log2(x) / log2(e)
-   // c = 1.0 / log2(e) = 0.693147181
-   const float c = 0.693147181;
-   return log2(x) * c;
-}
-
-vec2 log(const vec2 v)
-{
-   const float c = 0.693147181;
-   return log2(v) * c;
-}
-
-vec3 log(const vec3 v)
-{
-   const float c = 0.693147181;
-   return log2(v) * c;
-}
-
-vec4 log(const vec4 v)
-{
-   const float c = 0.693147181;
-   return log2(v) * c;
-}
-
-
-//// exp2
-
-float exp2(const float a)
-{
-   __asm float_exp2 __retVal, a;
-}
-
-vec2 exp2(const vec2 a)
-{
-   __asm float_exp2 __retVal.x, a.x;
-   __asm float_exp2 __retVal.y, a.y;
-}
-
-vec3 exp2(const vec3 a)
-{
-   __asm float_exp2 __retVal.x, a.x;
-   __asm float_exp2 __retVal.y, a.y;
-   __asm float_exp2 __retVal.z, a.z;
-}
-
-vec4 exp2(const vec4 a)
-{
-   __asm float_exp2 __retVal.x, a.x;
-   __asm float_exp2 __retVal.y, a.y;
-   __asm float_exp2 __retVal.z, a.z;
-   __asm float_exp2 __retVal.w, a.w;
-}
-
-
-//// sqrt
-
-float sqrt(const float x)
-{
-   const float nx = -x;
-   float r;
-   __asm float_rsq r, x;
-   r = r * x;
-   __asm vec4_cmp __retVal, nx, r, 0.0;
-}
-
-vec2 sqrt(const vec2 x)
-{
-   const vec2 nx = -x, zero = vec2(0.0);
-   vec2 r;
-   __asm float_rsq r.x, x.x;
-   __asm float_rsq r.y, x.y;
-   r = r * x;
-   __asm vec4_cmp __retVal, nx, r, zero;
-}
-
-vec3 sqrt(const vec3 x)
-{
-   const vec3 nx = -x, zero = vec3(0.0);
-   vec3 r;
-   __asm float_rsq r.x, x.x;
-   __asm float_rsq r.y, x.y;
-   __asm float_rsq r.z, x.z;
-   r = r * x;
-   __asm vec4_cmp __retVal, nx, r, zero;
-}
-
-vec4 sqrt(const vec4 x)
-{
-   const vec4 nx = -x, zero = vec4(0.0);
-   vec4 r;
-   __asm float_rsq r.x, x.x;
-   __asm float_rsq r.y, x.y;
-   __asm float_rsq r.z, x.z;
-   __asm float_rsq r.w, x.w;
-   r = r * x;
-   __asm vec4_cmp __retVal, nx, r, zero;
-}
-
-
-//// inversesqrt
-
-float inversesqrt(const float x)
-{
-   __asm float_rsq __retVal.x, x;
-}
-
-vec2 inversesqrt(const vec2 v)
-{
-   __asm float_rsq __retVal.x, v.x;
-   __asm float_rsq __retVal.y, v.y;
-}
-
-vec3 inversesqrt(const vec3 v)
-{
-   __asm float_rsq __retVal.x, v.x;
-   __asm float_rsq __retVal.y, v.y;
-   __asm float_rsq __retVal.z, v.z;
-}
-
-vec4 inversesqrt(const vec4 v)
-{
-   __asm float_rsq __retVal.x, v.x;
-   __asm float_rsq __retVal.y, v.y;
-   __asm float_rsq __retVal.z, v.z;
-   __asm float_rsq __retVal.w, v.w;
-}
-
-
-//// normalize
-
-float normalize(const float x)
-{
-   __retVal = 1.0;
-}
-
-vec2 normalize(const vec2 v)
-{
-   const float s = inversesqrt(dot(v, v));
-   __asm vec4_multiply __retVal.xy, v, s;
-}
-
-vec3 normalize(const vec3 v)
-{
-//   const float s = inversesqrt(dot(v, v));
-//   __retVal = v * s;
-// XXX note, we _could_ use __retVal.w instead of tmp and save a
-// register, but that's actually a compilation error because v is a vec3
-// and the .w suffix is illegal.  Oh well.
-   float tmp;
-   __asm vec3_dot tmp, v, v;
-   __asm float_rsq tmp, tmp;
-   __asm vec4_multiply __retVal.xyz, v, tmp;
-}
-
-vec4 normalize(const vec4 v)
-{
-   float tmp;
-   __asm vec4_dot tmp, v, v;
-   __asm float_rsq tmp, tmp;
-   __asm vec4_multiply __retVal.xyz, v, tmp;
-}
-
-
-
-//
-// 8.3 Common Functions
-//
-
-
-//// abs
-
-float abs(const float a)
-{
-   __asm vec4_abs __retVal, a;
-}
-
-vec2 abs(const vec2 a)
-{
-   __asm vec4_abs __retVal.xy, a;
-}
-
-vec3 abs(const vec3 a)
-{
-   __asm vec4_abs __retVal.xyz, a;
-}
-
-vec4 abs(const vec4 a)
-{
-   __asm vec4_abs __retVal, a;
-}
-
-
-//// sign
-
-float sign(const float x)
-{
-   float p, n;
-   __asm vec4_sgt p, x, 0.0;            // p = (x > 0)
-   __asm vec4_sgt n, 0.0, x;            // n = (x < 0)
-   __asm vec4_subtract __retVal, p, n;  // sign = p - n
-}
-
-vec2 sign(const vec2 v)
-{
-   vec2 p, n;
-   __asm vec4_sgt p.xy, v, 0.0;
-   __asm vec4_sgt n.xy, 0.0, v;
-   __asm vec4_subtract __retVal.xy, p, n;
-}
-
-vec3 sign(const vec3 v)
-{
-   vec3 p, n;
-   __asm vec4_sgt p.xyz, v, 0.0;
-   __asm vec4_sgt n.xyz, 0.0, v;
-   __asm vec4_subtract __retVal.xyz, p, n;
-}
-
-vec4 sign(const vec4 v)
-{
-   vec4 p, n;
-   __asm vec4_sgt p, v, 0.0;
-   __asm vec4_sgt n, 0.0, v;
-   __asm vec4_subtract __retVal, p, n;
-}
-
-
-//// floor
-
-float floor(const float a)
-{
-   __asm vec4_floor __retVal, a;
-}
-
-vec2 floor(const vec2 a)
-{
-   __asm vec4_floor __retVal.xy, a;
-}
-
-vec3 floor(const vec3 a)
-{
-   __asm vec4_floor __retVal.xyz, a;
-}
-
-vec4 floor(const vec4 a)
-{
-   __asm vec4_floor __retVal, a;
-}
-
-
-//// ceil
-
-float ceil(const float a)
-{
-   // XXX this could be improved
-   float b = -a;
-   __asm vec4_floor b, b;
-   __retVal = -b;
-}
-
-vec2 ceil(const vec2 a)
-{
-   vec2 b = -a;
-   __asm vec4_floor b, b;
-   __retVal.xy = -b;
-}
-
-vec3 ceil(const vec3 a)
-{
-   vec3 b = -a;
-   __asm vec4_floor b, b;
-   __retVal.xyz = -b;
-}
-
-vec4 ceil(const vec4 a)
-{
-   vec4 b = -a;
-   __asm vec4_floor b, b;
-   __retVal = -b;
-}
-
-
-//// fract
-
-float fract(const float a)
-{
-   __asm vec4_frac __retVal, a;
-}
-
-vec2 fract(const vec2 a)
-{
-   __asm vec4_frac __retVal.xy, a;
-}
-
-vec3 fract(const vec3 a)
-{
-   __asm vec4_frac __retVal.xyz, a;
-}
-
-vec4 fract(const vec4 a)
-{
-   __asm vec4_frac __retVal, a;
-}
-
-
-//// mod  (very untested!)
-
-float mod(const float a, const float b)
-{
-    float oneOverB;
-    __asm float_rcp oneOverB, b;
-    __retVal = a - b * floor(a * oneOverB);
-}
-
-vec2 mod(const vec2 a, const float b)
-{
-    float oneOverB;
-    __asm float_rcp oneOverB, b;
-    __retVal.xy = a - b * floor(a * oneOverB);
-}
-
-vec3 mod(const vec3 a, const float b)
-{
-    float oneOverB;
-    __asm float_rcp oneOverB, b;
-    __retVal.xyz = a - b * floor(a * oneOverB);
-}
-
-vec4 mod(const vec4 a, const float b)
-{
-    float oneOverB;
-    __asm float_rcp oneOverB, b;
-    __retVal = a - b * floor(a * oneOverB);
-}
-
-vec2 mod(const vec2 a, const vec2 b)
-{
-    vec2 oneOverB;
-    __asm float_rcp oneOverB.x, b.x;
-    __asm float_rcp oneOverB.y, b.y;
-    __retVal = a - b * floor(a * oneOverB);
-}
-
-vec3 mod(const vec3 a, const vec3 b)
-{
-    vec3 oneOverB;
-    __asm float_rcp oneOverB.x, b.x;
-    __asm float_rcp oneOverB.y, b.y;
-    __asm float_rcp oneOverB.z, b.z;
-    __retVal = a - b * floor(a * oneOverB);
-}
-
-vec4 mod(const vec4 a, const vec4 b)
-{
-    vec4 oneOverB;
-    __asm float_rcp oneOverB.x, b.x;
-    __asm float_rcp oneOverB.y, b.y;
-    __asm float_rcp oneOverB.z, b.z;
-    __asm float_rcp oneOverB.w, b.w;
-    __retVal = a - b * floor(a * oneOverB);
-}
-
-
-//// min
-
-float min(const float a, const float b)
-{
-   __asm vec4_min __retVal, a, b;
-}
-
-vec2 min(const vec2 a, const vec2 b)
-{
-   __asm vec4_min __retVal.xy, a.xy, b.xy;
-}
-
-vec3 min(const vec3 a, const vec3 b)
-{
-   __asm vec4_min __retVal.xyz, a.xyz, b.xyz;
-}
-
-vec4 min(const vec4 a, const vec4 b)
-{
-   __asm vec4_min __retVal, a, b;
-}
-
-vec2 min(const vec2 a, const float b)
-{
-   __asm vec4_min __retVal, a.xy, b;
-}
-
-vec3 min(const vec3 a, const float b)
-{
-   __asm vec4_min __retVal, a.xyz, b;
-}
-
-vec4 min(const vec4 a, const float b)
-{
-   __asm vec4_min __retVal, a, b;
-}
-
-
-//// max
-
-float max(const float a, const float b)
-{
-   __asm vec4_max __retVal, a, b;
-}
-
-vec2 max(const vec2 a, const vec2 b)
-{
-   __asm vec4_max __retVal.xy, a.xy, b.xy;
-}
-
-vec3 max(const vec3 a, const vec3 b)
-{
-   __asm vec4_max __retVal.xyz, a.xyz, b.xyz;
-}
-
-vec4 max(const vec4 a, const vec4 b)
-{
-   __asm vec4_max __retVal, a, b;
-}
-
-vec2 max(const vec2 a, const float b)
-{
-   __asm vec4_max __retVal, a.xy, b;
-}
-
-vec3 max(const vec3 a, const float b)
-{
-   __asm vec4_max __retVal, a.xyz, b;
-}
-
-vec4 max(const vec4 a, const float b)
-{
-   __asm vec4_max __retVal, a, b;
-}
-
-
-//// clamp
-
-float clamp(const float val, const float minVal, const float maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec2 clamp(const vec2 val, const float minVal, const float maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec3 clamp(const vec3 val, const float minVal, const float maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec4 clamp(const vec4 val, const float minVal, const float maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec2 clamp(const vec2 val, const vec2 minVal, const vec2 maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec3 clamp(const vec3 val, const vec3 minVal, const vec3 maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec4 clamp(const vec4 val, const vec4 minVal, const vec4 maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-
-//// mix
-
-float mix(const float x, const float y, const float a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec2 mix(const vec2 x, const vec2 y, const float a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec3 mix(const vec3 x, const vec3 y, const float a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec4 mix(const vec4 x, const vec4 y, const float a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec2 mix(const vec2 x, const vec2 y, const vec2 a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec3 mix(const vec3 x, const vec3 y, const vec3 a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec4 mix(const vec4 x, const vec4 y, const vec4 a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-
-//// step
-
-float step(const float edge, const float x)
-{
-   __asm vec4_sge __retVal, x, edge;
-}
-
-vec2 step(const vec2 edge, const vec2 x)
-{
-   __asm vec4_sge __retVal.xy, x, edge;
-}
-
-vec3 step(const vec3 edge, const vec3 x)
-{
-   __asm vec4_sge __retVal.xyz, x, edge;
-}
-
-vec4 step(const vec4 edge, const vec4 x)
-{
-   __asm vec4_sge __retVal, x, edge;
-}
-
-vec2 step(const float edge, const vec2 v)
-{
-   __asm vec4_sge __retVal.xy, v, edge;
-}
-
-vec3 step(const float edge, const vec3 v)
-{
-   __asm vec4_sge __retVal.xyz, v, edge;
-}
-
-vec4 step(const float edge, const vec4 v)
-{
-   __asm vec4_sge __retVal, v, edge;
-}
-
-
-//// smoothstep
-
-float smoothstep(const float edge0, const float edge1, const float x)
-{
-    float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
-    return t * t * (3.0 - 2.0 * t);
-}
-
-vec2 smoothstep(const vec2 edge0, const vec2 edge1, const vec2 v)
-{
-   vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
-   return t * t * (3.0 - 2.0 * t);
-}
-
-vec3 smoothstep(const vec3 edge0, const vec3 edge1, const vec3 v)
-{
-   vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
-   return t * t * (3.0 - 2.0 * t);
-}
-
-vec4 smoothstep(const vec4 edge0, const vec4 edge1, const vec4 v)
-{
-   vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
-   return t * t * (3.0 - 2.0 * t);
-}
-
-vec2 smoothstep(const float edge0, const float edge1, const vec2 v)
-{
-   vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
-   return t * t * (3.0 - 2.0 * t);
-}
-
-vec3 smoothstep(const float edge0, const float edge1, const vec3 v)
-{
-   vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
-   return t * t * (3.0 - 2.0 * t);
-}
-
-vec4 smoothstep(const float edge0, const float edge1, const vec4 v)
-{
-   vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
-   return t * t * (3.0 - 2.0 * t);
-}
-
-
-
-//
-// 8.4 Geometric Functions
-//
-
-
-//// length
-
-float length(const float x)
-{
-   return abs(x);
-}
-
-float length(const vec2 v)
-{
-   float r;
-   const float p = dot(v, v);      // p = v.x * v.x + v.y * v.y
-   __asm float_rsq r, p;           // r = 1 / sqrt(p)
-   __retVal = p * r;               // p * r = sqrt(p);
-}
-
-float length(const vec3 v)
-{
-   float r;
-   const float p = dot(v, v);      // p = v.x * v.x + v.y * v.y + v.z * v.z
-   __asm float_rsq r, p;           // r = 1 / sqrt(p)
-   __retVal = p * r;               // p * r = sqrt(p);
-}
-
-float length(const vec4 v)
-{
-   float r;
-   const float p = dot(v, v);      // p = v.x * v.x + v.y * v.y + ...
-   __asm float_rsq r, p;           // r = 1 / sqrt(p)
-   __retVal = p * r;               // p * r = sqrt(p);
-}
-
-
-//// distance
-
-float distance(const float x, const float y)
-{
-   const float d = x - y;
-   __retVal = length(d);
-}
-
-float distance(const vec2 v, const vec2 u)
-{
-   const vec2 d2 = v - u;
-   __retVal = length(d2);
-}
-
-float distance(const vec3 v, const vec3 u)
-{
-   const vec3 d3 = v - u;
-   __retVal = length(d3);
-}
-
-float distance(const vec4 v, const vec4 u)
-{
-   const vec4 d4 = v - u;
-   __retVal = length(d4);
-}
-
-
-//// cross
-
-vec3 cross(const vec3 v, const vec3 u)
-{
-   __asm vec3_cross __retVal.xyz, v, u;
-}
-
-
-//// faceforward
-
-float faceforward(const float N, const float I, const float Nref)
-{
-    // this could probably be done better
-    const float d = dot(Nref, I);
-    float s;
-    __asm vec4_sgt s, 0.0, d;  // s = (0.0 > d) ? 1 : 0
-    return mix(-N, N, s);
-}
-
-vec2 faceforward(const vec2 N, const vec2 I, const vec2 Nref)
-{
-    // this could probably be done better
-    const float d = dot(Nref, I);
-    float s;
-    __asm vec4_sgt s, 0.0, d;  // s = (0.0 > d) ? 1 : 0
-    return mix(-N, N, s);
-}
-
-vec3 faceforward(const vec3 N, const vec3 I, const vec3 Nref)
-{
-    // this could probably be done better
-    const float d = dot(Nref, I);
-    float s;
-    __asm vec4_sgt s, 0.0, d;  // s = (0.0 > d) ? 1 : 0
-    return mix(-N, N, s);
-}
-
-vec4 faceforward(const vec4 N, const vec4 I, const vec4 Nref)
-{
-    // this could probably be done better
-    const float d = dot(Nref, I);
-    float s;
-    __asm vec4_sgt s, 0.0, d;  // s = (0.0 > d) ? 1 : 0
-    return mix(-N, N, s);
-}
-
-
-//// reflect
-
-float reflect(const float I, const float N)
-{
-   return I - 2.0 * dot(N, I) * N;
-}
-
-vec2 reflect(const vec2 I, const vec2 N)
-{
-   return I - 2.0 * dot(N, I) * N;
-}
-
-vec3 reflect(const vec3 I, const vec3 N)
-{
-   return I - 2.0 * dot(N, I) * N;
-}
-
-vec4 reflect(const vec4 I, const vec4 N)
-{
-   return I - 2.0 * dot(N, I) * N;
-}
-
-//// refract
-
-float refract(const float I, const float N, const float eta)
-{
-   float n_dot_i = dot(N, I);
-   float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
-   float retval;
-   if (k < 0.0)
-      retval = 0.0;
-   else
-      retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
-   return retval;
-}
-
-vec2 refract(const vec2 I, const vec2 N, const float eta)
-{
-   float n_dot_i = dot(N, I);
-   float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
-   vec2 retval;
-   if (k < 0.0)
-      retval = vec2(0.0);
-   else
-      retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
-   return retval;
-}
-
-vec3 refract(const vec3 I, const vec3 N, const float eta)
-{
-   float n_dot_i = dot(N, I);
-   float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
-   vec3 retval;
-   if (k < 0.0)
-      retval = vec3(0.0);
-   else
-      retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
-   return retval;
-}
-
-vec4 refract(const vec4 I, const vec4 N, const float eta)
-{
-   float n_dot_i = dot(N, I);
-   float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
-   vec4 retval;
-   if (k < 0.0)
-      retval = vec4(0.0);
-   else
-      retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
-   return retval;
-}
-
-
-
-
-//
-// 8.5 Matrix Functions
-//
-
-mat2 matrixCompMult (mat2 m, mat2 n) {
-    return mat2 (m[0] * n[0], m[1] * n[1]);
-}
-
-mat3 matrixCompMult (mat3 m, mat3 n) {
-    return mat3 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
-}
-
-mat4 matrixCompMult (mat4 m, mat4 n) {
-    return mat4 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
-}
-
-
-
-
-//
-// 8.6 Vector Relational Functions
-//
-
-//// lessThan
-
-bvec2 lessThan(const vec2 u, const vec2 v)
-{
-   __asm vec4_slt __retVal.xy, u, v;
-}
-
-bvec3 lessThan(const vec3 u, const vec3 v)
-{
-   __asm vec4_slt __retVal.xyz, u, v;
-}
-
-bvec4 lessThan(const vec4 u, const vec4 v)
-{
-   __asm vec4_slt __retVal, u, v;
-}
-
-bvec2 lessThan(const ivec2 u, const ivec2 v)
-{
-   __asm vec4_slt __retVal.xy, u, v;
-}
-
-bvec3 lessThan(const ivec3 u, const ivec3 v)
-{
-   __asm vec4_slt __retVal.xyz, u, v;
-}
-
-bvec4 lessThan(const ivec4 u, const ivec4 v)
-{
-   __asm vec4_slt __retVal, u, v;
-}
-
-
-//// lessThanEqual
-
-bvec2 lessThanEqual(const vec2 u, const vec2 v)
-{
-   __asm vec4_sle __retVal.xy, u, v;
-}
-
-bvec3 lessThanEqual(const vec3 u, const vec3 v)
-{
-   __asm vec4_sle __retVal.xyz, u, v;
-}
-
-bvec4 lessThanEqual(const vec4 u, const vec4 v)
-{
-   __asm vec4_sle __retVal, u, v;
-}
-
-bvec2 lessThanEqual(const ivec2 u, const ivec2 v)
-{
-   __asm vec4_sle __retVal.xy, u, v;
-}
-
-bvec3 lessThanEqual(const ivec3 u, const ivec3 v)
-{
-   __asm vec4_sle __retVal.xyz, u, v;
-}
-
-bvec4 lessThanEqual(const ivec4 u, const ivec4 v)
-{
-   __asm vec4_sle __retVal, u, v;
-}
-
-
-//// greaterThan
-
-bvec2 greaterThan(const vec2 u, const vec2 v)
-{
-   __asm vec4_sgt __retVal.xy, u, v;
-}
-
-bvec3 greaterThan(const vec3 u, const vec3 v)
-{
-   __asm vec4_sgt __retVal.xyz, u, v;
-}
-
-bvec4 greaterThan(const vec4 u, const vec4 v)
-{
-   __asm vec4_sgt __retVal, u, v;
-}
-
-bvec2 greaterThan(const ivec2 u, const ivec2 v)
-{
-   __asm vec4_sgt __retVal.xy, u.xy, v.xy;
-}
-
-bvec3 greaterThan(const ivec3 u, const ivec3 v)
-{
-   __asm vec4_sgt __retVal.xyz, u, v;
-}
-
-bvec4 greaterThan(const ivec4 u, const ivec4 v)
-{
-   __asm vec4_sgt __retVal, u, v;
-}
-
-
-//// greaterThanEqual
-
-bvec2 greaterThanEqual(const vec2 u, const vec2 v)
-{
-   __asm vec4_sge __retVal.xy, u, v;
-}
-
-bvec3 greaterThanEqual(const vec3 u, const vec3 v)
-{
-   __asm vec4_sge __retVal.xyz, u, v;
-}
-
-bvec4 greaterThanEqual(const vec4 u, const vec4 v)
-{
-   __asm vec4_sge __retVal, u, v;
-}
-
-bvec2 greaterThanEqual(const ivec2 u, const ivec2 v)
-{
-   __asm vec4_sge __retVal.xy, u, v;
-}
-
-bvec3 greaterThanEqual(const ivec3 u, const ivec3 v)
-{
-   __asm vec4_sge __retVal.xyz, u, v;
-}
-
-bvec4 greaterThanEqual(const ivec4 u, const ivec4 v)
-{
-   __asm vec4_sge __retVal, u, v;
-}
-
-
-//// equal
-
-bvec2 equal(const vec2 u, const vec2 v)
-{
-   __asm vec4_seq __retVal.xy, u, v;
-}
-
-bvec3 equal(const vec3 u, const vec3 v)
-{
-   __asm vec4_seq __retVal.xyz, u, v;
-}
-
-bvec4 equal(const vec4 u, const vec4 v)
-{
-   __asm vec4_seq __retVal, u, v;
-}
-
-bvec2 equal(const ivec2 u, const ivec2 v)
-{
-   __asm vec4_seq __retVal.xy, u, v;
-}
-
-bvec3 equal(const ivec3 u, const ivec3 v)
-{
-   __asm vec4_seq __retVal.xyz, u, v;
-}
-
-bvec4 equal(const ivec4 u, const ivec4 v)
-{
-   __asm vec4_seq __retVal, u, v;
-}
-
-bvec2 equal(const bvec2 u, const bvec2 v)
-{
-   __asm vec4_seq __retVal.xy, u, v;
-}
-
-bvec3 equal(const bvec3 u, const bvec3 v)
-{
-   __asm vec4_seq __retVal.xyz, u, v;
-}
-
-bvec4 equal(const bvec4 u, const bvec4 v)
-{
-   __asm vec4_seq __retVal, u, v;
-}
-
-
-
-
-//// notEqual
-
-bvec2 notEqual(const vec2 u, const vec2 v)
-{
-   __asm vec4_sne __retVal.xy, u, v;
-}
-
-bvec3 notEqual(const vec3 u, const vec3 v)
-{
-   __asm vec4_sne __retVal.xyz, u, v;
-}
-
-bvec4 notEqual(const vec4 u, const vec4 v)
-{
-   __asm vec4_sne __retVal, u, v;
-}
-
-bvec2 notEqual(const ivec2 u, const ivec2 v)
-{
-   __asm vec4_sne __retVal.xy, u, v;
-}
-
-bvec3 notEqual(const ivec3 u, const ivec3 v)
-{
-   __asm vec4_sne __retVal.xyz, u, v;
-}
-
-bvec4 notEqual(const ivec4 u, const ivec4 v)
-{
-   __asm vec4_sne __retVal, u, v;
-}
-
-bvec2 notEqual(const bvec2 u, const bvec2 v)
-{
-   __asm vec4_sne __retVal.xy, u, v;
-}
-
-bvec3 notEqual(const bvec3 u, const bvec3 v)
-{
-   __asm vec4_sne __retVal.xyz, u, v;
-}
-
-bvec4 notEqual(const bvec4 u, const bvec4 v)
-{
-   __asm vec4_sne __retVal, u, v;
-}
-
-
-
-//// any
-
-bool any(const bvec2 v)
-{
-   float sum;
-   __asm vec4_add sum.x, v.x, v.y;
-   __asm vec4_sne __retVal.x, sum.x, 0.0;
-}
-
-bool any(const bvec3 v)
-{
-   float sum;
-   __asm vec4_add sum.x, v.x, v.y;
-   __asm vec4_add sum.x, sum.x, v.z;
-   __asm vec4_sne __retVal.x, sum.x, 0.0;
-}
-
-bool any(const bvec4 v)
-{
-   float sum;
-   __asm vec4_add sum.x, v.x, v.y;
-   __asm vec4_add sum.x, sum.x, v.z;
-   __asm vec4_add sum.x, sum.x, v.w;
-   __asm vec4_sne __retVal.x, sum.x, 0.0;
-}
-
-
-//// all
-
-bool all (const bvec2 v)
-{
-   float prod;
-   __asm vec4_multiply prod, v.x, v.y;
-   __asm vec4_sne __retVal, prod, 0.0;
-}
-
-bool all (const bvec3 v)
-{
-   float prod;
-   __asm vec4_multiply prod, v.x, v.y;
-   __asm vec4_multiply prod, prod, v.z;
-   __asm vec4_sne __retVal, prod, 0.0;
-}
-
-bool all (const bvec4 v)
-{
-   float prod;
-   __asm vec4_multiply prod, v.x, v.y;
-   __asm vec4_multiply prod, prod, v.z;
-   __asm vec4_multiply prod, prod, v.w;
-   __asm vec4_sne __retVal, prod, 0.0;
-}
-
-
-
-//// not
-
-bvec2 not (const bvec2 v)
-{
-   __asm vec4_seq __retVal.xy, v, 0.0;
-}
-
-bvec3 not (const bvec3 v)
-{
-   __asm vec4_seq __retVal.xyz, v, 0.0;
-}
-
-bvec4 not (const bvec4 v)
-{
-   __asm vec4_seq __retVal, v, 0.0;
-}
-
-
-
-//// Texture Lookup Functions  (for both fragment and vertex shaders)
-
-vec4 texture1D(const sampler1D sampler, const float coord)
-{
-   __asm vec4_tex_1d __retVal, sampler, coord;
-}
-
-vec4 texture1DProj(const sampler1D sampler, const vec2 coord)
-{
-   // need to swizzle .y into .w
-   __asm vec4_tex_1d_proj __retVal, sampler, coord.xyyy;
-}
-
-vec4 texture1DProj(const sampler1D sampler, const vec4 coord)
-{
-   __asm vec4_tex_1d_proj __retVal, sampler, coord;
-}
-
-
-vec4 texture2D(const sampler2D sampler, const vec2 coord)
-{
-   __asm vec4_tex_2d __retVal, sampler, coord;
-}
-
-vec4 texture2DProj(const sampler2D sampler, const vec3 coord)
-{
-   // need to swizzle 'z' into 'w'.
-   __asm vec4_tex_2d_proj __retVal, sampler, coord.xyzz;
-}
-
-vec4 texture2DProj(const sampler2D sampler, const vec4 coord)
-{
-   __asm vec4_tex_2d_proj __retVal, sampler, coord;
-}
-
-
-vec4 texture3D(const sampler3D sampler, const vec3 coord)
-{
-   __asm vec4_tex_3d __retVal, sampler, coord;
-}
-
-vec4 texture3DProj(const sampler3D sampler, const vec4 coord)
-{
-   __asm vec4_tex_3d_proj __retVal, sampler, coord;
-}
-
-
-vec4 textureCube(const samplerCube sampler, const vec3 coord)
-{
-   __asm vec4_tex_cube __retVal, sampler, coord;
-}
-
-
-
-vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord)
-{
-   __asm vec4_tex_1d_shadow __retVal, sampler, coord;
-}
-
-vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord)
-{
-   // .s and .p will be divided by .q
-   __asm vec4_tex_1d_proj_shadow __retVal, sampler, coord;
-}
-
-vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord)
-{
-   __asm vec4_tex_2d_shadow __retVal, sampler, coord;
-}
-
-vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord)
-{
-   // .s, .t and .p will be divided by .q
-   __asm vec4_tex_2d_proj_shadow __retVal, sampler, coord;
-}
-
-
-//// GL_ARB_texture_rectangle:
-vec4 texture2DRect(const sampler2DRect sampler, const vec2 coord)
-{
-   __asm vec4_tex_rect __retVal, sampler, coord;
-}
-
-vec4 texture2DRectProj(const sampler2DRect sampler, const vec3 coord)
-{
-   // need to swizzle .y into .w
-   __asm vec4_tex_rect_proj __retVal, sampler, coord.xyzz;
-}
-
-vec4 texture2DRectProj(const sampler2DRect sampler, const vec4 coord)
-{
-   __asm vec4_tex_rect_proj __retVal, sampler, ccoord;
-}
-
-vec4 shadow2DRect(const sampler2DRectShadow sampler, const vec3 coord)
-{
-   __asm vec4_tex_rect_shadow __retVal, sampler, coord;
-}
-
-vec4 shadow2DRectProj(const sampler2DRectShadow sampler, const vec4 coord)
-{
-   __asm vec4_tex_rect_proj_shadow __retVal, sampler, coord;
-}
-
-
-
-//// GL_EXT_texture_array
-vec4 texture1DArray(const sampler1DArray sampler, const vec2 coord)
-{
-   __asm vec4_tex_1d_array __retVal, sampler, coord;
-}
-
-vec4 texture2DArray(const sampler2DArray sampler, const vec3 coord)
-{
-   __asm vec4_tex_2d_array __retVal, sampler, coord;
-}
-
-
-//
-// 8.9 Noise Functions
-//
-// AUTHOR: Stefan Gustavson (stegu@itn.liu.se), Nov 26, 2005
-//
-
-float noise1(const float x)
-{
-   __asm float_noise1 __retVal, x;
-}
-
-
-float noise1(const vec2 x)
-{
-    __asm float_noise2 __retVal, x;
-}
-
-float noise1(const vec3 x)
-{
-    __asm float_noise3 __retVal, x;
-}
-
-float noise1(const vec4 x)
-{
-    __asm float_noise4 __retVal, x;
-}
-
-vec2 noise2(const float x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + 19.34);
-}
-
-vec2 noise2(const vec2 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec2(19.34, 7.66));
-}
-
-vec2 noise2(const vec3 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
-}
-
-vec2 noise2(const vec4 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
-}
-
-vec3 noise3(const float x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + 19.34);
-   __retVal.z = noise1(x + 5.47);
-}
-
-vec3 noise3(const vec2 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec2(19.34, 7.66));
-   __retVal.z = noise1(x + vec2(5.47, 17.85));
-}
-
-vec3 noise3(const vec3 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
-   __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04));
-}
-
-vec3 noise3(const vec4 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
-   __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19));
-}
-
-vec4 noise4(const float x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + 19.34);
-   __retVal.z = noise1(x + 5.47);
-   __retVal.w = noise1(x + 23.54);
-}
-
-vec4 noise4(const vec2 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec2 (19.34, 7.66));
-   __retVal.z = noise1(x + vec2 (5.47, 17.85));
-   __retVal.w = noise1(x + vec2 (23.54, 29.11));
-}
-
-vec4 noise4(const vec3 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
-   __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04));
-   __retVal.w = noise1(x + vec3(23.54, 29.11, 31.91));
-}
-
-vec4 noise4(const vec4 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
-   __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19));
-   __retVal.w = noise1(x + vec4(23.54, 29.11, 31.91, 37.48));
-}
diff --git a/src/mesa/shader/slang/library/slang_core.gc b/src/mesa/shader/slang/library/slang_core.gc
deleted file mode 100644 (file)
index 0a0d159..0000000
+++ /dev/null
@@ -1,2619 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// This file defines nearly all constructors and operators for built-in data
-// types, using extended language syntax. In general, compiler treats
-// constructors and operators as ordinary functions with some exceptions.
-// For example, the language does not allow functions to be called in
-// constant expressions - here the exception is made to allow it.
-//
-// Each implementation provides its own version of this file. Each
-// implementation can define the required set of operators and constructors
-// in its own fashion.
-//
-// The extended language syntax is only present when compiling this file.
-// It is implicitly included at the very beginning of the compiled shader,
-// so no built-in functions can be used.
-//
-// To communicate with the implementation, a special extended "__asm" keyword
-// is used, followed by an instruction name (any valid identifier), a
-// destination variable identifier and a list of zero or more source
-// variable identifiers.
-//
-// A variable identifier is a variable name declared earlier in the code
-// (as a function parameter, local or global variable).
-//
-// An instruction name designates an instruction that must be exported
-// by the implementation.  Each instruction receives data from source
-// variable identifiers and returns data in the destination variable
-// identifier.
-//
-// It is up to the implementation how to define a particular operator
-// or constructor. If it is expected to being used rarely, it can be
-// defined in terms of other operators and constructors,
-// for example:
-//
-// ivec2 __operator + (const ivec2 x, const ivec2 y) {
-//    return ivec2 (x[0] + y[0], x[1] + y[1]);
-// }
-//
-// If a particular operator or constructor is expected to be used very
-// often or is an atomic operation (that is, an operation that cannot be
-// expressed in terms of other operations or would create a dependency
-// cycle) it must be defined using one or more __asm constructs.
-//
-// Each implementation must define constructors for all scalar types
-// (bool, float, int).  There are 9 scalar-to-scalar constructors
-// (including identity constructors). However, since the language
-// introduces special constructors (like matrix constructor with a single
-// scalar value), implementations must also implement these cases.
-// The compiler provides the following algorithm when resolving a constructor:
-// - try to find a constructor with a prototype matching ours,
-// - if no constructor is found and this is a scalar-to-scalar constructor,
-//   raise an error,
-// - if a constructor is found, execute it and return,
-// - count the size of the constructor parameter list - if it is less than
-//   the size of our constructor's type, raise an error,
-// - for each parameter in the list do a recursive constructor matching for
-//   appropriate scalar fields in the constructed variable,
-//
-// Each implementation must also define a set of operators that deal with
-// built-in data types.
-// There are four kinds of operators:
-// 1) Operators that are implemented only by the compiler: "()" (function
-//    call), "," (sequence) and "?:" (selection).
-// 2) Operators that are implemented by the compiler by expressing it in
-//    terms of other operators:
-//    - "." (field selection) - translated to subscript access,
-//    - "&&" (logical and) - translated to "<left_expr> ? <right_expr> :
-//      false",
-//    - "||" (logical or) - translated to "<left_expr> ? true : <right_expr>",
-// 3) Operators that can be defined by the implementation and if the required
-//    prototype is not found, standard behaviour is used:
-//    - "==", "!=", "=" (equality, assignment) - compare or assign
-//      matching fields one-by-one;
-//      note that at least operators for scalar data types must be defined
-//      by the implementation to get it work,
-// 4) All other operators not mentioned above. If no required prototype is
-//    found, an error is raised. An implementation must follow the language
-//    specification to provide all valid operator prototypes.
-//
-
-
-
-//// Basic, scalar constructors/casts
-
-int __constructor(const float f)
-{
-   __asm vec4_to_ivec4 __retVal, f;
-}
-
-int __constructor(const bool b)
-{
-   __retVal = b;
-}
-
-int __constructor(const int i)
-{
-   __retVal = i;
-}
-
-bool __constructor(const int i)
-{
-   __asm vec4_sne __retVal, i, 0.0;
-}
-
-bool __constructor(const float f)
-{
-   __asm vec4_sne __retVal, f, 0.0;
-}
-
-bool __constructor(const bool b)
-{
-   __retVal = b;
-}
-
-float __constructor(const int i)
-{
-    __asm ivec4_to_vec4 __retVal, i;
-}
-
-float __constructor(const bool b)
-{
-    __asm ivec4_to_vec4 __retVal, b;
-}
-
-float __constructor(const float f)
-{
-   __retVal = f;
-}
-
-
-//// vec2 constructors
-
-vec2 __constructor(const float x, const float y)
-{
-   __retVal.x = x;
-   __retVal.y = y;
-}
-
-vec2 __constructor(const float f)
-{
-   __asm vec4_move __retVal.xy, f;
-}
-
-vec2 __constructor(const int i)
-{
-   __asm ivec4_to_vec4 __retVal.xy, i;
-}
-
-vec2 __constructor(const bool b)
-{
-   __asm ivec4_to_vec4 __retVal.xy, b;
-}
-
-vec2 __constructor(const bvec2 b)
-{
-//   __retVal = b;
-   __asm ivec4_to_vec4 __retVal.xy, b;
-}
-
-vec2 __constructor(const vec3 v)
-{
-   __asm vec4_move __retVal.xy, v.xy;
-}
-
-vec2 __constructor(const vec4 v)
-{
-   __asm vec4_move __retVal.xy, v.xy;
-}
-
-
-//// vec3 constructors
-
-vec3 __constructor(const float x, const float y, const float z)
-{
-   __retVal.x = x;
-   __retVal.y = y;
-   __retVal.z = z;
-}
-
-vec3 __constructor(const float f)
-{
-   // Note: this could be "__retVal.xyz = f" but that's an illegal assignment
-   __asm vec4_move __retVal.xyz, f;
-}
-
-vec3 __constructor(const int i)
-{
-   __asm ivec4_to_vec4 __retVal.xyz, i;
-}
-
-vec3 __constructor(const bool b)
-{
-   __asm ivec4_to_vec4 __retVal.xyz, b;
-}
-
-vec3 __constructor(const bvec3 b)
-{
-   __asm ivec4_to_vec4 __retVal.xyz, b;
-}
-
-vec3 __constructor(const vec4 v)
-{
-   __asm vec4_move __retVal.xyz, v;
-}
-
-
-//// vec4 constructors
-
-vec4 __constructor(const float x, const float y, const float z, const float w)
-{
-   __retVal.x = x;
-   __retVal.y = y;
-   __retVal.z = z;
-   __retVal.w = w;
-}
-
-vec4 __constructor(const float f)
-{
-   // Note: this could be "__retVal = f" but that's an illegal assignment
-   __asm vec4_move __retVal, f;
-}
-
-vec4 __constructor(const int i)
-{
-   __asm ivec4_to_vec4 __retVal, i;
-}
-
-vec4 __constructor(const bool b)
-{
-   __asm ivec4_to_vec4 __retVal, b;
-}
-
-vec4 __constructor(const bvec4 b)
-{
-   __asm ivec4_to_vec4 __retVal, b;
-}
-
-vec4 __constructor(const ivec4 i)
-{
-   __asm ivec4_to_vec4 __retVal, i;
-}
-
-vec4 __constructor(const vec3 v3, const float f)
-{
-   // XXX this constructor shouldn't be needed anymore
-   __retVal.xyz = v3;
-   __retVal.w = f;
-}
-
-vec4 __constructor(const vec2 v2, const float f1, const float f2)
-{
-   // XXX this constructor shouldn't be needed anymore
-   __retVal.xy = v2;
-   __retVal.z = f1;
-   __retVal.w = f2;
-}
-
-
-//// ivec2 constructors
-
-ivec2 __constructor(const int i, const int j)
-{
-   __retVal.x = i;
-   __retVal.y = j;
-}
-
-ivec2 __constructor(const int i)
-{
-   __asm vec4_move __retVal.xy, i;
-}
-
-ivec2 __constructor(const float f)
-{
-   __asm vec4_to_ivec4 __retVal.xy, f;
-}
-
-ivec2 __constructor(const bool b)
-{
-   __asm vec4_to_ivec4 __retVal.xy, b;
-}
-
-
-//// ivec3 constructors
-
-ivec3 __constructor(const int i, const int j, const int k)
-{
-   __retVal.x = i;
-   __retVal.y = j;
-   __retVal.z = k;
-}
-
-ivec3 __constructor(const int i)
-{
-   __asm vec4_move __retVal.xyz, i;
-}
-
-ivec3 __constructor(const float f)
-{
-   __asm vec4_to_ivec4 __retVal.xyz, f;
-}
-
-ivec3 __constructor(const bool b)
-{
-   __asm vec4_move __retVal.xyz, b;
-}
-
-
-//// ivec4 constructors
-
-ivec4 __constructor(const int x, const int y, const int z, const int w)
-{
-   __retVal.x = x;
-   __retVal.y = y;
-   __retVal.z = z;
-   __retVal.w = w;
-}
-
-ivec4 __constructor(const int i)
-{
-   __asm vec4_move __retVal, i;
-}
-
-ivec4 __constructor(const float f)
-{
-   __asm vec4_to_ivec4 __retVal, f;
-}
-
-ivec4 __constructor(const bool b)
-{
-   __asm vec4_to_ivec4 __retVal, b;
-}
-
-
-//// bvec2 constructors
-
-bvec2 __constructor(const bool b1, const bool b2)
-{
-   __retVal.x = b1;
-   __retVal.y = b2;
-}
-
-bvec2 __constructor(const int i1, const int i2)
-{
-   __asm vec4_sne __retVal.x, i1, 0.0;
-   __asm vec4_sne __retVal.y, i2, 0.0;
-}
-
-
-bvec2 __constructor(const bool b)
-{
-   __asm vec4_move __retVal.xy, b;
-}
-
-bvec2 __constructor(const float f)
-{
-   __asm vec4_sne __retVal.xy, f, 0.0;
-}
-
-bvec2 __constructor(const int i)
-{
-   __asm vec4_sne __retVal.xy, i, 0.0;
-}
-
-bvec2 __constructor(const vec2 v)
-{
-   __asm vec4_sne __retVal.xy, v, 0.0;
-}
-
-bvec2 __constructor(const ivec2 v)
-{
-   __asm vec4_sne __retVal.xy, v, 0.0;
-}
-
-
-
-//// bvec3 constructors
-
-bvec3 __constructor(const bool b1, const bool b2, const bool b3)
-{
-   __retVal.x = b1;
-   __retVal.y = b2;
-   __retVal.z = b3;
-}
-
-bvec3 __constructor(const float f1, const float f2, const float f3)
-{
-   __asm vec4_sne __retVal.x, f1, 0.0;
-   __asm vec4_sne __retVal.y, f2, 0.0;
-   __asm vec4_sne __retVal.z, f3, 0.0;
-}
-
-bvec3 __constructor(const bool b)
-{
-   __asm vec4_move __retVal.xyz, b;
-}
-
-bvec3 __constructor(const float f)
-{
-   __asm vec4_sne __retVal.xyz, f, 0.0;
-}
-
-bvec3 __constructor(const int i)
-{
-   __asm vec4_sne __retVal.xyz, i, 0.0;
-}
-
-bvec3 __constructor(const vec3 v)
-{
-   __asm vec4_sne __retVal.xyz, v, 0.0;
-}
-
-bvec3 __constructor(const ivec3 v)
-{
-   __asm vec4_sne __retVal.xyz, v, 0.0;
-}
-
-
-
-//// bvec4 constructors
-
-bvec4 __constructor(const bool b1, const bool b2, const bool b3, const bool b4)
-{
-   __retVal.x = b1;
-   __retVal.y = b2;
-   __retVal.z = b3;
-   __retVal.w = b4;
-}
-
-bvec4 __constructor(const float f1, const float f2, const float f3, const float f4)
-{
-   const float zero = 0.0;
-   __asm vec4_sne __retVal.x, f1, zero;   
-   __asm vec4_sne __retVal.y, f2, zero;   
-   __asm vec4_sne __retVal.z, f3, zero;   
-   __asm vec4_sne __retVal.w, f4, zero;   
-}
-
-bvec4 __constructor(const bool b)
-{
-   __asm vec4_move __retVal.xyzw, b;
-}
-
-bvec4 __constructor(const float f)
-{
-   __asm vec4_sne __retVal.xyzw, f, 0.0;
-}
-
-bvec4 __constructor(const int i)
-{
-   __asm vec4_sne __retVal.xyzw, i, 0.0;
-}
-
-bvec4 __constructor(const vec4 v)
-{
-   __asm vec4_sne __retVal.xyzw, v, 0.0;
-}
-
-bvec4 __constructor(const ivec4 v)
-{
-   __asm vec4_sne __retVal.xyzw, v, 0.0;
-}
-
-
-
-//// mat2 constructors
-
-mat2 __constructor(const float m00, const float m10,
-                   const float m01, const float m11)
-{
-   __retVal[0].x = m00;
-   __retVal[0].y = m10;
-   __retVal[1].x = m01;
-   __retVal[1].y = m11;
-}
-
-mat2 __constructor(const float f)
-{
-   __retVal[0].x = f;
-   __retVal[0].y = 0.0;
-   __retVal[1].x = 0.0;
-   __retVal[1].y = f;
-}
-
-mat2 __constructor(const int i)
-{
-   return mat2(float(i));
-}
-
-mat2 __constructor(const bool b)
-{
-   return mat2(float(b));
-}
-
-mat2 __constructor(const vec2 c0, const vec2 c1)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-}
-
-
-//// mat3 constructors
-
-mat3 __constructor(const float m00, const float m10, const float m20,
-                   const float m01, const float m11, const float m21,
-                   const float m02, const float m12, const float m22)
-{
-   __retVal[0].x = m00;
-   __retVal[0].y = m10;
-   __retVal[0].z = m20;
-   __retVal[1].x = m01;
-   __retVal[1].y = m11;
-   __retVal[1].z = m21;
-   __retVal[2].x = m02;
-   __retVal[2].y = m12;
-   __retVal[2].z = m22;
-}
-
-mat3 __constructor(const float f)
-{
-   vec2 v = vec2(f, 0.0);
-   __retVal[0] = v.xyy;
-   __retVal[1] = v.yxy;
-   __retVal[2] = v.yyx;
-}
-
-mat3 __constructor(const int i)
-{
-   return mat3(float(i));
-}
-
-mat3 __constructor(const bool b)
-{
-   return mat3(float(b));
-}
-
-mat3 __constructor(const vec3 c0, const vec3 c1, const vec3 c2)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-   __retVal[2] = c2;
-}
-
-
-//// mat4 constructors
-
-mat4 __constructor(const float m00, const float m10, const float m20, const float m30,
-                   const float m01, const float m11, const float m21, const float m31,
-                   const float m02, const float m12, const float m22, const float m32,
-                   const float m03, const float m13, const float m23, const float m33)
-{
-   __retVal[0].x = m00;
-   __retVal[0].y = m10;
-   __retVal[0].z = m20;
-   __retVal[0].w = m30;
-   __retVal[1].x = m01;
-   __retVal[1].y = m11;
-   __retVal[1].z = m21;
-   __retVal[1].w = m31;
-   __retVal[2].x = m02;
-   __retVal[2].y = m12;
-   __retVal[2].z = m22;
-   __retVal[2].w = m32;
-   __retVal[3].x = m03;
-   __retVal[3].y = m13;
-   __retVal[3].z = m23;
-   __retVal[3].w = m33;
-}
-
-
-mat4 __constructor(const float f)
-{
-   vec2 v = vec2(f, 0.0);
-   __retVal[0] = v.xyyy;
-   __retVal[1] = v.yxyy;
-   __retVal[2] = v.yyxy;
-   __retVal[3] = v.yyyx;
-}
-
-mat4 __constructor(const int i)
-{
-   return mat4(float(i));
-}
-
-mat4 __constructor(const bool b)
-{
-   return mat4(float(b));
-}
-
-mat4 __constructor(const vec4 c0, const vec4 c1, const vec4 c2, const vec4 c3)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-   __retVal[2] = c2;
-   __retVal[3] = c3;
-}
-
-
-
-//// Basic int operators
-
-int __operator + (const int a, const int b)
-{
-   __asm vec4_add __retVal, a, b;
-}
-
-int __operator - (const int a, const int b)
-{
-   __asm vec4_subtract __retVal, a, b;
-}
-
-int __operator * (const int a, const int b)
-{
-   __asm vec4_multiply __retVal, a, b;
-}
-
-int __operator / (const int a, const int b)
-{
-   float bInv, x;
-   __asm float_rcp bInv, b;
-   __asm vec4_multiply x, a, bInv;
-   __asm vec4_to_ivec4 __retVal, x;
-}
-
-
-//// Basic ivec2 operators
-
-ivec2 __operator + (const ivec2 a, const ivec2 b)
-{
-   __asm vec4_add __retVal, a, b;
-}
-
-ivec2 __operator - (const ivec2 a, const ivec2 b)
-{
-   __asm vec4_subtract __retVal, a, b;
-}
-
-ivec2 __operator * (const ivec2 a, const ivec2 b)
-{
-   __asm vec4_multiply __retVal, a, b;
-}
-
-ivec2 __operator / (const ivec2 a, const ivec2 b)
-{
-   vec2 bInv, x;
-   __asm float_rcp bInv.x, b.x;
-   __asm float_rcp bInv.y, b.y;
-   __asm vec4_multiply x, a, bInv;
-   __asm vec4_to_ivec4 __retVal, x;
-}
-
-
-//// Basic ivec3 operators
-
-ivec3 __operator + (const ivec3 a, const ivec3 b)
-{
-   __asm vec4_add __retVal, a, b;
-}
-
-ivec3 __operator - (const ivec3 a, const ivec3 b)
-{
-   __asm vec4_subtract __retVal, a, b;
-}
-
-ivec3 __operator * (const ivec3 a, const ivec3 b)
-{
-   __asm vec4_multiply __retVal, a, b;
-}
-
-ivec3 __operator / (const ivec3 a, const ivec3 b)
-{
-   vec3 bInv, x;
-   __asm float_rcp bInv.x, b.x;
-   __asm float_rcp bInv.y, b.y;
-   __asm float_rcp bInv.z, b.z;
-   __asm vec4_multiply x, a, bInv;
-   __asm vec4_to_ivec4 __retVal, x;
-}
-
-
-//// Basic ivec4 operators
-
-ivec4 __operator + (const ivec4 a, const ivec4 b)
-{
-   __asm vec4_add __retVal, a, b;
-}
-
-ivec4 __operator - (const ivec4 a, const ivec4 b)
-{
-   __asm vec4_subtract __retVal, a, b;
-}
-
-ivec4 __operator * (const ivec4 a, const ivec4 b)
-{
-   __asm vec4_multiply __retVal, a, b;
-}
-
-ivec4 __operator / (const ivec4 a, const ivec4 b)
-{
-   vec4 bInv, x;
-   __asm float_rcp bInv.x, b.x;
-   __asm float_rcp bInv.y, b.y;
-   __asm float_rcp bInv.z, b.z;
-   __asm float_rcp bInv.w, b.w;
-   __asm vec4_multiply x, a, bInv;
-   __asm vec4_to_ivec4 __retVal, x;
-}
-
-
-//// Basic float operators
-
-float __operator + (const float a, const float b)
-{
-   __asm vec4_add __retVal, a, b;
-}
-
-float __operator - (const float a, const float b)
-{
-   __asm vec4_subtract __retVal, a, b;
-}
-
-float __operator * (const float a, const float b)
-{
-    __asm vec4_multiply __retVal, a, b;
-}
-
-float __operator / (const float a, const float b)
-{
-   float bInv;
-   __asm float_rcp bInv.x, b;
-   __asm vec4_multiply __retVal, a, bInv;
-}
-
-
-//// Basic vec2 operators
-
-vec2 __operator + (const vec2 v, const vec2 u)
-{
-   __asm vec4_add __retVal.xy, v, u;
-}
-
-vec2 __operator - (const vec2 v, const vec2 u)
-{
-    __asm vec4_subtract __retVal.xy, v, u;
-}
-
-vec2 __operator * (const vec2 v, const vec2 u)
-{
-    __asm vec4_multiply __retVal.xy, v, u;
-}
-
-vec2 __operator / (const vec2 v, const vec2 u)
-{
-   vec2 w; // = 1 / u
-   __asm float_rcp w.x, u.x;
-   __asm float_rcp w.y, u.y;
-   __asm vec4_multiply __retVal.xy, v, w;
-}
-
-
-//// Basic vec3 operators
-
-vec3 __operator + (const vec3 v, const vec3 u)
-{
-   __asm vec4_add __retVal.xyz, v, u;
-}
-
-vec3 __operator - (const vec3 v, const vec3 u)
-{
-    __asm vec4_subtract __retVal.xyz, v, u;
-}
-
-vec3 __operator * (const vec3 v, const vec3 u)
-{
-    __asm vec4_multiply __retVal.xyz, v, u;
-}
-
-vec3 __operator / (const vec3 v, const vec3 u)
-{
-   vec3 w; // = 1 / u
-   __asm float_rcp w.x, u.x;
-   __asm float_rcp w.y, u.y;
-   __asm float_rcp w.z, u.z;
-   __asm vec4_multiply __retVal.xyz, v, w;
-}
-
-
-//// Basic vec4 operators
-
-vec4 __operator + (const vec4 v, const vec4 u)
-{
-   __asm vec4_add __retVal, v, u;
-}
-
-vec4 __operator - (const vec4 v, const vec4 u)
-{
-    __asm vec4_subtract __retVal, v, u;
-}
-
-vec4 __operator * (const vec4 v, const vec4 u)
-{
-    __asm vec4_multiply __retVal, v, u;
-}
-
-vec4 __operator / (const vec4 v, const vec4 u)
-{
-   vec4 w; // = 1 / u
-   __asm float_rcp w.x, u.x;
-   __asm float_rcp w.y, u.y;
-   __asm float_rcp w.z, u.z;
-   __asm float_rcp w.w, u.w;
-   __asm vec4_multiply __retVal, v, w;
-}
-
-
-
-
-//// Basic vec2/float operators
-
-vec2 __operator + (const float a, const vec2 u)
-{
-   __asm vec4_add __retVal.xy, a, u.xy;
-}
-
-vec2 __operator + (const vec2 v, const float b)
-{
-   __asm vec4_add __retVal.xy, v.xy, b;
-}
-
-vec2 __operator - (const float a, const vec2 u)
-{
-   __asm vec4_subtract __retVal.xy, a, u.xy;
-}
-
-vec2 __operator - (const vec2 v, const float b)
-{
-   __asm vec4_subtract __retVal.xy, v.xy, b;
-}
-
-vec2 __operator * (const float a, const vec2 u)
-{
-   __asm vec4_multiply __retVal.xy, a, u.xy;
-}
-
-vec2 __operator * (const vec2 v, const float b)
-{
-   __asm vec4_multiply __retVal.xy, v.xy, b;
-}
-
-vec2 __operator / (const float a, const vec2 u)
-{
-   vec2 invU;
-   __asm float_rcp invU.x, u.x;
-   __asm float_rcp invU.y, u.y;
-   __asm vec4_multiply __retVal.xy, a, invU.xy;
-}
-
-vec2 __operator / (const vec2 v, const float b)
-{
-   float invB;
-   __asm float_rcp invB, b;
-   __asm vec4_multiply __retVal.xy, v.xy, invB;
-}
-
-
-//// Basic vec3/float operators
-
-vec3 __operator + (const float a, const vec3 u)
-{
-   __asm vec4_add __retVal.xyz, a, u.xyz;
-}
-
-vec3 __operator + (const vec3 v, const float b)
-{
-   __asm vec4_add __retVal.xyz, v.xyz, b;
-}
-
-vec3 __operator - (const float a, const vec3 u)
-{
-   __asm vec4_subtract __retVal.xyz, a, u.xyz;
-}
-
-vec3 __operator - (const vec3 v, const float b)
-{
-   __asm vec4_subtract __retVal.xyz, v.xyz, b;
-}
-
-vec3 __operator * (const float a, const vec3 u)
-{
-   __asm vec4_multiply __retVal.xyz, a, u.xyz;
-}
-
-vec3 __operator * (const vec3 v, const float b)
-{
-   __asm vec4_multiply __retVal.xyz, v.xyz, b;
-}
-
-vec3 __operator / (const float a, const vec3 u)
-{
-   vec3 invU;
-   __asm float_rcp invU.x, u.x;
-   __asm float_rcp invU.y, u.y;
-   __asm float_rcp invU.z, u.z;
-   __asm vec4_multiply __retVal.xyz, a, invU.xyz;
-}
-
-vec3 __operator / (const vec3 v, const float b)
-{
-   float invB;
-   __asm float_rcp invB, b;
-   __asm vec4_multiply __retVal.xyz, v.xyz, invB;
-}
-
-
-//// Basic vec4/float operators
-
-vec4 __operator + (const float a, const vec4 u)
-{
-   __asm vec4_add __retVal, a, u;
-}
-
-vec4 __operator + (const vec4 v, const float b)
-{
-   __asm vec4_add __retVal, v, b;
-}
-
-vec4 __operator - (const float a, const vec4 u)
-{
-   __asm vec4_subtract __retVal, a, u;
-}
-
-vec4 __operator - (const vec4 v, const float b)
-{
-   __asm vec4_subtract __retVal, v, b;
-}
-
-vec4 __operator * (const float a, const vec4 u)
-{
-   __asm vec4_multiply __retVal, a, u;
-}
-
-vec4 __operator * (const vec4 v, const float b)
-{
-   __asm vec4_multiply __retVal, v, b;
-}
-
-vec4 __operator / (const float a, const vec4 u)
-{
-   vec4 invU;
-   __asm float_rcp invU.x, u.x;
-   __asm float_rcp invU.y, u.y;
-   __asm float_rcp invU.z, u.z;
-   __asm float_rcp invU.w, u.w;
-   __asm vec4_multiply __retVal, a, invU;
-}
-
-vec4 __operator / (const vec4 v, const float b)
-{
-   float invB;
-   __asm float_rcp invB, b;
-   __asm vec4_multiply __retVal, v, invB;
-}
-
-
-
-//// Basic ivec2/int operators
-
-ivec2 __operator + (const int a, const ivec2 u)
-{
-   __retVal = ivec2(a) + u;
-}
-
-ivec2 __operator + (const ivec2 v, const int b)
-{
-   __retVal = v + ivec2(b);
-}
-
-ivec2 __operator - (const int a, const ivec2 u)
-{
-   __retVal = ivec2(a) - u;
-}
-
-ivec2 __operator - (const ivec2 v, const int b)
-{
-   __retVal = v - ivec2(b);
-}
-
-ivec2 __operator * (const int a, const ivec2 u)
-{
-   __retVal = ivec2(a) * u;
-}
-
-ivec2 __operator * (const ivec2 v, const int b)
-{
-   __retVal = v * ivec2(b);
-}
-
-ivec2 __operator / (const int a, const ivec2 u)
-{
-   __retVal = ivec2(a) / u;
-}
-
-ivec2 __operator / (const ivec2 v, const int b)
-{
-   __retVal = v / ivec2(b);
-}
-
-
-//// Basic ivec3/int operators
-
-ivec3 __operator + (const int a, const ivec3 u)
-{
-   __retVal = ivec3(a) + u;
-}
-
-ivec3 __operator + (const ivec3 v, const int b)
-{
-   __retVal = v + ivec3(b);
-}
-
-ivec3 __operator - (const int a, const ivec3 u)
-{
-   __retVal = ivec3(a) - u;
-}
-
-ivec3 __operator - (const ivec3 v, const int b)
-{
-   __retVal = v - ivec3(b);
-}
-
-ivec3 __operator * (const int a, const ivec3 u)
-{
-   __retVal = ivec3(a) * u;
-}
-
-ivec3 __operator * (const ivec3 v, const int b)
-{
-   __retVal = v * ivec3(b);
-}
-
-ivec3 __operator / (const int a, const ivec3 u)
-{
-   __retVal = ivec3(a) / u;
-}
-
-ivec3 __operator / (const ivec3 v, const int b)
-{
-   __retVal = v / ivec3(b);
-}
-
-
-//// Basic ivec4/int operators
-
-ivec4 __operator + (const int a, const ivec4 u)
-{
-   __retVal = ivec4(a) + u;
-}
-
-ivec4 __operator + (const ivec4 v, const int b)
-{
-   __retVal = v + ivec4(b);
-}
-
-ivec4 __operator - (const int a, const ivec4 u)
-{
-   __retVal = ivec4(a) - u;
-}
-
-ivec4 __operator - (const ivec4 v, const int b)
-{
-   __retVal = v - ivec4(b);
-}
-
-ivec4 __operator * (const int a, const ivec4 u)
-{
-   __retVal = ivec4(a) * u;
-}
-
-ivec4 __operator * (const ivec4 v, const int b)
-{
-   __retVal = v * ivec4(b);
-}
-
-ivec4 __operator / (const int a, const ivec4 u)
-{
-   __retVal = ivec4(a) / u;
-}
-
-ivec4 __operator / (const ivec4 v, const int b)
-{
-   __retVal = v / ivec4(b);
-}
-
-
-
-
-//// Unary negation operator
-
-int __operator - (const int a)
-{
-   __asm vec4_negate __retVal.x, a;
-}
-
-ivec2 __operator - (const ivec2 v)
-{
-   __asm vec4_negate __retVal, v;
-}
-
-ivec3 __operator - (const ivec3 v)
-{
-   __asm vec4_negate __retVal, v;
-}
-
-ivec4 __operator - (const ivec4 v)
-{
-   __asm vec4_negate __retVal, v;
-}
-
-float __operator - (const float a)
-{
-   __asm vec4_negate __retVal.x, a;
-}
-
-vec2 __operator - (const vec2 v)
-{
-   __asm vec4_negate __retVal.xy, v.xy;
-}
-
-vec3 __operator - (const vec3 v)
-{
-   __asm vec4_negate __retVal.xyz, v.xyz;
-}
-
-vec4 __operator - (const vec4 v)
-{
-   __asm vec4_negate __retVal, v;
-}
-
-mat2 __operator - (const mat2 m)
-{
-   __retVal[0] = -m[0];
-   __retVal[1] = -m[1];
-}
-
-mat3 __operator - (const mat3 m)
-{
-   __retVal[0] = -m[0];
-   __retVal[1] = -m[1];
-   __retVal[2] = -m[2];
-}
-
-mat4 __operator - (const mat4 m)
-{
-   __retVal[0] = -m[0];
-   __retVal[1] = -m[1];
-   __retVal[2] = -m[2];
-   __retVal[3] = -m[3];
-}
-
-
-
-//// dot product
-
-float dot(const float a, const float b)
-{
-   __retVal = a * b;
-}
-
-float dot(const vec2 a, const vec2 b)
-{
-   __retVal = a.x * b.x + a.y * b.y;
-}
-
-float dot(const vec3 a, const vec3 b)
-{
-    __asm vec3_dot __retVal, a, b;
-}
-
-float dot(const vec4 a, const vec4 b)
-{
-    __asm vec4_dot __retVal, a, b;
-}
-
-
-
-//// int assignment operators
-
-int __operator += (inout int a, const int b)
-{
-   a = a + b;
-   return a;
-}
-
-int __operator -= (inout int a, const int b)
-{
-   a = a - b;
-   return a;
-}
-
-int __operator *= (inout int a, const int b)
-{
-   a = a * b;
-   return a;
-}
-
-int __operator /= (inout int a, const int b)
-{
-   a = a / b;
-   return a;
-}
-
-
-//// ivec2 assignment operators
-
-ivec2 __operator += (inout ivec2 v, const ivec2 u)
-{
-   v = v + u;
-   return v;
-}
-
-ivec2 __operator -= (inout ivec2 v, const ivec2 u)
-{
-   v = v - u;
-   return v;
-}
-
-ivec2 __operator *= (inout ivec2 v, const ivec2 u)
-{
-   v = v * u;
-   return v;
-}
-
-ivec2 __operator /= (inout ivec2 v, const ivec2 u)
-{
-   v = v / u;
-   return v;
-}
-
-
-//// ivec3 assignment operators
-
-ivec3 __operator += (inout ivec3 v, const ivec3 u)
-{
-   v = v + u;
-   return v;
-}
-
-ivec3 __operator -= (inout ivec3 v, const ivec3 u)
-{
-   v = v - u;
-   return v;
-}
-
-ivec3 __operator *= (inout ivec3 v, const ivec3 u)
-{
-   v = v * u;
-   return v;
-}
-
-ivec3 __operator /= (inout ivec3 v, const ivec3 u)
-{
-   v = v / u;
-   return v;
-}
-
-
-//// ivec4 assignment operators
-
-ivec4 __operator += (inout ivec4 v, const ivec4 u)
-{
-   v = v + u;
-   return v;
-}
-
-ivec4 __operator -= (inout ivec4 v, const ivec4 u)
-{
-   v = v - u;
-   return v;
-}
-
-ivec4 __operator *= (inout ivec4 v, const ivec4 u)
-{
-   v = v * u;
-   return v;
-}
-
-ivec4 __operator /= (inout ivec4 v, const ivec4 u)
-{
-   v = v / u;
-   return v;
-}
-
-
-//// float assignment operators
-
-float __operator += (inout float a, const float b)
-{
-   a = a + b;
-   return a;
-}
-
-float __operator -= (inout float a, const float b)
-{
-   a = a - b;
-   return a;
-}
-
-float __operator *= (inout float a, const float b)
-{
-   a = a * b;
-   return a;
-}
-
-float __operator /= (inout float a, const float b)
-{
-   a = a / b;
-   return a;
-}
-
-
-//// vec2 assignment operators
-
-vec2 __operator += (inout vec2 v, const vec2 u)
-{
-   v = v + u;
-   return v;
-}
-
-vec2 __operator -= (inout vec2 v, const vec2 u)
-{
-   v = v - u;
-   return v;
-}
-
-vec2 __operator *= (inout vec2 v, const vec2 u)
-{
-   v = v * u;
-   return v;
-}
-
-vec2 __operator /= (inout vec2 v, const vec2 u)
-{
-   v = v / u;
-   return v;
-}
-
-
-//// vec3 assignment operators
-
-vec3 __operator += (inout vec3 v, const vec3 u)
-{
-   v = v + u;
-   return v;
-}
-
-vec3 __operator -= (inout vec3 v, const vec3 u)
-{
-   v = v - u;
-   return v;
-}
-
-vec3 __operator *= (inout vec3 v, const vec3 u)
-{
-   v = v * u;
-   return v;
-}
-
-vec3 __operator /= (inout vec3 v, const vec3 u)
-{
-   v = v / u;
-   return v;
-}
-
-
-//// vec4 assignment operators
-
-vec4 __operator += (inout vec4 v, const vec4 u)
-{
-   v = v + u;
-   return v;
-}
-
-vec4 __operator -= (inout vec4 v, const vec4 u)
-{
-   v = v - u;
-   return v;
-}
-
-vec4 __operator *= (inout vec4 v, const vec4 u)
-{
-   v = v * u;
-   return v;
-}
-
-vec4 __operator /= (inout vec4 v, const vec4 u)
-{
-   v = v / u;
-   return v;
-}
-
-
-
-//// ivec2/int assignment operators
-
-ivec2 __operator += (inout ivec2 v, const int a)
-{
-   v = v + ivec2(a);
-   return v;
-}
-
-ivec2 __operator -= (inout ivec2 v, const int a)
-{
-   v = v - ivec2(a);
-   return v;
-}
-
-ivec2 __operator *= (inout ivec2 v, const int a)
-{
-   v = v * ivec2(a);
-   return v;
-}
-
-ivec2 __operator /= (inout ivec2 v, const int a)
-{
-   v = v / ivec2(a);
-   return v;
-}
-
-
-//// ivec3/int assignment operators
-
-ivec3 __operator += (inout ivec3 v, const int a)
-{
-   v = v + ivec3(a);
-   return v;
-}
-
-ivec3 __operator -= (inout ivec3 v, const int a)
-{
-   v = v - ivec3(a);
-   return v;
-}
-
-ivec3 __operator *= (inout ivec3 v, const int a)
-{
-   v = v * ivec3(a);
-   return v;
-}
-
-ivec4 __operator /= (inout ivec3 v, const int a)
-{
-   v = v / ivec3(a);
-   return v;
-}
-
-
-//// ivec4/int assignment operators
-
-ivec4 __operator += (inout ivec4 v, const int a)
-{
-   v = v + ivec4(a);
-   return v;
-}
-
-ivec4 __operator -= (inout ivec4 v, const int a)
-{
-   v = v - ivec4(a);
-   return v;
-}
-
-ivec4 __operator *= (inout ivec4 v, const int a)
-{
-   v = v * ivec4(a);
-   return v;
-}
-
-ivec4 __operator /= (inout ivec4 v, const int a)
-{
-   v = v / ivec4(a);
-   return v;
-}
-
-
-
-//// vec2/float assignment operators
-
-vec2 __operator += (inout vec2 v, const float a)
-{
-   v = v + vec2(a);
-   return v;
-}
-
-vec2 __operator -= (inout vec2 v, const float a)
-{
-   v = v - vec2(a);
-   return v;
-}
-
-vec2 __operator *= (inout vec2 v, const float a)
-{
-   v = v * vec2(a);
-   return v;
-}
-
-vec2 __operator /= (inout vec2 v, const float a)
-{
-   v = v / vec2(a);
-   return v;
-}
-
-
-//// vec3/float assignment operators
-
-vec3 __operator += (inout vec3 v, const float a)
-{
-   v = v + vec3(a);
-   return v;
-}
-
-vec3 __operator -= (inout vec3 v, const float a)
-{
-   v = v - vec3(a);
-   return v;
-}
-
-vec3 __operator *= (inout vec3 v, const float a)
-{
-   v = v * vec3(a);
-   return v;
-}
-
-vec3 __operator /= (inout vec3 v, const float a)
-{
-   v = v / vec3(a);
-   return v;
-}
-
-
-//// vec4/float assignment operators
-
-vec4 __operator += (inout vec4 v, const float a)
-{
-   v = v + vec4(a);
-   return v;
-}
-
-vec4 __operator -= (inout vec4 v, const float a)
-{
-   v = v - vec4(a);
-   return v;
-}
-
-vec4 __operator *= (inout vec4 v, const float a)
-{
-   v = v * vec4(a);
-   return v;
-}
-
-vec4 __operator /= (inout vec4 v, const float a)
-{
-   v = v / vec4(a);
-   return v;
-}
-
-
-
-
-
-//// Basic mat2 operations
-
-mat2 __operator + (const mat2 m, const mat2 n)
-{
-   __retVal[0] = m[0] + n[0];
-   __retVal[1] = m[1] + n[1];
-}
-
-mat2 __operator - (const mat2 m, const mat2 n)
-{
-   __retVal[0] = m[0] - n[0];
-   __retVal[1] = m[1] - n[1];
-}
-
-mat2 __operator * (const mat2 m, const mat2 n)
-{
-   __retVal[0] = m[0] * n[0].xx + m[1] * n[0].yy;
-   __retVal[1] = m[0] * n[1].xx + m[1] * n[1].yy;
-}
-
-mat2 __operator / (const mat2 m, const mat2 n)
-{
-   __retVal[0] = m[0] / n[0];
-   __retVal[1] = m[1] / n[1];
-}
-
-
-//// Basic mat3 operations
-
-mat3 __operator + (const mat3 m, const mat3 n)
-{
-   __retVal[0] = m[0] + n[0];
-   __retVal[1] = m[1] + n[1];
-   __retVal[2] = m[2] + n[2];
-}
-
-mat3 __operator - (const mat3 m, const mat3 n)
-{
-   __retVal[0] = m[0] - n[0];
-   __retVal[1] = m[1] - n[1];
-   __retVal[2] = m[2] - n[2];
-}
-
-mat3 __operator * (const mat3 m, const mat3 n)
-{
-   __retVal[0] = m[0] * n[0].xxx + m[1] * n[0].yyy + m[2] * n[0].zzz;
-   __retVal[1] = m[0] * n[1].xxx + m[1] * n[1].yyy + m[2] * n[1].zzz;
-   __retVal[2] = m[0] * n[2].xxx + m[1] * n[2].yyy + m[2] * n[2].zzz;
-}
-
-mat3 __operator / (const mat3 m, const mat3 n)
-{
-    __retVal[0] = m[0] / n[0];
-    __retVal[1] = m[1] / n[1];
-    __retVal[2] = m[2] / n[2];
-}
-
-
-//// Basic mat4 operations
-
-mat4 __operator + (const mat4 m, const mat4 n)
-{
-   __retVal[0] = m[0] + n[0];
-   __retVal[1] = m[1] + n[1];
-   __retVal[2] = m[2] + n[2];
-   __retVal[3] = m[3] + n[3];
-}
-
-mat4 __operator - (const mat4 m, const mat4 n)
-{
-   __retVal[0] = m[0] - n[0];
-   __retVal[1] = m[1] - n[1];
-   __retVal[2] = m[2] - n[2];
-   __retVal[3] = m[3] - n[3];
-}
-
-mat4 __operator * (const mat4 m, const mat4 n)
-{
-   __retVal[0] = m[0] * n[0].xxxx + m[1] * n[0].yyyy + m[2] * n[0].zzzz + m[3] * n[0].wwww;
-   __retVal[1] = m[0] * n[1].xxxx + m[1] * n[1].yyyy + m[2] * n[1].zzzz + m[3] * n[1].wwww;
-   __retVal[2] = m[0] * n[2].xxxx + m[1] * n[2].yyyy + m[2] * n[2].zzzz + m[3] * n[2].wwww;
-   __retVal[3] = m[0] * n[3].xxxx + m[1] * n[3].yyyy + m[2] * n[3].zzzz + m[3] * n[3].wwww;
-}
-
-mat4 __operator / (const mat4 m, const mat4 n)
-{
-    __retVal[0] = m[0] / n[0];
-    __retVal[1] = m[1] / n[1];
-    __retVal[2] = m[2] / n[2];
-    __retVal[3] = m[3] / n[3];
-}
-
-
-//// mat2/float operations
-
-mat2 __operator + (const float a, const mat2 n)
-{
-   __retVal[0] = a + n[0];
-   __retVal[1] = a + n[1];
-}
-
-mat2 __operator + (const mat2 m, const float b)
-{
-   __retVal[0] = m[0] + b;
-   __retVal[1] = m[1] + b;
-}
-
-mat2 __operator - (const float a, const mat2 n)
-{
-   __retVal[0] = a - n[0];
-   __retVal[1] = a - n[1];
-}
-
-mat2 __operator - (const mat2 m, const float b)
-{
-   __retVal[0] = m[0] - b;
-   __retVal[1] = m[1] - b;
-}
-
-mat2 __operator * (const float a, const mat2 n)
-{
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-}
-
-mat2 __operator * (const mat2 m, const float b)
-{
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-}
-
-mat2 __operator / (const float a, const mat2 n)
-{
-   __retVal[0] = a / n[0];
-   __retVal[1] = a / n[1];
-}
-
-mat2 __operator / (const mat2 m, const float b)
-{
-   __retVal[0] = m[0] / b;
-   __retVal[1] = m[1] / b;
-}
-
-
-//// mat3/float operations
-
-mat3 __operator + (const float a, const mat3 n)
-{
-   __retVal[0] = a + n[0];
-   __retVal[1] = a + n[1];
-   __retVal[2] = a + n[2];
-}
-
-mat3 __operator + (const mat3 m, const float b)
-{
-   __retVal[0] = m[0] + b;
-   __retVal[1] = m[1] + b;
-   __retVal[2] = m[2] + b;
-}
-
-mat3 __operator - (const float a, const mat3 n)
-{
-   __retVal[0] = a - n[0];
-   __retVal[1] = a - n[1];
-   __retVal[2] = a - n[2];
-}
-
-mat3 __operator - (const mat3 m, const float b)
-{
-   __retVal[0] = m[0] - b;
-   __retVal[1] = m[1] - b;
-   __retVal[2] = m[2] - b;
-}
-
-mat3 __operator * (const float a, const mat3 n)
-{
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-   __retVal[2] = a * n[2];
-}
-
-mat3 __operator * (const mat3 m, const float b)
-{
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-   __retVal[2] = m[2] * b;
-}
-
-mat3 __operator / (const float a, const mat3 n)
-{
-   __retVal[0] = a / n[0];
-   __retVal[1] = a / n[1];
-   __retVal[2] = a / n[2];
-}
-
-mat3 __operator / (const mat3 m, const float b)
-{
-   __retVal[0] = m[0] / b;
-   __retVal[1] = m[1] / b;
-   __retVal[2] = m[2] / b;
-}
-
-
-//// mat4/float operations
-
-mat4 __operator + (const float a, const mat4 n)
-{
-   __retVal[0] = a + n[0];
-   __retVal[1] = a + n[1];
-   __retVal[2] = a + n[2];
-   __retVal[3] = a + n[3];
-}
-
-mat4 __operator + (const mat4 m, const float b)
-{
-   __retVal[0] = m[0] + b;
-   __retVal[1] = m[1] + b;
-   __retVal[2] = m[2] + b;
-   __retVal[3] = m[3] + b;
-}
-
-mat4 __operator - (const float a, const mat4 n)
-{
-   __retVal[0] = a - n[0];
-   __retVal[1] = a - n[1];
-   __retVal[2] = a - n[2];
-   __retVal[3] = a - n[3];
-}
-
-mat4 __operator - (const mat4 m, const float b)
-{
-   __retVal[0] = m[0] - b;
-   __retVal[1] = m[1] - b;
-   __retVal[2] = m[2] - b;
-   __retVal[3] = m[3] - b;
-}
-
-mat4 __operator * (const float a, const mat4 n)
-{
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-   __retVal[2] = a * n[2];
-   __retVal[3] = a * n[3];
-}
-
-mat4 __operator * (const mat4 m, const float b)
-{
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-   __retVal[2] = m[2] * b;
-   __retVal[3] = m[3] * b;
-}
-
-mat4 __operator / (const float a, const mat4 n)
-{
-   __retVal[0] = a / n[0];
-   __retVal[1] = a / n[1];
-   __retVal[2] = a / n[2];
-   __retVal[3] = a / n[3];
-}
-
-mat4 __operator / (const mat4 m, const float b)
-{
-   __retVal[0] = m[0] / b;
-   __retVal[1] = m[1] / b;
-   __retVal[2] = m[2] / b;
-   __retVal[3] = m[3] / b;
-}
-
-
-
-//// matrix / vector products
-
-vec2 __operator * (const mat2 m, const vec2 v)
-{
-   __retVal = m[0] * v.xx
-            + m[1] * v.yy;
-}
-
-vec2 __operator * (const vec2 v, const mat2 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-}
-
-vec3 __operator * (const mat3 m, const vec3 v)
-{
-   __retVal = m[0] * v.xxx
-            + m[1] * v.yyy
-            + m[2] * v.zzz;
-}
-
-vec3 __operator * (const vec3 v, const mat3 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-   __retVal.z = dot(v, m[2]);
-}
-
-vec4 __operator * (const mat4 m, const vec4 v)
-{
-   __retVal = m[0] * v.xxxx
-            + m[1] * v.yyyy
-            + m[2] * v.zzzz
-            + m[3] * v.wwww;
-}
-
-vec4 __operator * (const vec4 v, const mat4 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-   __retVal.z = dot(v, m[2]);
-   __retVal.w = dot(v, m[3]);
-}
-
-
-
-//// mat2 assignment operators
-
-mat2 __operator += (inout mat2 m, const mat2 n)
-{
-   m[0] = m[0] + n[0];
-   m[1] = m[1] + n[1];
-   return m;
-}
-
-mat2 __operator -= (inout mat2 m, const mat2 n)
-{
-   m[0] = m[0] - n[0];
-   m[1] = m[1] - n[1];
-   return m;
-}
-
-mat2 __operator *= (inout mat2 m, const mat2 n)
-{
-   m = m * n;
-   return m;
-}
-
-mat2 __operator /= (inout mat2 m, const mat2 n)
-{
-   m[0] = m[0] / n[0];
-   m[1] = m[1] / n[1];
-   return m;
-}
-
-
-//// mat3 assignment operators
-
-mat3 __operator += (inout mat3 m, const mat3 n)
-{
-   m[0] = m[0] + n[0];
-   m[1] = m[1] + n[1];
-   m[2] = m[2] + n[2];
-   return m;
-}
-
-mat3 __operator -= (inout mat3 m, const mat3 n)
-{
-   m[0] = m[0] - n[0];
-   m[1] = m[1] - n[1];
-   m[2] = m[2] - n[2];
-   return m;
-}
-
-mat3 __operator *= (inout mat3 m, const mat3 n)
-{
-   m = m * n;
-   return m;
-}
-
-mat3 __operator /= (inout mat3 m, const mat3 n)
-{
-   m[0] = m[0] / n[0];
-   m[1] = m[1] / n[1];
-   m[2] = m[2] / n[2];
-   return m;
-}
-
-
-// mat4 assignment operators
-
-mat4 __operator += (inout mat4 m, const mat4 n)
-{
-   m[0] = m[0] + n[0];
-   m[1] = m[1] + n[1];
-   m[2] = m[2] + n[2];
-   m[3] = m[3] + n[3];
-   return m;
-}
-
-mat4 __operator -= (inout mat4 m, const mat4 n)
-{
-   m[0] = m[0] - n[0];
-   m[1] = m[1] - n[1];
-   m[2] = m[2] - n[2];
-   m[3] = m[3] - n[3];
-   return m;
-}
-
-mat4 __operator *= (inout mat4 m, const mat4 n)
-{
-   m = m * n;
-   return m;
-}
-
-mat4 __operator /= (inout mat4 m, const mat4 n)
-{
-   m[0] = m[0] / n[0];
-   m[1] = m[1] / n[1];
-   m[2] = m[2] / n[2];
-   m[3] = m[3] / n[3];
-   return m;
-}
-
-
-//// mat2/float assignment operators
-
-mat2 __operator += (inout mat2 m, const float a)
-{
-   vec2 v = vec2(a);
-   m[0] = m[0] + v;
-   m[1] = m[1] + v;
-   return m;
-}
-
-mat2 __operator -= (inout mat2 m, const float a)
-{
-   vec2 v = vec2(a);
-   m[0] = m[0] - v;
-   m[1] = m[1] - v;
-   return m;
-}
-
-mat2 __operator *= (inout mat2 m, const float a)
-{
-   vec2 v = vec2(a);
-   m[0] = m[0] * v;
-   m[1] = m[1] * v;
-   return m;
-}
-
-mat2 __operator /= (inout mat2 m, const float a)
-{
-   vec2 v = vec2(1.0 / a);
-   m[0] = m[0] * v;
-   m[1] = m[1] * v;
-   return m;
-}
-
-
-//// mat3/float assignment operators
-
-mat3 __operator += (inout mat3 m, const float a)
-{
-   vec3 v = vec3(a);
-   m[0] = m[0] + v;
-   m[1] = m[1] + v;
-   m[2] = m[2] + v;
-   return m;
-}
-
-mat3 __operator -= (inout mat3 m, const float a)
-{
-   vec3 v = vec3(a);
-   m[0] = m[0] - v;
-   m[1] = m[1] - v;
-   m[2] = m[2] - v;
-   return m;
-}
-
-mat3 __operator *= (inout mat3 m, const float a)
-{
-   vec3 v = vec3(a);
-   m[0] = m[0] * v;
-   m[1] = m[1] * v;
-   m[2] = m[2] * v;
-   return m;
-}
-
-mat3 __operator /= (inout mat3 m, const float a)
-{
-   vec3 v = vec3(1.0 / a);
-   m[0] = m[0] * v;
-   m[1] = m[1] * v;
-   m[2] = m[2] * v;
-   return m;
-}
-
-
-//// mat4/float assignment operators
-
-mat4 __operator += (inout mat4 m, const float a)
-{
-   vec4 v = vec4(a);
-   m[0] = m[0] + v;
-   m[1] = m[1] + v;
-   m[2] = m[2] + v;
-   m[3] = m[3] + v;
-   return m;
-}
-
-mat4 __operator -= (inout mat4 m, const float a)
-{
-   vec4 v = vec4(a);
-   m[0] = m[0] - v;
-   m[1] = m[1] - v;
-   m[2] = m[2] - v;
-   m[3] = m[3] - v;
-   return m;
-}
-
-mat4 __operator *= (inout mat4 m, const float a)
-{
-   vec4 v = vec4(a);
-   m[0] = m[0] * v;
-   m[1] = m[1] * v;
-   m[2] = m[2] * v;
-   m[3] = m[3] * v;
-   return m;
-}
-
-mat4 __operator /= (inout mat4 m, const float a)
-{
-   vec4 v = vec4(1.0 / a);
-   m[0] = m[0] * v;
-   m[1] = m[1] * v;
-   m[2] = m[2] * v;
-   m[3] = m[3] * v;
-   return m;
-}
-
-
-
-//// vec/mat assignment operators
-
-vec2 __operator *= (inout vec2 v, const mat2 m)
-{
-   v = v * m;
-   return v;
-}
-
-vec3 __operator *= (inout vec3 v, const mat3 m)
-{
-   v = v * m;
-   return v;
-}
-
-vec4 __operator *= (inout vec4 v, const mat4 m)
-{
-   v = v * m;
-   return v;
-}
-
-
-
-//// pre-decrement operators
-
-int __operator --(inout int a)
-{
-    a = a - 1;
-   __retVal = a;
-}
-
-ivec2 __operator --(inout ivec2 v)
-{
-   v = v - ivec2(1);
-   __retVal = v;
-}
-
-ivec3 __operator --(inout ivec3 v)
-{
-   v = v - ivec3(1);
-   __retVal = v;
-}
-
-ivec4 __operator --(inout ivec4 v)
-{
-   v = v - ivec4(1);
-   __retVal = v;
-}
-
-
-float __operator --(inout float a)
-{
-   a = a - 1.0;
-   __retVal = a;
-}
-
-vec2 __operator --(inout vec2 v)
-{
-   v = v - vec2(1.0);
-   __retVal = v;
-}
-
-vec3 __operator --(inout vec3 v)
-{
-   v = v - vec3(1.0);
-   __retVal = v;
-}
-
-vec4 __operator --(inout vec4 v)
-{
-   v = v - vec4(1.0);
-   __retVal = v;
-}
-
-
-mat2 __operator --(inout mat2 m)
-{
-   m[0] = m[0] - vec2(1.0);
-   m[1] = m[1] - vec2(1.0);
-   __retVal = m;
-}
-
-mat3 __operator --(inout mat3 m)
-{
-   m[0] = m[0] - vec3(1.0);
-   m[1] = m[1] - vec3(1.0);
-   m[2] = m[2] - vec3(1.0);
-   __retVal = m;
-}
-
-mat4 __operator --(inout mat4 m)
-{
-   m[0] = m[0] - vec4(1.0);
-   m[1] = m[1] - vec4(1.0);
-   m[2] = m[2] - vec4(1.0);
-   m[3] = m[3] - vec4(1.0);
-   __retVal = m;
-}
-
-
-//// pre-increment operators
-
-int __operator ++(inout int a)
-{
-    a = a + 1;
-    __retVal = a;
-}
-
-ivec2 __operator ++(inout ivec2 v)
-{
-   v = v + ivec2(1);
-   __retVal = v;
-}
-
-ivec3 __operator ++(inout ivec3 v)
-{
-   v = v + ivec3(1);
-   __retVal = v;
-}
-
-ivec4 __operator ++(inout ivec4 v)
-{
-   v = v + ivec4(1);
-   __retVal = v;
-}
-
-
-float __operator ++(inout float a)
-{
-    a = a + 1.0;
-    __retVal = a;
-}
-
-vec2 __operator ++(inout vec2 v)
-{
-   v = v + vec2(1.0);
-   __retVal = v;
-}
-
-vec3 __operator ++(inout vec3 v)
-{
-   v = v + vec3(1.0);
-   __retVal = v;
-}
-
-vec4 __operator ++(inout vec4 v)
-{
-   v = v + vec4(1.0);
-   __retVal = v;
-}
-
-
-mat2 __operator ++(inout mat2 m)
-{
-   m[0] = m[0] + vec2(1.0);
-   m[1] = m[1] + vec2(1.0);
-   __retVal = m;
-}
-
-mat3 __operator ++(inout mat3 m)
-{
-   m[0] = m[0] + vec3(1.0);
-   m[1] = m[1] + vec3(1.0);
-   m[2] = m[2] + vec3(1.0);
-   __retVal = m;
-}
-
-mat4 __operator ++(inout mat4 m)
-{
-   m[0] = m[0] + vec4(1.0);
-   m[1] = m[1] + vec4(1.0);
-   m[2] = m[2] + vec4(1.0);
-   m[3] = m[3] + vec4(1.0);
-   __retVal = m;
-}
-
-
-
-//// post-decrement
-
-int __postDecr(inout int a)
-{
-   __retVal = a;
-   a = a - 1;
-}
-
-ivec2 __postDecr(inout ivec2 v)
-{
-   __retVal = v;
-   v = v - ivec2(1);
-}
-
-ivec3 __postDecr(inout ivec3 v)
-{
-   __retVal = v;
-   v = v - ivec3(1);
-}
-
-ivec4 __postDecr(inout ivec4 v)
-{
-   __retVal = v;
-   v = v - ivec4(1);
-}
-
-
-float __postDecr(inout float a)
-{
-   __retVal = a;
-   a = a - 1.0;
-}
-
-vec2 __postDecr(inout vec2 v)
-{
-   __retVal = v;
-   v = v - vec2(1.0);
-}
-
-vec3 __postDecr(inout vec3 v)
-{
-   __retVal = v;
-   v = v - vec3(1.0);
-}
-
-vec4 __postDecr(inout vec4 v)
-{
-   __retVal = v;
-   v = v - vec4(1.0);
-}
-
-
-mat2 __postDecr(inout mat2 m)
-{
-   __retVal = m;
-   m[0] = m[0] - vec2(1.0);
-   m[1] = m[1] - vec2(1.0);
-}
-
-mat3 __postDecr(inout mat3 m)
-{
-   __retVal = m;
-   m[0] = m[0] - vec3(1.0);
-   m[1] = m[1] - vec3(1.0);
-   m[2] = m[2] - vec3(1.0);
-}
-
-mat4 __postDecr(inout mat4 m)
-{
-   __retVal = m;
-   m[0] = m[0] - vec4(1.0);
-   m[1] = m[1] - vec4(1.0);
-   m[2] = m[2] - vec4(1.0);
-   m[3] = m[3] - vec4(1.0);
-}
-
-
-//// post-increment
-
-float __postIncr(inout float a)
-{
-   __retVal = a;
-   a = a + 1;
-}
-
-vec2 __postIncr(inout vec2 v)
-{
-   __retVal = v;
-   v = v + vec2(1.0);
-}
-
-vec3 __postIncr(inout vec3 v)
-{
-   __retVal = v;
-   v = v + vec3(1.0);
-}
-
-vec4 __postIncr(inout vec4 v)
-{
-   __retVal = v;
-   v = v + vec4(1.0);
-}
-
-
-int __postIncr(inout int a)
-{
-   __retVal = a;
-   a = a + 1;
-}
-
-ivec2 __postIncr(inout ivec2 v)
-{
-   __retVal = v;
-   v = v + ivec2(1);
-}
-
-ivec3 __postIncr(inout ivec3 v)
-{
-   __retVal = v;
-   v = v + ivec3(1);
-}
-
-ivec4 __postIncr(inout ivec4 v)
-{
-   __retVal = v;
-   v = v + ivec3(1);
-}
-
-
-mat2 __postIncr(inout mat2 m)
-{
-   mat2 n = m;
-   m[0] = m[0] + vec2(1.0);
-   m[1] = m[1] + vec2(1.0);
-   return n;
-}
-
-mat3 __postIncr(inout mat3 m)
-{
-   mat3 n = m;
-   m[0] = m[0] + vec3(1.0);
-   m[1] = m[1] + vec3(1.0);
-   m[2] = m[2] + vec3(1.0);
-   return n;
-}
-
-mat4 __postIncr(inout mat4 m)
-{
-   mat4 n = m;
-   m[0] = m[0] + vec4(1.0);
-   m[1] = m[1] + vec4(1.0);
-   m[2] = m[2] + vec4(1.0);
-   m[3] = m[3] + vec4(1.0);
-   return n;
-}
-
-
-
-//// inequality operators
-
-
-// XXX are the inequality operators for floats/ints really needed????
-bool __operator < (const float a, const float b)
-{
-   __asm vec4_sgt __retVal.x, b, a;
-}
-
-
-bool __operator < (const int a, const int b) {
-    return float (a) < float (b);
-}
-
-bool __operator > (const float a, const float b) {
-    bool c;
-    __asm float_less c, b, a;
-    return c;
-}
-
-bool __operator > (const int a, const int b) {
-    return float (a) > float (b);
-}
-
-bool __operator >= (const float a, const float b) {
-    bool g, e;
-    __asm float_less  g, b, a;
-    __asm float_equal e, a, b;
-    return g || e;
-}
-
-bool __operator >= (const int a, const int b) {
-    return float (a) >= float (b);
-}
-
-bool __operator <= (const float a, const float b) {
-    bool g, e;
-    __asm float_less  g, a, b;
-    __asm float_equal e, a, b;
-    return g || e;
-}
-
-bool __operator <= (const int a, const int b) {
-    return float (a) <= float (b);
-}
-
-
-
-//
-// MESA-specific extension functions.
-//
-
-void printMESA (const float f) {
-    __asm float_print f;
-}
-
-void printMESA (const int i) {
-    __asm int_print i;
-}
-
-void printMESA (const bool b) {
-    __asm bool_print b;
-}
-
-void printMESA (const vec2 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-}
-
-void printMESA (const vec3 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-    printMESA (v.z);
-}
-
-void printMESA (const vec4 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-    printMESA (v.z);
-    printMESA (v.w);
-}
-
-void printMESA (const ivec2 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-}
-
-void printMESA (const ivec3 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-    printMESA (v.z);
-}
-
-void printMESA (const ivec4 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-    printMESA (v.z);
-    printMESA (v.w);
-}
-
-void printMESA (const bvec2 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-}
-
-void printMESA (const bvec3 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-    printMESA (v.z);
-}
-
-void printMESA (const bvec4 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-    printMESA (v.z);
-    printMESA (v.w);
-}
-
-void printMESA (const mat2 m) {
-    printMESA (m[0]);
-    printMESA (m[1]);
-}
-
-void printMESA (const mat3 m) {
-    printMESA (m[0]);
-    printMESA (m[1]);
-    printMESA (m[2]);
-}
-
-void printMESA (const mat4 m) {
-    printMESA (m[0]);
-    printMESA (m[1]);
-    printMESA (m[2]);
-    printMESA (m[3]);
-}
-
-void printMESA (const sampler1D e) {
-    __asm int_print e;
-}
-
-void printMESA (const sampler2D e) {
-    __asm int_print e;
-}
-
-void printMESA (const sampler3D e) {
-    __asm int_print e;
-}
-
-void printMESA (const samplerCube e) {
-    __asm int_print e;
-}
-
-void printMESA (const sampler1DShadow e) {
-    __asm int_print e;
-}
-
-void printMESA (const sampler2DShadow e) {
-    __asm int_print e;
-}
-
diff --git a/src/mesa/shader/slang/library/slang_fragment_builtin.gc b/src/mesa/shader/slang/library/slang_fragment_builtin.gc
deleted file mode 100644 (file)
index 54a80ea..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// From Shader Spec, ver. 1.10, rev. 59
-//
-
-__fixed_input vec4 gl_FragCoord;
-__fixed_input bool gl_FrontFacing;
-__fixed_output vec4 gl_FragColor;
-__fixed_output vec4 gl_FragData[gl_MaxDrawBuffers];
-__fixed_output float gl_FragDepth;
-
-varying vec4 gl_Color;
-varying vec4 gl_SecondaryColor;
-varying vec4 gl_TexCoord[gl_MaxTextureCoords];
-varying float gl_FogFragCoord;
-
-
-
-//// 8.7 Texture Lookup Functions (with bias)
-
-vec4 texture1D(const sampler1D sampler, const float coord, const float bias)
-{
-   vec4 coord4;
-   coord4.x = coord;
-   coord4.w = bias;
-   __asm vec4_tex_1d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture1DProj(const sampler1D sampler, const vec2 coord, const float bias)
-{
-   // do projection here (there's no vec4_texbp1d instruction)
-   vec4 pcoord;
-   pcoord.x = coord.x / coord.y;
-   pcoord.w = bias;
-   __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
-}
-
-vec4 texture1DProj(const sampler1D sampler, const vec4 coord, const float bias)
-{
-   // do projection here (there's no vec4_texbp1d instruction)
-   vec4 pcoord;
-   pcoord.x = coord.x / coord.z;
-   pcoord.w = bias;
-   __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
-}
-
-
-
-
-vec4 texture2D(const sampler2D sampler, const vec2 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xy = coord.xy;
-   coord4.w = bias;
-   __asm vec4_tex_2d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture2DProj(const sampler2D sampler, const vec3 coord, const float bias)
-{
-   // do projection here (there's no vec4_texbp2d instruction)
-   vec4 pcoord;
-   pcoord.xy = coord.xy / coord.z;
-   pcoord.w = bias;
-   __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
-}
-
-vec4 texture2DProj(const sampler2D sampler, const vec4 coord, const float bias)
-{
-   // do projection here (there's no vec4_texbp2d instruction)
-   vec4 pcoord;
-   pcoord.xy = coord.xy / coord.w;
-   pcoord.w = bias;
-   __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
-}
-
-
-
-
-vec4 texture3D(const sampler3D sampler, const vec3 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xyz = coord.xyz;
-   coord4.w = bias;
-   __asm vec4_tex_3d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture3DProj(const sampler3D sampler, const vec4 coord, const float bias)
-{
-   // do projection here (there's no vec4_texbp3d instruction)
-   vec4 pcoord;
-   pcoord.xyz = coord.xyz / coord.w;
-   pcoord.w = bias;
-   __asm vec4_tex_3d_bias __retVal, sampler, pcoord;
-}
-
-
-
-
-vec4 textureCube(const samplerCube sampler, const vec3 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = bias;
-   __asm vec4_tex_cube __retVal, sampler, coord4;
-}
-
-
-
-vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = bias;
-   __asm vec4_tex_1d_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord, const float bias)
-{
-   vec4 pcoord;
-   pcoord.x = coord.x / coord.w;
-   pcoord.z = coord.z;
-   pcoord.w = bias;
-   __asm vec4_tex_1d_bias_shadow __retVal, sampler, pcoord;
-}
-
-vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = bias;
-   __asm vec4_tex_2d_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord, const float bias)
-{
-   vec4 pcoord;
-   pcoord.xy = coord.xy / coord.w;
-   pcoord.z = coord.z;
-   pcoord.w = bias;
-   __asm vec4_tex_2d_bias_shadow __retVal, sampler, pcoord;
-}
-
-
-
-//// GL_EXT_texture_array
-
-vec4 texture1DArray(const sampler1DArray sampler, const vec2 coord)
-{
-   vec4 coord4;
-   coord4.xy = coord;
-   __asm vec4_tex_1d_array __retVal, sampler, coord4;
-}
-
-vec4 texture1DArray(const sampler1DArray sampler, const vec2 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xy = coord;
-   coord4.w = bias;
-   __asm vec4_tex_1d_array_bias __retVal, sampler, coord4;
-}
-
-vec4 texure2DArray(const sampler2DArray sampler, const vec3 coord)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   __asm vec4_tex_2d_array __retVal, sampler, coord4;
-}
-
-vec4 texture2DArray(const sampler2DArray sampler, const vec3 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = bias;
-   __asm vec4_tex_2d_array_bias __retVal, sampler, coord4;
-}
-
-vec4 shadow1DArray(const sampler1DArrayShadow sampler, const vec2 coord)
-{
-   vec4 coord4;
-   coord4.xy = coord;
-   __asm vec4_tex_1d_array_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow1DArray(const sampler1DArrayShadow sampler, const vec2 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xy = coord;
-   coord4.w = bias;
-   __asm vec4_tex_1d_array_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow2DArray(const sampler2DArrayShadow sampler, const vec3 coord)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   __asm vec4_tex_2d_array_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow2DArray(const sampler2DArrayShadow sampler, const vec3 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = bias;
-   __asm vec4_tex_2d_array_bias_shadow __retVal, sampler, coord4;
-}
-
-
-
-//
-// 8.8 Fragment Processing Functions
-//
-
-float dFdx(const float p)
-{
-   __asm vec4_ddx __retVal.x, p.xxxx;
-}
-
-vec2 dFdx(const vec2 p)
-{
-   __asm vec4_ddx __retVal.xy, p.xyyy;
-}
-
-vec3 dFdx(const vec3 p)
-{
-   __asm vec4_ddx __retVal.xyz, p.xyzz;
-}
-
-vec4 dFdx(const vec4 p)
-{
-   __asm vec4_ddx __retVal, p;
-}
-
-float dFdy(const float p)
-{
-   __asm vec4_ddy __retVal.x, p.xxxx;
-}
-
-vec2 dFdy(const vec2 p)
-{
-   __asm vec4_ddy __retVal.xy, p.xyyy;
-}
-
-vec3 dFdy(const vec3 p)
-{
-   __asm vec4_ddy __retVal.xyz, p.xyzz;
-}
-
-vec4 dFdy(const vec4 p)
-{
-   __asm vec4_ddy __retVal, p;
-}
-
-float fwidth (const float p)
-{
-   // XXX hand-write with __asm
-   return abs(dFdx(p)) + abs(dFdy(p));
-}
-
-vec2 fwidth(const vec2 p)
-{
-   // XXX hand-write with __asm
-   return abs(dFdx(p)) + abs(dFdy(p));
-}
-
-vec3 fwidth(const vec3 p)
-{
-   // XXX hand-write with __asm
-   return abs(dFdx(p)) + abs(dFdy(p));
-}
-
-vec4 fwidth(const vec4 p)
-{
-   // XXX hand-write with __asm
-   return abs(dFdx(p)) + abs(dFdy(p));
-}
-
diff --git a/src/mesa/shader/slang/library/slang_vertex_builtin.gc b/src/mesa/shader/slang/library/slang_vertex_builtin.gc
deleted file mode 100644 (file)
index 0c67c2e..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// From Shader Spec, ver. 1.10, rev. 59
-//
-
-__fixed_output vec4 gl_Position;
-__fixed_output float gl_PointSize;
-__fixed_output vec4 gl_ClipVertex;
-
-attribute vec4 gl_Color;
-attribute vec4 gl_SecondaryColor;
-attribute vec3 gl_Normal;
-attribute vec4 gl_Vertex;
-attribute vec4 gl_MultiTexCoord0;
-attribute vec4 gl_MultiTexCoord1;
-attribute vec4 gl_MultiTexCoord2;
-attribute vec4 gl_MultiTexCoord3;
-attribute vec4 gl_MultiTexCoord4;
-attribute vec4 gl_MultiTexCoord5;
-attribute vec4 gl_MultiTexCoord6;
-attribute vec4 gl_MultiTexCoord7;
-attribute float gl_FogCoord;
-
-varying vec4 gl_FrontColor;
-varying vec4 gl_BackColor;
-varying vec4 gl_FrontSecondaryColor;
-varying vec4 gl_BackSecondaryColor;
-varying vec4 gl_TexCoord[gl_MaxTextureCoords];
-varying float gl_FogFragCoord;
-
-//
-// Geometric Functions
-//
-
-vec4 ftransform()
-{
-   __retVal = gl_ModelViewProjectionMatrix[0] * gl_Vertex.xxxx
-            + gl_ModelViewProjectionMatrix[1] * gl_Vertex.yyyy
-            + gl_ModelViewProjectionMatrix[2] * gl_Vertex.zzzz
-            + gl_ModelViewProjectionMatrix[3] * gl_Vertex.wwww;
-}
-
-
-
-//
-// 8.7 Texture Lookup Functions
-// These are pretty much identical to the ones in slang_fragment_builtin.gc
-// When used in a vertex program, the texture sample instructions should not
-// be using a LOD term so it's effectively zero.  Adding 'lod' to that does
-// what we want.
-//
-
-vec4 texture1DLod(const sampler1D sampler, const float coord, const float lod)
-{
-   vec4 coord4;
-   coord4.x = coord;
-   coord4.w = lod;
-   __asm vec4_tex_1d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture1DProjLod(const sampler1D sampler, const vec2 coord, const float lod)
-{
-   vec4 pcoord;
-   pcoord.x = coord.x / coord.y;
-   pcoord.w = lod;
-   __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
-}
-
-vec4 texture1DProjLod(const sampler1D sampler, const vec4 coord, const float lod)
-{
-   vec4 pcoord;
-   pcoord.x = coord.x / coord.z;
-   pcoord.w = lod;
-   __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
-}
-
-
-
-vec4 texture2DLod(const sampler2D sampler, const vec2 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xy = coord.xy;
-   coord4.w = lod;
-   __asm vec4_tex_2d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture2DProjLod(const sampler2D sampler, const vec3 coord, const float lod)
-{
-   vec4 pcoord;
-   pcoord.xy = coord.xy / coord.z;
-   pcoord.w = lod;
-   __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
-}
-
-vec4 texture2DProjLod(const sampler2D sampler, const vec4 coord, const float lod)
-{
-   vec4 pcoord;
-   pcoord.xy = coord.xy / coord.z;
-   pcoord.w = lod;
-   __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
-}
-
-
-vec4 texture3DLod(const sampler3D sampler, const vec3 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xyz = coord.xyz;
-   coord4.w = lod;
-   __asm vec4_tex_3d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture3DProjLod(const sampler3D sampler, const vec4 coord, const float lod)
-{
-   // do projection here (there's no vec4_tex_3d_bias_proj instruction)
-   vec4 pcoord;
-   pcoord.xyz = coord.xyz / coord.w;
-   pcoord.w = lod;
-   __asm vec4_tex_3d_bias __retVal, sampler, pcoord;
-}
-
-
-vec4 textureCubeLod(const samplerCube sampler, const vec3 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = lod;
-   __asm vec4_tex_cube __retVal, sampler, coord4;
-}
-
-
-vec4 shadow1DLod(const sampler1DShadow sampler, const vec3 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = lod;
-   __asm vec4_tex_1d_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow1DProjLod(const sampler1DShadow sampler, const vec4 coord,
-                     const float lod)
-{
-   vec4 pcoord;
-   pcoord.x = coord.x / coord.w;
-   pcoord.z = coord.z;
-   pcoord.w = lod;
-   __asm vec4_tex_1d_bias_shadow __retVal, sampler, pcoord;
-}
-
-
-vec4 shadow2DLod(const sampler2DShadow sampler, const vec3 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = lod;
-   __asm vec4_tex_2d_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow2DProjLod(const sampler2DShadow sampler, const vec4 coord,
-                     const float lod)
-{
-   vec4 pcoord;
-   pcoord.xy = coord.xy / coord.w;
-   pcoord.z = coord.z;
-   pcoord.w = lod;
-   __asm vec4_tex_2d_bias_shadow __retVal, sampler, pcoord;
-}
-
-
-//// GL_EXT_texture_array
-
-vec4 texture1DArrayLod(const sampler1DArray sampler, const vec2 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xy = coord;
-   coord4.w = lod;
-   __asm vec4_tex_1d_array_bias __retVal, sampler, coord4;
-}
-
-
-vec4 texture2DArrayLod(const sampler2DArray sampler, const vec3 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = lod;
-   __asm vec4_tex_2d_array_bias __retVal, sampler, coord4;
-}
-
diff --git a/src/mesa/shader/slang/slang_builtin.c b/src/mesa/shader/slang/slang_builtin.c
deleted file mode 100644 (file)
index b7bf4e0..0000000
+++ /dev/null
@@ -1,937 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.3
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- * Copyright (C) 2008  VMware, Inc.   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_builtin.c
- * Resolve built-in uniform vars.
- * \author Brian Paul
- */
-
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "shader/program.h"
-#include "shader/prog_instruction.h"
-#include "shader/prog_parameter.h"
-#include "shader/prog_statevars.h"
-#include "shader/slang/slang_ir.h"
-#include "shader/slang/slang_builtin.h"
-
-
-/** special state token (see below) */
-#define STATE_ARRAY ((gl_state_index) 0xfffff)
-
-
-/**
- * Lookup GL state given a variable name, 0, 1 or 2 indexes and a field.
- * Allocate room for the state in the given param list and return position
- * in the list.
- * Yes, this is kind of ugly, but it works.
- */
-static GLint
-lookup_statevar(const char *var, GLint index1, GLint index2, const char *field,
-                GLuint *swizzleOut,
-                struct gl_program_parameter_list *paramList)
-{
-   /*
-    * NOTE: The ARB_vertex_program extension specified that matrices get
-    * loaded in registers in row-major order.  With GLSL, we want column-
-    * major order.  So, we need to transpose all matrices here...
-    */
-   static const struct {
-      const char *name;
-      gl_state_index matrix;
-      gl_state_index modifier;
-   } matrices[] = {
-      { "gl_ModelViewMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE },
-      { "gl_ModelViewMatrixInverse", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS },
-      { "gl_ModelViewMatrixTranspose", STATE_MODELVIEW_MATRIX, 0 },
-      { "gl_ModelViewMatrixInverseTranspose", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
-
-      { "gl_ProjectionMatrix", STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE },
-      { "gl_ProjectionMatrixInverse", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS },
-      { "gl_ProjectionMatrixTranspose", STATE_PROJECTION_MATRIX, 0 },
-      { "gl_ProjectionMatrixInverseTranspose", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE },
-
-      { "gl_ModelViewProjectionMatrix", STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE },
-      { "gl_ModelViewProjectionMatrixInverse", STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS },
-      { "gl_ModelViewProjectionMatrixTranspose", STATE_MVP_MATRIX, 0 },
-      { "gl_ModelViewProjectionMatrixInverseTranspose", STATE_MVP_MATRIX, STATE_MATRIX_INVERSE },
-
-      { "gl_TextureMatrix", STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE },
-      { "gl_TextureMatrixInverse", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS },
-      { "gl_TextureMatrixTranspose", STATE_TEXTURE_MATRIX, 0 },
-      { "gl_TextureMatrixInverseTranspose", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE },
-
-      { "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
-
-      { NULL, 0, 0 }
-   };
-   gl_state_index tokens[STATE_LENGTH];
-   GLuint i;
-   GLboolean isMatrix = GL_FALSE;
-
-   for (i = 0; i < STATE_LENGTH; i++) {
-      tokens[i] = 0;
-   }
-   *swizzleOut = SWIZZLE_NOOP;
-
-   /* first, look if var is a pre-defined matrix */
-   for (i = 0; matrices[i].name; i++) {
-      if (strcmp(var, matrices[i].name) == 0) {
-         tokens[0] = matrices[i].matrix;
-         /* tokens[1], [2] and [3] filled below */
-         tokens[4] = matrices[i].modifier;
-         isMatrix = GL_TRUE;
-         break;
-      }
-   }
-
-   if (isMatrix) {
-      if (tokens[0] == STATE_TEXTURE_MATRIX) {
-         /* texture_matrix[index1][index2] */
-         tokens[1] = index1 >= 0 ? index1 : 0; /* which texture matrix */
-         index1 = index2; /* move matrix row value to index1 */
-      }
-      if (index1 < 0) {
-         /* index1 is unused: prevent extra addition at end of function */
-         index1 = 0;
-      }
-   }
-   else if (strcmp(var, "gl_DepthRange") == 0) {
-      tokens[0] = STATE_DEPTH_RANGE;
-      assert(field);
-      if (strcmp(field, "near") == 0) {
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else if (strcmp(field, "far") == 0) {
-         *swizzleOut = SWIZZLE_YYYY;
-      }
-      else if (strcmp(field, "diff") == 0) {
-         *swizzleOut = SWIZZLE_ZZZZ;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_ClipPlane") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_CLIPPLANE;
-      tokens[1] = index1;
-   }
-   else if (strcmp(var, "gl_Point") == 0) {
-      assert(field);
-      if (strcmp(field, "size") == 0) {
-         tokens[0] = STATE_POINT_SIZE;
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else if (strcmp(field, "sizeMin") == 0) {
-         tokens[0] = STATE_POINT_SIZE;
-         *swizzleOut = SWIZZLE_YYYY;
-      }
-      else if (strcmp(field, "sizeMax") == 0) {
-         tokens[0] = STATE_POINT_SIZE;
-         *swizzleOut = SWIZZLE_ZZZZ;
-      }
-      else if (strcmp(field, "fadeThresholdSize") == 0) {
-         tokens[0] = STATE_POINT_SIZE;
-         *swizzleOut = SWIZZLE_WWWW;
-      }
-      else if (strcmp(field, "distanceConstantAttenuation") == 0) {
-         tokens[0] = STATE_POINT_ATTENUATION;
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else if (strcmp(field, "distanceLinearAttenuation") == 0) {
-         tokens[0] = STATE_POINT_ATTENUATION;
-         *swizzleOut = SWIZZLE_YYYY;
-      }
-      else if (strcmp(field, "distanceQuadraticAttenuation") == 0) {
-         tokens[0] = STATE_POINT_ATTENUATION;
-         *swizzleOut = SWIZZLE_ZZZZ;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_FrontMaterial") == 0 ||
-            strcmp(var, "gl_BackMaterial") == 0) {
-      tokens[0] = STATE_MATERIAL;
-      if (strcmp(var, "gl_FrontMaterial") == 0)
-         tokens[1] = 0;
-      else
-         tokens[1] = 1;
-      assert(field);
-      if (strcmp(field, "emission") == 0) {
-         tokens[2] = STATE_EMISSION;
-      }
-      else if (strcmp(field, "ambient") == 0) {
-         tokens[2] = STATE_AMBIENT;
-      }
-      else if (strcmp(field, "diffuse") == 0) {
-         tokens[2] = STATE_DIFFUSE;
-      }
-      else if (strcmp(field, "specular") == 0) {
-         tokens[2] = STATE_SPECULAR;
-      }
-      else if (strcmp(field, "shininess") == 0) {
-         tokens[2] = STATE_SHININESS;
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_LightSource") == 0) {
-      if (!field || index1 < 0)
-         return -1;
-
-      tokens[0] = STATE_LIGHT;
-      tokens[1] = index1;
-
-      if (strcmp(field, "ambient") == 0) {
-         tokens[2] = STATE_AMBIENT;
-      }
-      else if (strcmp(field, "diffuse") == 0) {
-         tokens[2] = STATE_DIFFUSE;
-      }
-      else if (strcmp(field, "specular") == 0) {
-         tokens[2] = STATE_SPECULAR;
-      }
-      else if (strcmp(field, "position") == 0) {
-         tokens[2] = STATE_POSITION;
-      }
-      else if (strcmp(field, "halfVector") == 0) {
-         tokens[2] = STATE_HALF_VECTOR;
-      }
-      else if (strcmp(field, "spotDirection") == 0) {
-         tokens[2] = STATE_SPOT_DIRECTION;
-      }
-      else if (strcmp(field, "spotCosCutoff") == 0) {
-         tokens[2] = STATE_SPOT_DIRECTION;
-         *swizzleOut = SWIZZLE_WWWW;
-      }
-      else if (strcmp(field, "spotCutoff") == 0) {
-         tokens[2] = STATE_SPOT_CUTOFF;
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else if (strcmp(field, "spotExponent") == 0) {
-         tokens[2] = STATE_ATTENUATION;
-         *swizzleOut = SWIZZLE_WWWW;
-      }
-      else if (strcmp(field, "constantAttenuation") == 0) {
-         tokens[2] = STATE_ATTENUATION;
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else if (strcmp(field, "linearAttenuation") == 0) {
-         tokens[2] = STATE_ATTENUATION;
-         *swizzleOut = SWIZZLE_YYYY;
-      }
-      else if (strcmp(field, "quadraticAttenuation") == 0) {
-         tokens[2] = STATE_ATTENUATION;
-         *swizzleOut = SWIZZLE_ZZZZ;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_LightModel") == 0) {
-      if (strcmp(field, "ambient") == 0) {
-         tokens[0] = STATE_LIGHTMODEL_AMBIENT;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_FrontLightModelProduct") == 0) {
-      if (strcmp(field, "sceneColor") == 0) {
-         tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
-         tokens[1] = 0;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_BackLightModelProduct") == 0) {
-      if (strcmp(field, "sceneColor") == 0) {
-         tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
-         tokens[1] = 1;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_FrontLightProduct") == 0 ||
-            strcmp(var, "gl_BackLightProduct") == 0) {
-      if (index1 < 0 || !field)
-         return -1;
-
-      tokens[0] = STATE_LIGHTPROD;
-      tokens[1] = index1; /* light number */
-      if (strcmp(var, "gl_FrontLightProduct") == 0) {
-         tokens[2] = 0; /* front */
-      }
-      else {
-         tokens[2] = 1; /* back */
-      }
-      if (strcmp(field, "ambient") == 0) {
-         tokens[3] = STATE_AMBIENT;
-      }
-      else if (strcmp(field, "diffuse") == 0) {
-         tokens[3] = STATE_DIFFUSE;
-      }
-      else if (strcmp(field, "specular") == 0) {
-         tokens[3] = STATE_SPECULAR;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_TextureEnvColor") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXENV_COLOR;
-      tokens[1] = index1;
-   }
-   else if (strcmp(var, "gl_EyePlaneS") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_EYE_S;
-   }
-   else if (strcmp(var, "gl_EyePlaneT") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_EYE_T;
-   }
-   else if (strcmp(var, "gl_EyePlaneR") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_EYE_R;
-   }
-   else if (strcmp(var, "gl_EyePlaneQ") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_EYE_Q;
-   }
-   else if (strcmp(var, "gl_ObjectPlaneS") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_OBJECT_S;
-   }
-   else if (strcmp(var, "gl_ObjectPlaneT") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_OBJECT_T;
-   }
-   else if (strcmp(var, "gl_ObjectPlaneR") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_OBJECT_R;
-   }
-   else if (strcmp(var, "gl_ObjectPlaneQ") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_OBJECT_Q;
-   }
-   else if (strcmp(var, "gl_Fog") == 0) {
-      if (strcmp(field, "color") == 0) {
-         tokens[0] = STATE_FOG_COLOR;
-      }
-      else if (strcmp(field, "density") == 0) {
-         tokens[0] = STATE_FOG_PARAMS;
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else if (strcmp(field, "start") == 0) {
-         tokens[0] = STATE_FOG_PARAMS;
-         *swizzleOut = SWIZZLE_YYYY;
-      }
-      else if (strcmp(field, "end") == 0) {
-         tokens[0] = STATE_FOG_PARAMS;
-         *swizzleOut = SWIZZLE_ZZZZ;
-      }
-      else if (strcmp(field, "scale") == 0) {
-         tokens[0] = STATE_FOG_PARAMS;
-         *swizzleOut = SWIZZLE_WWWW;
-      }
-      else {
-         return -1;
-      }
-   }
-   else {
-      return -1;
-   }
-
-   if (isMatrix) {
-      /* load all four columns of matrix */
-      GLint pos[4];
-      GLuint j;
-      for (j = 0; j < 4; j++) {
-         tokens[2] = tokens[3] = j; /* jth row of matrix */
-         pos[j] = _mesa_add_state_reference(paramList, tokens);
-         assert(pos[j] >= 0);
-         ASSERT(pos[j] >= 0);
-      }
-      return pos[0] + index1;
-   }
-   else {
-      /* allocate a single register */
-      GLint pos = _mesa_add_state_reference(paramList, tokens);
-      ASSERT(pos >= 0);
-      return pos;
-   }
-}
-
-
-
-/**
- * Given a variable name and datatype, emit uniform/constant buffer
- * entries which will store that state variable.
- * For example, if name="gl_LightSource" we'll emit 64 state variable
- * vectors/references and return position where that data starts.  This will
- * allow run-time array indexing into the light source array.
- *
- * Note that this is a recursive function.
- *
- * \return -1 if error, else index of start of data in the program parameter list
- */
-static GLint
-emit_statevars(const char *name, int array_len,
-               const slang_type_specifier *type,
-               gl_state_index tokens[STATE_LENGTH],
-               struct gl_program_parameter_list *paramList)
-{
-   if (type->type == SLANG_SPEC_ARRAY) {
-      GLint i, pos = -1;
-      assert(array_len > 0);
-      if (strcmp(name, "gl_ClipPlane") == 0) {
-         tokens[0] = STATE_CLIPPLANE;
-      }
-      else if (strcmp(name, "gl_LightSource") == 0) {
-         tokens[0] = STATE_LIGHT;
-      }
-      else if (strcmp(name, "gl_FrontLightProduct") == 0) {
-         tokens[0] = STATE_LIGHTPROD;
-         tokens[2] = 0; /* front */
-      }
-      else if (strcmp(name, "gl_BackLightProduct") == 0) {
-         tokens[0] = STATE_LIGHTPROD;
-         tokens[2] = 1; /* back */
-      }
-      else if (strcmp(name, "gl_TextureEnvColor") == 0) {
-         tokens[0] = STATE_TEXENV_COLOR;
-      }
-      else if (strcmp(name, "gl_EyePlaneS") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_EYE_S;
-      }
-      else if (strcmp(name, "gl_EyePlaneT") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_EYE_T;
-      }
-      else if (strcmp(name, "gl_EyePlaneR") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_EYE_R;
-      }
-      else if (strcmp(name, "gl_EyePlaneQ") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_EYE_Q;
-      }
-      else if (strcmp(name, "gl_ObjectPlaneS") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_OBJECT_S;
-      }
-      else if (strcmp(name, "gl_ObjectPlaneT") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_OBJECT_T;
-      }
-      else if (strcmp(name, "gl_ObjectPlaneR") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_OBJECT_R;
-      }
-      else if (strcmp(name, "gl_ObjectPlaneQ") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_OBJECT_Q;
-      }
-      else {
-         return -1; /* invalid array name */
-      }
-      for (i = 0; i < array_len; i++) {
-         GLint p;
-         tokens[1] = i;
-         p = emit_statevars(NULL, 0, type->_array, tokens, paramList);
-         if (i == 0)
-            pos = p;
-      }
-      return pos;
-   }
-   else if (type->type == SLANG_SPEC_STRUCT) {
-      const slang_variable_scope *fields = type->_struct->fields;
-      GLuint i, pos = 0;
-      for (i = 0; i < fields->num_variables; i++) {
-         const slang_variable *var = fields->variables[i];
-         GLint p = emit_statevars(var->a_name, 0, &var->type.specifier,
-                                  tokens, paramList);
-         if (i == 0)
-            pos = p;
-      }
-      return pos;
-   }
-   else {
-      GLint pos;
-      assert(type->type == SLANG_SPEC_VEC4 ||
-             type->type == SLANG_SPEC_VEC3 ||
-             type->type == SLANG_SPEC_VEC2 ||
-             type->type == SLANG_SPEC_FLOAT ||
-             type->type == SLANG_SPEC_IVEC4 ||
-             type->type == SLANG_SPEC_IVEC3 ||
-             type->type == SLANG_SPEC_IVEC2 ||
-             type->type == SLANG_SPEC_INT);
-      if (name) {
-         GLint t;
-
-         if (tokens[0] == STATE_LIGHT)
-            t = 2;
-         else if (tokens[0] == STATE_LIGHTPROD)
-            t = 3;
-         else
-            return -1; /* invalid array name */
-
-         if (strcmp(name, "ambient") == 0) {
-            tokens[t] = STATE_AMBIENT;
-         }
-         else if (strcmp(name, "diffuse") == 0) {
-            tokens[t] = STATE_DIFFUSE;
-         }
-         else if (strcmp(name, "specular") == 0) {
-            tokens[t] = STATE_SPECULAR;
-         }
-         else if (strcmp(name, "position") == 0) {
-            tokens[t] = STATE_POSITION;
-         }
-         else if (strcmp(name, "halfVector") == 0) {
-            tokens[t] = STATE_HALF_VECTOR;
-         }
-         else if (strcmp(name, "spotDirection") == 0) {
-            tokens[t] = STATE_SPOT_DIRECTION; /* xyz components */
-         }
-         else if (strcmp(name, "spotCosCutoff") == 0) {
-            tokens[t] = STATE_SPOT_DIRECTION; /* w component */
-         }
-
-         else if (strcmp(name, "constantAttenuation") == 0) {
-            tokens[t] = STATE_ATTENUATION; /* x component */
-         }
-         else if (strcmp(name, "linearAttenuation") == 0) {
-            tokens[t] = STATE_ATTENUATION; /* y component */
-         }
-         else if (strcmp(name, "quadraticAttenuation") == 0) {
-            tokens[t] = STATE_ATTENUATION; /* z component */
-         }
-         else if (strcmp(name, "spotExponent") == 0) {
-            tokens[t] = STATE_ATTENUATION; /* w = spot exponent */
-         }
-
-         else if (strcmp(name, "spotCutoff") == 0) {
-            tokens[t] = STATE_SPOT_CUTOFF; /* x component */
-         }
-
-         else {
-            return -1; /* invalid field name */
-         }
-      }
-
-      pos = _mesa_add_state_reference(paramList, tokens);
-      return pos;
-   }
-
-   return 1;
-}
-
-
-/**
- * Unroll the named built-in uniform variable into a sequence of state
- * vars in the given parameter list.
- */
-static GLint
-alloc_state_var_array(const slang_variable *var,
-                      struct gl_program_parameter_list *paramList)
-{
-   gl_state_index tokens[STATE_LENGTH];
-   GLuint i;
-   GLint pos;
-
-   /* Initialize the state tokens array.  This is very important.
-    * When we call _mesa_add_state_reference() it'll searches the parameter
-    * list to see if the given statevar token sequence is already present.
-    * This is normally a good thing since it prevents redundant values in the
-    * constant buffer.
-    *
-    * But when we're building arrays of state this can be bad.  For example,
-    * consider this fragment of GLSL code:
-    *   foo = gl_LightSource[3].diffuse;
-    *   ...
-    *   bar = gl_LightSource[i].diffuse;
-    *
-    * When we unroll the gl_LightSource array (for "bar") we want to re-emit
-    * gl_LightSource[3].diffuse and not re-use the first instance (from "foo")
-    * since that would upset the array layout.  We handle this situation by
-    * setting the last token in the state var token array to the special
-    * value STATE_ARRAY.
-    * This token will only be set for array state.  We can hijack the last
-    * element in the array for this since it's never used for light, clipplane
-    * or texture env array state.
-    */
-   for (i = 0; i < STATE_LENGTH; i++)
-      tokens[i] = 0;
-   tokens[STATE_LENGTH - 1] = STATE_ARRAY;
-
-   pos = emit_statevars(var->a_name, var->array_len, &var->type.specifier,
-                        tokens, paramList);
-
-   return pos;
-}
-
-
-
-/**
- * Allocate storage for a pre-defined uniform (a GL state variable).
- * As a memory-saving optimization, we try to only allocate storage for
- * state vars that are actually used.
- *
- * Arrays such as gl_LightSource are handled specially.  For an expression
- * like "gl_LightSource[2].diffuse", we can allocate a single uniform/constant
- * slot and return the index.  In this case, we return direct=TRUE.
- *
- * Buf for something like "gl_LightSource[i].diffuse" we don't know the value
- * of 'i' at compile time so we need to "unroll" the gl_LightSource array
- * into a consecutive sequence of uniform/constant slots so it can be indexed
- * at runtime.  In this case, we return direct=FALSE.
- *
- * Currently, all pre-defined uniforms are in one of these forms:
- *   var
- *   var[i]
- *   var.field
- *   var[i].field
- *   var[i][j]
- *
- * \return -1 upon error, else position in paramList of the state variable/data
- */
-GLint
-_slang_alloc_statevar(slang_ir_node *n,
-                      struct gl_program_parameter_list *paramList,
-                      GLboolean *direct)
-{
-   slang_ir_node *n0 = n;
-   const char *field = NULL;
-   GLint index1 = -1, index2 = -1;
-   GLuint swizzle;
-
-   *direct = GL_TRUE;
-
-   if (n->Opcode == IR_FIELD) {
-      field = n->Field;
-      n = n->Children[0];
-   }
-
-   if (n->Opcode == IR_ELEMENT) {
-      if (n->Children[1]->Opcode == IR_FLOAT) {
-         index1 = (GLint) n->Children[1]->Value[0];
-      }
-      else {
-         *direct = GL_FALSE;
-      }
-      n = n->Children[0];
-   }
-
-   if (n->Opcode == IR_ELEMENT) {
-      /* XXX can only handle constant indexes for now */
-      if (n->Children[1]->Opcode == IR_FLOAT) {
-         /* two-dimensional array index: mat[i][j] */
-         index2 = index1;
-         index1 = (GLint) n->Children[1]->Value[0];
-      }
-      else {
-         *direct = GL_FALSE;
-      }
-      n = n->Children[0];
-   }
-
-   assert(n->Opcode == IR_VAR);
-
-   if (*direct) {
-      const char *var = (const char *) n->Var->a_name;
-      GLint pos =
-         lookup_statevar(var, index1, index2, field, &swizzle, paramList);
-      if (pos >= 0) {
-         /* newly resolved storage for the statevar/constant/uniform */
-         n0->Store->File = PROGRAM_STATE_VAR;
-         n0->Store->Index = pos;
-         n0->Store->Swizzle = swizzle;
-         n0->Store->Parent = NULL;
-         return pos;
-      }
-   }
-
-   *direct = GL_FALSE;
-   return alloc_state_var_array(n->Var, paramList);
-}
-
-
-
-
-#define SWIZZLE_ZWWW MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W)
-
-
-/** Predefined shader inputs */
-struct input_info
-{
-   const char *Name;
-   GLuint Attrib;
-   GLenum Type;
-   GLuint Swizzle;
-};
-
-/** Predefined vertex shader inputs/attributes */
-static const struct input_info vertInputs[] = {
-   { "gl_Vertex", VERT_ATTRIB_POS, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_Normal", VERT_ATTRIB_NORMAL, GL_FLOAT_VEC3, SWIZZLE_NOOP },
-   { "gl_Color", VERT_ATTRIB_COLOR0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_SecondaryColor", VERT_ATTRIB_COLOR1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_FogCoord", VERT_ATTRIB_FOG, GL_FLOAT, SWIZZLE_XXXX },
-   { "gl_MultiTexCoord0", VERT_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_MultiTexCoord1", VERT_ATTRIB_TEX1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_MultiTexCoord2", VERT_ATTRIB_TEX2, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_MultiTexCoord3", VERT_ATTRIB_TEX3, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_MultiTexCoord4", VERT_ATTRIB_TEX4, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_MultiTexCoord5", VERT_ATTRIB_TEX5, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_MultiTexCoord6", VERT_ATTRIB_TEX6, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_MultiTexCoord7", VERT_ATTRIB_TEX7, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { NULL, 0, GL_NONE, SWIZZLE_NOOP }
-};
-
-/** Predefined fragment shader inputs */
-static const struct input_info fragInputs[] = {
-   { "gl_FragCoord", FRAG_ATTRIB_WPOS, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_Color", FRAG_ATTRIB_COL0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_SecondaryColor", FRAG_ATTRIB_COL1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_TexCoord", FRAG_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
-   { "gl_FogFragCoord", FRAG_ATTRIB_FOGC, GL_FLOAT, SWIZZLE_XXXX },
-   { "gl_FrontFacing", FRAG_ATTRIB_FACE, GL_FLOAT, SWIZZLE_XXXX },
-   { "gl_PointCoord", FRAG_ATTRIB_PNTC, GL_FLOAT_VEC2, SWIZZLE_XYZW },
-   { NULL, 0, GL_NONE, SWIZZLE_NOOP }
-};
-
-
-/**
- * Return the VERT_ATTRIB_* or FRAG_ATTRIB_* value that corresponds to
- * a vertex or fragment program input variable.  Return -1 if the input
- * name is invalid.
- * XXX return size too
- */
-GLint
-_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut)
-{
-   const struct input_info *inputs;
-   GLuint i;
-
-   switch (target) {
-   case GL_VERTEX_PROGRAM_ARB:
-      inputs = vertInputs;
-      break;
-   case GL_FRAGMENT_PROGRAM_ARB:
-      inputs = fragInputs;
-      break;
-   /* XXX geom program */
-   default:
-      _mesa_problem(NULL, "bad target in _slang_input_index");
-      return -1;
-   }
-
-   ASSERT(MAX_TEXTURE_COORD_UNITS == 8); /* if this fails, fix vertInputs above */
-
-   for (i = 0; inputs[i].Name; i++) {
-      if (strcmp(inputs[i].Name, name) == 0) {
-         /* found */
-         *swizzleOut = inputs[i].Swizzle;
-         return inputs[i].Attrib;
-      }
-   }
-   return -1;
-}
-
-
-/**
- * Return name of the given vertex attribute (VERT_ATTRIB_x).
- */
-const char *
-_slang_vert_attrib_name(GLuint attrib)
-{
-   GLuint i;
-   assert(attrib < VERT_ATTRIB_GENERIC0);
-   for (i = 0; vertInputs[i].Name; i++) {
-      if (vertInputs[i].Attrib == attrib)
-         return vertInputs[i].Name;
-   }
-   return NULL;
-}
-
-
-/**
- * Return type (GL_FLOAT, GL_FLOAT_VEC2, etc) of the given vertex
- * attribute (VERT_ATTRIB_x).
- */
-GLenum
-_slang_vert_attrib_type(GLuint attrib)
-{
-   GLuint i;
-   assert(attrib < VERT_ATTRIB_GENERIC0);
-   for (i = 0; vertInputs[i].Name; i++) {
-      if (vertInputs[i].Attrib == attrib)
-         return vertInputs[i].Type;
-   }
-   return GL_NONE;
-}
-
-
-
-
-
-/** Predefined shader output info */
-struct output_info
-{
-   const char *Name;
-   GLuint Attrib;
-   GLenum Type;
-};
-
-/** Predefined vertex shader outputs */
-static const struct output_info vertOutputs[] = {
-   { "gl_Position", VERT_RESULT_HPOS, GL_FLOAT_VEC4 },
-   { "gl_FrontColor", VERT_RESULT_COL0, GL_FLOAT_VEC4 },
-   { "gl_BackColor", VERT_RESULT_BFC0, GL_FLOAT_VEC4 },
-   { "gl_FrontSecondaryColor", VERT_RESULT_COL1, GL_FLOAT_VEC4 },
-   { "gl_BackSecondaryColor", VERT_RESULT_BFC1, GL_FLOAT_VEC4 },
-   { "gl_TexCoord", VERT_RESULT_TEX0, GL_FLOAT_VEC4 },
-   { "gl_FogFragCoord", VERT_RESULT_FOGC, GL_FLOAT },
-   { "gl_PointSize", VERT_RESULT_PSIZ, GL_FLOAT },
-   { NULL, 0, GL_NONE }
-};
-
-/** Predefined fragment shader outputs */
-static const struct output_info fragOutputs[] = {
-   { "gl_FragColor", FRAG_RESULT_COLOR, GL_FLOAT_VEC4 },
-   { "gl_FragDepth", FRAG_RESULT_DEPTH, GL_FLOAT },
-   { "gl_FragData", FRAG_RESULT_DATA0, GL_FLOAT_VEC4 },
-   { NULL, 0, GL_NONE }
-};
-
-
-/**
- * Return the VERT_RESULT_* or FRAG_RESULT_* value that corresponds to
- * a vertex or fragment program output variable.  Return -1 for an invalid
- * output name.
- */
-GLint
-_slang_output_index(const char *name, GLenum target)
-{
-   const struct output_info *outputs;
-   GLuint i;
-
-   switch (target) {
-   case GL_VERTEX_PROGRAM_ARB:
-      outputs = vertOutputs;
-      break;
-   case GL_FRAGMENT_PROGRAM_ARB:
-      outputs = fragOutputs;
-      break;
-   /* XXX geom program */
-   default:
-      _mesa_problem(NULL, "bad target in _slang_output_index");
-      return -1;
-   }
-
-   for (i = 0; outputs[i].Name; i++) {
-      if (strcmp(outputs[i].Name, name) == 0) {
-         /* found */
-         return outputs[i].Attrib;
-      }
-   }
-   return -1;
-}
-
-
-/**
- * Given a VERT_RESULT_x index, return the corresponding string name.
- */
-const char *
-_slang_vertex_output_name(gl_vert_result index)
-{
-   if (index < Elements(vertOutputs))
-      return vertOutputs[index].Name;
-   else
-      return NULL;
-}
-
-
-/**
- * Given a FRAG_RESULT_x index, return the corresponding string name.
- */
-const char *
-_slang_fragment_output_name(gl_frag_result index)
-{
-   if (index < Elements(fragOutputs))
-      return fragOutputs[index].Name;
-   else
-      return NULL;
-}
-
-
-/**
- * Given a VERT_RESULT_x index, return the corresponding varying
- * var's datatype.
- */
-GLenum
-_slang_vertex_output_type(gl_vert_result index)
-{
-   if (index < Elements(vertOutputs))
-      return vertOutputs[index].Type;
-   else
-      return GL_NONE;
-}
diff --git a/src/mesa/shader/slang/slang_builtin.h b/src/mesa/shader/slang/slang_builtin.h
deleted file mode 100644 (file)
index c3021ca..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef SLANG_BUILTIN_H
-#define SLANG_BUILTIN_H
-
-#include "shader/prog_parameter.h"
-#include "slang_utility.h"
-#include "slang_ir.h"
-
-
-extern GLint
-_slang_alloc_statevar(slang_ir_node *n,
-                      struct gl_program_parameter_list *paramList,
-                      GLboolean *direct);
-
-
-extern GLint
-_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut);
-
-extern GLint
-_slang_output_index(const char *name, GLenum target);
-
-
-extern const char *
-_slang_vert_attrib_name(GLuint attrib);
-
-extern GLenum
-_slang_vert_attrib_type(GLuint attrib);
-
-
-const char *
-_slang_vertex_output_name(gl_vert_result index);
-
-const char *
-_slang_fragment_output_name(gl_frag_result index);
-
-GLenum
-_slang_vertex_output_type(gl_vert_result index);
-
-
-#endif /* SLANG_BUILTIN_H */
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
deleted file mode 100644 (file)
index 0504d47..0000000
+++ /dev/null
@@ -1,5357 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- * Copyright (C) 2008 VMware, Inc.  All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_codegen.c
- * Generate IR tree from AST.
- * \author Brian Paul
- */
-
-
-/***
- *** NOTES:
- *** The new_() functions return a new instance of a simple IR node.
- *** The gen_() functions generate larger IR trees from the simple nodes.
- ***/
-
-
-
-#include "main/imports.h"
-#include "main/macros.h"
-#include "main/mtypes.h"
-#include "shader/program.h"
-#include "shader/prog_instruction.h"
-#include "shader/prog_parameter.h"
-#include "shader/prog_print.h"
-#include "shader/prog_statevars.h"
-#include "slang_typeinfo.h"
-#include "slang_builtin.h"
-#include "slang_codegen.h"
-#include "slang_compile.h"
-#include "slang_label.h"
-#include "slang_mem.h"
-#include "slang_simplify.h"
-#include "slang_emit.h"
-#include "slang_vartable.h"
-#include "slang_ir.h"
-#include "slang_print.h"
-
-
-/** Max iterations to unroll */
-const GLuint MAX_FOR_LOOP_UNROLL_ITERATIONS = 32;
-
-/** Max for-loop body size (in slang operations) to unroll */
-const GLuint MAX_FOR_LOOP_UNROLL_BODY_SIZE = 50;
-
-/** Max for-loop body complexity to unroll.
- * We'll compute complexity as the product of the number of iterations
- * and the size of the body.  So long-ish loops with very simple bodies
- * can be unrolled, as well as short loops with larger bodies.
- */
-const GLuint MAX_FOR_LOOP_UNROLL_COMPLEXITY = 256;
-
-
-
-static slang_ir_node *
-_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper);
-
-static void
-slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
-                 GLuint substCount, slang_variable **substOld,
-                slang_operation **substNew, GLboolean isLHS);
-
-
-/**
- * Retrieves type information about an operation.
- * Returns GL_TRUE on success.
- * Returns GL_FALSE otherwise.
- */
-static GLboolean
-typeof_operation(const struct slang_assemble_ctx_ *A,
-                 slang_operation *op,
-                 slang_typeinfo *ti)
-{
-   return _slang_typeof_operation(op, &A->space, ti, A->atoms, A->log);
-}
-
-
-static GLboolean
-is_sampler_type(const slang_fully_specified_type *t)
-{
-   switch (t->specifier.type) {
-   case SLANG_SPEC_SAMPLER_1D:
-   case SLANG_SPEC_SAMPLER_2D:
-   case SLANG_SPEC_SAMPLER_3D:
-   case SLANG_SPEC_SAMPLER_CUBE:
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-   case SLANG_SPEC_SAMPLER_RECT:
-   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
-   case SLANG_SPEC_SAMPLER_1D_ARRAY:
-   case SLANG_SPEC_SAMPLER_2D_ARRAY:
-   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
-   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Return the offset (in floats or ints) of the named field within
- * the given struct.  Return -1 if field not found.
- * If field is NULL, return the size of the struct instead.
- */
-static GLint
-_slang_field_offset(const slang_type_specifier *spec, slang_atom field)
-{
-   GLint offset = 0;
-   GLuint i;
-   for (i = 0; i < spec->_struct->fields->num_variables; i++) {
-      const slang_variable *v = spec->_struct->fields->variables[i];
-      const GLuint sz = _slang_sizeof_type_specifier(&v->type.specifier);
-      if (sz > 1) {
-         /* types larger than 1 float are register (4-float) aligned */
-         offset = (offset + 3) & ~3;
-      }
-      if (field && v->a_name == field) {
-         return offset;
-      }
-      offset += sz;
-   }
-   if (field)
-      return -1; /* field not found */
-   else
-      return offset;  /* struct size */
-}
-
-
-/**
- * Return the size (in floats) of the given type specifier.
- * If the size is greater than 4, the size should be a multiple of 4
- * so that the correct number of 4-float registers are allocated.
- * For example, a mat3x2 is size 12 because we want to store the
- * 3 columns in 3 float[4] registers.
- */
-GLuint
-_slang_sizeof_type_specifier(const slang_type_specifier *spec)
-{
-   GLuint sz;
-   switch (spec->type) {
-   case SLANG_SPEC_VOID:
-      sz = 0;
-      break;
-   case SLANG_SPEC_BOOL:
-      sz = 1;
-      break;
-   case SLANG_SPEC_BVEC2:
-      sz = 2;
-      break;
-   case SLANG_SPEC_BVEC3:
-      sz = 3;
-      break;
-   case SLANG_SPEC_BVEC4:
-      sz = 4;
-      break;
-   case SLANG_SPEC_INT:
-      sz = 1;
-      break;
-   case SLANG_SPEC_IVEC2:
-      sz = 2;
-      break;
-   case SLANG_SPEC_IVEC3:
-      sz = 3;
-      break;
-   case SLANG_SPEC_IVEC4:
-      sz = 4;
-      break;
-   case SLANG_SPEC_FLOAT:
-      sz = 1;
-      break;
-   case SLANG_SPEC_VEC2:
-      sz = 2;
-      break;
-   case SLANG_SPEC_VEC3:
-      sz = 3;
-      break;
-   case SLANG_SPEC_VEC4:
-      sz = 4;
-      break;
-   case SLANG_SPEC_MAT2:
-      sz = 2 * 4; /* 2 columns (regs) */
-      break;
-   case SLANG_SPEC_MAT3:
-      sz = 3 * 4;
-      break;
-   case SLANG_SPEC_MAT4:
-      sz = 4 * 4;
-      break;
-   case SLANG_SPEC_MAT23:
-      sz = 2 * 4; /* 2 columns (regs) */
-      break;
-   case SLANG_SPEC_MAT32:
-      sz = 3 * 4; /* 3 columns (regs) */
-      break;
-   case SLANG_SPEC_MAT24:
-      sz = 2 * 4;
-      break;
-   case SLANG_SPEC_MAT42:
-      sz = 4 * 4; /* 4 columns (regs) */
-      break;
-   case SLANG_SPEC_MAT34:
-      sz = 3 * 4;
-      break;
-   case SLANG_SPEC_MAT43:
-      sz = 4 * 4; /* 4 columns (regs) */
-      break;
-   case SLANG_SPEC_SAMPLER_1D:
-   case SLANG_SPEC_SAMPLER_2D:
-   case SLANG_SPEC_SAMPLER_3D:
-   case SLANG_SPEC_SAMPLER_CUBE:
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-   case SLANG_SPEC_SAMPLER_RECT:
-   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
-   case SLANG_SPEC_SAMPLER_1D_ARRAY:
-   case SLANG_SPEC_SAMPLER_2D_ARRAY:
-   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
-   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
-      sz = 1; /* a sampler is basically just an integer index */
-      break;
-   case SLANG_SPEC_STRUCT:
-      sz = _slang_field_offset(spec, 0); /* special use */
-      if (sz == 1) {
-         /* 1-float structs are actually troublesome to deal with since they
-          * might get placed at R.x, R.y, R.z or R.z.  Return size=2 to
-          * ensure the object is placed at R.x
-          */
-         sz = 2;
-      }
-      else if (sz > 4) {
-         sz = (sz + 3) & ~0x3; /* round up to multiple of four */
-      }
-      break;
-   case SLANG_SPEC_ARRAY:
-      sz = _slang_sizeof_type_specifier(spec->_array);
-      break;
-   default:
-      _mesa_problem(NULL, "Unexpected type in _slang_sizeof_type_specifier()");
-      sz = 0;
-   }
-
-   if (sz > 4) {
-      /* if size is > 4, it should be a multiple of four */
-      assert((sz & 0x3) == 0);
-   }
-   return sz;
-}
-
-
-/**
- * Query variable/array length (number of elements).
- * This is slightly non-trivial because there are two ways to express
- * arrays: "float x[3]" vs. "float[3] x".
- * \return the length of the array for the given variable, or 0 if not an array
- */
-static GLint
-_slang_array_length(const slang_variable *var)
-{
-   if (var->type.array_len > 0) {
-      /* Ex: float[4] x; */
-      return var->type.array_len;
-   }
-   if (var->array_len > 0) {
-      /* Ex: float x[4]; */
-      return var->array_len;
-   }
-   return 0;
-}
-
-
-/**
- * Compute total size of array give size of element, number of elements.
- * \return size in floats
- */
-static GLint
-_slang_array_size(GLint elemSize, GLint arrayLen)
-{
-   GLint total;
-   assert(elemSize > 0);
-   if (arrayLen > 1) {
-      /* round up base type to multiple of 4 */
-      total = ((elemSize + 3) & ~0x3) * MAX2(arrayLen, 1);
-   }
-   else {
-      total = elemSize;
-   }
-   return total;
-}
-
-
-/**
- * Return the TEXTURE_*_INDEX value that corresponds to a sampler type,
- * or -1 if the type is not a sampler.
- */
-static GLint
-sampler_to_texture_index(const slang_type_specifier_type type)
-{
-   switch (type) {
-   case SLANG_SPEC_SAMPLER_1D:
-      return TEXTURE_1D_INDEX;
-   case SLANG_SPEC_SAMPLER_2D:
-      return TEXTURE_2D_INDEX;
-   case SLANG_SPEC_SAMPLER_3D:
-      return TEXTURE_3D_INDEX;
-   case SLANG_SPEC_SAMPLER_CUBE:
-      return TEXTURE_CUBE_INDEX;
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-      return TEXTURE_1D_INDEX; /* XXX fix */
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-      return TEXTURE_2D_INDEX; /* XXX fix */
-   case SLANG_SPEC_SAMPLER_RECT:
-      return TEXTURE_RECT_INDEX;
-   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
-      return TEXTURE_RECT_INDEX; /* XXX fix */
-   case SLANG_SPEC_SAMPLER_1D_ARRAY:
-      return TEXTURE_1D_ARRAY_INDEX;
-   case SLANG_SPEC_SAMPLER_2D_ARRAY:
-      return TEXTURE_2D_ARRAY_INDEX;
-   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
-      return TEXTURE_1D_ARRAY_INDEX;
-   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
-      return TEXTURE_2D_ARRAY_INDEX;
-   default:
-      return -1;
-   }
-}
-
-
-/** helper to build a SLANG_OPER_IDENTIFIER node */
-static void
-slang_operation_identifier(slang_operation *oper,
-                           slang_assemble_ctx *A,
-                           const char *name)
-{
-   oper->type = SLANG_OPER_IDENTIFIER;
-   oper->a_id = slang_atom_pool_atom(A->atoms, name);
-}
-
-
-/**
- * Called when we begin code/IR generation for a new while/do/for loop.
- */
-static void
-push_loop(slang_assemble_ctx *A, slang_operation *loopOper, slang_ir_node *loopIR)
-{
-   A->LoopOperStack[A->LoopDepth] = loopOper;
-   A->LoopIRStack[A->LoopDepth] = loopIR;
-   A->LoopDepth++;
-}
-
-
-/**
- * Called when we end code/IR generation for a new while/do/for loop.
- */
-static void
-pop_loop(slang_assemble_ctx *A)
-{
-   assert(A->LoopDepth > 0);
-   A->LoopDepth--;
-}
-
-
-/**
- * Return pointer to slang_operation for the loop we're currently inside,
- * or NULL if not in a loop.
- */
-static const slang_operation *
-current_loop_oper(const slang_assemble_ctx *A)
-{
-   if (A->LoopDepth > 0)
-      return A->LoopOperStack[A->LoopDepth - 1];
-   else
-      return NULL;
-}
-
-
-/**
- * Return pointer to slang_ir_node for the loop we're currently inside,
- * or NULL if not in a loop.
- */
-static slang_ir_node *
-current_loop_ir(const slang_assemble_ctx *A)
-{
-   if (A->LoopDepth > 0)
-      return A->LoopIRStack[A->LoopDepth - 1];
-   else
-      return NULL;
-}
-
-
-/**********************************************************************/
-
-
-/**
- * Map "_asm foo" to IR_FOO, etc.
- */
-typedef struct
-{
-   const char *Name;
-   slang_ir_opcode Opcode;
-   GLuint HaveRetValue, NumParams;
-} slang_asm_info;
-
-
-static slang_asm_info AsmInfo[] = {
-   /* vec4 binary op */
-   { "vec4_add", IR_ADD, 1, 2 },
-   { "vec4_subtract", IR_SUB, 1, 2 },
-   { "vec4_multiply", IR_MUL, 1, 2 },
-   { "vec4_dot", IR_DOT4, 1, 2 },
-   { "vec3_dot", IR_DOT3, 1, 2 },
-   { "vec2_dot", IR_DOT2, 1, 2 },
-   { "vec3_nrm", IR_NRM3, 1, 1 },
-   { "vec4_nrm", IR_NRM4, 1, 1 },
-   { "vec3_cross", IR_CROSS, 1, 2 },
-   { "vec4_lrp", IR_LRP, 1, 3 },
-   { "vec4_min", IR_MIN, 1, 2 },
-   { "vec4_max", IR_MAX, 1, 2 },
-   { "vec4_cmp", IR_CMP, 1, 3 },
-   { "vec4_clamp", IR_CLAMP, 1, 3 },
-   { "vec4_seq", IR_SEQUAL, 1, 2 },
-   { "vec4_sne", IR_SNEQUAL, 1, 2 },
-   { "vec4_sge", IR_SGE, 1, 2 },
-   { "vec4_sgt", IR_SGT, 1, 2 },
-   { "vec4_sle", IR_SLE, 1, 2 },
-   { "vec4_slt", IR_SLT, 1, 2 },
-   /* vec4 unary */
-   { "vec4_move", IR_MOVE, 1, 1 },
-   { "vec4_floor", IR_FLOOR, 1, 1 },
-   { "vec4_frac", IR_FRAC, 1, 1 },
-   { "vec4_abs", IR_ABS, 1, 1 },
-   { "vec4_negate", IR_NEG, 1, 1 },
-   { "vec4_ddx", IR_DDX, 1, 1 },
-   { "vec4_ddy", IR_DDY, 1, 1 },
-   /* float binary op */
-   { "float_power", IR_POW, 1, 2 },
-   /* texture / sampler */
-   { "vec4_tex_1d", IR_TEX, 1, 2 },
-   { "vec4_tex_1d_bias", IR_TEXB, 1, 2 },  /* 1d w/ bias */
-   { "vec4_tex_1d_proj", IR_TEXP, 1, 2 },  /* 1d w/ projection */
-   { "vec4_tex_2d", IR_TEX, 1, 2 },
-   { "vec4_tex_2d_bias", IR_TEXB, 1, 2 },  /* 2d w/ bias */
-   { "vec4_tex_2d_proj", IR_TEXP, 1, 2 },  /* 2d w/ projection */
-   { "vec4_tex_3d", IR_TEX, 1, 2 },
-   { "vec4_tex_3d_bias", IR_TEXB, 1, 2 },  /* 3d w/ bias */
-   { "vec4_tex_3d_proj", IR_TEXP, 1, 2 },  /* 3d w/ projection */
-   { "vec4_tex_cube", IR_TEX, 1, 2 },      /* cubemap */
-   { "vec4_tex_rect", IR_TEX, 1, 2 },      /* rectangle */
-   { "vec4_tex_rect_bias", IR_TEX, 1, 2 }, /* rectangle w/ projection */
-   { "vec4_tex_1d_array", IR_TEX, 1, 2 },
-   { "vec4_tex_1d_array_bias", IR_TEXB, 1, 2 },
-   { "vec4_tex_1d_array_shadow", IR_TEX, 1, 2 },
-   { "vec4_tex_1d_array_bias_shadow", IR_TEXB, 1, 2 },
-   { "vec4_tex_2d_array", IR_TEX, 1, 2 },
-   { "vec4_tex_2d_array_bias", IR_TEXB, 1, 2 },
-   { "vec4_tex_2d_array_shadow", IR_TEX, 1, 2 },
-   { "vec4_tex_2d_array_bias_shadow", IR_TEXB, 1, 2 },
-
-   /* texture / sampler but with shadow comparison */
-   { "vec4_tex_1d_shadow", IR_TEX_SH, 1, 2 },
-   { "vec4_tex_1d_bias_shadow", IR_TEXB_SH, 1, 2 },
-   { "vec4_tex_1d_proj_shadow", IR_TEXP_SH, 1, 2 },
-   { "vec4_tex_2d_shadow", IR_TEX_SH, 1, 2 },
-   { "vec4_tex_2d_bias_shadow", IR_TEXB_SH, 1, 2 },
-   { "vec4_tex_2d_proj_shadow", IR_TEXP_SH, 1, 2 },
-   { "vec4_tex_rect_shadow", IR_TEX_SH, 1, 2 },
-   { "vec4_tex_rect_proj_shadow", IR_TEXP_SH, 1, 2 },
-
-   /* unary op */
-   { "ivec4_to_vec4", IR_I_TO_F, 1, 1 }, /* int[4] to float[4] */
-   { "vec4_to_ivec4", IR_F_TO_I, 1, 1 },  /* float[4] to int[4] */
-   { "float_exp", IR_EXP, 1, 1 },
-   { "float_exp2", IR_EXP2, 1, 1 },
-   { "float_log2", IR_LOG2, 1, 1 },
-   { "float_rsq", IR_RSQ, 1, 1 },
-   { "float_rcp", IR_RCP, 1, 1 },
-   { "float_sine", IR_SIN, 1, 1 },
-   { "float_cosine", IR_COS, 1, 1 },
-   { "float_noise1", IR_NOISE1, 1, 1},
-   { "float_noise2", IR_NOISE2, 1, 1},
-   { "float_noise3", IR_NOISE3, 1, 1},
-   { "float_noise4", IR_NOISE4, 1, 1},
-
-   { NULL, IR_NOP, 0, 0 }
-};
-
-
-static slang_ir_node *
-new_node3(slang_ir_opcode op,
-          slang_ir_node *c0, slang_ir_node *c1, slang_ir_node *c2)
-{
-   slang_ir_node *n = (slang_ir_node *) _slang_alloc(sizeof(slang_ir_node));
-   if (n) {
-      n->Opcode = op;
-      n->Children[0] = c0;
-      n->Children[1] = c1;
-      n->Children[2] = c2;
-      n->InstLocation = -1;
-   }
-   return n;
-}
-
-static slang_ir_node *
-new_node2(slang_ir_opcode op, slang_ir_node *c0, slang_ir_node *c1)
-{
-   return new_node3(op, c0, c1, NULL);
-}
-
-static slang_ir_node *
-new_node1(slang_ir_opcode op, slang_ir_node *c0)
-{
-   return new_node3(op, c0, NULL, NULL);
-}
-
-static slang_ir_node *
-new_node0(slang_ir_opcode op)
-{
-   return new_node3(op, NULL, NULL, NULL);
-}
-
-
-/**
- * Create sequence of two nodes.
- */
-static slang_ir_node *
-new_seq(slang_ir_node *left, slang_ir_node *right)
-{
-   if (!left)
-      return right;
-   if (!right)
-      return left;
-   return new_node2(IR_SEQ, left, right);
-}
-
-static slang_ir_node *
-new_label(slang_label *label)
-{
-   slang_ir_node *n = new_node0(IR_LABEL);
-   assert(label);
-   if (n)
-      n->Label = label;
-   return n;
-}
-
-static slang_ir_node *
-new_float_literal(const float v[4], GLuint size)
-{
-   slang_ir_node *n = new_node0(IR_FLOAT);
-   assert(size <= 4);
-   COPY_4V(n->Value, v);
-   /* allocate a storage object, but compute actual location (Index) later */
-   n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size);
-   return n;
-}
-
-
-static slang_ir_node *
-new_not(slang_ir_node *n)
-{
-   return new_node1(IR_NOT, n);
-}
-
-
-/**
- * Non-inlined function call.
- */
-static slang_ir_node *
-new_function_call(slang_ir_node *code, slang_label *name)
-{
-   slang_ir_node *n = new_node1(IR_CALL, code);
-   assert(name);
-   if (n)
-      n->Label = name;
-   return n;
-}
-
-
-/**
- * Unconditional jump.
- */
-static slang_ir_node *
-new_return(slang_label *dest)
-{
-   slang_ir_node *n = new_node0(IR_RETURN);
-   assert(dest);
-   if (n)
-      n->Label = dest;
-   return n;
-}
-
-
-static slang_ir_node *
-new_loop(slang_ir_node *body)
-{
-   return new_node1(IR_LOOP, body);
-}
-
-
-static slang_ir_node *
-new_break(slang_ir_node *loopNode)
-{
-   slang_ir_node *n = new_node0(IR_BREAK);
-   assert(loopNode);
-   assert(loopNode->Opcode == IR_LOOP);
-   if (n) {
-      /* insert this node at head of linked list of cont/break instructions */
-      n->List = loopNode->List;
-      loopNode->List = n;
-   }
-   return n;
-}
-
-
-/**
- * Make new IR_BREAK_IF_TRUE.
- */
-static slang_ir_node *
-new_break_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
-{
-   slang_ir_node *loopNode = current_loop_ir(A);
-   slang_ir_node *n;
-   assert(loopNode);
-   assert(loopNode->Opcode == IR_LOOP);
-   n = new_node1(IR_BREAK_IF_TRUE, cond);
-   if (n) {
-      /* insert this node at head of linked list of cont/break instructions */
-      n->List = loopNode->List;
-      loopNode->List = n;
-   }
-   return n;
-}
-
-
-/**
- * Make new IR_CONT_IF_TRUE node.
- */
-static slang_ir_node *
-new_cont_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
-{
-   slang_ir_node *loopNode = current_loop_ir(A);
-   slang_ir_node *n;
-   assert(loopNode);
-   assert(loopNode->Opcode == IR_LOOP);
-   n = new_node1(IR_CONT_IF_TRUE, cond);
-   if (n) {
-      n->Parent = loopNode; /* pointer to containing loop */
-      /* insert this node at head of linked list of cont/break instructions */
-      n->List = loopNode->List;
-      loopNode->List = n;
-   }
-   return n;
-}
-
-
-static slang_ir_node *
-new_cond(slang_ir_node *n)
-{
-   slang_ir_node *c = new_node1(IR_COND, n);
-   return c;
-}
-
-
-static slang_ir_node *
-new_if(slang_ir_node *cond, slang_ir_node *ifPart, slang_ir_node *elsePart)
-{
-   return new_node3(IR_IF, cond, ifPart, elsePart);
-}
-
-
-/**
- * New IR_VAR node - a reference to a previously declared variable.
- */
-static slang_ir_node *
-new_var(slang_assemble_ctx *A, slang_variable *var)
-{
-   slang_ir_node *n = new_node0(IR_VAR);
-   if (n) {
-      ASSERT(var);
-      ASSERT(var->store);
-      ASSERT(!n->Store);
-      ASSERT(!n->Var);
-
-      /* Set IR node's Var and Store pointers */
-      n->Var = var;
-      n->Store = var->store;
-   }
-   return n;
-}
-
-
-/**
- * Check if the given function is really just a wrapper for a
- * basic assembly instruction.
- */
-static GLboolean
-slang_is_asm_function(const slang_function *fun)
-{
-   if (fun->body->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE &&
-       fun->body->num_children == 1 &&
-       fun->body->children[0].type == SLANG_OPER_ASM) {
-      return GL_TRUE;
-   }
-   return GL_FALSE;
-}
-
-
-static GLboolean
-_slang_is_noop(const slang_operation *oper)
-{
-   if (!oper ||
-       oper->type == SLANG_OPER_VOID ||
-       (oper->num_children == 1 && oper->children[0].type == SLANG_OPER_VOID))
-      return GL_TRUE;
-   else
-      return GL_FALSE;
-}
-
-
-/**
- * Recursively search tree for a node of the given type.
- */
-#if 0
-static slang_operation *
-_slang_find_node_type(slang_operation *oper, slang_operation_type type)
-{
-   GLuint i;
-   if (oper->type == type)
-      return oper;
-   for (i = 0; i < oper->num_children; i++) {
-      slang_operation *p = _slang_find_node_type(&oper->children[i], type);
-      if (p)
-         return p;
-   }
-   return NULL;
-}
-#endif
-
-
-/**
- * Count the number of operations of the given time rooted at 'oper'.
- */
-static GLuint
-_slang_count_node_type(const slang_operation *oper, slang_operation_type type)
-{
-   GLuint i, count = 0;
-   if (oper->type == type) {
-      return 1;
-   }
-   for (i = 0; i < oper->num_children; i++) {
-      count += _slang_count_node_type(&oper->children[i], type);
-   }
-   return count;
-}
-
-
-/**
- * Check if the 'return' statement found under 'oper' is a "tail return"
- * that can be no-op'd.  For example:
- *
- * void func(void)
- * {
- *    .. do something ..
- *    return;   // this is a no-op
- * }
- *
- * This is used when determining if a function can be inlined.  If the
- * 'return' is not the last statement, we can't inline the function since
- * we still need the semantic behaviour of the 'return' but we don't want
- * to accidentally return from the _calling_ function.  We'd need to use an
- * unconditional branch, but we don't have such a GPU instruction (not
- * always, at least).
- */
-static GLboolean
-_slang_is_tail_return(const slang_operation *oper)
-{
-   GLuint k = oper->num_children;
-
-   while (k > 0) {
-      const slang_operation *last = &oper->children[k - 1];
-      if (last->type == SLANG_OPER_RETURN)
-         return GL_TRUE;
-      else if (last->type == SLANG_OPER_IDENTIFIER ||
-               last->type == SLANG_OPER_LABEL)
-         k--; /* try prev child */
-      else if (last->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE ||
-               last->type == SLANG_OPER_BLOCK_NEW_SCOPE)
-         /* try sub-children */
-         return _slang_is_tail_return(last);
-      else
-         break;
-   }
-
-   return GL_FALSE;
-}
-
-
-/**
- * Generate a variable declaration opeartion.
- * I.e.: generate AST code for "bool flag = false;"
- */
-static void
-slang_generate_declaration(slang_assemble_ctx *A,
-                           slang_variable_scope *scope,
-                           slang_operation *decl,
-                           slang_type_specifier_type type,
-                           const char *name,
-                           GLint initValue)
-{
-   slang_variable *var;
-
-   assert(type == SLANG_SPEC_BOOL ||
-          type == SLANG_SPEC_INT);
-
-   decl->type = SLANG_OPER_VARIABLE_DECL;
-
-   var = slang_variable_scope_grow(scope);
-
-   slang_fully_specified_type_construct(&var->type);
-
-   var->type.specifier.type = type;
-   var->a_name = slang_atom_pool_atom(A->atoms, name);
-   decl->a_id = var->a_name;
-   var->initializer = slang_operation_new(1);
-   slang_operation_literal_bool(var->initializer, initValue);
-}
-
-
-static void
-slang_resolve_variable(slang_operation *oper)
-{
-   if (oper->type == SLANG_OPER_IDENTIFIER && !oper->var) {
-      oper->var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
-   }
-}
-
-
-/**
- * Rewrite AST code for "return expression;".
- *
- * We return values from functions by assinging the returned value to
- * the hidden __retVal variable which is an extra 'out' parameter we add
- * to the function signature.
- * This code basically converts "return expr;" into "__retVal = expr; return;"
- *
- * \return the new AST code.
- */
-static slang_operation *
-gen_return_with_expression(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_operation *blockOper, *assignOper;
-
-   assert(oper->type == SLANG_OPER_RETURN);
-
-   if (A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) {
-      slang_info_log_error(A->log, "illegal return expression");
-      return NULL;
-   }
-
-   blockOper = slang_operation_new(1);
-   blockOper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
-   blockOper->locals->outer_scope = oper->locals->outer_scope;
-   slang_operation_add_children(blockOper, 2);
-
-   if (A->UseReturnFlag) {
-      /* Emit:
-       *    {
-       *       if (__notRetFlag)
-       *          __retVal = expr;
-       *       __notRetFlag = 0;
-       *    }
-       */
-      {
-         slang_operation *ifOper = slang_oper_child(blockOper, 0);
-         ifOper->type = SLANG_OPER_IF;
-         slang_operation_add_children(ifOper, 3);
-         {
-            slang_operation *cond = slang_oper_child(ifOper, 0);
-            cond->type = SLANG_OPER_IDENTIFIER;
-            cond->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
-         }
-         {
-            slang_operation *elseOper = slang_oper_child(ifOper, 2);
-            elseOper->type = SLANG_OPER_VOID;
-         }
-         assignOper = slang_oper_child(ifOper, 1);
-      }
-      {
-         slang_operation *setOper = slang_oper_child(blockOper, 1);
-         setOper->type = SLANG_OPER_ASSIGN;
-         slang_operation_add_children(setOper, 2);
-         {
-            slang_operation *lhs = slang_oper_child(setOper, 0);
-            lhs->type = SLANG_OPER_IDENTIFIER;
-            lhs->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
-         }
-         {
-            slang_operation *rhs = slang_oper_child(setOper, 1);
-            slang_operation_literal_bool(rhs, GL_FALSE);
-         }
-      }
-   }
-   else {
-      /* Emit:
-       *    {
-       *       __retVal = expr;
-       *       return_inlined;
-       *    }
-       */
-      assignOper = slang_oper_child(blockOper, 0);
-      {
-         slang_operation *returnOper = slang_oper_child(blockOper, 1);
-         returnOper->type = SLANG_OPER_RETURN_INLINED;
-         assert(returnOper->num_children == 0);
-      }
-   }
-
-   /* __retVal = expression; */
-   assignOper->type = SLANG_OPER_ASSIGN;
-   slang_operation_add_children(assignOper, 2);
-   {
-      slang_operation *lhs = slang_oper_child(assignOper, 0);
-      lhs->type = SLANG_OPER_IDENTIFIER;
-      lhs->a_id = slang_atom_pool_atom(A->atoms, "__retVal");
-   }
-   {
-      slang_operation *rhs = slang_oper_child(assignOper, 1);
-      slang_operation_copy(rhs, &oper->children[0]);
-   }
-
-   /*blockOper->locals->outer_scope = oper->locals->outer_scope;*/
-
-   /*slang_print_tree(blockOper, 0);*/
-
-   return blockOper;
-}
-
-
-/**
- * Rewrite AST code for "return;" (no expression).
- */
-static slang_operation *
-gen_return_without_expression(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_operation *newRet;
-
-   assert(oper->type == SLANG_OPER_RETURN);
-
-   if (A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
-      slang_info_log_error(A->log, "return statement requires an expression");
-      return NULL;
-   }
-
-   if (A->UseReturnFlag) {
-      /* Emit:
-       *    __notRetFlag = 0;
-       */
-      {
-         newRet = slang_operation_new(1);
-         newRet->locals->outer_scope = oper->locals->outer_scope;
-         newRet->type = SLANG_OPER_ASSIGN;
-         slang_operation_add_children(newRet, 2);
-         {
-            slang_operation *lhs = slang_oper_child(newRet, 0);
-            lhs->type = SLANG_OPER_IDENTIFIER;
-            lhs->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
-         }
-         {
-            slang_operation *rhs = slang_oper_child(newRet, 1);
-            slang_operation_literal_bool(rhs, GL_FALSE);
-         }
-      }
-   }
-   else {
-      /* Emit:
-       *    return_inlined;
-       */
-      newRet = slang_operation_new(1);
-      newRet->locals->outer_scope = oper->locals->outer_scope;
-      newRet->type = SLANG_OPER_RETURN_INLINED;
-   }
-
-   /*slang_print_tree(newRet, 0);*/
-
-   return newRet;
-}
-
-
-
-
-/**
- * Replace particular variables (SLANG_OPER_IDENTIFIER) with new expressions.
- */
-static void
-slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
-                 GLuint substCount, slang_variable **substOld,
-                slang_operation **substNew, GLboolean isLHS)
-{
-   switch (oper->type) {
-   case SLANG_OPER_VARIABLE_DECL:
-      {
-         slang_variable *v = _slang_variable_locate(oper->locals,
-                                                    oper->a_id, GL_TRUE);
-         assert(v);
-         if (v->initializer && oper->num_children == 0) {
-            /* set child of oper to copy of initializer */
-            oper->num_children = 1;
-            oper->children = slang_operation_new(1);
-            slang_operation_copy(&oper->children[0], v->initializer);
-         }
-         if (oper->num_children == 1) {
-            /* the initializer */
-            slang_substitute(A, &oper->children[0], substCount,
-                             substOld, substNew, GL_FALSE);
-         }
-      }
-      break;
-   case SLANG_OPER_IDENTIFIER:
-      assert(oper->num_children == 0);
-      if (1/**!isLHS XXX FIX */) {
-         slang_atom id = oper->a_id;
-         slang_variable *v;
-        GLuint i;
-         v = _slang_variable_locate(oper->locals, id, GL_TRUE);
-        if (!v) {
-            if (strcmp((char *) oper->a_id, "__notRetFlag"))
-               _mesa_problem(NULL, "var %s not found!\n", (char *) oper->a_id);
-            return;
-        }
-
-        /* look for a substitution */
-        for (i = 0; i < substCount; i++) {
-           if (v == substOld[i]) {
-               /* OK, replace this SLANG_OPER_IDENTIFIER with a new expr */
-#if 0 /* DEBUG only */
-              if (substNew[i]->type == SLANG_OPER_IDENTIFIER) {
-                  assert(substNew[i]->var);
-                  assert(substNew[i]->var->a_name);
-                 printf("Substitute %s with %s in id node %p\n",
-                        (char*)v->a_name, (char*) substNew[i]->var->a_name,
-                        (void*) oper);
-               }
-              else {
-                 printf("Substitute %s with %f in id node %p\n",
-                        (char*)v->a_name, substNew[i]->literal[0],
-                        (void*) oper);
-               }
-#endif
-              slang_operation_copy(oper, substNew[i]);
-              break;
-           }
-        }
-      }
-      break;
-
-   case SLANG_OPER_RETURN:
-      {
-         slang_operation *newReturn;
-         /* generate new 'return' code' */
-         if (slang_oper_child(oper, 0)->type == SLANG_OPER_VOID)
-            newReturn = gen_return_without_expression(A, oper);
-         else
-            newReturn = gen_return_with_expression(A, oper);
-
-         if (!newReturn)
-            return;
-
-         /* do substitutions on the new 'return' code */
-         slang_substitute(A, newReturn,
-                          substCount, substOld, substNew, GL_FALSE);
-
-         /* install new 'return' code */
-         slang_operation_copy(oper, newReturn);
-         slang_operation_destruct(newReturn);
-      }
-      break;
-
-   case SLANG_OPER_ASSIGN:
-   case SLANG_OPER_SUBSCRIPT:
-      /* special case:
-       * child[0] can't have substitutions but child[1] can.
-       */
-      slang_substitute(A, &oper->children[0],
-                       substCount, substOld, substNew, GL_TRUE);
-      slang_substitute(A, &oper->children[1],
-                       substCount, substOld, substNew, GL_FALSE);
-      break;
-   case SLANG_OPER_FIELD:
-      /* XXX NEW - test */
-      slang_substitute(A, &oper->children[0],
-                       substCount, substOld, substNew, GL_TRUE);
-      break;
-   default:
-      {
-         GLuint i;
-         for (i = 0; i < oper->num_children; i++) 
-            slang_substitute(A, &oper->children[i],
-                             substCount, substOld, substNew, GL_FALSE);
-      }
-   }
-}
-
-
-/**
- * Produce inline code for a call to an assembly instruction.
- * This is typically used to compile a call to a built-in function like this:
- *
- * vec4 mix(const vec4 x, const vec4 y, const vec4 a)
- * {
- *    __asm vec4_lrp __retVal, a, y, x;
- * }
- *
- *
- * A call to
- *     r = mix(p1, p2, p3);
- *
- * Becomes:
- *
- *              mov
- *             /   \
- *            r   vec4_lrp
- *                 /  |  \
- *                p3  p2  p1
- *
- * We basically translate a SLANG_OPER_CALL into a SLANG_OPER_ASM.
- */
-static slang_operation *
-slang_inline_asm_function(slang_assemble_ctx *A,
-                          slang_function *fun, slang_operation *oper)
-{
-   const GLuint numArgs = oper->num_children;
-   GLuint i;
-   slang_operation *inlined;
-   const GLboolean haveRetValue = _slang_function_has_return_value(fun);
-   slang_variable **substOld;
-   slang_operation **substNew;
-
-   ASSERT(slang_is_asm_function(fun));
-   ASSERT(fun->param_count == numArgs + haveRetValue);
-
-   /*
-   printf("Inline %s as %s\n",
-          (char*) fun->header.a_name,
-          (char*) fun->body->children[0].a_id);
-   */
-
-   /*
-    * We'll substitute formal params with actual args in the asm call.
-    */
-   substOld = (slang_variable **)
-      _slang_alloc(numArgs * sizeof(slang_variable *));
-   substNew = (slang_operation **)
-      _slang_alloc(numArgs * sizeof(slang_operation *));
-   for (i = 0; i < numArgs; i++) {
-      substOld[i] = fun->parameters->variables[i];
-      substNew[i] = oper->children + i;
-   }
-
-   /* make a copy of the code to inline */
-   inlined = slang_operation_new(1);
-   slang_operation_copy(inlined, &fun->body->children[0]);
-   if (haveRetValue) {
-      /* get rid of the __retVal child */
-      inlined->num_children--;
-      for (i = 0; i < inlined->num_children; i++) {
-         inlined->children[i] = inlined->children[i + 1];
-      }
-   }
-
-   /* now do formal->actual substitutions */
-   slang_substitute(A, inlined, numArgs, substOld, substNew, GL_FALSE);
-
-   _slang_free(substOld);
-   _slang_free(substNew);
-
-#if 0
-   printf("+++++++++++++ inlined asm function %s +++++++++++++\n",
-          (char *) fun->header.a_name);
-   slang_print_tree(inlined, 3);
-   printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n");
-#endif
-
-   return inlined;
-}
-
-
-/**
- * Inline the given function call operation.
- * Return a new slang_operation that corresponds to the inlined code.
- */
-static slang_operation *
-slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
-                          slang_operation *oper, slang_operation *returnOper)
-{
-   typedef enum {
-      SUBST = 1,
-      COPY_IN,
-      COPY_OUT
-   } ParamMode;
-   ParamMode *paramMode;
-   const GLboolean haveRetValue = _slang_function_has_return_value(fun);
-   const GLuint numArgs = oper->num_children;
-   const GLuint totalArgs = numArgs + haveRetValue;
-   slang_operation *args = oper->children;
-   slang_operation *inlined, *top;
-   slang_variable **substOld;
-   slang_operation **substNew;
-   GLuint substCount, numCopyIn, i;
-   slang_function *prevFunction;
-   slang_variable_scope *newScope = NULL;
-
-   /* save / push */
-   prevFunction = A->CurFunction;
-   A->CurFunction = fun;
-
-   /*assert(oper->type == SLANG_OPER_CALL); (or (matrix) multiply, etc) */
-   assert(fun->param_count == totalArgs);
-
-   /* allocate temporary arrays */
-   paramMode = (ParamMode *)
-      _slang_alloc(totalArgs * sizeof(ParamMode));
-   substOld = (slang_variable **)
-      _slang_alloc(totalArgs * sizeof(slang_variable *));
-   substNew = (slang_operation **)
-      _slang_alloc(totalArgs * sizeof(slang_operation *));
-
-#if 0
-   printf("\nInline call to %s  (total vars=%d  nparams=%d)\n",
-         (char *) fun->header.a_name,
-         fun->parameters->num_variables, numArgs);
-#endif
-
-   if (haveRetValue && !returnOper) {
-      /* Create 3-child comma sequence for inlined code:
-       * child[0]:  declare __resultTmp
-       * child[1]:  inlined function body
-       * child[2]:  __resultTmp
-       */
-      slang_operation *commaSeq;
-      slang_operation *declOper = NULL;
-      slang_variable *resultVar;
-
-      commaSeq = slang_operation_new(1);
-      commaSeq->type = SLANG_OPER_SEQUENCE;
-      assert(commaSeq->locals);
-      commaSeq->locals->outer_scope = oper->locals->outer_scope;
-      commaSeq->num_children = 3;
-      commaSeq->children = slang_operation_new(3);
-      /* allocate the return var */
-      resultVar = slang_variable_scope_grow(commaSeq->locals);
-      /*
-      printf("Alloc __resultTmp in scope %p for retval of calling %s\n",
-             (void*)commaSeq->locals, (char *) fun->header.a_name);
-      */
-
-      resultVar->a_name = slang_atom_pool_atom(A->atoms, "__resultTmp");
-      resultVar->type = fun->header.type; /* XXX copy? */
-      resultVar->isTemp = GL_TRUE;
-
-      /* child[0] = __resultTmp declaration */
-      declOper = &commaSeq->children[0];
-      declOper->type = SLANG_OPER_VARIABLE_DECL;
-      declOper->a_id = resultVar->a_name;
-      declOper->locals->outer_scope = commaSeq->locals;
-
-      /* child[1] = function body */
-      inlined = &commaSeq->children[1];
-      inlined->locals->outer_scope = commaSeq->locals;
-
-      /* child[2] = __resultTmp reference */
-      returnOper = &commaSeq->children[2];
-      returnOper->type = SLANG_OPER_IDENTIFIER;
-      returnOper->a_id = resultVar->a_name;
-      returnOper->locals->outer_scope = commaSeq->locals;
-
-      top = commaSeq;
-   }
-   else {
-      top = inlined = slang_operation_new(1);
-      /* XXXX this may be inappropriate!!!! */
-      inlined->locals->outer_scope = oper->locals->outer_scope;
-   }
-
-
-   assert(inlined->locals);
-
-   /* Examine the parameters, look for inout/out params, look for possible
-    * substitutions, etc:
-    *    param type      behaviour
-    *     in             copy actual to local
-    *     const in       substitute param with actual
-    *     out            copy out
-    */
-   substCount = 0;
-   for (i = 0; i < totalArgs; i++) {
-      slang_variable *p = fun->parameters->variables[i];
-      /*
-      printf("Param %d: %s %s \n", i,
-             slang_type_qual_string(p->type.qualifier),
-            (char *) p->a_name);
-      */
-      if (p->type.qualifier == SLANG_QUAL_INOUT ||
-         p->type.qualifier == SLANG_QUAL_OUT) {
-        /* an output param */
-         slang_operation *arg;
-         if (i < numArgs)
-            arg = &args[i];
-         else
-            arg = returnOper;
-        paramMode[i] = SUBST;
-
-        if (arg->type == SLANG_OPER_IDENTIFIER)
-            slang_resolve_variable(arg);
-
-         /* replace parameter 'p' with argument 'arg' */
-        substOld[substCount] = p;
-        substNew[substCount] = arg; /* will get copied */
-        substCount++;
-      }
-      else if (p->type.qualifier == SLANG_QUAL_CONST) {
-        /* a constant input param */
-         if (args[i].type == SLANG_OPER_IDENTIFIER ||
-             args[i].type == SLANG_OPER_LITERAL_FLOAT ||
-             args[i].type == SLANG_OPER_SUBSCRIPT) {
-           /* replace all occurances of this parameter variable with the
-            * actual argument variable or a literal.
-            */
-           paramMode[i] = SUBST;
-            slang_resolve_variable(&args[i]);
-           substOld[substCount] = p;
-           substNew[substCount] = &args[i]; /* will get copied */
-           substCount++;
-        }
-        else {
-           paramMode[i] = COPY_IN;
-        }
-      }
-      else {
-        paramMode[i] = COPY_IN;
-      }
-      assert(paramMode[i]);
-   }
-
-   /* actual code inlining: */
-   slang_operation_copy(inlined, fun->body);
-
-   /*** XXX review this */
-   assert(inlined->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE ||
-          inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE);
-   inlined->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-
-#if 0
-   printf("======================= orig body code ======================\n");
-   printf("=== params scope = %p\n", (void*) fun->parameters);
-   slang_print_tree(fun->body, 8);
-   printf("======================= copied code =========================\n");
-   slang_print_tree(inlined, 8);
-#endif
-
-   /* do parameter substitution in inlined code: */
-   slang_substitute(A, inlined, substCount, substOld, substNew, GL_FALSE);
-
-#if 0
-   printf("======================= subst code ==========================\n");
-   slang_print_tree(inlined, 8);
-   printf("=============================================================\n");
-#endif
-
-   /* New prolog statements: (inserted before the inlined code)
-    * Copy the 'in' arguments.
-    */
-   numCopyIn = 0;
-   for (i = 0; i < numArgs; i++) {
-      if (paramMode[i] == COPY_IN) {
-        slang_variable *p = fun->parameters->variables[i];
-        /* declare parameter 'p' */
-        slang_operation *decl = slang_operation_insert(&inlined->num_children,
-                                                       &inlined->children,
-                                                       numCopyIn);
-
-        decl->type = SLANG_OPER_VARIABLE_DECL;
-         assert(decl->locals);
-         decl->locals->outer_scope = inlined->locals;
-        decl->a_id = p->a_name;
-        decl->num_children = 1;
-        decl->children = slang_operation_new(1);
-
-         /* child[0] is the var's initializer */
-         slang_operation_copy(&decl->children[0], args + i);
-
-         /* add parameter 'p' to the local variable scope here */
-         {
-            slang_variable *pCopy = slang_variable_scope_grow(inlined->locals);
-            pCopy->type = p->type;
-            pCopy->a_name = p->a_name;
-            pCopy->array_len = p->array_len;
-         }
-
-         newScope = inlined->locals;
-        numCopyIn++;
-      }
-   }
-
-   /* Now add copies of the function's local vars to the new variable scope */
-   for (i = totalArgs; i < fun->parameters->num_variables; i++) {
-      slang_variable *p = fun->parameters->variables[i];
-      slang_variable *pCopy = slang_variable_scope_grow(inlined->locals);
-      pCopy->type = p->type;
-      pCopy->a_name = p->a_name;
-      pCopy->array_len = p->array_len;
-   }
-
-
-   /* New epilog statements:
-    * 1. Create end of function label to jump to from return statements.
-    * 2. Copy the 'out' parameter vars
-    */
-   {
-      slang_operation *lab = slang_operation_insert(&inlined->num_children,
-                                                    &inlined->children,
-                                                    inlined->num_children);
-      lab->type = SLANG_OPER_LABEL;
-      lab->label = A->curFuncEndLabel;
-   }
-
-   for (i = 0; i < totalArgs; i++) {
-      if (paramMode[i] == COPY_OUT) {
-        const slang_variable *p = fun->parameters->variables[i];
-        /* actualCallVar = outParam */
-        /*if (i > 0 || !haveRetValue)*/
-        slang_operation *ass = slang_operation_insert(&inlined->num_children,
-                                                      &inlined->children,
-                                                      inlined->num_children);
-        ass->type = SLANG_OPER_ASSIGN;
-        ass->num_children = 2;
-         ass->locals->outer_scope = inlined->locals;
-        ass->children = slang_operation_new(2);
-        ass->children[0] = args[i]; /*XXX copy */
-        ass->children[1].type = SLANG_OPER_IDENTIFIER;
-        ass->children[1].a_id = p->a_name;
-         ass->children[1].locals->outer_scope = ass->locals;
-      }
-   }
-
-   _slang_free(paramMode);
-   _slang_free(substOld);
-   _slang_free(substNew);
-
-   /* Update scoping to use the new local vars instead of the
-    * original function's vars.  This is especially important
-    * for nested inlining.
-    */
-   if (newScope)
-      slang_replace_scope(inlined, fun->parameters, newScope);
-
-#if 0
-   printf("Done Inline call to %s  (total vars=%d  nparams=%d)\n\n",
-         (char *) fun->header.a_name,
-         fun->parameters->num_variables, numArgs);
-   slang_print_tree(top, 0);
-#endif
-
-   /* pop */
-   A->CurFunction = prevFunction;
-
-   return top;
-}
-
-
-/**
- * Insert declaration for "bool __notRetFlag" in given block operation.
- * This is used when we can't emit "early" return statements in subroutines.
- */
-static void
-declare_return_flag(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_operation *decl;
-
-   assert(oper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
-          oper->type == SLANG_OPER_SEQUENCE);
-
-   decl = slang_operation_insert_child(oper, 1);
-
-   slang_generate_declaration(A, oper->locals, decl,
-                              SLANG_SPEC_BOOL, "__notRetFlag", GL_TRUE);
-
-   /*slang_print_tree(oper, 0);*/
-}
-
-
-/**
- * Recursively replace instances of the old node type with the new type.
- */
-static void
-replace_node_type(slang_operation *oper, slang_operation_type oldType,
-                  slang_operation_type newType)
-{
-   GLuint i;
-
-   if (oper->type == oldType)
-      oper->type = newType;
-
-   for (i = 0; i < slang_oper_num_children(oper); i++) {
-      replace_node_type(slang_oper_child(oper, i), oldType, newType);
-   }
-}
-
-
-
-/**
- * Test if the given function body has an "early return".  That is, there's
- * a 'return' statement that's not the very last instruction in the body.
- */
-static GLboolean
-has_early_return(const slang_operation *funcBody)
-{
-   GLuint retCount = _slang_count_node_type(funcBody, SLANG_OPER_RETURN);
-   if (retCount == 0)
-      return GL_FALSE;
-   else if (retCount == 1 && _slang_is_tail_return(funcBody))
-      return GL_FALSE;
-   else
-      return GL_TRUE;
-}
-
-
-/**
- * Emit IR code for a function call.  This does one of two things:
- * 1. Inline the function's code
- * 2. Create an IR for the function's body and create a real call to it.
- */
-static slang_ir_node *
-_slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
-                         slang_operation *oper, slang_operation *dest)
-{
-   slang_ir_node *n;
-   slang_operation *instance;
-   slang_label *prevFuncEndLabel;
-   char name[200];
-
-   prevFuncEndLabel = A->curFuncEndLabel;
-   _mesa_snprintf(name, sizeof(name), "__endOfFunc_%s_", (char *) fun->header.a_name);
-   A->curFuncEndLabel = _slang_label_new(name);
-   assert(A->curFuncEndLabel);
-
-   /*
-    * 'instance' is basically a copy of the function's body with various
-    * transformations.
-    */
-
-   if (slang_is_asm_function(fun) && !dest) {
-      /* assemble assembly function - tree style */
-      instance = slang_inline_asm_function(A, fun, oper);
-   }
-   else {
-      /* non-assembly function */
-      /* We always generate an "inline-able" block of code here.
-       * We may either:
-       *  1. insert the inline code
-       *  2. Generate a call to the "inline" code as a subroutine
-       */
-      const GLboolean earlyReturn = has_early_return(fun->body);
-
-      if (earlyReturn && !A->EmitContReturn) {
-         A->UseReturnFlag = GL_TRUE;
-      }
-
-      instance = slang_inline_function_call(A, fun, oper, dest);
-      if (!instance)
-         return NULL;
-
-      if (earlyReturn) {
-         /* The function we're calling has one or more 'return' statements
-          * that prevent us from inlining the function's code.
-          *
-          * In this case, change the function's body type from
-          * SLANG_OPER_BLOCK_NEW_SCOPE to SLANG_OPER_NON_INLINED_CALL.
-          * During code emit this will result in a true subroutine call.
-          *
-          * Also, convert SLANG_OPER_RETURN_INLINED nodes to SLANG_OPER_RETURN.
-          */
-         slang_operation *callOper;
-
-         assert(instance->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
-                instance->type == SLANG_OPER_SEQUENCE);
-
-         if (_slang_function_has_return_value(fun) && !dest) {
-            assert(instance->children[0].type == SLANG_OPER_VARIABLE_DECL);
-            assert(instance->children[2].type == SLANG_OPER_IDENTIFIER);
-            callOper = &instance->children[1];
-         }
-         else {
-            callOper = instance;
-         }
-
-         if (A->UseReturnFlag) {
-            /* Early returns not supported.  Create a _returnFlag variable
-             * that's set upon 'return' and tested elsewhere to no-op any
-             * remaining instructions in the subroutine.
-             */
-            assert(callOper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
-                   callOper->type == SLANG_OPER_SEQUENCE);
-            declare_return_flag(A, callOper);
-         }
-         else {
-            /* We can emit real 'return' statements.  If we generated any
-             * 'inline return' statements during function instantiation,
-             * change them back to regular 'return' statements.
-             */
-            replace_node_type(instance, SLANG_OPER_RETURN_INLINED,
-                              SLANG_OPER_RETURN);
-         }
-
-         callOper->type = SLANG_OPER_NON_INLINED_CALL;
-         callOper->fun = fun;
-         callOper->label = _slang_label_new_unique((char*) fun->header.a_name);
-      }
-      else {
-         /* If there are any 'return' statements remaining, they're at the
-          * very end of the function and can effectively become no-ops.
-          */
-         replace_node_type(instance, SLANG_OPER_RETURN_INLINED,
-                           SLANG_OPER_VOID);
-      }
-   }
-
-   if (!instance)
-      return NULL;
-
-   /* Replace the function call with the instance block (or new CALL stmt) */
-   slang_operation_destruct(oper);
-   *oper = *instance;
-   _slang_free(instance);
-
-#if 0
-   assert(instance->locals);
-   printf("*** Inlined code for call to %s:\n", (char*) fun->header.a_name);
-   slang_print_tree(oper, 10);
-   printf("\n");
-#endif
-
-   n = _slang_gen_operation(A, oper);
-
-   /*_slang_label_delete(A->curFuncEndLabel);*/
-   A->curFuncEndLabel = prevFuncEndLabel;
-
-   if (A->pragmas->Debug) {
-      char s[1000];
-      _mesa_snprintf(s, sizeof(s), "Call/inline %s()", (char *) fun->header.a_name);
-      n->Comment = _slang_strdup(s);
-   }
-
-   A->UseReturnFlag = GL_FALSE;
-
-   return n;
-}
-
-
-static slang_asm_info *
-slang_find_asm_info(const char *name)
-{
-   GLuint i;
-   for (i = 0; AsmInfo[i].Name; i++) {
-      if (strcmp(AsmInfo[i].Name, name) == 0) {
-         return AsmInfo + i;
-      }
-   }
-   return NULL;
-}
-
-
-/**
- * Some write-masked assignments are simple, but others are hard.
- * Simple example:
- *    vec3 v;
- *    v.xy = vec2(a, b);
- * Hard example:
- *    vec3 v;
- *    v.zy = vec2(a, b);
- * this gets transformed/swizzled into:
- *    v.zy = vec2(a, b).*yx*         (* = don't care)
- * This function helps to determine simple vs. non-simple.
- */
-static GLboolean
-_slang_simple_writemask(GLuint writemask, GLuint swizzle)
-{
-   switch (writemask) {
-   case WRITEMASK_X:
-      return GET_SWZ(swizzle, 0) == SWIZZLE_X;
-   case WRITEMASK_Y:
-      return GET_SWZ(swizzle, 1) == SWIZZLE_Y;
-   case WRITEMASK_Z:
-      return GET_SWZ(swizzle, 2) == SWIZZLE_Z;
-   case WRITEMASK_W:
-      return GET_SWZ(swizzle, 3) == SWIZZLE_W;
-   case WRITEMASK_XY:
-      return (GET_SWZ(swizzle, 0) == SWIZZLE_X)
-         && (GET_SWZ(swizzle, 1) == SWIZZLE_Y);
-   case WRITEMASK_XYZ:
-      return (GET_SWZ(swizzle, 0) == SWIZZLE_X)
-         && (GET_SWZ(swizzle, 1) == SWIZZLE_Y)
-         && (GET_SWZ(swizzle, 2) == SWIZZLE_Z);
-   case WRITEMASK_XYZW:
-      return swizzle == SWIZZLE_NOOP;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Convert the given swizzle into a writemask.  In some cases this
- * is trivial, in other cases, we'll need to also swizzle the right
- * hand side to put components in the right places.
- * See comment above for more info.
- * XXX this function could be simplified and should probably be renamed.
- * \param swizzle  the incoming swizzle
- * \param writemaskOut  returns the writemask
- * \param swizzleOut  swizzle to apply to the right-hand-side
- * \return GL_FALSE for simple writemasks, GL_TRUE for non-simple
- */
-static GLboolean
-swizzle_to_writemask(slang_assemble_ctx *A, GLuint swizzle,
-                     GLuint *writemaskOut, GLuint *swizzleOut)
-{
-   GLuint mask = 0x0, newSwizzle[4];
-   GLint i, size;
-
-   /* make new dst writemask, compute size */
-   for (i = 0; i < 4; i++) {
-      const GLuint swz = GET_SWZ(swizzle, i);
-      if (swz == SWIZZLE_NIL) {
-         /* end */
-         break;
-      }
-      assert(swz <= 3);
-
-      if (swizzle != SWIZZLE_XXXX &&
-          swizzle != SWIZZLE_YYYY &&
-          swizzle != SWIZZLE_ZZZZ &&
-          swizzle != SWIZZLE_WWWW &&
-          (mask & (1 << swz))) {
-         /* a channel can't be specified twice (ex: ".xyyz") */
-         slang_info_log_error(A->log, "Invalid writemask '%s'",
-                              _mesa_swizzle_string(swizzle, 0, 0));
-         return GL_FALSE;
-      }
-
-      mask |= (1 << swz);
-   }
-   assert(mask <= 0xf);
-   size = i;  /* number of components in mask/swizzle */
-
-   *writemaskOut = mask;
-
-   /* make new src swizzle, by inversion */
-   for (i = 0; i < 4; i++) {
-      newSwizzle[i] = i; /*identity*/
-   }
-   for (i = 0; i < size; i++) {
-      const GLuint swz = GET_SWZ(swizzle, i);
-      newSwizzle[swz] = i;
-   }
-   *swizzleOut = MAKE_SWIZZLE4(newSwizzle[0],
-                               newSwizzle[1],
-                               newSwizzle[2],
-                               newSwizzle[3]);
-
-   if (_slang_simple_writemask(mask, *swizzleOut)) {
-      if (size >= 1)
-         assert(GET_SWZ(*swizzleOut, 0) == SWIZZLE_X);
-      if (size >= 2)
-         assert(GET_SWZ(*swizzleOut, 1) == SWIZZLE_Y);
-      if (size >= 3)
-         assert(GET_SWZ(*swizzleOut, 2) == SWIZZLE_Z);
-      if (size >= 4)
-         assert(GET_SWZ(*swizzleOut, 3) == SWIZZLE_W);
-      return GL_TRUE;
-   }
-   else
-      return GL_FALSE;
-}
-
-
-#if 0 /* not used, but don't remove just yet */
-/**
- * Recursively traverse 'oper' to produce a swizzle mask in the event
- * of any vector subscripts and swizzle suffixes.
- * Ex:  for "vec4 v",  "v[2].x" resolves to v.z
- */
-static GLuint
-resolve_swizzle(const slang_operation *oper)
-{
-   if (oper->type == SLANG_OPER_FIELD) {
-      /* writemask from .xyzw suffix */
-      slang_swizzle swz;
-      if (_slang_is_swizzle((char*) oper->a_id, 4, &swz)) {
-         GLuint swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
-                                        swz.swizzle[1],
-                                        swz.swizzle[2],
-                                        swz.swizzle[3]);
-         GLuint child_swizzle = resolve_swizzle(&oper->children[0]);
-         GLuint s = _slang_swizzle_swizzle(child_swizzle, swizzle);
-         return s;
-      }
-      else
-         return SWIZZLE_XYZW;
-   }
-   else if (oper->type == SLANG_OPER_SUBSCRIPT &&
-            oper->children[1].type == SLANG_OPER_LITERAL_INT) {
-      /* writemask from [index] */
-      GLuint child_swizzle = resolve_swizzle(&oper->children[0]);
-      GLuint i = (GLuint) oper->children[1].literal[0];
-      GLuint swizzle;
-      GLuint s;
-      switch (i) {
-      case 0:
-         swizzle = SWIZZLE_XXXX;
-         break;
-      case 1:
-         swizzle = SWIZZLE_YYYY;
-         break;
-      case 2:
-         swizzle = SWIZZLE_ZZZZ;
-         break;
-      case 3:
-         swizzle = SWIZZLE_WWWW;
-         break;
-      default:
-         swizzle = SWIZZLE_XYZW;
-      }
-      s = _slang_swizzle_swizzle(child_swizzle, swizzle);
-      return s;
-   }
-   else {
-      return SWIZZLE_XYZW;
-   }
-}
-#endif
-
-
-#if 0
-/**
- * Recursively descend through swizzle nodes to find the node's storage info.
- */
-static slang_ir_storage *
-get_store(const slang_ir_node *n)
-{
-   if (n->Opcode == IR_SWIZZLE) {
-      return get_store(n->Children[0]);
-   }
-   return n->Store;
-}
-#endif
-
-
-/**
- * Generate IR tree for an asm instruction/operation such as:
- *    __asm vec4_dot __retVal.x, v1, v2;
- */
-static slang_ir_node *
-_slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper,
-               slang_operation *dest)
-{
-   const slang_asm_info *info;
-   slang_ir_node *kids[3], *n;
-   GLuint j, firstOperand;
-
-   assert(oper->type == SLANG_OPER_ASM);
-
-   info = slang_find_asm_info((char *) oper->a_id);
-   if (!info) {
-      _mesa_problem(NULL, "undefined __asm function %s\n",
-                    (char *) oper->a_id);
-      assert(info);
-      return NULL;
-   }
-   assert(info->NumParams <= 3);
-
-   if (info->NumParams == oper->num_children) {
-      /* Storage for result is not specified.
-       * Children[0], [1], [2] are the operands.
-       */
-      firstOperand = 0;
-   }
-   else {
-      /* Storage for result (child[0]) is specified.
-       * Children[1], [2], [3] are the operands.
-       */
-      firstOperand = 1;
-   }
-
-   /* assemble child(ren) */
-   kids[0] = kids[1] = kids[2] = NULL;
-   for (j = 0; j < info->NumParams; j++) {
-      kids[j] = _slang_gen_operation(A, &oper->children[firstOperand + j]);
-      if (!kids[j])
-         return NULL;
-   }
-
-   n = new_node3(info->Opcode, kids[0], kids[1], kids[2]);
-
-   if (firstOperand) {
-      /* Setup n->Store to be a particular location.  Otherwise, storage
-       * for the result (a temporary) will be allocated later.
-       */
-      slang_operation *dest_oper;
-      slang_ir_node *n0;
-
-      dest_oper = &oper->children[0];
-
-      n0 = _slang_gen_operation(A, dest_oper);
-      if (!n0)
-         return NULL;
-
-      assert(!n->Store);
-      n->Store = n0->Store;
-
-      assert(n->Store->File != PROGRAM_UNDEFINED || n->Store->Parent);
-
-      _slang_free(n0);
-   }
-
-   return n;
-}
-
-
-#if 0
-static void
-print_funcs(struct slang_function_scope_ *scope, const char *name)
-{
-   GLuint i;
-   for (i = 0; i < scope->num_functions; i++) {
-      slang_function *f = &scope->functions[i];
-      if (!name || strcmp(name, (char*) f->header.a_name) == 0)
-          printf("  %s (%d args)\n", name, f->param_count);
-
-   }
-   if (scope->outer_scope)
-      print_funcs(scope->outer_scope, name);
-}
-#endif
-
-
-/**
- * Find a function of the given name, taking 'numArgs' arguments.
- * This is the function we'll try to call when there is no exact match
- * between function parameters and call arguments.
- *
- * XXX we should really create a list of candidate functions and try
- * all of them...
- */
-static slang_function *
-_slang_find_function_by_argc(slang_function_scope *scope,
-                             const char *name, int numArgs)
-{
-   while (scope) {
-      GLuint i;
-      for (i = 0; i < scope->num_functions; i++) {
-         slang_function *f = &scope->functions[i];
-         if (strcmp(name, (char*) f->header.a_name) == 0) {
-            int haveRetValue = _slang_function_has_return_value(f);
-            if (numArgs == f->param_count - haveRetValue)
-               return f;
-         }
-      }
-      scope = scope->outer_scope;
-   }
-
-   return NULL;
-}
-
-
-static slang_function *
-_slang_find_function_by_max_argc(slang_function_scope *scope,
-                                 const char *name)
-{
-   slang_function *maxFunc = NULL;
-   GLuint maxArgs = 0;
-
-   while (scope) {
-      GLuint i;
-      for (i = 0; i < scope->num_functions; i++) {
-         slang_function *f = &scope->functions[i];
-         if (strcmp(name, (char*) f->header.a_name) == 0) {
-            if (f->param_count > maxArgs) {
-               maxArgs = f->param_count;
-               maxFunc = f;
-            }
-         }
-      }
-      scope = scope->outer_scope;
-   }
-
-   return maxFunc;
-}
-
-
-/**
- * Generate a new slang_function which is a constructor for a user-defined
- * struct type.
- */
-static slang_function *
-_slang_make_struct_constructor(slang_assemble_ctx *A, slang_struct *str)
-{
-   const GLint numFields = str->fields->num_variables;
-   slang_function *fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
-
-   /* function header (name, return type) */
-   fun->header.a_name = str->a_name;
-   fun->header.type.qualifier = SLANG_QUAL_NONE;
-   fun->header.type.specifier.type = SLANG_SPEC_STRUCT;
-   fun->header.type.specifier._struct = str;
-
-   /* function parameters (= struct's fields) */
-   {
-      GLint i;
-      for (i = 0; i < numFields; i++) {
-         /*
-         printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name);
-         */
-         slang_variable *p = slang_variable_scope_grow(fun->parameters);
-         *p = *str->fields->variables[i]; /* copy the variable and type */
-         p->type.qualifier = SLANG_QUAL_CONST;
-      }
-      fun->param_count = fun->parameters->num_variables;
-   }
-
-   /* Add __retVal to params */
-   {
-      slang_variable *p = slang_variable_scope_grow(fun->parameters);
-      slang_atom a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
-      assert(a_retVal);
-      p->a_name = a_retVal;
-      p->type = fun->header.type;
-      p->type.qualifier = SLANG_QUAL_OUT;
-      fun->param_count++;
-   }
-
-   /* function body is:
-    *    block:
-    *       declare T;
-    *       T.f1 = p1;
-    *       T.f2 = p2;
-    *       ...
-    *       T.fn = pn;
-    *       return T;
-    */
-   {
-      slang_variable_scope *scope;
-      slang_variable *var;
-      GLint i;
-
-      fun->body = slang_operation_new(1);
-      fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-      fun->body->num_children = numFields + 2;
-      fun->body->children = slang_operation_new(numFields + 2);
-
-      scope = fun->body->locals;
-      scope->outer_scope = fun->parameters;
-
-      /* create local var 't' */
-      var = slang_variable_scope_grow(scope);
-      var->a_name = slang_atom_pool_atom(A->atoms, "t");
-      var->type = fun->header.type;
-
-      /* declare t */
-      {
-         slang_operation *decl;
-
-         decl = &fun->body->children[0];
-         decl->type = SLANG_OPER_VARIABLE_DECL;
-         decl->locals = _slang_variable_scope_new(scope);
-         decl->a_id = var->a_name;
-      }
-
-      /* assign params to fields of t */
-      for (i = 0; i < numFields; i++) {
-         slang_operation *assign = &fun->body->children[1 + i];
-
-         assign->type = SLANG_OPER_ASSIGN;
-         assign->locals = _slang_variable_scope_new(scope);
-         assign->num_children = 2;
-         assign->children = slang_operation_new(2);
-         
-         {
-            slang_operation *lhs = &assign->children[0];
-
-            lhs->type = SLANG_OPER_FIELD;
-            lhs->locals = _slang_variable_scope_new(scope);
-            lhs->num_children = 1;
-            lhs->children = slang_operation_new(1);
-            lhs->a_id = str->fields->variables[i]->a_name;
-
-            lhs->children[0].type = SLANG_OPER_IDENTIFIER;
-            lhs->children[0].a_id = var->a_name;
-            lhs->children[0].locals = _slang_variable_scope_new(scope);
-
-#if 0
-            lhs->children[1].num_children = 1;
-            lhs->children[1].children = slang_operation_new(1);
-            lhs->children[1].children[0].type = SLANG_OPER_IDENTIFIER;
-            lhs->children[1].children[0].a_id = str->fields->variables[i]->a_name;
-            lhs->children[1].children->locals = _slang_variable_scope_new(scope);
-#endif
-         }
-
-         {
-            slang_operation *rhs = &assign->children[1];
-
-            rhs->type = SLANG_OPER_IDENTIFIER;
-            rhs->locals = _slang_variable_scope_new(scope);
-            rhs->a_id = str->fields->variables[i]->a_name;
-         }         
-      }
-
-      /* return t; */
-      {
-         slang_operation *ret = &fun->body->children[numFields + 1];
-
-         ret->type = SLANG_OPER_RETURN;
-         ret->locals = _slang_variable_scope_new(scope);
-         ret->num_children = 1;
-         ret->children = slang_operation_new(1);
-         ret->children[0].type = SLANG_OPER_IDENTIFIER;
-         ret->children[0].a_id = var->a_name;
-         ret->children[0].locals = _slang_variable_scope_new(scope);
-      }
-   }
-   /*
-   slang_print_function(fun, 1);
-   */
-   return fun;
-}
-
-
-/**
- * Find/create a function (constructor) for the given structure name.
- */
-static slang_function *
-_slang_locate_struct_constructor(slang_assemble_ctx *A, const char *name)
-{
-   unsigned int i;
-   for (i = 0; i < A->space.structs->num_structs; i++) {
-      slang_struct *str = &A->space.structs->structs[i];
-      if (strcmp(name, (const char *) str->a_name) == 0) {
-         /* found a structure type that matches the function name */
-         if (!str->constructor) {
-            /* create the constructor function now */
-            str->constructor = _slang_make_struct_constructor(A, str);
-         }
-         return str->constructor;
-      }
-   }
-   return NULL;
-}
-
-
-/**
- * Generate a new slang_function to satisfy a call to an array constructor.
- * Ex:  float[3](1., 2., 3.)
- */
-static slang_function *
-_slang_make_array_constructor(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_type_specifier_type baseType;
-   slang_function *fun;
-   int num_elements;
-
-   fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
-   if (!fun)
-      return NULL;
-
-   baseType = slang_type_specifier_type_from_string((char *) oper->a_id);
-
-   num_elements = oper->num_children;
-
-   /* function header, return type */
-   {
-      fun->header.a_name = oper->a_id;
-      fun->header.type.qualifier = SLANG_QUAL_NONE;
-      fun->header.type.specifier.type = SLANG_SPEC_ARRAY;
-      fun->header.type.specifier._array =
-         slang_type_specifier_new(baseType, NULL, NULL);
-      fun->header.type.array_len = num_elements;
-   }
-
-   /* function parameters (= number of elements) */
-   {
-      GLint i;
-      for (i = 0; i < num_elements; i++) {
-         /*
-         printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name);
-         */
-         slang_variable *p = slang_variable_scope_grow(fun->parameters);
-         char name[10];
-         _mesa_snprintf(name, sizeof(name), "p%d", i);
-         p->a_name = slang_atom_pool_atom(A->atoms, name);
-         p->type.qualifier = SLANG_QUAL_CONST;
-         p->type.specifier.type = baseType;
-      }
-      fun->param_count = fun->parameters->num_variables;
-   }
-
-   /* Add __retVal to params */
-   {
-      slang_variable *p = slang_variable_scope_grow(fun->parameters);
-      slang_atom a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
-      assert(a_retVal);
-      p->a_name = a_retVal;
-      p->type = fun->header.type;
-      p->type.qualifier = SLANG_QUAL_OUT;
-      p->type.specifier.type = baseType;
-      fun->param_count++;
-   }
-
-   /* function body is:
-    *    block:
-    *       declare T;
-    *       T[0] = p0;
-    *       T[1] = p1;
-    *       ...
-    *       T[n] = pn;
-    *       return T;
-    */
-   {
-      slang_variable_scope *scope;
-      slang_variable *var;
-      GLint i;
-
-      fun->body = slang_operation_new(1);
-      fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-      fun->body->num_children = num_elements + 2;
-      fun->body->children = slang_operation_new(num_elements + 2);
-
-      scope = fun->body->locals;
-      scope->outer_scope = fun->parameters;
-
-      /* create local var 't' */
-      var = slang_variable_scope_grow(scope);
-      var->a_name = slang_atom_pool_atom(A->atoms, "ttt");
-      var->type = fun->header.type;/*XXX copy*/
-
-      /* declare t */
-      {
-         slang_operation *decl;
-
-         decl = &fun->body->children[0];
-         decl->type = SLANG_OPER_VARIABLE_DECL;
-         decl->locals = _slang_variable_scope_new(scope);
-         decl->a_id = var->a_name;
-      }
-
-      /* assign params to elements of t */
-      for (i = 0; i < num_elements; i++) {
-         slang_operation *assign = &fun->body->children[1 + i];
-
-         assign->type = SLANG_OPER_ASSIGN;
-         assign->locals = _slang_variable_scope_new(scope);
-         assign->num_children = 2;
-         assign->children = slang_operation_new(2);
-         
-         {
-            slang_operation *lhs = &assign->children[0];
-
-            lhs->type = SLANG_OPER_SUBSCRIPT;
-            lhs->locals = _slang_variable_scope_new(scope);
-            lhs->num_children = 2;
-            lhs->children = slang_operation_new(2);
-            lhs->children[0].type = SLANG_OPER_IDENTIFIER;
-            lhs->children[0].a_id = var->a_name;
-            lhs->children[0].locals = _slang_variable_scope_new(scope);
-
-            lhs->children[1].type = SLANG_OPER_LITERAL_INT;
-            lhs->children[1].literal[0] = (GLfloat) i;
-         }
-
-         {
-            slang_operation *rhs = &assign->children[1];
-
-            rhs->type = SLANG_OPER_IDENTIFIER;
-            rhs->locals = _slang_variable_scope_new(scope);
-            rhs->a_id = fun->parameters->variables[i]->a_name;
-         }         
-      }
-
-      /* return t; */
-      {
-         slang_operation *ret = &fun->body->children[num_elements + 1];
-
-         ret->type = SLANG_OPER_RETURN;
-         ret->locals = _slang_variable_scope_new(scope);
-         ret->num_children = 1;
-         ret->children = slang_operation_new(1);
-         ret->children[0].type = SLANG_OPER_IDENTIFIER;
-         ret->children[0].a_id = var->a_name;
-         ret->children[0].locals = _slang_variable_scope_new(scope);
-      }
-   }
-
-   /*
-   slang_print_function(fun, 1);
-   */
-
-   return fun;
-}
-
-
-static GLboolean
-_slang_is_vec_mat_type(const char *name)
-{
-   static const char *vecmat_types[] = {
-      "float", "int", "bool",
-      "vec2", "vec3", "vec4",
-      "ivec2", "ivec3", "ivec4",
-      "bvec2", "bvec3", "bvec4",
-      "mat2", "mat3", "mat4",
-      "mat2x3", "mat2x4", "mat3x2", "mat3x4", "mat4x2", "mat4x3",
-      NULL
-   };
-   int i;
-   for (i = 0; vecmat_types[i]; i++)
-      if (strcmp(name, vecmat_types[i]) == 0)
-         return GL_TRUE;
-   return GL_FALSE;
-}
-
-
-/**
- * Assemble a function call, given a particular function name.
- * \param name  the function's name (operators like '*' are possible).
- */
-static slang_ir_node *
-_slang_gen_function_call_name(slang_assemble_ctx *A, const char *name,
-                              slang_operation *oper, slang_operation *dest)
-{
-   slang_operation *params = oper->children;
-   const GLuint param_count = oper->num_children;
-   slang_atom atom;
-   slang_function *fun;
-   slang_ir_node *n;
-
-   atom = slang_atom_pool_atom(A->atoms, name);
-   if (atom == SLANG_ATOM_NULL)
-      return NULL;
-
-   if (oper->array_constructor) {
-      /* this needs special handling */
-      fun = _slang_make_array_constructor(A, oper);
-   }
-   else {
-      /* Try to find function by name and exact argument type matching */
-      GLboolean error = GL_FALSE;
-      fun = _slang_function_locate(A->space.funcs, atom, params, param_count,
-                                   &A->space, A->atoms, A->log, &error);
-      if (error) {
-         slang_info_log_error(A->log,
-                              "Function '%s' not found (check argument types)",
-                              name);
-         return NULL;
-      }
-   }
-
-   if (!fun) {
-      /* Next, try locating a constructor function for a user-defined type */
-      fun = _slang_locate_struct_constructor(A, name);
-   }
-
-   /*
-    * At this point, some heuristics are used to try to find a function
-    * that matches the calling signature by means of casting or "unrolling"
-    * of constructors.
-    */
-
-   if (!fun && _slang_is_vec_mat_type(name)) {
-      /* Next, if this call looks like a vec() or mat() constructor call,
-       * try "unwinding" the args to satisfy a constructor.
-       */
-      fun = _slang_find_function_by_max_argc(A->space.funcs, name);
-      if (fun) {
-         if (!_slang_adapt_call(oper, fun, &A->space, A->atoms, A->log)) {
-            slang_info_log_error(A->log,
-                                 "Function '%s' not found (check argument types)",
-                                 name);
-            return NULL;
-         }
-      }
-   }
-
-   if (!fun && _slang_is_vec_mat_type(name)) {
-      /* Next, try casting args to the types of the formal parameters */
-      int numArgs = oper->num_children;
-      fun = _slang_find_function_by_argc(A->space.funcs, name, numArgs);
-      if (!fun || !_slang_cast_func_params(oper, fun, &A->space, A->atoms, A->log)) {
-         slang_info_log_error(A->log,
-                              "Function '%s' not found (check argument types)",
-                              name);
-         return NULL;
-      }
-      assert(fun);
-   }
-
-   if (!fun) {
-      slang_info_log_error(A->log,
-                           "Function '%s' not found (check argument types)",
-                           name);
-      return NULL;
-   }
-
-   if (!fun->body) {
-      /* The function body may be in another compilation unit.
-       * We'll try concatenating the shaders and recompile at link time.
-       */
-      A->UnresolvedRefs = GL_TRUE;
-      return new_node1(IR_NOP, NULL);
-   }
-
-   /* type checking to be sure function's return type matches 'dest' type */
-   if (dest) {
-      slang_typeinfo t0;
-
-      slang_typeinfo_construct(&t0);
-      typeof_operation(A, dest, &t0);
-
-      if (!slang_type_specifier_equal(&t0.spec, &fun->header.type.specifier)) {
-         slang_info_log_error(A->log,
-                              "Incompatible type returned by call to '%s'",
-                              name);
-         return NULL;
-      }
-   }
-
-   n = _slang_gen_function_call(A, fun, oper, dest);
-
-   if (n && !n->Store && !dest
-       && fun->header.type.specifier.type != SLANG_SPEC_VOID) {
-      /* setup n->Store for the result of the function call */
-      GLint size = _slang_sizeof_type_specifier(&fun->header.type.specifier);
-      n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, size);
-      /*printf("Alloc storage for function result, size %d \n", size);*/
-   }
-
-   if (oper->array_constructor) {
-      /* free the temporary array constructor function now */
-      slang_function_destruct(fun);
-   }
-
-   return n;
-}
-
-
-static slang_ir_node *
-_slang_gen_method_call(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_atom *a_length = slang_atom_pool_atom(A->atoms, "length");
-   slang_ir_node *n;
-   slang_variable *var;
-
-   /* NOTE: In GLSL 1.20, there's only one kind of method
-    * call: array.length().  Anything else is an error.
-    */
-   if (oper->a_id != a_length) {
-      slang_info_log_error(A->log,
-                           "Undefined method call '%s'", (char *) oper->a_id);
-      return NULL;
-   }
-
-   /* length() takes no arguments */
-   if (oper->num_children > 0) {
-      slang_info_log_error(A->log, "Invalid arguments to length() method");
-      return NULL;
-   }
-
-   /* lookup the object/variable */
-   var = _slang_variable_locate(oper->locals, oper->a_obj, GL_TRUE);
-   if (!var || var->type.specifier.type != SLANG_SPEC_ARRAY) {
-      slang_info_log_error(A->log,
-                           "Undefined object '%s'", (char *) oper->a_obj);
-      return NULL;
-   }
-
-   /* Create a float/literal IR node encoding the array length */
-   n = new_node0(IR_FLOAT);
-   if (n) {
-      n->Value[0] = (float) _slang_array_length(var);
-      n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, 1);
-   }
-   return n;
-}
-
-
-static GLboolean
-_slang_is_constant_cond(const slang_operation *oper, GLboolean *value)
-{
-   if (oper->type == SLANG_OPER_LITERAL_FLOAT ||
-       oper->type == SLANG_OPER_LITERAL_INT ||
-       oper->type == SLANG_OPER_LITERAL_BOOL) {
-      if (oper->literal[0])
-         *value = GL_TRUE;
-      else
-         *value = GL_FALSE;
-      return GL_TRUE;
-   }
-   else if (oper->type == SLANG_OPER_EXPRESSION &&
-            oper->num_children == 1) {
-      return _slang_is_constant_cond(&oper->children[0], value);
-   }
-   return GL_FALSE;
-}
-
-
-/**
- * Test if an operation is a scalar or boolean.
- */
-static GLboolean
-_slang_is_scalar_or_boolean(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_typeinfo type;
-   GLint size;
-
-   slang_typeinfo_construct(&type);
-   typeof_operation(A, oper, &type);
-   size = _slang_sizeof_type_specifier(&type.spec);
-   slang_typeinfo_destruct(&type);
-   return size == 1;
-}
-
-
-/**
- * Test if an operation is boolean.
- */
-static GLboolean
-_slang_is_boolean(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_typeinfo type;
-   GLboolean isBool;
-
-   slang_typeinfo_construct(&type);
-   typeof_operation(A, oper, &type);
-   isBool = (type.spec.type == SLANG_SPEC_BOOL);
-   slang_typeinfo_destruct(&type);
-   return isBool;
-}
-
-
-/**
- * Check if a loop contains a 'continue' statement.
- * Stop looking if we find a nested loop.
- */
-static GLboolean
-_slang_loop_contains_continue(const slang_operation *oper)
-{
-   switch (oper->type) {
-   case SLANG_OPER_CONTINUE:
-      return GL_TRUE;
-   case SLANG_OPER_FOR:
-   case SLANG_OPER_DO:
-   case SLANG_OPER_WHILE:
-      /* stop upon finding a nested loop */
-      return GL_FALSE;
-   default:
-       /* recurse */
-      {
-         GLuint i;
-         for (i = 0; i < oper->num_children; i++) {
-            const slang_operation *child = slang_oper_child_const(oper, i);
-            if (_slang_loop_contains_continue(child))
-               return GL_TRUE;
-         }
-      }
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Check if a loop contains a 'continue' or 'break' statement.
- * Stop looking if we find a nested loop.
- */
-static GLboolean
-_slang_loop_contains_continue_or_break(const slang_operation *oper)
-{
-   switch (oper->type) {
-   case SLANG_OPER_CONTINUE:
-   case SLANG_OPER_BREAK:
-      return GL_TRUE;
-   case SLANG_OPER_FOR:
-   case SLANG_OPER_DO:
-   case SLANG_OPER_WHILE:
-      /* stop upon finding a nested loop */
-      return GL_FALSE;
-   default:
-       /* recurse */
-      {
-         GLuint i;
-         for (i = 0; i < oper->num_children; i++) {
-            const slang_operation *child = slang_oper_child_const(oper, i);
-            if (_slang_loop_contains_continue_or_break(child))
-               return GL_TRUE;
-         }
-      }
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Replace 'break' and 'continue' statements inside a do and while loops.
- * This is a recursive helper function used by
- * _slang_gen_do/while_without_continue().
- */
-static void
-replace_break_and_cont(slang_assemble_ctx *A, slang_operation *oper)
-{
-   switch (oper->type) {
-   case SLANG_OPER_BREAK:
-      /* replace 'break' with "_notBreakFlag = false; break" */
-      {
-         slang_operation *block = oper;
-         block->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-         slang_operation_add_children(block, 2);
-         {
-            slang_operation *assign = slang_oper_child(block, 0);
-            assign->type = SLANG_OPER_ASSIGN;
-            slang_operation_add_children(assign, 2);
-            {
-               slang_operation *lhs = slang_oper_child(assign, 0);
-               slang_operation_identifier(lhs, A, "_notBreakFlag");
-            }
-            {
-               slang_operation *rhs = slang_oper_child(assign, 1);
-               slang_operation_literal_bool(rhs, GL_FALSE);
-            }
-         }
-         {
-            slang_operation *brk = slang_oper_child(block, 1);
-            brk->type = SLANG_OPER_BREAK;
-            assert(!brk->children);
-         }
-      }
-      break;
-   case SLANG_OPER_CONTINUE:
-      /* convert continue into a break */
-      oper->type = SLANG_OPER_BREAK;
-      break;
-   case SLANG_OPER_FOR:
-   case SLANG_OPER_DO:
-   case SLANG_OPER_WHILE:
-      /* stop upon finding a nested loop */
-      break;
-   default:
-      /* recurse */
-      {
-         GLuint i;
-         for (i = 0; i < oper->num_children; i++) {
-            replace_break_and_cont(A, slang_oper_child(oper, i));
-         }
-      }
-   }
-}
-
-
-/**
- * Transform a while-loop so that continue statements are converted to breaks.
- * Then do normal IR code generation.
- *
- * Before:
- * 
- * while (LOOPCOND) {
- *    A;
- *    if (IFCOND)
- *       continue;
- *    B;
- *    break;
- *    C;
- * }
- * 
- * After:
- * 
- * {
- *    bool _notBreakFlag = 1;
- *    while (_notBreakFlag && LOOPCOND) {
- *       do {
- *          A;
- *          if (IFCOND) {
- *             break;  // was continue
- *          }
- *          B;
- *          _notBreakFlag = 0; // was
- *          break;             // break
- *          C;
- *       } while (0)
- *    }
- * }
- */
-static slang_ir_node *
-_slang_gen_while_without_continue(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_operation *top;
-   slang_operation *innerBody;
-
-   assert(oper->type == SLANG_OPER_WHILE);
-
-   top = slang_operation_new(1);
-   top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-   top->locals->outer_scope = oper->locals->outer_scope;
-   slang_operation_add_children(top, 2);
-
-   /* declare: bool _notBreakFlag = true */
-   {
-      slang_operation *condDecl = slang_oper_child(top, 0);
-      slang_generate_declaration(A, top->locals, condDecl,
-                                 SLANG_SPEC_BOOL, "_notBreakFlag", GL_TRUE);
-   }
-
-   /* build outer while-loop:  while (_notBreakFlag && LOOPCOND) { ... } */
-   {
-      slang_operation *outerWhile = slang_oper_child(top, 1);
-      outerWhile->type = SLANG_OPER_WHILE;
-      slang_operation_add_children(outerWhile, 2);
-
-      /* _notBreakFlag && LOOPCOND */
-      {
-         slang_operation *cond = slang_oper_child(outerWhile, 0);
-         cond->type = SLANG_OPER_LOGICALAND;
-         slang_operation_add_children(cond, 2);
-         {
-            slang_operation *notBreak = slang_oper_child(cond, 0);
-            slang_operation_identifier(notBreak, A, "_notBreakFlag");
-         }
-         {
-            slang_operation *origCond = slang_oper_child(cond, 1);
-            slang_operation_copy(origCond, slang_oper_child(oper, 0));
-         }
-      }
-
-      /* inner loop */
-      {
-         slang_operation *innerDo = slang_oper_child(outerWhile, 1);
-         innerDo->type = SLANG_OPER_DO;
-         slang_operation_add_children(innerDo, 2);
-
-         /* copy original do-loop body into inner do-loop's body */
-         innerBody = slang_oper_child(innerDo, 0);
-         slang_operation_copy(innerBody, slang_oper_child(oper, 1));
-         innerBody->locals->outer_scope = innerDo->locals;
-
-         /* inner do-loop's condition is constant/false */
-         {
-            slang_operation *constFalse = slang_oper_child(innerDo, 1);
-            slang_operation_literal_bool(constFalse, GL_FALSE);
-         }
-      }
-   }
-
-   /* Finally, in innerBody,
-    *   replace "break" with "_notBreakFlag = 0; break"
-    *   replace "continue" with "break"
-    */
-   replace_break_and_cont(A, innerBody);
-
-   /*slang_print_tree(top, 0);*/
-
-   return _slang_gen_operation(A, top);
-
-   return NULL;
-}
-
-
-/**
- * Generate loop code using high-level IR_LOOP instruction
- */
-static slang_ir_node *
-_slang_gen_while(slang_assemble_ctx * A, slang_operation *oper)
-{
-   /*
-    * LOOP:
-    *    BREAK if !expr (child[0])
-    *    body code (child[1])
-    */
-   slang_ir_node *loop, *breakIf, *body;
-   GLboolean isConst, constTrue = GL_FALSE;
-
-   if (!A->EmitContReturn) {
-      /* We don't want to emit CONT instructions.  If this while-loop has
-       * a continue, translate it away.
-       */
-      if (_slang_loop_contains_continue(slang_oper_child(oper, 1))) {
-         return _slang_gen_while_without_continue(A, oper);
-      }
-   }
-
-   /* type-check expression */
-   if (!_slang_is_boolean(A, &oper->children[0])) {
-      slang_info_log_error(A->log, "scalar/boolean expression expected for 'while'");
-      return NULL;
-   }
-
-   /* Check if loop condition is a constant */
-   isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
-
-   if (isConst && !constTrue) {
-      /* loop is never executed! */
-      return new_node0(IR_NOP);
-   }
-
-   /* Begin new loop */
-   loop = new_loop(NULL);
-
-   /* save loop state */
-   push_loop(A, oper, loop);
-
-   if (isConst && constTrue) {
-      /* while(nonzero constant), no conditional break */
-      breakIf = NULL;
-   }
-   else {
-      slang_ir_node *cond
-         = new_cond(new_not(_slang_gen_operation(A, &oper->children[0])));
-      breakIf = new_break_if_true(A, cond);
-   }
-   body = _slang_gen_operation(A, &oper->children[1]);
-   loop->Children[0] = new_seq(breakIf, body);
-
-   /* Do infinite loop detection */
-   /* loop->List is head of linked list of break/continue nodes */
-   if (!loop->List && isConst && constTrue) {
-      /* infinite loop detected */
-      pop_loop(A);
-      slang_info_log_error(A->log, "Infinite loop detected!");
-      return NULL;
-   }
-
-   /* restore loop state */
-   pop_loop(A);
-
-   return loop;
-}
-
-
-/**
- * Transform a do-while-loop so that continue statements are converted to breaks.
- * Then do normal IR code generation.
- *
- * Before:
- * 
- * do {
- *    A;
- *    if (IFCOND)
- *       continue;
- *    B;
- *    break;
- *    C;
- * } while (LOOPCOND);
- * 
- * After:
- * 
- * {
- *    bool _notBreakFlag = 1;
- *    do {
- *       do {
- *          A;
- *          if (IFCOND) {
- *             break;  // was continue
- *          }
- *          B;
- *          _notBreakFlag = 0; // was
- *          break;             // break
- *          C;
- *       } while (0)
- *    } while (_notBreakFlag && LOOPCOND);
- * }
- */
-static slang_ir_node *
-_slang_gen_do_without_continue(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_operation *top;
-   slang_operation *innerBody;
-
-   assert(oper->type == SLANG_OPER_DO);
-
-   top = slang_operation_new(1);
-   top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-   top->locals->outer_scope = oper->locals->outer_scope;
-   slang_operation_add_children(top, 2);
-
-   /* declare: bool _notBreakFlag = true */
-   {
-      slang_operation *condDecl = slang_oper_child(top, 0);
-      slang_generate_declaration(A, top->locals, condDecl,
-                                 SLANG_SPEC_BOOL, "_notBreakFlag", GL_TRUE);
-   }
-
-   /* build outer do-loop:  do { ... } while (_notBreakFlag && LOOPCOND) */
-   {
-      slang_operation *outerDo = slang_oper_child(top, 1);
-      outerDo->type = SLANG_OPER_DO;
-      slang_operation_add_children(outerDo, 2);
-
-      /* inner do-loop */
-      {
-         slang_operation *innerDo = slang_oper_child(outerDo, 0);
-         innerDo->type = SLANG_OPER_DO;
-         slang_operation_add_children(innerDo, 2);
-
-         /* copy original do-loop body into inner do-loop's body */
-         innerBody = slang_oper_child(innerDo, 0);
-         slang_operation_copy(innerBody, slang_oper_child(oper, 0));
-         innerBody->locals->outer_scope = innerDo->locals;
-
-         /* inner do-loop's condition is constant/false */
-         {
-            slang_operation *constFalse = slang_oper_child(innerDo, 1);
-            slang_operation_literal_bool(constFalse, GL_FALSE);
-         }
-      }
-
-      /* _notBreakFlag && LOOPCOND */
-      {
-         slang_operation *cond = slang_oper_child(outerDo, 1);
-         cond->type = SLANG_OPER_LOGICALAND;
-         slang_operation_add_children(cond, 2);
-         {
-            slang_operation *notBreak = slang_oper_child(cond, 0);
-            slang_operation_identifier(notBreak, A, "_notBreakFlag");
-         }
-         {
-            slang_operation *origCond = slang_oper_child(cond, 1);
-            slang_operation_copy(origCond, slang_oper_child(oper, 1));
-         }
-      }
-   }
-
-   /* Finally, in innerBody,
-    *   replace "break" with "_notBreakFlag = 0; break"
-    *   replace "continue" with "break"
-    */
-   replace_break_and_cont(A, innerBody);
-
-   /*slang_print_tree(top, 0);*/
-
-   return _slang_gen_operation(A, top);
-}
-
-
-/**
- * Generate IR tree for a do-while loop using high-level LOOP, IF instructions.
- */
-static slang_ir_node *
-_slang_gen_do(slang_assemble_ctx * A, slang_operation *oper)
-{
-   /*
-    * LOOP:
-    *    body code (child[0])
-    *    tail code:
-    *       BREAK if !expr (child[1])
-    */
-   slang_ir_node *loop;
-   GLboolean isConst, constTrue;
-
-   if (!A->EmitContReturn) {
-      /* We don't want to emit CONT instructions.  If this do-loop has
-       * a continue, translate it away.
-       */
-      if (_slang_loop_contains_continue(slang_oper_child(oper, 0))) {
-         return _slang_gen_do_without_continue(A, oper);
-      }
-   }
-
-   /* type-check expression */
-   if (!_slang_is_boolean(A, &oper->children[1])) {
-      slang_info_log_error(A->log, "scalar/boolean expression expected for 'do/while'");
-      return NULL;
-   }
-
-   loop = new_loop(NULL);
-
-   /* save loop state */
-   push_loop(A, oper, loop);
-
-   /* loop body: */
-   loop->Children[0] = _slang_gen_operation(A, &oper->children[0]);
-
-   /* Check if loop condition is a constant */
-   isConst = _slang_is_constant_cond(&oper->children[1], &constTrue);
-   if (isConst && constTrue) {
-      /* do { } while(1)   ==> no conditional break */
-      loop->Children[1] = NULL; /* no tail code */
-   }
-   else {
-      slang_ir_node *cond
-         = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
-      loop->Children[1] = new_break_if_true(A, cond);
-   }
-
-   /* XXX we should do infinite loop detection, as above */
-
-   /* restore loop state */
-   pop_loop(A);
-
-   return loop;
-}
-
-
-/**
- * Recursively count the number of operations rooted at 'oper'.
- * This gives some kind of indication of the size/complexity of an operation.
- */
-static GLuint
-sizeof_operation(const slang_operation *oper)
-{
-   if (oper) {
-      GLuint count = 1; /* me */
-      GLuint i;
-      for (i = 0; i < oper->num_children; i++) {
-         count += sizeof_operation(&oper->children[i]);
-      }
-      return count;
-   }
-   else {
-      return 0;
-   }
-}
-
-
-/**
- * Determine if a for-loop can be unrolled.
- * At this time, only a rather narrow class of for loops can be unrolled.
- * See code for details.
- * When a loop can't be unrolled because it's too large we'll emit a
- * message to the log.
- */
-static GLboolean
-_slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   GLuint bodySize;
-   GLint start, end;
-   const char *varName;
-   slang_atom varId;
-
-   if (oper->type != SLANG_OPER_FOR)
-      return GL_FALSE;
-
-   assert(oper->num_children == 4);
-
-   if (_slang_loop_contains_continue_or_break(slang_oper_child_const(oper, 3)))
-      return GL_FALSE;
-
-   /* children[0] must be either "int i=constant" or "i=constant" */
-   if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
-      slang_variable *var;
-
-      if (oper->children[0].children[0].type != SLANG_OPER_VARIABLE_DECL)
-         return GL_FALSE;
-
-      varId = oper->children[0].children[0].a_id;
-
-      var = _slang_variable_locate(oper->children[0].children[0].locals,
-                                   varId, GL_TRUE);
-      if (!var)
-         return GL_FALSE;
-      if (!var->initializer)
-         return GL_FALSE;
-      if (var->initializer->type != SLANG_OPER_LITERAL_INT)
-         return GL_FALSE;
-      start = (GLint) var->initializer->literal[0];
-   }
-   else if (oper->children[0].type == SLANG_OPER_EXPRESSION) {
-      if (oper->children[0].children[0].type != SLANG_OPER_ASSIGN)
-         return GL_FALSE;
-      if (oper->children[0].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
-         return GL_FALSE;
-      if (oper->children[0].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
-         return GL_FALSE;
-
-      varId = oper->children[0].children[0].children[0].a_id;
-
-      start = (GLint) oper->children[0].children[0].children[1].literal[0];
-   }
-   else {
-      return GL_FALSE;
-   }
-
-   /* children[1] must be "i<constant" */
-   if (oper->children[1].type != SLANG_OPER_EXPRESSION)
-      return GL_FALSE;
-   if (oper->children[1].children[0].type != SLANG_OPER_LESS)
-      return GL_FALSE;
-   if (oper->children[1].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
-      return GL_FALSE;
-   if (oper->children[1].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
-      return GL_FALSE;
-
-   end = (GLint) oper->children[1].children[0].children[1].literal[0];
-
-   /* children[2] must be "i++" or "++i" */
-   if (oper->children[2].type != SLANG_OPER_POSTINCREMENT &&
-       oper->children[2].type != SLANG_OPER_PREINCREMENT)
-      return GL_FALSE;
-   if (oper->children[2].children[0].type != SLANG_OPER_IDENTIFIER)
-      return GL_FALSE;
-
-   /* make sure the same variable name is used in all places */
-   if ((oper->children[1].children[0].children[0].a_id != varId) ||
-       (oper->children[2].children[0].a_id != varId))
-      return GL_FALSE;
-
-   varName = (const char *) varId;
-
-   /* children[3], the loop body, can't be too large */
-   bodySize = sizeof_operation(&oper->children[3]);
-   if (bodySize > MAX_FOR_LOOP_UNROLL_BODY_SIZE) {
-      slang_info_log_print(A->log,
-                           "Note: 'for (%s ... )' body is too large/complex"
-                           " to unroll",
-                           varName);
-      return GL_FALSE;
-   }
-
-   if (start >= end)
-      return GL_FALSE; /* degenerate case */
-
-   if ((GLuint)(end - start) > MAX_FOR_LOOP_UNROLL_ITERATIONS) {
-      slang_info_log_print(A->log,
-                           "Note: 'for (%s=%d; %s<%d; ++%s)' is too"
-                           " many iterations to unroll",
-                           varName, start, varName, end, varName);
-      return GL_FALSE;
-   }
-
-   if ((end - start) * bodySize > MAX_FOR_LOOP_UNROLL_COMPLEXITY) {
-      slang_info_log_print(A->log,
-                           "Note: 'for (%s=%d; %s<%d; ++%s)' will generate"
-                           " too much code to unroll",
-                           varName, start, varName, end, varName);
-      return GL_FALSE;
-   }
-
-   return GL_TRUE; /* we can unroll the loop */
-}
-
-
-/**
- * Unroll a for-loop.
- * First we determine the number of iterations to unroll.
- * Then for each iteration:
- *   make a copy of the loop body
- *   replace instances of the loop variable with the current iteration value
- *   generate IR code for the body
- * \return pointer to generated IR code or NULL if error, out of memory, etc.
- */
-static slang_ir_node *
-_slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   GLint start, end, iter;
-   slang_ir_node *n, *root = NULL;
-   slang_atom varId;
-
-   if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
-      /* for (int i=0; ... */
-      slang_variable *var;
-
-      varId = oper->children[0].children[0].a_id;
-      var = _slang_variable_locate(oper->children[0].children[0].locals,
-                                   varId, GL_TRUE);
-      assert(var);
-      start = (GLint) var->initializer->literal[0];
-   }
-   else {
-      /* for (i=0; ... */
-      varId = oper->children[0].children[0].children[0].a_id;
-      start = (GLint) oper->children[0].children[0].children[1].literal[0];
-   }
-
-   end = (GLint) oper->children[1].children[0].children[1].literal[0];
-
-   for (iter = start; iter < end; iter++) {
-      slang_operation *body;
-
-      /* make a copy of the loop body */
-      body = slang_operation_new(1);
-      if (!body)
-         return NULL;
-
-      if (!slang_operation_copy(body, &oper->children[3]))
-         return NULL;
-
-      /* in body, replace instances of 'varId' with literal 'iter' */
-      {
-         slang_variable *oldVar;
-         slang_operation *newOper;
-
-         oldVar = _slang_variable_locate(oper->locals, varId, GL_TRUE);
-         if (!oldVar) {
-            /* undeclared loop variable */
-            slang_operation_delete(body);
-            return NULL;
-         }
-
-         newOper = slang_operation_new(1);
-         newOper->type = SLANG_OPER_LITERAL_INT;
-         newOper->literal_size = 1;
-         newOper->literal[0] = (GLfloat) iter;
-
-         /* replace instances of the loop variable with newOper */
-         slang_substitute(A, body, 1, &oldVar, &newOper, GL_FALSE);
-      }
-
-      /* do IR codegen for body */
-      n = _slang_gen_operation(A, body);
-      if (!n)
-         return NULL;
-
-      root = new_seq(root, n);
-
-      slang_operation_delete(body);
-   }
-
-   return root;
-}
-
-
-/**
- * Replace 'continue' statement with 'break' inside a for-loop.
- * This is a recursive helper function used by _slang_gen_for_without_continue().
- */
-static void
-replace_continue_with_break(slang_assemble_ctx *A, slang_operation *oper)
-{
-   switch (oper->type) {
-   case SLANG_OPER_CONTINUE:
-      oper->type = SLANG_OPER_BREAK;
-      break;
-   case SLANG_OPER_FOR:
-   case SLANG_OPER_DO:
-   case SLANG_OPER_WHILE:
-      /* stop upon finding a nested loop */
-      break;
-   default:
-      /* recurse */
-      {
-         GLuint i;
-         for (i = 0; i < oper->num_children; i++) {
-            replace_continue_with_break(A, slang_oper_child(oper, i));
-         }
-      }
-   }
-}
-
-
-/**
- * Transform a for-loop so that continue statements are converted to breaks.
- * Then do normal IR code generation.
- *
- * Before:
- * 
- * for (INIT; LOOPCOND; INCR) {
- *    A;
- *    if (IFCOND) {
- *       continue;
- *    }
- *    B;
- * }
- * 
- * After:
- * 
- * {
- *    bool _condFlag = 1;
- *    for (INIT; _condFlag; ) {
- *       for ( ; _condFlag = LOOPCOND; INCR) {
- *          A;
- *          if (IFCOND) {
- *             break;
- *          }
- *          B;
- *       }
- *       if (_condFlag)
- *          INCR;
- *    }
- * }
- */
-static slang_ir_node *
-_slang_gen_for_without_continue(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_operation *top;
-   slang_operation *outerFor, *innerFor, *init, *cond, *incr;
-   slang_operation *lhs, *rhs;
-
-   assert(oper->type == SLANG_OPER_FOR);
-
-   top = slang_operation_new(1);
-   top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-   top->locals->outer_scope = oper->locals->outer_scope;
-   slang_operation_add_children(top, 2);
-
-   /* declare: bool _condFlag = true */
-   {
-      slang_operation *condDecl = slang_oper_child(top, 0);
-      slang_generate_declaration(A, top->locals, condDecl,
-                                 SLANG_SPEC_BOOL, "_condFlag", GL_TRUE);
-   }
-
-   /* build outer loop:  for (INIT; _condFlag; ) { */
-   outerFor = slang_oper_child(top, 1);
-   outerFor->type = SLANG_OPER_FOR;
-   slang_operation_add_children(outerFor, 4);
-
-   init = slang_oper_child(outerFor, 0);
-   slang_operation_copy(init, slang_oper_child(oper, 0));
-
-   cond = slang_oper_child(outerFor, 1);
-   cond->type = SLANG_OPER_IDENTIFIER;
-   cond->a_id = slang_atom_pool_atom(A->atoms, "_condFlag");
-
-   incr = slang_oper_child(outerFor, 2);
-   incr->type = SLANG_OPER_VOID;
-
-   /* body of the outer loop */
-   {
-      slang_operation *block = slang_oper_child(outerFor, 3);
-
-      slang_operation_add_children(block, 2);
-      block->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
-
-      /* build inner loop:  for ( ; _condFlag = LOOPCOND; INCR) { */
-      {
-         innerFor = slang_oper_child(block, 0);
-
-         /* make copy of orig loop */
-         slang_operation_copy(innerFor, oper);
-         assert(innerFor->type == SLANG_OPER_FOR);
-         innerFor->locals->outer_scope = block->locals;
-
-         init = slang_oper_child(innerFor, 0);
-         init->type = SLANG_OPER_VOID; /* leak? */
-
-         cond = slang_oper_child(innerFor, 1);
-         slang_operation_destruct(cond);
-         cond->type = SLANG_OPER_ASSIGN;
-         cond->locals = _slang_variable_scope_new(innerFor->locals);
-         slang_operation_add_children(cond, 2);
-
-         lhs = slang_oper_child(cond, 0);
-         lhs->type = SLANG_OPER_IDENTIFIER;
-         lhs->a_id = slang_atom_pool_atom(A->atoms, "_condFlag");
-
-         rhs = slang_oper_child(cond, 1);
-         slang_operation_copy(rhs, slang_oper_child(oper, 1));
-      }
-
-      /* if (_condFlag) INCR; */
-      {
-         slang_operation *ifop = slang_oper_child(block, 1);
-         ifop->type = SLANG_OPER_IF;
-         slang_operation_add_children(ifop, 2);
-
-         /* re-use cond node build above */
-         slang_operation_copy(slang_oper_child(ifop, 0), cond);
-
-         /* incr node from original for-loop operation */
-         slang_operation_copy(slang_oper_child(ifop, 1),
-                              slang_oper_child(oper, 2));
-      }
-
-      /* finally, replace "continue" with "break" in the inner for-loop */
-      replace_continue_with_break(A, slang_oper_child(innerFor, 3));
-   }
-
-   return _slang_gen_operation(A, top);
-}
-
-
-
-/**
- * Generate IR for a for-loop.  Unrolling will be done when possible.
- */
-static slang_ir_node *
-_slang_gen_for(slang_assemble_ctx * A, slang_operation *oper)
-{
-   GLboolean unroll;
-
-   if (!A->EmitContReturn) {
-      /* We don't want to emit CONT instructions.  If this for-loop has
-       * a continue, translate it away.
-       */
-      if (_slang_loop_contains_continue(slang_oper_child(oper, 3))) {
-         return _slang_gen_for_without_continue(A, oper);
-      }
-   }
-
-   unroll = _slang_can_unroll_for_loop(A, oper);
-   if (unroll) {
-      slang_ir_node *code = _slang_unroll_for_loop(A, oper);
-      if (code)
-         return code;
-   }
-
-   assert(oper->type == SLANG_OPER_FOR);
-
-   /* conventional for-loop code generation */
-   {
-      /*
-       * init code (child[0])
-       * LOOP:
-       *    BREAK if !expr (child[1])
-       *    body code (child[3])
-       *    tail code:
-       *       incr code (child[2])   // XXX continue here
-       */
-      slang_ir_node *loop, *cond, *breakIf, *body, *init, *incr;
-      init = _slang_gen_operation(A, &oper->children[0]);
-      loop = new_loop(NULL);
-
-      /* save loop state */
-      push_loop(A, oper, loop);
-
-      cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
-      breakIf = new_break_if_true(A, cond);
-      body = _slang_gen_operation(A, &oper->children[3]);
-      incr = _slang_gen_operation(A, &oper->children[2]);
-
-      loop->Children[0] = new_seq(breakIf, body);
-      loop->Children[1] = incr;  /* tail code */
-
-      /* restore loop state */
-      pop_loop(A);
-
-      return new_seq(init, loop);
-   }
-}
-
-
-static slang_ir_node *
-_slang_gen_continue(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   slang_ir_node *n, *cont, *incr = NULL, *loopNode;
-
-   assert(oper->type == SLANG_OPER_CONTINUE);
-   loopNode = current_loop_ir(A);
-   assert(loopNode);
-   assert(loopNode->Opcode == IR_LOOP);
-
-   cont = new_node0(IR_CONT);
-   if (cont) {
-      cont->Parent = loopNode;
-      /* insert this node at head of linked list of cont/break instructions */
-      cont->List = loopNode->List;
-      loopNode->List = cont;
-   }
-
-   n = new_seq(incr, cont);
-   return n;
-}
-
-
-/**
- * Determine if the given operation is of a specific type.
- */
-static GLboolean
-is_operation_type(const slang_operation *oper, slang_operation_type type)
-{
-   if (oper->type == type)
-      return GL_TRUE;
-   else if ((oper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
-             oper->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) &&
-            oper->num_children == 1)
-      return is_operation_type(&oper->children[0], type);
-   else
-      return GL_FALSE;
-}
-
-
-/**
- * Generate IR tree for an if/then/else conditional using high-level
- * IR_IF instruction.
- */
-static slang_ir_node *
-_slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   /*
-    * eval expr (child[0])
-    * IF expr THEN
-    *    if-body code
-    * ELSE
-    *    else-body code
-    * ENDIF
-    */
-   const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]);
-   slang_ir_node *ifNode, *cond, *ifBody, *elseBody;
-   GLboolean isConst, constTrue;
-
-   /* type-check expression */
-   if (!_slang_is_boolean(A, &oper->children[0])) {
-      slang_info_log_error(A->log, "boolean expression expected for 'if'");
-      return NULL;
-   }
-
-   if (!_slang_is_scalar_or_boolean(A, &oper->children[0])) {
-      slang_info_log_error(A->log, "scalar/boolean expression expected for 'if'");
-      return NULL;
-   }
-
-   isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
-   if (isConst) {
-      if (constTrue) {
-         /* if (true) ... */
-         return _slang_gen_operation(A, &oper->children[1]);
-      }
-      else {
-         /* if (false) ... */
-         return _slang_gen_operation(A, &oper->children[2]);
-      }
-   }
-
-   cond = _slang_gen_operation(A, &oper->children[0]);
-   cond = new_cond(cond);
-
-   if (is_operation_type(&oper->children[1], SLANG_OPER_BREAK)
-       && !haveElseClause) {
-      /* Special case: generate a conditional break */
-      ifBody = new_break_if_true(A, cond);
-      return ifBody;
-   }
-   else if (is_operation_type(&oper->children[1], SLANG_OPER_CONTINUE)
-            && !haveElseClause
-            && current_loop_oper(A)
-            && current_loop_oper(A)->type != SLANG_OPER_FOR) {
-      /* Special case: generate a conditional continue */
-      ifBody = new_cont_if_true(A, cond);
-      return ifBody;
-   }
-   else {
-      /* general case */
-      ifBody = _slang_gen_operation(A, &oper->children[1]);
-      if (haveElseClause)
-         elseBody = _slang_gen_operation(A, &oper->children[2]);
-      else
-         elseBody = NULL;
-      ifNode = new_if(cond, ifBody, elseBody);
-      return ifNode;
-   }
-}
-
-
-
-static slang_ir_node *
-_slang_gen_not(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   slang_ir_node *n;
-
-   assert(oper->type == SLANG_OPER_NOT);
-
-   /* type-check expression */
-   if (!_slang_is_scalar_or_boolean(A, &oper->children[0])) {
-      slang_info_log_error(A->log,
-                           "scalar/boolean expression expected for '!'");
-      return NULL;
-   }
-
-   n = _slang_gen_operation(A, &oper->children[0]);
-   if (n)
-      return new_not(n);
-   else
-      return NULL;
-}
-
-
-static slang_ir_node *
-_slang_gen_xor(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   slang_ir_node *n1, *n2;
-
-   assert(oper->type == SLANG_OPER_LOGICALXOR);
-
-   if (!_slang_is_scalar_or_boolean(A, &oper->children[0]) ||
-       !_slang_is_scalar_or_boolean(A, &oper->children[0])) {
-      slang_info_log_error(A->log,
-                           "scalar/boolean expressions expected for '^^'");
-      return NULL;
-   }
-
-   n1 = _slang_gen_operation(A, &oper->children[0]);
-   if (!n1)
-      return NULL;
-   n2 = _slang_gen_operation(A, &oper->children[1]);
-   if (!n2)
-      return NULL;
-   return new_node2(IR_NOTEQUAL, n1, n2);
-}
-
-
-/**
- * Generate IR node for storage of a temporary of given size.
- */
-static slang_ir_node *
-_slang_gen_temporary(GLint size)
-{
-   slang_ir_storage *store;
-   slang_ir_node *n = NULL;
-
-   store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -2, size);
-   if (store) {
-      n = new_node0(IR_VAR_DECL);
-      if (n) {
-         n->Store = store;
-      }
-      else {
-         _slang_free(store);
-      }
-   }
-   return n;
-}
-
-
-/**
- * Generate program constants for an array.
- * Ex: const vec2[3] v = vec2[3](vec2(1,1), vec2(2,2), vec2(3,3));
- * This will allocate and initialize three vector constants, storing
- * the array in constant memory, not temporaries like a non-const array.
- * This can also be used for uniform array initializers.
- * \return GL_TRUE for success, GL_FALSE if failure (semantic error, etc).
- */
-static GLboolean
-make_constant_array(slang_assemble_ctx *A,
-                    slang_variable *var,
-                    slang_operation *initializer)
-{
-   struct gl_program *prog = A->program;
-   const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
-   const char *varName = (char *) var->a_name;
-   const GLuint numElements = initializer->num_children;
-   GLint size;
-   GLuint i, j;
-   GLfloat *values;
-
-   if (!var->store) {
-      var->store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -6, -6);
-   }
-   size = var->store->Size;
-
-   assert(var->type.qualifier == SLANG_QUAL_CONST ||
-          var->type.qualifier == SLANG_QUAL_UNIFORM);
-   assert(initializer->type == SLANG_OPER_CALL);
-   assert(initializer->array_constructor);
-
-   values = (GLfloat *) malloc(numElements * 4 * sizeof(GLfloat));
-
-   /* convert constructor params into ordinary floats */
-   for (i = 0; i < numElements; i++) {
-      const slang_operation *op = &initializer->children[i];
-      if (op->type != SLANG_OPER_LITERAL_FLOAT) {
-         /* unsupported type for this optimization */
-         free(values);
-         return GL_FALSE;
-      }
-      for (j = 0; j < op->literal_size; j++) {
-         values[i * 4 + j] = op->literal[j];
-      }
-      for ( ; j < 4; j++) {
-         values[i * 4 + j] = 0.0f;
-      }
-   }
-
-   /* slightly different paths for constants vs. uniforms */
-   if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
-      var->store->File = PROGRAM_UNIFORM;
-      var->store->Index = _mesa_add_uniform(prog->Parameters, varName,
-                                            size, datatype, values);
-   }
-   else {
-      var->store->File = PROGRAM_CONSTANT;
-      var->store->Index = _mesa_add_named_constant(prog->Parameters, varName,
-                                                   values, size);
-   }
-   assert(var->store->Size == size);
-
-   free(values);
-
-   return GL_TRUE;
-}
-
-
-
-/**
- * Generate IR node for allocating/declaring a variable (either a local or
- * a global).
- * Generally, this involves allocating an slang_ir_storage instance for the
- * variable, choosing a register file (temporary, constant, etc).
- * For ordinary variables we do not yet allocate storage though.  We do that
- * when we find the first actual use of the variable to avoid allocating temp
- * regs that will never get used.
- * At this time, uniforms are always allocated space in this function.
- *
- * \param initializer  Optional initializer expression for the variable.
- */
-static slang_ir_node *
-_slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
-                    slang_operation *initializer)
-{
-   const char *varName = (const char *) var->a_name;
-   const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
-   slang_ir_node *varDecl, *n;
-   slang_ir_storage *store;
-   GLint arrayLen, size, totalSize;  /* if array then totalSize > size */
-   gl_register_file file;
-
-   /*assert(!var->declared);*/
-   var->declared = GL_TRUE;
-
-   /* determine GPU register file for simple cases */
-   if (is_sampler_type(&var->type)) {
-      file = PROGRAM_SAMPLER;
-   }
-   else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
-      file = PROGRAM_UNIFORM;
-   }
-   else {
-      file = PROGRAM_TEMPORARY;
-   }
-
-   size = _slang_sizeof_type_specifier(&var->type.specifier);
-   if (size <= 0) {
-      slang_info_log_error(A->log, "invalid declaration for '%s'", varName);
-      return NULL;
-   }
-
-   arrayLen = _slang_array_length(var);
-   totalSize = _slang_array_size(size, arrayLen);
-
-   /* Allocate IR node for the declaration */
-   varDecl = new_node0(IR_VAR_DECL);
-   if (!varDecl)
-      return NULL;
-
-   /* Allocate slang_ir_storage for this variable if needed.
-    * Note that we may not actually allocate a constant or temporary register
-    * until later.
-    */
-   if (!var->store) {
-      GLint index = -7;  /* TBD / unknown */
-      var->store = _slang_new_ir_storage(file, index, totalSize);
-      if (!var->store)
-         return NULL; /* out of memory */
-   }
-
-   /* set the IR node's Var and Store pointers */
-   varDecl->Var = var;
-   varDecl->Store = var->store;
-
-
-   store = var->store;
-
-   /* if there's an initializer, generate IR for the expression */
-   if (initializer) {
-      slang_ir_node *varRef, *init;
-
-      if (var->type.qualifier == SLANG_QUAL_CONST) {
-         /* if the variable is const, the initializer must be a const
-          * expression as well.
-          */
-#if 0
-         if (!_slang_is_constant_expr(initializer)) {
-            slang_info_log_error(A->log,
-                                 "initializer for %s not constant", varName);
-            return NULL;
-         }
-#endif
-      }
-
-      if (var->type.qualifier == SLANG_QUAL_UNIFORM &&
-          !A->allow_uniform_initializers) {
-         slang_info_log_error(A->log,
-                              "initializer for uniform %s not allowed",
-                              varName);
-         return NULL;
-      }
-
-      /* IR for the variable we're initializing */
-      varRef = new_var(A, var);
-      if (!varRef) {
-         slang_info_log_error(A->log, "out of memory");
-         return NULL;
-      }
-
-      /* constant-folding, etc here */
-      _slang_simplify(initializer, &A->space, A->atoms); 
-
-      /* look for simple constant-valued variables and uniforms */
-      if (var->type.qualifier == SLANG_QUAL_CONST ||
-          var->type.qualifier == SLANG_QUAL_UNIFORM) {
-
-         if (initializer->type == SLANG_OPER_CALL &&
-             initializer->array_constructor) {
-            /* array initializer */
-            if (make_constant_array(A, var, initializer))
-               return varRef;
-         }
-         else if (initializer->type == SLANG_OPER_LITERAL_FLOAT ||
-                  initializer->type == SLANG_OPER_LITERAL_INT) {
-            /* simple float/vector initializer */
-            if (store->File == PROGRAM_UNIFORM) {
-               store->Index = _mesa_add_uniform(A->program->Parameters,
-                                                varName,
-                                                totalSize, datatype,
-                                                initializer->literal);
-               store->Swizzle = _slang_var_swizzle(size, 0);
-               return varRef;
-            }
-#if 0
-            else {
-               store->File = PROGRAM_CONSTANT;
-               store->Index = _mesa_add_named_constant(A->program->Parameters,
-                                                       varName,
-                                                       initializer->literal,
-                                                       totalSize);
-               store->Swizzle = _slang_var_swizzle(size, 0);
-               return varRef;
-            }
-#endif
-         }
-      }
-
-      /* IR for initializer */
-      init = _slang_gen_operation(A, initializer);
-      if (!init)
-         return NULL;
-
-      /* XXX remove this when type checking is added above */
-      if (init->Store && init->Store->Size != totalSize) {
-         slang_info_log_error(A->log, "invalid assignment (wrong types)");
-         return NULL;
-      }
-
-      /* assign RHS to LHS */
-      n = new_node2(IR_COPY, varRef, init);
-      n = new_seq(varDecl, n);
-   }
-   else {
-      /* no initializer */
-      n = varDecl;
-   }
-
-   if (store->File == PROGRAM_UNIFORM && store->Index < 0) {
-      /* always need to allocate storage for uniforms at this point */
-      store->Index = _mesa_add_uniform(A->program->Parameters, varName,
-                                       totalSize, datatype, NULL);
-      store->Swizzle = _slang_var_swizzle(size, 0);
-   }
-
-#if 0
-   printf("%s var %p %s  store=%p index=%d size=%d\n",
-          __FUNCTION__, (void *) var, (char *) varName,
-          (void *) store, store->Index, store->Size);
-#endif
-
-   return n;
-}
-
-
-/**
- * Generate code for a selection expression:   b ? x : y
- * XXX In some cases we could implement a selection expression
- * with an LRP instruction (use the boolean as the interpolant).
- * Otherwise, we use an IF/ELSE/ENDIF construct.
- */
-static slang_ir_node *
-_slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_ir_node *cond, *ifNode, *trueExpr, *falseExpr, *trueNode, *falseNode;
-   slang_ir_node *tmpDecl, *tmpVar, *tree;
-   slang_typeinfo type0, type1, type2;
-   int size, isBool, isEqual;
-
-   assert(oper->type == SLANG_OPER_SELECT);
-   assert(oper->num_children == 3);
-
-   /* type of children[0] must be boolean */
-   slang_typeinfo_construct(&type0);
-   typeof_operation(A, &oper->children[0], &type0);
-   isBool = (type0.spec.type == SLANG_SPEC_BOOL);
-   slang_typeinfo_destruct(&type0);
-   if (!isBool) {
-      slang_info_log_error(A->log, "selector type is not boolean");
-      return NULL;
-   }
-
-   slang_typeinfo_construct(&type1);
-   slang_typeinfo_construct(&type2);
-   typeof_operation(A, &oper->children[1], &type1);
-   typeof_operation(A, &oper->children[2], &type2);
-   isEqual = slang_type_specifier_equal(&type1.spec, &type2.spec);
-   slang_typeinfo_destruct(&type1);
-   slang_typeinfo_destruct(&type2);
-   if (!isEqual) {
-      slang_info_log_error(A->log, "incompatible types for ?: operator");
-      return NULL;
-   }
-
-   /* size of x or y's type */
-   size = _slang_sizeof_type_specifier(&type1.spec);
-   assert(size > 0);
-
-   /* temporary var */
-   tmpDecl = _slang_gen_temporary(size);
-
-   /* the condition (child 0) */
-   cond = _slang_gen_operation(A, &oper->children[0]);
-   cond = new_cond(cond);
-
-   /* if-true body (child 1) */
-   tmpVar = new_node0(IR_VAR);
-   tmpVar->Store = tmpDecl->Store;
-   trueExpr = _slang_gen_operation(A, &oper->children[1]);
-   trueNode = new_node2(IR_COPY, tmpVar, trueExpr);
-
-   /* if-false body (child 2) */
-   tmpVar = new_node0(IR_VAR);
-   tmpVar->Store = tmpDecl->Store;
-   falseExpr = _slang_gen_operation(A, &oper->children[2]);
-   falseNode = new_node2(IR_COPY, tmpVar, falseExpr);
-
-   ifNode = new_if(cond, trueNode, falseNode);
-
-   /* tmp var value */
-   tmpVar = new_node0(IR_VAR);
-   tmpVar->Store = tmpDecl->Store;
-
-   tree = new_seq(ifNode, tmpVar);
-   tree = new_seq(tmpDecl, tree);
-
-   /*_slang_print_ir_tree(tree, 10);*/
-   return tree;
-}
-
-
-/**
- * Generate code for &&.
- */
-static slang_ir_node *
-_slang_gen_logical_and(slang_assemble_ctx *A, slang_operation *oper)
-{
-   /* rewrite "a && b" as  "a ? b : false" */
-   slang_operation *select;
-   slang_ir_node *n;
-
-   select = slang_operation_new(1);
-   select->type = SLANG_OPER_SELECT;
-   slang_operation_add_children(select, 3);
-
-   slang_operation_copy(slang_oper_child(select, 0), &oper->children[0]);
-   slang_operation_copy(slang_oper_child(select, 1), &oper->children[1]);
-   slang_operation_literal_bool(slang_oper_child(select, 2), GL_FALSE);
-
-   n = _slang_gen_select(A, select);
-   return n;
-}
-
-
-/**
- * Generate code for ||.
- */
-static slang_ir_node *
-_slang_gen_logical_or(slang_assemble_ctx *A, slang_operation *oper)
-{
-   /* rewrite "a || b" as  "a ? true : b" */
-   slang_operation *select;
-   slang_ir_node *n;
-
-   select = slang_operation_new(1);
-   select->type = SLANG_OPER_SELECT;
-   slang_operation_add_children(select, 3);
-
-   slang_operation_copy(slang_oper_child(select, 0), &oper->children[0]);
-   slang_operation_literal_bool(slang_oper_child(select, 1), GL_TRUE);
-   slang_operation_copy(slang_oper_child(select, 2), &oper->children[1]);
-
-   n = _slang_gen_select(A, select);
-   return n;
-}
-
-
-/**
- * Generate IR tree for a return statement.
- */
-static slang_ir_node *
-_slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
-{
-   assert(oper->type == SLANG_OPER_RETURN);
-   return new_return(A->curFuncEndLabel);
-}
-
-
-#if 0
-/**
- * Determine if the given operation/expression is const-valued.
- */
-static GLboolean
-_slang_is_constant_expr(const slang_operation *oper)
-{
-   slang_variable *var;
-   GLuint i;
-
-   switch (oper->type) {
-   case SLANG_OPER_IDENTIFIER:
-      var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
-      if (var && var->type.qualifier == SLANG_QUAL_CONST)
-         return GL_TRUE;
-      return GL_FALSE;
-   default:
-      for (i = 0; i < oper->num_children; i++) {
-         if (!_slang_is_constant_expr(&oper->children[i]))
-            return GL_FALSE;
-      }
-      return GL_TRUE;
-   }
-}
-#endif
-
-
-/**
- * Check if an assignment of type t1 to t0 is legal.
- * XXX more cases needed.
- */
-static GLboolean
-_slang_assignment_compatible(slang_assemble_ctx *A,
-                             slang_operation *op0,
-                             slang_operation *op1)
-{
-   slang_typeinfo t0, t1;
-   GLuint sz0, sz1;
-
-   if (op0->type == SLANG_OPER_POSTINCREMENT ||
-       op0->type == SLANG_OPER_POSTDECREMENT) {
-      return GL_FALSE;
-   }
-
-   slang_typeinfo_construct(&t0);
-   typeof_operation(A, op0, &t0);
-
-   slang_typeinfo_construct(&t1);
-   typeof_operation(A, op1, &t1);
-
-   sz0 = _slang_sizeof_type_specifier(&t0.spec);
-   sz1 = _slang_sizeof_type_specifier(&t1.spec);
-
-#if 1
-   if (sz0 != sz1) {
-      /*printf("assignment size mismatch %u vs %u\n", sz0, sz1);*/
-      return GL_FALSE;
-   }
-#endif
-
-   if (t0.spec.type == SLANG_SPEC_STRUCT &&
-       t1.spec.type == SLANG_SPEC_STRUCT &&
-       t0.spec._struct->a_name != t1.spec._struct->a_name)
-      return GL_FALSE;
-
-   if (t0.spec.type == SLANG_SPEC_FLOAT &&
-       t1.spec.type == SLANG_SPEC_BOOL)
-      return GL_FALSE;
-
-#if 0 /* not used just yet - causes problems elsewhere */
-   if (t0.spec.type == SLANG_SPEC_INT &&
-       t1.spec.type == SLANG_SPEC_FLOAT)
-      return GL_FALSE;
-#endif
-
-   if (t0.spec.type == SLANG_SPEC_BOOL &&
-       t1.spec.type == SLANG_SPEC_FLOAT)
-      return GL_FALSE;
-
-   if (t0.spec.type == SLANG_SPEC_BOOL &&
-       t1.spec.type == SLANG_SPEC_INT)
-      return GL_FALSE;
-
-   return GL_TRUE;
-}
-
-
-/**
- * Generate IR tree for a local variable declaration.
- * Basically do some error checking and call _slang_gen_var_decl().
- */
-static slang_ir_node *
-_slang_gen_declaration(slang_assemble_ctx *A, slang_operation *oper)
-{
-   const char *varName = (char *) oper->a_id;
-   slang_variable *var;
-   slang_ir_node *varDecl;
-   slang_operation *initializer;
-
-   assert(oper->type == SLANG_OPER_VARIABLE_DECL);
-   assert(oper->num_children <= 1);
-
-
-   /* lookup the variable by name */
-   var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
-   if (!var)
-      return NULL;  /* "shouldn't happen" */
-
-   if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
-       var->type.qualifier == SLANG_QUAL_VARYING ||
-       var->type.qualifier == SLANG_QUAL_UNIFORM) {
-      /* can't declare attribute/uniform vars inside functions */
-      slang_info_log_error(A->log,
-                "local variable '%s' cannot be an attribute/uniform/varying",
-                varName);
-      return NULL;
-   }
-
-#if 0
-   if (v->declared) {
-      slang_info_log_error(A->log, "variable '%s' redeclared", varName);
-      return NULL;
-   }
-#endif
-
-   /* check if the var has an initializer */
-   if (oper->num_children > 0) {
-      assert(oper->num_children == 1);
-      initializer = &oper->children[0];
-   }
-   else if (var->initializer) {
-      initializer = var->initializer;
-   }
-   else {
-      initializer = NULL;
-   }
-
-   if (initializer) {
-      /* check/compare var type and initializer type */
-      if (!_slang_assignment_compatible(A, oper, initializer)) {
-         slang_info_log_error(A->log, "incompatible types in assignment");
-         return NULL;
-      }         
-   }
-   else {
-      if (var->type.qualifier == SLANG_QUAL_CONST) {
-         slang_info_log_error(A->log,
-                       "const-qualified variable '%s' requires initializer",
-                       varName);
-         return NULL;
-      }
-   }
-
-   /* Generate IR node */
-   varDecl = _slang_gen_var_decl(A, var, initializer);
-   if (!varDecl)
-      return NULL;
-
-   return varDecl;
-}
-
-
-/**
- * Generate IR tree for a reference to a variable (such as in an expression).
- * This is different from a variable declaration.
- */
-static slang_ir_node *
-_slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper)
-{
-   /* If there's a variable associated with this oper (from inlining)
-    * use it.  Otherwise, use the oper's var id.
-    */
-   slang_atom name = oper->var ? oper->var->a_name : oper->a_id;
-   slang_variable *var = _slang_variable_locate(oper->locals, name, GL_TRUE);
-   slang_ir_node *n;
-   if (!var || !var->declared) {
-      slang_info_log_error(A->log, "undefined variable '%s'", (char *) name);
-      return NULL;
-   }
-   n = new_var(A, var);
-   return n;
-}
-
-
-
-/**
- * Return the number of components actually named by the swizzle.
- * Recall that swizzles may have undefined/don't-care values.
- */
-static GLuint
-swizzle_size(GLuint swizzle)
-{
-   GLuint size = 0, i;
-   for (i = 0; i < 4; i++) {
-      GLuint swz = GET_SWZ(swizzle, i);
-      size += (swz <= 3);
-   }
-   return size;
-}
-
-
-static slang_ir_node *
-_slang_gen_swizzle(slang_ir_node *child, GLuint swizzle)
-{
-   slang_ir_node *n = new_node1(IR_SWIZZLE, child);
-   assert(child);
-   if (n) {
-      assert(!n->Store);
-      n->Store = _slang_new_ir_storage_relative(0,
-                                                swizzle_size(swizzle),
-                                                child->Store);
-      assert(n->Store);
-      n->Store->Swizzle = swizzle;
-   }
-   return n;
-}
-
-
-static GLboolean
-is_store_writable(const slang_assemble_ctx *A, const slang_ir_storage *store)
-{
-   while (store->Parent)
-      store = store->Parent;
-
-   if (!(store->File == PROGRAM_OUTPUT ||
-         store->File == PROGRAM_TEMPORARY ||
-         (store->File == PROGRAM_VARYING &&
-          A->program->Target == GL_VERTEX_PROGRAM_ARB))) {
-      return GL_FALSE;
-   }
-   else {
-      return GL_TRUE;
-   }
-}
-
-
-/**
- * Walk up an IR storage path to compute the final swizzle.
- * This is used when we find an expression such as "foo.xz.yx".
- */
-static GLuint
-root_swizzle(const slang_ir_storage *st)
-{
-   GLuint swizzle = st->Swizzle;
-   while (st->Parent) {
-      st = st->Parent;
-      swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
-   }
-   return swizzle;
-}
-
-
-/**
- * Generate IR tree for an assignment (=).
- */
-static slang_ir_node *
-_slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
-{
-   slang_operation *pred = NULL;
-   slang_ir_node *n = NULL;
-
-   if (oper->children[0].type == SLANG_OPER_IDENTIFIER) {
-      /* Check that var is writeable */
-      const char *varName = (char *) oper->children[0].a_id;
-      slang_variable *var
-         = _slang_variable_locate(oper->children[0].locals,
-                                  oper->children[0].a_id, GL_TRUE);
-      if (!var) {
-         slang_info_log_error(A->log, "undefined variable '%s'", varName);
-         return NULL;
-      }
-
-      if (var->type.qualifier == SLANG_QUAL_CONST ||
-          var->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
-          var->type.qualifier == SLANG_QUAL_UNIFORM ||
-          (var->type.qualifier == SLANG_QUAL_VARYING &&
-           A->program->Target == GL_FRAGMENT_PROGRAM_ARB)) {
-         slang_info_log_error(A->log,
-                              "illegal assignment to read-only variable '%s'",
-                              varName);
-         return NULL;
-      }
-
-      /* check if we need to predicate this assignment based on __notRetFlag */
-      if ((var->is_global ||
-           var->type.qualifier == SLANG_QUAL_OUT ||
-           var->type.qualifier == SLANG_QUAL_INOUT) && A->UseReturnFlag) {
-         /* create predicate, used below */
-         pred = slang_operation_new(1);
-         pred->type = SLANG_OPER_IDENTIFIER;
-         pred->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
-         pred->locals->outer_scope = oper->locals->outer_scope;
-      }
-   }
-
-   if (oper->children[0].type == SLANG_OPER_IDENTIFIER &&
-       oper->children[1].type == SLANG_OPER_CALL) {
-      /* Special case of:  x = f(a, b)
-       * Replace with f(a, b, x)  (where x == hidden __retVal out param)
-       *
-       * XXX this could be even more effective if we could accomodate
-       * cases such as "v.x = f();"  - would help with typical vertex
-       * transformation.
-       */
-      n = _slang_gen_function_call_name(A,
-                                      (const char *) oper->children[1].a_id,
-                                      &oper->children[1], &oper->children[0]);
-   }
-   else {
-      slang_ir_node *lhs, *rhs;
-
-      /* lhs and rhs type checking */
-      if (!_slang_assignment_compatible(A,
-                                        &oper->children[0],
-                                        &oper->children[1])) {
-         slang_info_log_error(A->log, "incompatible types in assignment");
-         return NULL;
-      }
-
-      lhs = _slang_gen_operation(A, &oper->children[0]);
-      if (!lhs) {
-         return NULL;
-      }
-
-      if (!lhs->Store) {
-         slang_info_log_error(A->log,
-                              "invalid left hand side for assignment");
-         return NULL;
-      }
-
-      /* check that lhs is writable */
-      if (!is_store_writable(A, lhs->Store)) {
-         slang_info_log_error(A->log,
-                              "illegal assignment to read-only l-value");
-         return NULL;
-      }
-
-      rhs = _slang_gen_operation(A, &oper->children[1]);
-      if (lhs && rhs) {
-         /* convert lhs swizzle into writemask */
-         const GLuint swizzle = root_swizzle(lhs->Store);
-         GLuint writemask, newSwizzle = 0x0;
-         if (!swizzle_to_writemask(A, swizzle, &writemask, &newSwizzle)) {
-            /* Non-simple writemask, need to swizzle right hand side in
-             * order to put components into the right place.
-             */
-            rhs = _slang_gen_swizzle(rhs, newSwizzle);
-         }
-         n = new_node2(IR_COPY, lhs, rhs);
-      }
-      else {
-         return NULL;
-      }
-   }
-
-   if (n && pred) {
-      /* predicate the assignment code on __notRetFlag */
-      slang_ir_node *top, *cond;
-
-      cond = _slang_gen_operation(A, pred);
-      top = new_if(cond, n, NULL);
-      return top;
-   }
-   return n;
-}
-
-
-/**
- * Generate IR tree for referencing a field in a struct (or basic vector type)
- */
-static slang_ir_node *
-_slang_gen_struct_field(slang_assemble_ctx * A, slang_operation *oper)
-{
-   slang_typeinfo ti;
-
-   /* type of struct */
-   slang_typeinfo_construct(&ti);
-   typeof_operation(A, &oper->children[0], &ti);
-
-   if (_slang_type_is_vector(ti.spec.type)) {
-      /* the field should be a swizzle */
-      const GLuint rows = _slang_type_dim(ti.spec.type);
-      slang_swizzle swz;
-      slang_ir_node *n;
-      GLuint swizzle;
-      if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
-         slang_info_log_error(A->log, "Bad swizzle");
-         return NULL;
-      }
-      swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
-                              swz.swizzle[1],
-                              swz.swizzle[2],
-                              swz.swizzle[3]);
-
-      n = _slang_gen_operation(A, &oper->children[0]);
-      /* create new parent node with swizzle */
-      if (n)
-         n = _slang_gen_swizzle(n, swizzle);
-      return n;
-   }
-   else if (   ti.spec.type == SLANG_SPEC_FLOAT
-            || ti.spec.type == SLANG_SPEC_INT
-            || ti.spec.type == SLANG_SPEC_BOOL) {
-      const GLuint rows = 1;
-      slang_swizzle swz;
-      slang_ir_node *n;
-      GLuint swizzle;
-      if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
-         slang_info_log_error(A->log, "Bad swizzle");
-      }
-      swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
-                              swz.swizzle[1],
-                              swz.swizzle[2],
-                              swz.swizzle[3]);
-      n = _slang_gen_operation(A, &oper->children[0]);
-      /* create new parent node with swizzle */
-      n = _slang_gen_swizzle(n, swizzle);
-      return n;
-   }
-   else {
-      /* the field is a structure member (base.field) */
-      /* oper->children[0] is the base */
-      /* oper->a_id is the field name */
-      slang_ir_node *base, *n;
-      slang_typeinfo field_ti;
-      GLint fieldSize, fieldOffset = -1;
-
-      /* type of field */
-      slang_typeinfo_construct(&field_ti);
-      typeof_operation(A, oper, &field_ti);
-
-      fieldSize = _slang_sizeof_type_specifier(&field_ti.spec);
-      if (fieldSize > 0)
-         fieldOffset = _slang_field_offset(&ti.spec, oper->a_id);
-
-      if (fieldSize == 0 || fieldOffset < 0) {
-         const char *structName;
-         if (ti.spec._struct)
-            structName = (char *) ti.spec._struct->a_name;
-         else
-            structName = "unknown";
-         slang_info_log_error(A->log,
-                              "\"%s\" is not a member of struct \"%s\"",
-                              (char *) oper->a_id, structName);
-         return NULL;
-      }
-      assert(fieldSize >= 0);
-
-      base = _slang_gen_operation(A, &oper->children[0]);
-      if (!base) {
-         /* error msg should have already been logged */
-         return NULL;
-      }
-
-      n = new_node1(IR_FIELD, base);
-      if (!n)
-         return NULL;
-
-      n->Field = (char *) oper->a_id;
-
-      /* Store the field's offset in storage->Index */
-      n->Store = _slang_new_ir_storage(base->Store->File,
-                                       fieldOffset,
-                                       fieldSize);
-
-      return n;
-   }
-}
-
-
-/**
- * Gen code for array indexing.
- */
-static slang_ir_node *
-_slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper)
-{
-   slang_typeinfo array_ti;
-
-   /* get array's type info */
-   slang_typeinfo_construct(&array_ti);
-   typeof_operation(A, &oper->children[0], &array_ti);
-
-   if (_slang_type_is_vector(array_ti.spec.type)) {
-      /* indexing a simple vector type: "vec4 v; v[0]=p;" */
-      /* translate the index into a swizzle/writemask: "v.x=p" */
-      const GLuint max = _slang_type_dim(array_ti.spec.type);
-      GLint index;
-      slang_ir_node *n;
-
-      index = (GLint) oper->children[1].literal[0];
-      if (oper->children[1].type != SLANG_OPER_LITERAL_INT ||
-          index >= (GLint) max) {
-#if 0
-         slang_info_log_error(A->log, "Invalid array index for vector type");
-         printf("type = %d\n", oper->children[1].type);
-         printf("index = %d, max = %d\n", index, max);
-         printf("array = %s\n", (char*)oper->children[0].a_id);
-         printf("index = %s\n", (char*)oper->children[1].a_id);
-         return NULL;
-#else
-         index = 0;
-#endif
-      }
-
-      n = _slang_gen_operation(A, &oper->children[0]);
-      if (n) {
-         /* use swizzle to access the element */
-         GLuint swizzle = MAKE_SWIZZLE4(SWIZZLE_X + index,
-                                        SWIZZLE_NIL,
-                                        SWIZZLE_NIL,
-                                        SWIZZLE_NIL);
-         n = _slang_gen_swizzle(n, swizzle);
-      }
-      return n;
-   }
-   else {
-      /* conventional array */
-      slang_typeinfo elem_ti;
-      slang_ir_node *elem, *array, *index;
-      GLint elemSize, arrayLen;
-
-      /* size of array element */
-      slang_typeinfo_construct(&elem_ti);
-      typeof_operation(A, oper, &elem_ti);
-      elemSize = _slang_sizeof_type_specifier(&elem_ti.spec);
-
-      if (_slang_type_is_matrix(array_ti.spec.type))
-         arrayLen = _slang_type_dim(array_ti.spec.type);
-      else
-         arrayLen = array_ti.array_len;
-
-      slang_typeinfo_destruct(&array_ti);
-      slang_typeinfo_destruct(&elem_ti);
-
-      if (elemSize <= 0) {
-         /* unknown var or type */
-         slang_info_log_error(A->log, "Undefined variable or type");
-         return NULL;
-      }
-
-      array = _slang_gen_operation(A, &oper->children[0]);
-      index = _slang_gen_operation(A, &oper->children[1]);
-      if (array && index) {
-         /* bounds check */
-         GLint constIndex = -1;
-         if (index->Opcode == IR_FLOAT) {
-            constIndex = (int) index->Value[0];
-            if (constIndex < 0 || constIndex >= arrayLen) {
-               slang_info_log_error(A->log,
-                                "Array index out of bounds (index=%d size=%d)",
-                                 constIndex, arrayLen);
-               _slang_free_ir_tree(array);
-               _slang_free_ir_tree(index);
-               return NULL;
-            }
-         }
-
-         if (!array->Store) {
-            slang_info_log_error(A->log, "Invalid array");
-            return NULL;
-         }
-
-         elem = new_node2(IR_ELEMENT, array, index);
-
-         /* The storage info here will be updated during code emit */
-         elem->Store = _slang_new_ir_storage(array->Store->File,
-                                             array->Store->Index,
-                                             elemSize);
-         elem->Store->Swizzle = _slang_var_swizzle(elemSize, 0);
-         return elem;
-      }
-      else {
-         _slang_free_ir_tree(array);
-         _slang_free_ir_tree(index);
-         return NULL;
-      }
-   }
-}
-
-
-static slang_ir_node *
-_slang_gen_compare(slang_assemble_ctx *A, slang_operation *oper,
-                   slang_ir_opcode opcode)
-{
-   slang_typeinfo t0, t1;
-   slang_ir_node *n;
-   
-   slang_typeinfo_construct(&t0);
-   typeof_operation(A, &oper->children[0], &t0);
-
-   slang_typeinfo_construct(&t1);
-   typeof_operation(A, &oper->children[0], &t1);
-
-   if (t0.spec.type == SLANG_SPEC_ARRAY ||
-       t1.spec.type == SLANG_SPEC_ARRAY) {
-      slang_info_log_error(A->log, "Illegal array comparison");
-      return NULL;
-   }
-
-   if (oper->type != SLANG_OPER_EQUAL &&
-       oper->type != SLANG_OPER_NOTEQUAL) {
-      /* <, <=, >, >= can only be used with scalars */
-      if ((t0.spec.type != SLANG_SPEC_INT &&
-           t0.spec.type != SLANG_SPEC_FLOAT) ||
-          (t1.spec.type != SLANG_SPEC_INT &&
-           t1.spec.type != SLANG_SPEC_FLOAT)) {
-         slang_info_log_error(A->log, "Incompatible type(s) for inequality operator");
-         return NULL;
-      }
-   }
-
-   n =  new_node2(opcode,
-                  _slang_gen_operation(A, &oper->children[0]),
-                  _slang_gen_operation(A, &oper->children[1]));
-
-   /* result is a bool (size 1) */
-   n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
-
-   return n;
-}
-
-
-#if 0
-static void
-print_vars(slang_variable_scope *s)
-{
-   int i;
-   printf("vars: ");
-   for (i = 0; i < s->num_variables; i++) {
-      printf("%s %d, \n",
-             (char*) s->variables[i]->a_name,
-             s->variables[i]->declared);
-   }
-
-   printf("\n");
-}
-#endif
-
-
-#if 0
-static void
-_slang_undeclare_vars(slang_variable_scope *locals)
-{
-   if (locals->num_variables > 0) {
-      int i;
-      for (i = 0; i < locals->num_variables; i++) {
-         slang_variable *v = locals->variables[i];
-         printf("undeclare %s at %p\n", (char*) v->a_name, v);
-         v->declared = GL_FALSE;
-      }
-   }
-}
-#endif
-
-
-/**
- * Generate IR tree for a slang_operation (AST node)
- */
-static slang_ir_node *
-_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
-{
-   switch (oper->type) {
-   case SLANG_OPER_BLOCK_NEW_SCOPE:
-      {
-         slang_ir_node *n;
-
-         _slang_push_var_table(A->vartable);
-
-         oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE; /* temp change */
-         n = _slang_gen_operation(A, oper);
-         oper->type = SLANG_OPER_BLOCK_NEW_SCOPE; /* restore */
-
-         _slang_pop_var_table(A->vartable);
-
-         /*_slang_undeclare_vars(oper->locals);*/
-         /*print_vars(oper->locals);*/
-
-         if (n)
-            n = new_node1(IR_SCOPE, n);
-         return n;
-      }
-      break;
-
-   case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
-      /* list of operations */
-      if (oper->num_children > 0)
-      {
-         slang_ir_node *n, *tree = NULL;
-         GLuint i;
-
-         for (i = 0; i < oper->num_children; i++) {
-            n = _slang_gen_operation(A, &oper->children[i]);
-            if (!n) {
-               _slang_free_ir_tree(tree);
-               return NULL; /* error must have occured */
-            }
-            tree = new_seq(tree, n);
-         }
-
-         return tree;
-      }
-      else {
-         return new_node0(IR_NOP);
-      }
-
-   case SLANG_OPER_EXPRESSION:
-      return _slang_gen_operation(A, &oper->children[0]);
-
-   case SLANG_OPER_FOR:
-      return _slang_gen_for(A, oper);
-   case SLANG_OPER_DO:
-      return _slang_gen_do(A, oper);
-   case SLANG_OPER_WHILE:
-      return _slang_gen_while(A, oper);
-   case SLANG_OPER_BREAK:
-      if (!current_loop_oper(A)) {
-         slang_info_log_error(A->log, "'break' not in loop");
-         return NULL;
-      }
-      return new_break(current_loop_ir(A));
-   case SLANG_OPER_CONTINUE:
-      if (!current_loop_oper(A)) {
-         slang_info_log_error(A->log, "'continue' not in loop");
-         return NULL;
-      }
-      return _slang_gen_continue(A, oper);
-   case SLANG_OPER_DISCARD:
-      return new_node0(IR_KILL);
-
-   case SLANG_OPER_EQUAL:
-      return _slang_gen_compare(A, oper, IR_EQUAL);
-   case SLANG_OPER_NOTEQUAL:
-      return _slang_gen_compare(A, oper, IR_NOTEQUAL);
-   case SLANG_OPER_GREATER:
-      return _slang_gen_compare(A, oper, IR_SGT);
-   case SLANG_OPER_LESS:
-      return _slang_gen_compare(A, oper, IR_SLT);
-   case SLANG_OPER_GREATEREQUAL:
-      return _slang_gen_compare(A, oper, IR_SGE);
-   case SLANG_OPER_LESSEQUAL:
-      return _slang_gen_compare(A, oper, IR_SLE);
-   case SLANG_OPER_ADD:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "+", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_SUBTRACT:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "-", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_MULTIPLY:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-         n = _slang_gen_function_call_name(A, "*", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_DIVIDE:
-      {
-         slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "/", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_MINUS:
-      {
-         slang_ir_node *n;
-         assert(oper->num_children == 1);
-        n = _slang_gen_function_call_name(A, "-", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_PLUS:
-      /* +expr   --> do nothing */
-      return _slang_gen_operation(A, &oper->children[0]);
-   case SLANG_OPER_VARIABLE_DECL:
-      return _slang_gen_declaration(A, oper);
-   case SLANG_OPER_ASSIGN:
-      return _slang_gen_assignment(A, oper);
-   case SLANG_OPER_ADDASSIGN:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "+=", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_SUBASSIGN:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "-=", oper, NULL);
-        return n;
-      }
-      break;
-   case SLANG_OPER_MULASSIGN:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "*=", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_DIVASSIGN:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "/=", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_LOGICALAND:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_logical_and(A, oper);
-        return n;
-      }
-   case SLANG_OPER_LOGICALOR:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_logical_or(A, oper);
-        return n;
-      }
-   case SLANG_OPER_LOGICALXOR:
-      return _slang_gen_xor(A, oper);
-   case SLANG_OPER_NOT:
-      return _slang_gen_not(A, oper);
-   case SLANG_OPER_SELECT:  /* b ? x : y */
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 3);
-        n = _slang_gen_select(A, oper);
-        return n;
-      }
-
-   case SLANG_OPER_ASM:
-      return _slang_gen_asm(A, oper, NULL);
-   case SLANG_OPER_CALL:
-      return _slang_gen_function_call_name(A, (const char *) oper->a_id,
-                                           oper, NULL);
-   case SLANG_OPER_METHOD:
-      return _slang_gen_method_call(A, oper);
-   case SLANG_OPER_RETURN:
-      return _slang_gen_return(A, oper);
-   case SLANG_OPER_RETURN_INLINED:
-      return _slang_gen_return(A, oper);
-   case SLANG_OPER_LABEL:
-      return new_label(oper->label);
-   case SLANG_OPER_IDENTIFIER:
-      return _slang_gen_variable(A, oper);
-   case SLANG_OPER_IF:
-      return _slang_gen_if(A, oper);
-   case SLANG_OPER_FIELD:
-      return _slang_gen_struct_field(A, oper);
-   case SLANG_OPER_SUBSCRIPT:
-      return _slang_gen_array_element(A, oper);
-   case SLANG_OPER_LITERAL_FLOAT:
-      /* fall-through */
-   case SLANG_OPER_LITERAL_INT:
-      /* fall-through */
-   case SLANG_OPER_LITERAL_BOOL:
-      return new_float_literal(oper->literal, oper->literal_size);
-
-   case SLANG_OPER_POSTINCREMENT:   /* var++ */
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 1);
-        n = _slang_gen_function_call_name(A, "__postIncr", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_POSTDECREMENT:   /* var-- */
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 1);
-        n = _slang_gen_function_call_name(A, "__postDecr", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_PREINCREMENT:   /* ++var */
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 1);
-        n = _slang_gen_function_call_name(A, "++", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_PREDECREMENT:   /* --var */
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 1);
-        n = _slang_gen_function_call_name(A, "--", oper, NULL);
-        return n;
-      }
-
-   case SLANG_OPER_NON_INLINED_CALL:
-   case SLANG_OPER_SEQUENCE:
-      {
-         slang_ir_node *tree = NULL;
-         GLuint i;
-         for (i = 0; i < oper->num_children; i++) {
-            slang_ir_node *n = _slang_gen_operation(A, &oper->children[i]);
-            tree = new_seq(tree, n);
-            if (n)
-               tree->Store = n->Store;
-         }
-         if (oper->type == SLANG_OPER_NON_INLINED_CALL) {
-            tree = new_function_call(tree, oper->label);
-         }
-         return tree;
-      }
-
-   case SLANG_OPER_NONE:
-   case SLANG_OPER_VOID:
-      /* returning NULL here would generate an error */
-      return new_node0(IR_NOP);
-
-   default:
-      _mesa_problem(NULL, "bad node type %d in _slang_gen_operation",
-                    oper->type);
-      return new_node0(IR_NOP);
-   }
-
-   return NULL;
-}
-
-
-/**
- * Check if the given type specifier is a rectangular texture sampler.
- */
-static GLboolean
-is_rect_sampler_spec(const slang_type_specifier *spec)
-{
-   while (spec->_array) {
-      spec = spec->_array;
-   }
-   return spec->type == SLANG_SPEC_SAMPLER_RECT ||
-          spec->type == SLANG_SPEC_SAMPLER_RECT_SHADOW;
-}
-
-
-
-/**
- * Called by compiler when a global variable has been parsed/compiled.
- * Here we examine the variable's type to determine what kind of register
- * storage will be used.
- *
- * A uniform such as "gl_Position" will become the register specification
- * (PROGRAM_OUTPUT, VERT_RESULT_HPOS).  Or, uniform "gl_FogFragCoord"
- * will be (PROGRAM_INPUT, FRAG_ATTRIB_FOGC).
- *
- * Samplers are interesting.  For "uniform sampler2D tex;" we'll specify
- * (PROGRAM_SAMPLER, index) where index is resolved at link-time to an
- * actual texture unit (as specified by the user calling glUniform1i()).
- */
-GLboolean
-_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
-                               slang_unit_type type)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_program *prog = A->program;
-   const char *varName = (char *) var->a_name;
-   GLboolean success = GL_TRUE;
-   slang_ir_storage *store = NULL;
-   int dbg = 0;
-   const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
-   const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
-   const GLint arrayLen = _slang_array_length(var);
-   const GLint totalSize = _slang_array_size(size, arrayLen);
-   GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
-
-   var->is_global = GL_TRUE;
-
-   /* check for sampler2D arrays */
-   if (texIndex == -1 && var->type.specifier._array)
-      texIndex = sampler_to_texture_index(var->type.specifier._array->type);
-
-   if (texIndex != -1) {
-      /* This is a texture sampler variable...
-       * store->File = PROGRAM_SAMPLER
-       * store->Index = sampler number (0..7, typically)
-       * store->Size = texture type index (1D, 2D, 3D, cube, etc)
-       */
-      if (var->initializer) {
-         slang_info_log_error(A->log, "illegal assignment to '%s'", varName);
-         return GL_FALSE;
-      }
-#if FEATURE_es2_glsl /* XXX should use FEATURE_texture_rect */
-      /* disallow rect samplers */
-      if (ctx->API == API_OPENGLES2 &&
-         is_rect_sampler_spec(&var->type.specifier)) {
-         slang_info_log_error(A->log, "invalid sampler type for '%s'", varName);
-         return GL_FALSE;
-      }
-#else
-      (void) is_rect_sampler_spec; /* silence warning */
-      (void) ctx;
-#endif
-      {
-         GLint sampNum = _mesa_add_sampler(prog->Parameters, varName, datatype);
-         store = _slang_new_ir_storage_sampler(sampNum, texIndex, totalSize);
-
-         /* If we have a sampler array, then we need to allocate the 
-         * additional samplers to ensure we don't allocate them elsewhere.
-         * We can't directly use _mesa_add_sampler() as that checks the
-         * varName and gets a match, so we call _mesa_add_parameter()
-         * directly and use the last sampler number from the call above.
-         */
-        if (arrayLen > 0) {
-           GLint a = arrayLen - 1;
-           GLint i;
-           for (i = 0; i < a; i++) {
-               GLfloat value = (GLfloat)(i + sampNum + 1);
-               (void) _mesa_add_parameter(prog->Parameters, PROGRAM_SAMPLER,
-                                 varName, 1, datatype, &value, NULL, 0x0);
-           }
-        }
-      }
-      if (dbg) printf("SAMPLER ");
-   }
-   else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
-      /* Uniform variable */
-      const GLuint swizzle = _slang_var_swizzle(totalSize, 0);
-
-      if (prog) {
-         /* user-defined uniform */
-         if (datatype == GL_NONE) {
-           if ((var->type.specifier.type == SLANG_SPEC_ARRAY &&
-                var->type.specifier._array->type == SLANG_SPEC_STRUCT) ||
-                (var->type.specifier.type == SLANG_SPEC_STRUCT)) {
-               /* temporary work-around */
-               GLenum datatype = GL_FLOAT;
-               GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName,
-                                                    totalSize, datatype, NULL);
-               store = _slang_new_ir_storage_swz(PROGRAM_UNIFORM, uniformLoc,
-                                                 totalSize, swizzle);
-        
-              if (arrayLen > 0) {
-                 GLint a = arrayLen - 1;
-                 GLint i;
-                 for (i = 0; i < a; i++) {
-                     GLfloat value = (GLfloat)(i + uniformLoc + 1);
-                     (void) _mesa_add_parameter(prog->Parameters, PROGRAM_UNIFORM,
-                                 varName, 1, datatype, &value, NULL, 0x0);
-                  }
-              }
-
-               /* XXX what we need to do is unroll the struct into its
-                * basic types, creating a uniform variable for each.
-                * For example:
-                * struct foo {
-                *   vec3 a;
-                *   vec4 b;
-                * };
-                * uniform foo f;
-                *
-                * Should produce uniforms:
-                * "f.a"  (GL_FLOAT_VEC3)
-                * "f.b"  (GL_FLOAT_VEC4)
-                */
-
-               if (var->initializer) {
-                  slang_info_log_error(A->log,
-                     "unsupported initializer for uniform '%s'", varName);
-                  return GL_FALSE;
-               }
-            }
-            else {
-               slang_info_log_error(A->log,
-                                    "invalid datatype for uniform variable %s",
-                                    varName);
-               return GL_FALSE;
-            }
-         }
-         else {
-            /* non-struct uniform */
-            if (!_slang_gen_var_decl(A, var, var->initializer))
-               return GL_FALSE;
-            store = var->store;
-         }
-      }
-      else {
-         /* pre-defined uniform, like gl_ModelviewMatrix */
-         /* We know it's a uniform, but don't allocate storage unless
-          * it's really used.
-          */
-         store = _slang_new_ir_storage_swz(PROGRAM_STATE_VAR, -1,
-                                           totalSize, swizzle);
-      }
-      if (dbg) printf("UNIFORM (sz %d) ", totalSize);
-   }
-   else if (var->type.qualifier == SLANG_QUAL_VARYING) {
-      /* varyings must be float, vec or mat */
-      if (!_slang_type_is_float_vec_mat(var->type.specifier.type) &&
-          var->type.specifier.type != SLANG_SPEC_ARRAY) {
-         slang_info_log_error(A->log,
-                              "varying '%s' must be float/vector/matrix",
-                              varName);
-         return GL_FALSE;
-      }
-
-      if (var->initializer) {
-         slang_info_log_error(A->log, "illegal initializer for varying '%s'",
-                              varName);
-         return GL_FALSE;
-      }
-
-      if (prog) {
-         /* user-defined varying */
-         GLbitfield flags;
-         GLint varyingLoc;
-         GLuint swizzle;
-
-         flags = 0x0;
-         if (var->type.centroid == SLANG_CENTROID)
-            flags |= PROG_PARAM_BIT_CENTROID;
-         if (var->type.variant == SLANG_INVARIANT)
-            flags |= PROG_PARAM_BIT_INVARIANT;
-
-         varyingLoc = _mesa_add_varying(prog->Varying, varName,
-                                        totalSize, GL_NONE, flags);
-         swizzle = _slang_var_swizzle(size, 0);
-         store = _slang_new_ir_storage_swz(PROGRAM_VARYING, varyingLoc,
-                                           totalSize, swizzle);
-      }
-      else {
-         /* pre-defined varying, like gl_Color or gl_TexCoord */
-         if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
-            /* fragment program input */
-            GLuint swizzle;
-            GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
-                                             &swizzle);
-            assert(index >= 0);
-            assert(index < FRAG_ATTRIB_MAX);
-            store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index,
-                                              size, swizzle);
-         }
-         else {
-            /* vertex program output */
-            GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
-            GLuint swizzle = _slang_var_swizzle(size, 0);
-            assert(index >= 0);
-            assert(index < VERT_RESULT_MAX);
-            assert(type == SLANG_UNIT_VERTEX_BUILTIN);
-            store = _slang_new_ir_storage_swz(PROGRAM_OUTPUT, index,
-                                              size, swizzle);
-         }
-         if (dbg) printf("V/F ");
-      }
-      if (dbg) printf("VARYING ");
-   }
-   else if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE) {
-      GLuint swizzle;
-      GLint index;
-      /* attributes must be float, vec or mat */
-      if (!_slang_type_is_float_vec_mat(var->type.specifier.type)) {
-         slang_info_log_error(A->log,
-                              "attribute '%s' must be float/vector/matrix",
-                              varName);
-         return GL_FALSE;
-      }
-
-      if (prog) {
-         /* user-defined vertex attribute */
-         const GLint attr = -1; /* unknown */
-         swizzle = _slang_var_swizzle(size, 0);
-         index = _mesa_add_attribute(prog->Attributes, varName,
-                                     size, datatype, attr);
-         assert(index >= 0);
-         index = VERT_ATTRIB_GENERIC0 + index;
-      }
-      else {
-         /* pre-defined vertex attrib */
-         index = _slang_input_index(varName, GL_VERTEX_PROGRAM_ARB, &swizzle);
-         assert(index >= 0);
-      }
-      store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
-      if (dbg) printf("ATTRIB ");
-   }
-   else if (var->type.qualifier == SLANG_QUAL_FIXEDINPUT) {
-      GLuint swizzle = SWIZZLE_XYZW; /* silence compiler warning */
-      GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
-                                       &swizzle);
-      store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
-      if (dbg) printf("INPUT ");
-   }
-   else if (var->type.qualifier == SLANG_QUAL_FIXEDOUTPUT) {
-      if (type == SLANG_UNIT_VERTEX_BUILTIN) {
-         GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
-         store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
-      }
-      else {
-         GLint index = _slang_output_index(varName, GL_FRAGMENT_PROGRAM_ARB);
-         GLint specialSize = 4; /* treat all fragment outputs as float[4] */
-         assert(type == SLANG_UNIT_FRAGMENT_BUILTIN);
-         store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, specialSize);
-      }
-      if (dbg) printf("OUTPUT ");
-   }
-   else if (var->type.qualifier == SLANG_QUAL_CONST && !prog) {
-      /* pre-defined global constant, like gl_MaxLights */
-      store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size);
-      if (dbg) printf("CONST ");
-   }
-   else {
-      /* ordinary variable (may be const) */
-      slang_ir_node *n;
-
-      /* IR node to declare the variable */
-      n = _slang_gen_var_decl(A, var, var->initializer);
-
-      /* emit GPU instructions */
-      success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_FALSE, A->log);
-
-      _slang_free_ir_tree(n);
-   }
-
-   if (dbg) printf("GLOBAL VAR %s  idx %d\n", (char*) var->a_name,
-                   store ? store->Index : -2);
-
-   if (store)
-      var->store = store;  /* save var's storage info */
-
-   var->declared = GL_TRUE;
-
-   return success;
-}
-
-
-/**
- * Produce an IR tree from a function AST (fun->body).
- * Then call the code emitter to convert the IR tree into gl_program
- * instructions.
- */
-GLboolean
-_slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
-{
-   slang_ir_node *n;
-   GLboolean success = GL_TRUE;
-
-   if (strcmp((char *) fun->header.a_name, "main") != 0) {
-      /* we only really generate code for main, all other functions get
-       * inlined or codegen'd upon an actual call.
-       */
-#if 0
-      /* do some basic error checking though */
-      if (fun->header.type.specifier.type != SLANG_SPEC_VOID) {
-         /* check that non-void functions actually return something */
-         slang_operation *op
-            = _slang_find_node_type(fun->body, SLANG_OPER_RETURN);
-         if (!op) {
-            slang_info_log_error(A->log,
-                                 "function \"%s\" has no return statement",
-                                 (char *) fun->header.a_name);
-            printf(
-                   "function \"%s\" has no return statement\n",
-                   (char *) fun->header.a_name);
-            return GL_FALSE;
-         }
-      }
-#endif
-      return GL_TRUE;  /* not an error */
-   }
-
-#if 0
-   printf("\n*********** codegen_function %s\n", (char *) fun->header.a_name);
-   slang_print_function(fun, 1);
-#endif
-
-   /* should have been allocated earlier: */
-   assert(A->program->Parameters );
-   assert(A->program->Varying);
-   assert(A->vartable);
-
-   A->LoopDepth = 0;
-   A->UseReturnFlag = GL_FALSE;
-   A->CurFunction = fun;
-
-   /* fold constant expressions, etc. */
-   _slang_simplify(fun->body, &A->space, A->atoms);
-
-#if 0
-   printf("\n*********** simplified %s\n", (char *) fun->header.a_name);
-   slang_print_function(fun, 1);
-#endif
-
-   /* Create an end-of-function label */
-   A->curFuncEndLabel = _slang_label_new("__endOfFunc__main");
-
-   /* push new vartable scope */
-   _slang_push_var_table(A->vartable);
-
-   /* Generate IR tree for the function body code */
-   n = _slang_gen_operation(A, fun->body);
-   if (n)
-      n = new_node1(IR_SCOPE, n);
-
-   /* pop vartable, restore previous */
-   _slang_pop_var_table(A->vartable);
-
-   if (!n) {
-      /* XXX record error */
-      return GL_FALSE;
-   }
-
-   /* append an end-of-function-label to IR tree */
-   n = new_seq(n, new_label(A->curFuncEndLabel));
-
-   /*_slang_label_delete(A->curFuncEndLabel);*/
-   A->curFuncEndLabel = NULL;
-
-#if 0
-   printf("************* New AST for %s *****\n", (char*)fun->header.a_name);
-   slang_print_function(fun, 1);
-#endif
-#if 0
-   printf("************* IR for %s *******\n", (char*)fun->header.a_name);
-   _slang_print_ir_tree(n, 0);
-#endif
-#if 0
-   printf("************* End codegen function ************\n\n");
-#endif
-
-   if (A->UnresolvedRefs) {
-      /* Can't codegen at this time.
-       * At link time we'll concatenate all the vertex shaders and/or all
-       * the fragment shaders and try recompiling.
-       */
-      return GL_TRUE;
-   }
-
-   /* Emit program instructions */
-   success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_TRUE, A->log);
-   _slang_free_ir_tree(n);
-
-   /* free codegen context */
-   /*
-   free(A->codegen);
-   */
-
-   return success;
-}
-
diff --git a/src/mesa/shader/slang/slang_codegen.h b/src/mesa/shader/slang/slang_codegen.h
deleted file mode 100644 (file)
index 461633f..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef SLANG_CODEGEN_H
-#define SLANG_CODEGEN_H
-
-
-#include "main/imports.h"
-#include "slang_compile.h"
-
-
-#define MAX_LOOP_DEPTH 30
-
-
-typedef struct slang_assemble_ctx_
-{
-   slang_atom_pool *atoms;
-   slang_name_space space;
-   struct gl_program *program;
-   struct gl_sl_pragmas *pragmas;
-   slang_var_table *vartable;
-   slang_info_log *log;
-   GLboolean allow_uniform_initializers;
-
-   /* current loop stack */
-   const slang_operation *LoopOperStack[MAX_LOOP_DEPTH];
-   struct slang_ir_node_ *LoopIRStack[MAX_LOOP_DEPTH];
-   GLuint LoopDepth;
-
-   /* current function */
-   struct slang_function_ *CurFunction;
-   struct slang_label_ *curFuncEndLabel;
-   GLboolean UseReturnFlag;
-
-   GLboolean UnresolvedRefs;
-   GLboolean EmitContReturn;
-} slang_assemble_ctx;
-
-
-extern GLuint
-_slang_sizeof_type_specifier(const slang_type_specifier *spec);
-
-extern GLboolean
-_slang_codegen_function(slang_assemble_ctx *A , struct slang_function_ *fun);
-
-extern GLboolean
-_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
-                               slang_unit_type type);
-
-
-#endif /* SLANG_CODEGEN_H */
diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c
deleted file mode 100644 (file)
index b6b1f3c..0000000
+++ /dev/null
@@ -1,3044 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
- * Copyright (C) 2008 VMware, Inc.  All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_compile.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "shader/program.h"
-#include "shader/programopt.h"
-#include "shader/prog_optimize.h"
-#include "shader/prog_print.h"
-#include "shader/prog_parameter.h"
-#include "../../glsl/pp/sl_pp_public.h"
-#include "../../glsl/cl/sl_cl_parse.h"
-#include "slang_codegen.h"
-#include "slang_compile.h"
-#include "slang_storage.h"
-#include "slang_log.h"
-#include "slang_mem.h"
-#include "slang_vartable.h"
-#include "slang_simplify.h"
-
-/*
- * This is a straightforward implementation of the slang front-end
- * compiler.  Lots of error-checking functionality is missing but
- * every well-formed shader source should compile successfully and
- * execute as expected. However, some semantically ill-formed shaders
- * may be accepted resulting in undefined behaviour.
- */
-
-
-/** re-defined below, should be the same though */
-#define TYPE_SPECIFIER_COUNT 36
-
-
-/**
- * Check if the given identifier is legal.
- */
-static GLboolean
-legal_identifier(slang_atom name)
-{
-   /* "gl_" is a reserved prefix */
-   if (strncmp((char *) name, "gl_", 3) == 0) {
-      return GL_FALSE;
-   }
-   return GL_TRUE;
-}
-
-
-/*
- * slang_code_unit
- */
-
-GLvoid
-_slang_code_unit_ctr(slang_code_unit * self,
-                     struct slang_code_object_ * object)
-{
-   _slang_variable_scope_ctr(&self->vars);
-   _slang_function_scope_ctr(&self->funs);
-   _slang_struct_scope_ctr(&self->structs);
-   self->object = object;
-}
-
-GLvoid
-_slang_code_unit_dtr(slang_code_unit * self)
-{
-   slang_variable_scope_destruct(&self->vars);
-   slang_function_scope_destruct(&self->funs);
-   slang_struct_scope_destruct(&self->structs);
-}
-
-/*
- * slang_code_object
- */
-
-GLvoid
-_slang_code_object_ctr(slang_code_object * self)
-{
-   GLuint i;
-
-   for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
-      _slang_code_unit_ctr(&self->builtin[i], self);
-   _slang_code_unit_ctr(&self->unit, self);
-   slang_atom_pool_construct(&self->atompool);
-}
-
-GLvoid
-_slang_code_object_dtr(slang_code_object * self)
-{
-   GLuint i;
-
-   for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
-      _slang_code_unit_dtr(&self->builtin[i]);
-   _slang_code_unit_dtr(&self->unit);
-   slang_atom_pool_destruct(&self->atompool);
-}
-
-
-/* slang_parse_ctx */
-
-typedef struct slang_parse_ctx_
-{
-   const unsigned char *I;
-   slang_info_log *L;
-   int parsing_builtin;
-   GLboolean global_scope;   /**< Is object being declared a global? */
-   slang_atom_pool *atoms;
-   slang_unit_type type;     /**< Vertex vs. Fragment */
-   GLuint version;           /**< user-specified (or default) #version */
-} slang_parse_ctx;
-
-/* slang_output_ctx */
-
-typedef struct slang_output_ctx_
-{
-   slang_variable_scope *vars;
-   slang_function_scope *funs;
-   slang_struct_scope *structs;
-   struct gl_program *program;
-   struct gl_sl_pragmas *pragmas;
-   slang_var_table *vartable;
-   GLuint default_precision[TYPE_SPECIFIER_COUNT];
-   GLboolean allow_precision;
-   GLboolean allow_invariant;
-   GLboolean allow_centroid;
-   GLboolean allow_array_types;  /* float[] syntax */
-} slang_output_ctx;
-
-/* _slang_compile() */
-
-
-/* Debugging aid, print file/line where parsing error is detected */
-#define RETURN0 \
-   do { \
-      if (0) \
-         printf("slang error at %s:%d\n", __FILE__, __LINE__); \
-      return 0; \
-   } while (0)
-
-
-static void
-parse_identifier_str(slang_parse_ctx * C, char **id)
-{
-   *id = (char *) C->I;
-   C->I += strlen(*id) + 1;
-}
-
-static slang_atom
-parse_identifier(slang_parse_ctx * C)
-{
-   const char *id;
-
-   id = (const char *) C->I;
-   C->I += strlen(id) + 1;
-   return slang_atom_pool_atom(C->atoms, id);
-}
-
-static int
-is_hex_digit(char c)
-{
-   return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
-}
-
-static int
-parse_general_number(slang_parse_ctx *ctx, float *number)
-{
-   char *flt = NULL;
-
-   if (*ctx->I == '0') {
-      int value = 0;
-      const unsigned char *pi;
-
-      if (ctx->I[1] == 'x' || ctx->I[1] == 'X') {
-         ctx->I += 2;
-         if (!is_hex_digit(*ctx->I)) {
-            return 0;
-         }
-         do {
-            int digit;
-
-            if (*ctx->I >= '0' && *ctx->I <= '9') {
-               digit = (int)(*ctx->I - '0');
-            } else if (*ctx->I >= 'a' && *ctx->I <= 'f') {
-               digit = (int)(*ctx->I - 'a') + 10;
-            } else {
-               digit = (int)(*ctx->I - 'A') + 10;
-            }
-            value = value * 0x10 + digit;
-            ctx->I++;
-         } while (is_hex_digit(*ctx->I));
-         if (*ctx->I != '\0') {
-            return 0;
-         }
-         ctx->I++;
-         *number = (float)value;
-         return 1;
-      }
-
-      pi = ctx->I;
-      pi++;
-      while (*pi >= '0' && *pi <= '7') {
-         int digit;
-
-         digit = (int)(*pi - '0');
-         value = value * 010 + digit;
-         pi++;
-      }
-      if (*pi == '\0') {
-         pi++;
-         ctx->I = pi;
-         *number = (float)value;
-         return 1;
-      }
-   }
-
-   parse_identifier_str(ctx, &flt);
-   flt = _mesa_strdup(flt);
-   if (!flt) {
-      return 0;
-   }
-   if (flt[strlen(flt) - 1] == 'f' || flt[strlen(flt) - 1] == 'F') {
-      flt[strlen(flt) - 1] = '\0';
-   }
-   *number = _mesa_strtof(flt, (char **)NULL);
-   free(flt);
-
-   return 1;
-}
-
-static int
-parse_number(slang_parse_ctx * C, int *number)
-{
-   const int radix = (int) (*C->I++);
-
-   if (radix == 1) {
-      float f = 0.0f;
-
-      parse_general_number(C, &f);
-      *number = (int)f;
-   } else {
-      *number = 0;
-      while (*C->I != '\0') {
-         int digit;
-         if (*C->I >= '0' && *C->I <= '9')
-            digit = (int) (*C->I - '0');
-         else if (*C->I >= 'A' && *C->I <= 'Z')
-            digit = (int) (*C->I - 'A') + 10;
-         else
-            digit = (int) (*C->I - 'a') + 10;
-         *number = *number * radix + digit;
-         C->I++;
-      }
-      C->I++;
-   }
-   if (*number > 65535)
-      slang_info_log_warning(C->L, "%d: literal integer overflow.", *number);
-   return 1;
-}
-
-static int
-parse_float(slang_parse_ctx * C, float *number)
-{
-   if (*C->I == 1) {
-      C->I++;
-      parse_general_number(C, number);
-   } else {
-      char *integral = NULL;
-      char *fractional = NULL;
-      char *exponent = NULL;
-      char *whole = NULL;
-
-      parse_identifier_str(C, &integral);
-      parse_identifier_str(C, &fractional);
-      parse_identifier_str(C, &exponent);
-
-      whole = (char *) _slang_alloc((strlen(integral) +
-                                     strlen(fractional) +
-                                     strlen(exponent) + 3) * sizeof(char));
-      if (whole == NULL) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-
-      slang_string_copy(whole, integral);
-      slang_string_concat(whole, ".");
-      slang_string_concat(whole, fractional);
-      slang_string_concat(whole, "E");
-      slang_string_concat(whole, exponent);
-
-      *number = _mesa_strtof(whole, (char **) NULL);
-
-      _slang_free(whole);
-   }
-
-   return 1;
-}
-
-/* revision number - increment after each change affecting emitted output */
-#define REVISION 5
-
-static int
-check_revision(slang_parse_ctx * C)
-{
-   if (*C->I != REVISION) {
-      slang_info_log_error(C->L, "Internal compiler error.");
-      RETURN0;
-   }
-   C->I++;
-   return 1;
-}
-
-static int parse_statement(slang_parse_ctx *, slang_output_ctx *,
-                           slang_operation *);
-static int parse_expression(slang_parse_ctx *, slang_output_ctx *,
-                            slang_operation *);
-static int parse_type_specifier(slang_parse_ctx *, slang_output_ctx *,
-                                slang_type_specifier *);
-static int
-parse_type_array_size(slang_parse_ctx *C,
-                      slang_output_ctx *O,
-                      GLint *array_len);
-
-static GLboolean
-parse_array_len(slang_parse_ctx * C, slang_output_ctx * O, GLuint * len)
-{
-   slang_operation array_size;
-   slang_name_space space;
-   GLboolean result;
-
-   if (!slang_operation_construct(&array_size))
-      return GL_FALSE;
-   if (!parse_expression(C, O, &array_size)) {
-      slang_operation_destruct(&array_size);
-      return GL_FALSE;
-   }
-
-   space.funcs = O->funs;
-   space.structs = O->structs;
-   space.vars = O->vars;
-
-   /* evaluate compile-time expression which is array size */
-   _slang_simplify(&array_size, &space, C->atoms);
-
-   if (array_size.type == SLANG_OPER_LITERAL_INT) {
-      result = GL_TRUE;
-      *len = (GLint) array_size.literal[0];
-   } else if (array_size.type == SLANG_OPER_IDENTIFIER) {
-      slang_variable *var = _slang_variable_locate(array_size.locals, array_size.a_id, GL_TRUE);
-      if (!var) {
-         slang_info_log_error(C->L, "undefined variable '%s'",
-                              (char *) array_size.a_id);
-         result = GL_FALSE;
-      } else if (var->type.qualifier == SLANG_QUAL_CONST &&
-                 var->type.specifier.type == SLANG_SPEC_INT) {
-         if (var->initializer &&
-             var->initializer->type == SLANG_OPER_LITERAL_INT) {
-            *len = (GLint) var->initializer->literal[0];
-            result = GL_TRUE;
-         } else {
-            slang_info_log_error(C->L, "unable to parse array size declaration");
-            result = GL_FALSE;
-         }
-      } else {
-         slang_info_log_error(C->L, "unable to parse array size declaration");
-         result = GL_FALSE;
-      }
-   } else {
-      result = GL_FALSE;
-   }
-
-   slang_operation_destruct(&array_size);
-   return result;
-}
-
-static GLboolean
-calculate_var_size(slang_parse_ctx * C, slang_output_ctx * O,
-                   slang_variable * var)
-{
-   slang_storage_aggregate agg;
-
-   if (!slang_storage_aggregate_construct(&agg))
-      return GL_FALSE;
-   if (!_slang_aggregate_variable(&agg, &var->type.specifier, var->array_len,
-                                  O->funs, O->structs, O->vars, C->atoms)) {
-      slang_storage_aggregate_destruct(&agg);
-      return GL_FALSE;
-   }
-   var->size = _slang_sizeof_aggregate(&agg);
-   slang_storage_aggregate_destruct(&agg);
-   return GL_TRUE;
-}
-
-static void
-promote_type_to_array(slang_parse_ctx *C,
-                      slang_fully_specified_type *type,
-                      GLint array_len)
-{
-   slang_type_specifier *baseType =
-      slang_type_specifier_new(type->specifier.type, NULL, NULL);
-
-   type->specifier.type = SLANG_SPEC_ARRAY;
-   type->specifier._array = baseType;
-   type->array_len = array_len;
-}
-
-
-static GLboolean
-convert_to_array(slang_parse_ctx * C, slang_variable * var,
-                 const slang_type_specifier * sp)
-{
-   /* sized array - mark it as array, copy the specifier to the array element
-    * and parse the expression */
-   var->type.specifier.type = SLANG_SPEC_ARRAY;
-   var->type.specifier._array = (slang_type_specifier *)
-      _slang_alloc(sizeof(slang_type_specifier));
-   if (var->type.specifier._array == NULL) {
-      slang_info_log_memory(C->L);
-      return GL_FALSE;
-   }
-   slang_type_specifier_ctr(var->type.specifier._array);
-   return slang_type_specifier_copy(var->type.specifier._array, sp);
-}
-
-/* structure field */
-#define FIELD_NONE 0
-#define FIELD_NEXT 1
-#define FIELD_ARRAY 2
-
-static GLboolean
-parse_struct_field_var(slang_parse_ctx * C, slang_output_ctx * O,
-                       slang_variable * var, slang_atom a_name,
-                       const slang_type_specifier * sp,
-                       GLuint array_len)
-{
-   var->a_name = a_name;
-   if (var->a_name == SLANG_ATOM_NULL)
-      return GL_FALSE;
-
-   switch (*C->I++) {
-   case FIELD_NONE:
-      if (array_len != -1) {
-         if (!convert_to_array(C, var, sp))
-            return GL_FALSE;
-         var->array_len = array_len;
-      }
-      else {
-         if (!slang_type_specifier_copy(&var->type.specifier, sp))
-            return GL_FALSE;
-      }
-      break;
-   case FIELD_ARRAY:
-      if (array_len != -1)
-         return GL_FALSE;
-      if (!convert_to_array(C, var, sp))
-         return GL_FALSE;
-      if (!parse_array_len(C, O, &var->array_len))
-         return GL_FALSE;
-      break;
-   default:
-      return GL_FALSE;
-   }
-
-   return calculate_var_size(C, O, var);
-}
-
-static int
-parse_struct_field(slang_parse_ctx * C, slang_output_ctx * O,
-                   slang_struct * st, slang_type_specifier * sp)
-{
-   slang_output_ctx o = *O;
-   GLint array_len;
-
-   o.structs = st->structs;
-   if (!parse_type_specifier(C, &o, sp))
-      RETURN0;
-   if (!parse_type_array_size(C, &o, &array_len))
-      RETURN0;
-
-   do {
-      slang_atom a_name;
-      slang_variable *var = slang_variable_scope_grow(st->fields);
-      if (!var) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      a_name = parse_identifier(C);
-      if (_slang_variable_locate(st->fields, a_name, GL_FALSE)) {
-         slang_info_log_error(C->L, "duplicate field '%s'", (char *) a_name);
-         RETURN0;
-      }
-
-      if (!parse_struct_field_var(C, &o, var, a_name, sp, array_len))
-         RETURN0;
-   }
-   while (*C->I++ != FIELD_NONE);
-
-   return 1;
-}
-
-static int
-parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st)
-{
-   slang_atom a_name;
-   const char *name;
-
-   /* parse struct name (if any) and make sure it is unique in current scope */
-   a_name = parse_identifier(C);
-   if (a_name == SLANG_ATOM_NULL)
-      RETURN0;
-
-   name = slang_atom_pool_id(C->atoms, a_name);
-   if (name[0] != '\0'
-       && slang_struct_scope_find(O->structs, a_name, 0) != NULL) {
-      slang_info_log_error(C->L, "%s: duplicate type name.", name);
-      RETURN0;
-   }
-
-   /* set-up a new struct */
-   *st = (slang_struct *) _slang_alloc(sizeof(slang_struct));
-   if (*st == NULL) {
-      slang_info_log_memory(C->L);
-      RETURN0;
-   }
-   if (!slang_struct_construct(*st)) {
-      _slang_free(*st);
-      *st = NULL;
-      slang_info_log_memory(C->L);
-      RETURN0;
-   }
-   (**st).a_name = a_name;
-   (**st).structs->outer_scope = O->structs;
-
-   /* parse individual struct fields */
-   do {
-      slang_type_specifier sp;
-
-      slang_type_specifier_ctr(&sp);
-      if (!parse_struct_field(C, O, *st, &sp)) {
-         slang_type_specifier_dtr(&sp);
-         RETURN0;
-      }
-      slang_type_specifier_dtr(&sp);
-   }
-   while (*C->I++ != FIELD_NONE);
-
-   /* if named struct, copy it to current scope */
-   if (name[0] != '\0') {
-      slang_struct *s;
-
-      O->structs->structs =
-         (slang_struct *) _slang_realloc(O->structs->structs,
-                                         O->structs->num_structs
-                                         * sizeof(slang_struct),
-                                         (O->structs->num_structs + 1)
-                                         * sizeof(slang_struct));
-      if (O->structs->structs == NULL) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      s = &O->structs->structs[O->structs->num_structs];
-      if (!slang_struct_construct(s))
-         RETURN0;
-      O->structs->num_structs++;
-      if (!slang_struct_copy(s, *st))
-         RETURN0;
-   }
-
-   return 1;
-}
-
-
-/* invariant qualifer */
-#define TYPE_VARIANT    90
-#define TYPE_INVARIANT  91
-
-static int
-parse_type_variant(slang_parse_ctx * C, slang_type_variant *variant)
-{
-   GLuint invariant = *C->I++;
-   switch (invariant) {
-   case TYPE_VARIANT:
-      *variant = SLANG_VARIANT;
-      return 1;
-   case TYPE_INVARIANT:
-      *variant = SLANG_INVARIANT;
-      return 1;
-   default:
-      RETURN0;
-   }
-}
-
-
-/* centroid qualifer */
-#define TYPE_CENTER    95
-#define TYPE_CENTROID  96
-
-static int
-parse_type_centroid(slang_parse_ctx * C, slang_type_centroid *centroid)
-{
-   GLuint c = *C->I++;
-   switch (c) {
-   case TYPE_CENTER:
-      *centroid = SLANG_CENTER;
-      return 1;
-   case TYPE_CENTROID:
-      *centroid = SLANG_CENTROID;
-      return 1;
-   default:
-      RETURN0;
-   }
-}
-
-
-/* Layout qualifiers */
-#define LAYOUT_QUALIFIER_NONE                      0
-#define LAYOUT_QUALIFIER_UPPER_LEFT                1
-#define LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER      2
-
-static int
-parse_layout_qualifiers(slang_parse_ctx * C, slang_layout_qualifier *layout)
-{
-   *layout = 0x0;
-
-   /* the layout qualifiers come as a list of LAYOUT_QUALIFER_x tokens,
-    * terminated by LAYOUT_QUALIFIER_NONE.
-    */
-   while (1) {
-      GLuint c = *C->I++;
-      switch (c) {
-      case LAYOUT_QUALIFIER_NONE:
-         /* end of list of qualifiers */
-         return 1;
-      case LAYOUT_QUALIFIER_UPPER_LEFT:
-         *layout |= SLANG_LAYOUT_UPPER_LEFT_BIT;
-         break;
-      case LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER:
-         *layout |= SLANG_LAYOUT_PIXEL_CENTER_INTEGER_BIT;
-         break;
-      default:
-         assert(0 && "Bad layout qualifier");
-      }
-   }
-}
-
-
-/* type qualifier */
-#define TYPE_QUALIFIER_NONE 0
-#define TYPE_QUALIFIER_CONST 1
-#define TYPE_QUALIFIER_ATTRIBUTE 2
-#define TYPE_QUALIFIER_VARYING 3
-#define TYPE_QUALIFIER_UNIFORM 4
-#define TYPE_QUALIFIER_FIXEDOUTPUT 5
-#define TYPE_QUALIFIER_FIXEDINPUT 6
-
-static int
-parse_type_qualifier(slang_parse_ctx * C, slang_type_qualifier * qual)
-{
-   GLuint qualifier = *C->I++;
-   switch (qualifier) {
-   case TYPE_QUALIFIER_NONE:
-      *qual = SLANG_QUAL_NONE;
-      break;
-   case TYPE_QUALIFIER_CONST:
-      *qual = SLANG_QUAL_CONST;
-      break;
-   case TYPE_QUALIFIER_ATTRIBUTE:
-      *qual = SLANG_QUAL_ATTRIBUTE;
-      break;
-   case TYPE_QUALIFIER_VARYING:
-      *qual = SLANG_QUAL_VARYING;
-      break;
-   case TYPE_QUALIFIER_UNIFORM:
-      *qual = SLANG_QUAL_UNIFORM;
-      break;
-   case TYPE_QUALIFIER_FIXEDOUTPUT:
-      *qual = SLANG_QUAL_FIXEDOUTPUT;
-      break;
-   case TYPE_QUALIFIER_FIXEDINPUT:
-      *qual = SLANG_QUAL_FIXEDINPUT;
-      break;
-   default:
-      RETURN0;
-   }
-   return 1;
-}
-
-/* type specifier */
-#define TYPE_SPECIFIER_VOID 0
-#define TYPE_SPECIFIER_BOOL 1
-#define TYPE_SPECIFIER_BVEC2 2
-#define TYPE_SPECIFIER_BVEC3 3
-#define TYPE_SPECIFIER_BVEC4 4
-#define TYPE_SPECIFIER_INT 5
-#define TYPE_SPECIFIER_IVEC2 6
-#define TYPE_SPECIFIER_IVEC3 7
-#define TYPE_SPECIFIER_IVEC4 8
-#define TYPE_SPECIFIER_FLOAT 9
-#define TYPE_SPECIFIER_VEC2 10
-#define TYPE_SPECIFIER_VEC3 11
-#define TYPE_SPECIFIER_VEC4 12
-#define TYPE_SPECIFIER_MAT2 13
-#define TYPE_SPECIFIER_MAT3 14
-#define TYPE_SPECIFIER_MAT4 15
-#define TYPE_SPECIFIER_SAMPLER1D 16
-#define TYPE_SPECIFIER_SAMPLER2D 17
-#define TYPE_SPECIFIER_SAMPLER3D 18
-#define TYPE_SPECIFIER_SAMPLERCUBE 19
-#define TYPE_SPECIFIER_SAMPLER1DSHADOW 20
-#define TYPE_SPECIFIER_SAMPLER2DSHADOW 21
-#define TYPE_SPECIFIER_SAMPLER2DRECT 22
-#define TYPE_SPECIFIER_SAMPLER2DRECTSHADOW 23
-#define TYPE_SPECIFIER_STRUCT 24
-#define TYPE_SPECIFIER_TYPENAME 25
-#define TYPE_SPECIFIER_MAT23 26
-#define TYPE_SPECIFIER_MAT32 27
-#define TYPE_SPECIFIER_MAT24 28
-#define TYPE_SPECIFIER_MAT42 29
-#define TYPE_SPECIFIER_MAT34 30
-#define TYPE_SPECIFIER_MAT43 31
-#define TYPE_SPECIFIER_SAMPLER_1D_ARRAY 32
-#define TYPE_SPECIFIER_SAMPLER_2D_ARRAY 33
-#define TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW 34
-#define TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW 35
-#define TYPE_SPECIFIER_COUNT 36
-
-static int
-parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O,
-                     slang_type_specifier * spec)
-{
-   int type = *C->I++;
-   switch (type) {
-   case TYPE_SPECIFIER_VOID:
-      spec->type = SLANG_SPEC_VOID;
-      break;
-   case TYPE_SPECIFIER_BOOL:
-      spec->type = SLANG_SPEC_BOOL;
-      break;
-   case TYPE_SPECIFIER_BVEC2:
-      spec->type = SLANG_SPEC_BVEC2;
-      break;
-   case TYPE_SPECIFIER_BVEC3:
-      spec->type = SLANG_SPEC_BVEC3;
-      break;
-   case TYPE_SPECIFIER_BVEC4:
-      spec->type = SLANG_SPEC_BVEC4;
-      break;
-   case TYPE_SPECIFIER_INT:
-      spec->type = SLANG_SPEC_INT;
-      break;
-   case TYPE_SPECIFIER_IVEC2:
-      spec->type = SLANG_SPEC_IVEC2;
-      break;
-   case TYPE_SPECIFIER_IVEC3:
-      spec->type = SLANG_SPEC_IVEC3;
-      break;
-   case TYPE_SPECIFIER_IVEC4:
-      spec->type = SLANG_SPEC_IVEC4;
-      break;
-   case TYPE_SPECIFIER_FLOAT:
-      spec->type = SLANG_SPEC_FLOAT;
-      break;
-   case TYPE_SPECIFIER_VEC2:
-      spec->type = SLANG_SPEC_VEC2;
-      break;
-   case TYPE_SPECIFIER_VEC3:
-      spec->type = SLANG_SPEC_VEC3;
-      break;
-   case TYPE_SPECIFIER_VEC4:
-      spec->type = SLANG_SPEC_VEC4;
-      break;
-   case TYPE_SPECIFIER_MAT2:
-      spec->type = SLANG_SPEC_MAT2;
-      break;
-   case TYPE_SPECIFIER_MAT3:
-      spec->type = SLANG_SPEC_MAT3;
-      break;
-   case TYPE_SPECIFIER_MAT4:
-      spec->type = SLANG_SPEC_MAT4;
-      break;
-   case TYPE_SPECIFIER_MAT23:
-      spec->type = SLANG_SPEC_MAT23;
-      break;
-   case TYPE_SPECIFIER_MAT32:
-      spec->type = SLANG_SPEC_MAT32;
-      break;
-   case TYPE_SPECIFIER_MAT24:
-      spec->type = SLANG_SPEC_MAT24;
-      break;
-   case TYPE_SPECIFIER_MAT42:
-      spec->type = SLANG_SPEC_MAT42;
-      break;
-   case TYPE_SPECIFIER_MAT34:
-      spec->type = SLANG_SPEC_MAT34;
-      break;
-   case TYPE_SPECIFIER_MAT43:
-      spec->type = SLANG_SPEC_MAT43;
-      break;
-   case TYPE_SPECIFIER_SAMPLER1D:
-      spec->type = SLANG_SPEC_SAMPLER_1D;
-      break;
-   case TYPE_SPECIFIER_SAMPLER2D:
-      spec->type = SLANG_SPEC_SAMPLER_2D;
-      break;
-   case TYPE_SPECIFIER_SAMPLER3D:
-      spec->type = SLANG_SPEC_SAMPLER_3D;
-      break;
-   case TYPE_SPECIFIER_SAMPLERCUBE:
-      spec->type = SLANG_SPEC_SAMPLER_CUBE;
-      break;
-   case TYPE_SPECIFIER_SAMPLER2DRECT:
-      spec->type = SLANG_SPEC_SAMPLER_RECT;
-      break;
-   case TYPE_SPECIFIER_SAMPLER1DSHADOW:
-      spec->type = SLANG_SPEC_SAMPLER_1D_SHADOW;
-      break;
-   case TYPE_SPECIFIER_SAMPLER2DSHADOW:
-      spec->type = SLANG_SPEC_SAMPLER_2D_SHADOW;
-      break;
-   case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW:
-      spec->type = SLANG_SPEC_SAMPLER_RECT_SHADOW;
-      break;
-   case TYPE_SPECIFIER_SAMPLER_1D_ARRAY:
-      spec->type = SLANG_SPEC_SAMPLER_1D_ARRAY;
-      break;
-   case TYPE_SPECIFIER_SAMPLER_2D_ARRAY:
-      spec->type = SLANG_SPEC_SAMPLER_2D_ARRAY;
-      break;
-   case TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW:
-      spec->type = SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW;
-      break;
-   case TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW:
-      spec->type = SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW;
-      break;
-   case TYPE_SPECIFIER_STRUCT:
-      spec->type = SLANG_SPEC_STRUCT;
-      if (!parse_struct(C, O, &spec->_struct))
-         RETURN0;
-      break;
-   case TYPE_SPECIFIER_TYPENAME:
-      spec->type = SLANG_SPEC_STRUCT;
-      {
-         slang_atom a_name;
-         slang_struct *stru;
-
-         a_name = parse_identifier(C);
-         if (a_name == NULL)
-            RETURN0;
-
-         stru = slang_struct_scope_find(O->structs, a_name, 1);
-         if (stru == NULL) {
-            slang_info_log_error(C->L, "undeclared type name '%s'",
-                                 slang_atom_pool_id(C->atoms, a_name));
-            RETURN0;
-         }
-
-         spec->_struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
-         if (spec->_struct == NULL) {
-            slang_info_log_memory(C->L);
-            RETURN0;
-         }
-         if (!slang_struct_construct(spec->_struct)) {
-            _slang_free(spec->_struct);
-            spec->_struct = NULL;
-            RETURN0;
-         }
-         if (!slang_struct_copy(spec->_struct, stru))
-            RETURN0;
-      }
-      break;
-   default:
-      RETURN0;
-   }
-   return 1;
-}
-
-#define TYPE_SPECIFIER_NONARRAY 0
-#define TYPE_SPECIFIER_ARRAY    1
-
-static int
-parse_type_array_size(slang_parse_ctx *C,
-                      slang_output_ctx *O,
-                      GLint *array_len)
-{
-   GLuint size;
-
-   switch (*C->I++) {
-   case TYPE_SPECIFIER_NONARRAY:
-      *array_len = -1; /* -1 = not an array */
-      break;
-   case TYPE_SPECIFIER_ARRAY:
-      if (!parse_array_len(C, O, &size))
-         RETURN0;
-      *array_len = (GLint) size;
-      break;
-   default:
-      assert(0);
-      RETURN0;
-   }
-   return 1;
-}
-
-#define PRECISION_DEFAULT 0
-#define PRECISION_LOW     1
-#define PRECISION_MEDIUM  2
-#define PRECISION_HIGH    3
-
-static int
-parse_type_precision(slang_parse_ctx *C,
-                     slang_type_precision *precision)
-{
-   GLint prec = *C->I++;
-   switch (prec) {
-   case PRECISION_DEFAULT:
-      *precision = SLANG_PREC_DEFAULT;
-      return 1;
-   case PRECISION_LOW:
-      *precision = SLANG_PREC_LOW;
-      return 1;
-   case PRECISION_MEDIUM:
-      *precision = SLANG_PREC_MEDIUM;
-      return 1;
-   case PRECISION_HIGH:
-      *precision = SLANG_PREC_HIGH;
-      return 1;
-   default:
-      RETURN0;
-   }
-}
-
-static int
-parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
-                           slang_fully_specified_type * type)
-{
-   if (!parse_layout_qualifiers(C, &type->layout))
-      RETURN0;
-
-   if (!parse_type_variant(C, &type->variant))
-      RETURN0;
-
-   if (!parse_type_centroid(C, &type->centroid))
-      RETURN0;
-
-   if (!parse_type_qualifier(C, &type->qualifier))
-      RETURN0;
-
-   if (!parse_type_precision(C, &type->precision))
-      RETURN0;
-
-   if (!parse_type_specifier(C, O, &type->specifier))
-      RETURN0;
-
-   if (!parse_type_array_size(C, O, &type->array_len))
-      RETURN0;
-
-   if (!O->allow_invariant && type->variant == SLANG_INVARIANT) {
-      slang_info_log_error(C->L,
-         "'invariant' keyword not allowed (perhaps set #version 120)");
-      RETURN0;
-   }
-
-   if (!O->allow_centroid && type->centroid == SLANG_CENTROID) {
-      slang_info_log_error(C->L,
-         "'centroid' keyword not allowed (perhaps set #version 120)");
-      RETURN0;
-   }
-   else if (type->centroid == SLANG_CENTROID &&
-            type->qualifier != SLANG_QUAL_VARYING) {
-      slang_info_log_error(C->L,
-         "'centroid' keyword only allowed for varying vars");
-      RETURN0;
-   }
-
-
-   /* need this?
-   if (type->qualifier != SLANG_QUAL_VARYING &&
-       type->variant == SLANG_INVARIANT) {
-      slang_info_log_error(C->L,
-                           "invariant qualifer only allowed for varying vars");
-      RETURN0;
-   }
-   */
-
-   if (O->allow_precision) {
-      if (type->precision == SLANG_PREC_DEFAULT) {
-         assert(type->specifier.type < TYPE_SPECIFIER_COUNT);
-         /* use the default precision for this datatype */
-         type->precision = O->default_precision[type->specifier.type];
-      }
-   }
-   else {
-      /* only default is allowed */
-      if (type->precision != SLANG_PREC_DEFAULT) {
-         slang_info_log_error(C->L, "precision qualifiers not allowed");
-         RETURN0;
-      }
-   }
-
-   if (!O->allow_array_types && type->array_len >= 0) {
-      slang_info_log_error(C->L, "first-class array types not allowed");
-      RETURN0;
-   }
-
-   if (type->array_len >= 0) {
-      /* convert type to array type (ex: convert "int" to "array of int" */
-      promote_type_to_array(C, type, type->array_len);
-   }
-
-   return 1;
-}
-
-/* operation */
-#define OP_END 0
-#define OP_BLOCK_BEGIN_NO_NEW_SCOPE 1
-#define OP_BLOCK_BEGIN_NEW_SCOPE 2
-#define OP_DECLARE 3
-#define OP_ASM 4
-#define OP_BREAK 5
-#define OP_CONTINUE 6
-#define OP_DISCARD 7
-#define OP_RETURN 8
-#define OP_EXPRESSION 9
-#define OP_IF 10
-#define OP_WHILE 11
-#define OP_DO 12
-#define OP_FOR 13
-#define OP_PUSH_VOID 14
-#define OP_PUSH_BOOL 15
-#define OP_PUSH_INT 16
-#define OP_PUSH_FLOAT 17
-#define OP_PUSH_IDENTIFIER 18
-#define OP_SEQUENCE 19
-#define OP_ASSIGN 20
-#define OP_ADDASSIGN 21
-#define OP_SUBASSIGN 22
-#define OP_MULASSIGN 23
-#define OP_DIVASSIGN 24
-/*#define OP_MODASSIGN 25*/
-/*#define OP_LSHASSIGN 26*/
-/*#define OP_RSHASSIGN 27*/
-/*#define OP_ORASSIGN 28*/
-/*#define OP_XORASSIGN 29*/
-/*#define OP_ANDASSIGN 30*/
-#define OP_SELECT 31
-#define OP_LOGICALOR 32
-#define OP_LOGICALXOR 33
-#define OP_LOGICALAND 34
-/*#define OP_BITOR 35*/
-/*#define OP_BITXOR 36*/
-/*#define OP_BITAND 37*/
-#define OP_EQUAL 38
-#define OP_NOTEQUAL 39
-#define OP_LESS 40
-#define OP_GREATER 41
-#define OP_LESSEQUAL 42
-#define OP_GREATEREQUAL 43
-/*#define OP_LSHIFT 44*/
-/*#define OP_RSHIFT 45*/
-#define OP_ADD 46
-#define OP_SUBTRACT 47
-#define OP_MULTIPLY 48
-#define OP_DIVIDE 49
-/*#define OP_MODULUS 50*/
-#define OP_PREINCREMENT 51
-#define OP_PREDECREMENT 52
-#define OP_PLUS 53
-#define OP_MINUS 54
-/*#define OP_COMPLEMENT 55*/
-#define OP_NOT 56
-#define OP_SUBSCRIPT 57
-#define OP_CALL 58
-#define OP_FIELD 59
-#define OP_POSTINCREMENT 60
-#define OP_POSTDECREMENT 61
-#define OP_PRECISION 62
-#define OP_METHOD 63
-
-
-/**
- * When parsing a compound production, this function is used to parse the
- * children.
- * For example, a while-loop compound will have two children, the
- * while condition expression and the loop body.  So, this function will
- * be called twice to parse those two sub-expressions.
- * \param C  the parsing context
- * \param O  the output context
- * \param oper  the operation we're parsing
- * \param statement  indicates whether parsing a statement, or expression
- * \return 1 if success, 0 if error
- */
-static int
-parse_child_operation(slang_parse_ctx * C, slang_output_ctx * O,
-                      slang_operation * oper, GLboolean statement)
-{
-   slang_operation *ch;
-
-   /* grow child array */
-   ch = slang_operation_grow(&oper->num_children, &oper->children);
-   if (statement)
-      return parse_statement(C, O, ch);
-   return parse_expression(C, O, ch);
-}
-
-static int parse_declaration(slang_parse_ctx * C, slang_output_ctx * O);
-
-static int
-parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
-                slang_operation * oper)
-{
-   int op;
-
-   oper->locals->outer_scope = O->vars;
-
-   op = *C->I++;
-   switch (op) {
-   case OP_BLOCK_BEGIN_NO_NEW_SCOPE:
-      /* parse child statements, do not create new variable scope */
-      oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
-      while (*C->I != OP_END)
-         if (!parse_child_operation(C, O, oper, GL_TRUE))
-            RETURN0;
-      C->I++;
-      break;
-   case OP_BLOCK_BEGIN_NEW_SCOPE:
-      /* parse child statements, create new variable scope */
-      {
-         slang_output_ctx o = *O;
-
-         oper->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-         o.vars = oper->locals;
-         while (*C->I != OP_END)
-            if (!parse_child_operation(C, &o, oper, GL_TRUE))
-               RETURN0;
-         C->I++;
-      }
-      break;
-   case OP_DECLARE:
-      /* local variable declaration, individual declarators are stored as
-       * children identifiers
-       */
-      oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
-      {
-         const unsigned int first_var = O->vars->num_variables;
-
-         /* parse the declaration, note that there can be zero or more
-          * than one declarators
-          */
-         if (!parse_declaration(C, O))
-            RETURN0;
-         if (first_var < O->vars->num_variables) {
-            const unsigned int num_vars = O->vars->num_variables - first_var;
-            unsigned int i;
-            assert(oper->num_children == 0);
-            oper->num_children = num_vars;
-            oper->children = slang_operation_new(num_vars);
-            if (oper->children == NULL) {
-               slang_info_log_memory(C->L);
-               RETURN0;
-            }
-            for (i = first_var; i < O->vars->num_variables; i++) {
-               slang_operation *o = &oper->children[i - first_var];
-               slang_variable *var = O->vars->variables[i];
-               o->type = SLANG_OPER_VARIABLE_DECL;
-               o->locals->outer_scope = O->vars;
-               o->a_id = var->a_name;
-
-               /* new/someday...
-               calculate_var_size(C, O, var);
-               */
-
-               if (!legal_identifier(o->a_id)) {
-                  slang_info_log_error(C->L, "illegal variable name '%s'",
-                                       (char *) o->a_id);
-                  RETURN0;
-               }
-            }
-         }
-      }
-      break;
-   case OP_ASM:
-      /* the __asm statement, parse the mnemonic and all its arguments
-       * as expressions
-       */
-      oper->type = SLANG_OPER_ASM;
-      oper->a_id = parse_identifier(C);
-      if (oper->a_id == SLANG_ATOM_NULL)
-         RETURN0;
-      while (*C->I != OP_END) {
-         if (!parse_child_operation(C, O, oper, GL_FALSE))
-            RETURN0;
-      }
-      C->I++;
-      break;
-   case OP_BREAK:
-      oper->type = SLANG_OPER_BREAK;
-      break;
-   case OP_CONTINUE:
-      oper->type = SLANG_OPER_CONTINUE;
-      break;
-   case OP_DISCARD:
-      oper->type = SLANG_OPER_DISCARD;
-      break;
-   case OP_RETURN:
-      oper->type = SLANG_OPER_RETURN;
-      if (!parse_child_operation(C, O, oper, GL_FALSE))
-         RETURN0;
-      break;
-   case OP_EXPRESSION:
-      oper->type = SLANG_OPER_EXPRESSION;
-      if (!parse_child_operation(C, O, oper, GL_FALSE))
-         RETURN0;
-      break;
-   case OP_IF:
-      oper->type = SLANG_OPER_IF;
-      if (!parse_child_operation(C, O, oper, GL_FALSE))
-         RETURN0;
-      if (!parse_child_operation(C, O, oper, GL_TRUE))
-         RETURN0;
-      if (!parse_child_operation(C, O, oper, GL_TRUE))
-         RETURN0;
-      break;
-   case OP_WHILE:
-      {
-         slang_output_ctx o = *O;
-
-         oper->type = SLANG_OPER_WHILE;
-         o.vars = oper->locals;
-         if (!parse_child_operation(C, &o, oper, GL_TRUE))
-            RETURN0;
-         if (!parse_child_operation(C, &o, oper, GL_TRUE))
-            RETURN0;
-      }
-      break;
-   case OP_DO:
-      oper->type = SLANG_OPER_DO;
-      if (!parse_child_operation(C, O, oper, GL_TRUE))
-         RETURN0;
-      if (!parse_child_operation(C, O, oper, GL_FALSE))
-         RETURN0;
-      break;
-   case OP_FOR:
-      {
-         slang_output_ctx o = *O;
-
-         oper->type = SLANG_OPER_FOR;
-         o.vars = oper->locals;
-         if (!parse_child_operation(C, &o, oper, GL_TRUE))
-            RETURN0;
-         if (!parse_child_operation(C, &o, oper, GL_TRUE))
-            RETURN0;
-         if (!parse_child_operation(C, &o, oper, GL_FALSE))
-            RETURN0;
-         if (!parse_child_operation(C, &o, oper, GL_TRUE))
-            RETURN0;
-      }
-      break;
-   case OP_PRECISION:
-      {
-         /* set default precision for a type in this scope */
-         /* ignored at this time */
-         int prec_qual = *C->I++;
-         int datatype = *C->I++;
-         (void) prec_qual;
-         (void) datatype;
-      }
-      break;
-   default:
-      /*printf("Unexpected operation %d\n", op);*/
-      RETURN0;
-   }
-   return 1;
-}
-
-static int
-handle_nary_expression(slang_parse_ctx * C, slang_operation * op,
-                       slang_operation ** ops, unsigned int *total_ops,
-                       unsigned int n)
-{
-   unsigned int i;
-
-   op->children = slang_operation_new(n);
-   if (op->children == NULL) {
-      slang_info_log_memory(C->L);
-      RETURN0;
-   }
-   op->num_children = n;
-
-   for (i = 0; i < n; i++) {
-      slang_operation_destruct(&op->children[i]);
-      op->children[i] = (*ops)[*total_ops - (n + 1 - i)];
-   }
-
-   (*ops)[*total_ops - (n + 1)] = (*ops)[*total_ops - 1];
-   *total_ops -= n;
-
-   *ops = (slang_operation *)
-      _slang_realloc(*ops,
-                     (*total_ops + n) * sizeof(slang_operation),
-                     *total_ops * sizeof(slang_operation));
-   if (*ops == NULL) {
-      slang_info_log_memory(C->L);
-      RETURN0;
-   }
-   return 1;
-}
-
-static int
-is_constructor_name(const char *name, slang_atom a_name,
-                    slang_struct_scope * structs)
-{
-   if (slang_type_specifier_type_from_string(name) != SLANG_SPEC_VOID)
-      return 1;
-   return slang_struct_scope_find(structs, a_name, 1) != NULL;
-}
-
-#define FUNCTION_CALL_NONARRAY 0
-#define FUNCTION_CALL_ARRAY    1
-
-static int
-parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
-                 slang_operation * oper)
-{
-   slang_operation *ops = NULL;
-   unsigned int num_ops = 0;
-   int number;
-
-   while (*C->I != OP_END) {
-      slang_operation *op;
-      const unsigned int op_code = *C->I++;
-
-      /* allocate default operation, becomes a no-op if not used  */
-      ops = (slang_operation *)
-         _slang_realloc(ops,
-                        num_ops * sizeof(slang_operation),
-                        (num_ops + 1) * sizeof(slang_operation));
-      if (ops == NULL) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      op = &ops[num_ops];
-      if (!slang_operation_construct(op)) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      num_ops++;
-      op->locals->outer_scope = O->vars;
-
-      switch (op_code) {
-      case OP_PUSH_VOID:
-         op->type = SLANG_OPER_VOID;
-         break;
-      case OP_PUSH_BOOL:
-         op->type = SLANG_OPER_LITERAL_BOOL;
-         if (!parse_number(C, &number))
-            RETURN0;
-         op->literal[0] =
-         op->literal[1] =
-         op->literal[2] =
-         op->literal[3] = (GLfloat) number;
-         op->literal_size = 1;
-         break;
-      case OP_PUSH_INT:
-         op->type = SLANG_OPER_LITERAL_INT;
-         if (!parse_number(C, &number))
-            RETURN0;
-         op->literal[0] =
-         op->literal[1] =
-         op->literal[2] =
-         op->literal[3] = (GLfloat) number;
-         op->literal_size = 1;
-         break;
-      case OP_PUSH_FLOAT:
-         op->type = SLANG_OPER_LITERAL_FLOAT;
-         if (!parse_float(C, &op->literal[0]))
-            RETURN0;
-         op->literal[1] =
-         op->literal[2] =
-         op->literal[3] = op->literal[0];
-         op->literal_size = 1;
-         break;
-      case OP_PUSH_IDENTIFIER:
-         op->type = SLANG_OPER_IDENTIFIER;
-         op->a_id = parse_identifier(C);
-         if (op->a_id == SLANG_ATOM_NULL)
-            RETURN0;
-         break;
-      case OP_SEQUENCE:
-         op->type = SLANG_OPER_SEQUENCE;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_ASSIGN:
-         op->type = SLANG_OPER_ASSIGN;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_ADDASSIGN:
-         op->type = SLANG_OPER_ADDASSIGN;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_SUBASSIGN:
-         op->type = SLANG_OPER_SUBASSIGN;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_MULASSIGN:
-         op->type = SLANG_OPER_MULASSIGN;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_DIVASSIGN:
-         op->type = SLANG_OPER_DIVASSIGN;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-         /*case OP_MODASSIGN: */
-         /*case OP_LSHASSIGN: */
-         /*case OP_RSHASSIGN: */
-         /*case OP_ORASSIGN: */
-         /*case OP_XORASSIGN: */
-         /*case OP_ANDASSIGN: */
-      case OP_SELECT:
-         op->type = SLANG_OPER_SELECT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 3))
-            RETURN0;
-         break;
-      case OP_LOGICALOR:
-         op->type = SLANG_OPER_LOGICALOR;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_LOGICALXOR:
-         op->type = SLANG_OPER_LOGICALXOR;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_LOGICALAND:
-         op->type = SLANG_OPER_LOGICALAND;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-         /*case OP_BITOR: */
-         /*case OP_BITXOR: */
-         /*case OP_BITAND: */
-      case OP_EQUAL:
-         op->type = SLANG_OPER_EQUAL;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_NOTEQUAL:
-         op->type = SLANG_OPER_NOTEQUAL;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_LESS:
-         op->type = SLANG_OPER_LESS;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_GREATER:
-         op->type = SLANG_OPER_GREATER;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_LESSEQUAL:
-         op->type = SLANG_OPER_LESSEQUAL;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_GREATEREQUAL:
-         op->type = SLANG_OPER_GREATEREQUAL;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-         /*case OP_LSHIFT: */
-         /*case OP_RSHIFT: */
-      case OP_ADD:
-         op->type = SLANG_OPER_ADD;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_SUBTRACT:
-         op->type = SLANG_OPER_SUBTRACT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_MULTIPLY:
-         op->type = SLANG_OPER_MULTIPLY;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_DIVIDE:
-         op->type = SLANG_OPER_DIVIDE;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-         /*case OP_MODULUS: */
-      case OP_PREINCREMENT:
-         op->type = SLANG_OPER_PREINCREMENT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      case OP_PREDECREMENT:
-         op->type = SLANG_OPER_PREDECREMENT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      case OP_PLUS:
-         op->type = SLANG_OPER_PLUS;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      case OP_MINUS:
-         op->type = SLANG_OPER_MINUS;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      case OP_NOT:
-         op->type = SLANG_OPER_NOT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-         /*case OP_COMPLEMENT: */
-      case OP_SUBSCRIPT:
-         op->type = SLANG_OPER_SUBSCRIPT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_METHOD:
-         op->type = SLANG_OPER_METHOD;
-         op->a_obj = parse_identifier(C);
-         if (op->a_obj == SLANG_ATOM_NULL)
-            RETURN0;
-
-         op->a_id = parse_identifier(C);
-         if (op->a_id == SLANG_ATOM_NULL)
-            RETURN0;
-
-         assert(*C->I == OP_END);
-         C->I++;
-
-         while (*C->I != OP_END)
-            if (!parse_child_operation(C, O, op, GL_FALSE))
-               RETURN0;
-         C->I++;
-#if 0
-         /* don't lookup the method (not yet anyway) */
-         if (!C->parsing_builtin
-             && !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) {
-            const char *id;
-
-            id = slang_atom_pool_id(C->atoms, op->a_id);
-            if (!is_constructor_name(id, op->a_id, O->structs)) {
-               slang_info_log_error(C->L, "%s: undeclared function name.", id);
-               RETURN0;
-            }
-         }
-#endif
-         break;
-      case OP_CALL:
-         {
-            GLboolean array_constructor = GL_FALSE;
-            GLint array_constructor_size = 0;
-
-            op->type = SLANG_OPER_CALL;
-            op->a_id = parse_identifier(C);
-            if (op->a_id == SLANG_ATOM_NULL)
-               RETURN0;
-            switch (*C->I++) {
-            case FUNCTION_CALL_NONARRAY:
-               /* Nothing to do. */
-               break;
-            case FUNCTION_CALL_ARRAY:
-               /* Calling an array constructor. For example:
-                *   float[3](1.1, 2.2, 3.3);
-                */
-               if (!O->allow_array_types) {
-                  slang_info_log_error(C->L,
-                                       "array constructors not allowed "
-                                       "in this GLSL version");
-                  RETURN0;
-               }
-               else {
-                  /* parse the array constructor size */
-                  slang_operation array_size;
-                  array_constructor = GL_TRUE;
-                  slang_operation_construct(&array_size);
-                  if (!parse_expression(C, O, &array_size)) {
-                     slang_operation_destruct(&array_size);
-                     return GL_FALSE;
-                  }
-                  if (array_size.type != SLANG_OPER_LITERAL_INT) {
-                     slang_info_log_error(C->L,
-                        "constructor array size is not an integer");
-                     slang_operation_destruct(&array_size);
-                     RETURN0;
-                  }
-                  array_constructor_size = (int) array_size.literal[0];
-                  op->array_constructor = GL_TRUE;
-                  slang_operation_destruct(&array_size);
-               }
-               break;
-            default:
-               assert(0);
-               RETURN0;
-            }
-            while (*C->I != OP_END)
-               if (!parse_child_operation(C, O, op, GL_FALSE))
-                  RETURN0;
-            C->I++;
-
-            if (array_constructor &&
-                array_constructor_size != op->num_children) {
-               slang_info_log_error(C->L, "number of parameters to array"
-                                    " constructor does not match array size");
-               RETURN0;
-            }
-
-            if (!C->parsing_builtin
-                && !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) {
-               const char *id;
-
-               id = slang_atom_pool_id(C->atoms, op->a_id);
-               if (!is_constructor_name(id, op->a_id, O->structs)) {
-                  slang_info_log_error(C->L, "%s: undeclared function name.", id);
-                  RETURN0;
-               }
-            }
-         }
-         break;
-      case OP_FIELD:
-         op->type = SLANG_OPER_FIELD;
-         op->a_id = parse_identifier(C);
-         if (op->a_id == SLANG_ATOM_NULL)
-            RETURN0;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      case OP_POSTINCREMENT:
-         op->type = SLANG_OPER_POSTINCREMENT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      case OP_POSTDECREMENT:
-         op->type = SLANG_OPER_POSTDECREMENT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      default:
-         RETURN0;
-      }
-   }
-   C->I++;
-
-   slang_operation_destruct(oper);
-   *oper = *ops; /* struct copy */
-   _slang_free(ops);
-
-   return 1;
-}
-
-/* parameter qualifier */
-#define PARAM_QUALIFIER_IN 0
-#define PARAM_QUALIFIER_OUT 1
-#define PARAM_QUALIFIER_INOUT 2
-
-/* function parameter array presence */
-#define PARAMETER_ARRAY_NOT_PRESENT 0
-#define PARAMETER_ARRAY_PRESENT 1
-
-static int
-parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
-                            slang_variable * param)
-{
-   int param_qual, precision_qual;
-
-   /* parse and validate the parameter's type qualifiers (there can be
-    * two at most) because not all combinations are valid
-    */
-   if (!parse_type_qualifier(C, &param->type.qualifier))
-      RETURN0;
-
-   param_qual = *C->I++;
-   switch (param_qual) {
-   case PARAM_QUALIFIER_IN:
-      if (param->type.qualifier != SLANG_QUAL_CONST
-          && param->type.qualifier != SLANG_QUAL_NONE) {
-         slang_info_log_error(C->L, "Invalid type qualifier.");
-         RETURN0;
-      }
-      break;
-   case PARAM_QUALIFIER_OUT:
-      if (param->type.qualifier == SLANG_QUAL_NONE)
-         param->type.qualifier = SLANG_QUAL_OUT;
-      else {
-         slang_info_log_error(C->L, "Invalid type qualifier.");
-         RETURN0;
-      }
-      break;
-   case PARAM_QUALIFIER_INOUT:
-      if (param->type.qualifier == SLANG_QUAL_NONE)
-         param->type.qualifier = SLANG_QUAL_INOUT;
-      else {
-         slang_info_log_error(C->L, "Invalid type qualifier.");
-         RETURN0;
-      }
-      break;
-   default:
-      RETURN0;
-   }
-
-   /* parse precision qualifier (lowp, mediump, highp */
-   precision_qual = *C->I++;
-   /* ignored at this time */
-   (void) precision_qual;
-
-   /* parse parameter's type specifier and name */
-   if (!parse_type_specifier(C, O, &param->type.specifier))
-      RETURN0;
-   if (!parse_type_array_size(C, O, &param->type.array_len))
-      RETURN0;
-   param->a_name = parse_identifier(C);
-   if (param->a_name == SLANG_ATOM_NULL)
-      RETURN0;
-
-   /* first-class array
-    */
-   if (param->type.array_len >= 0) {
-      slang_type_specifier p;
-
-      slang_type_specifier_ctr(&p);
-      if (!slang_type_specifier_copy(&p, &param->type.specifier)) {
-         slang_type_specifier_dtr(&p);
-         RETURN0;
-      }
-      if (!convert_to_array(C, param, &p)) {
-         slang_type_specifier_dtr(&p);
-         RETURN0;
-      }
-      slang_type_specifier_dtr(&p);
-      param->array_len = param->type.array_len;
-   }
-
-   /* if the parameter is an array, parse its size (the size must be
-    * explicitly defined
-    */
-   if (*C->I++ == PARAMETER_ARRAY_PRESENT) {
-      slang_type_specifier p;
-
-      if (param->type.array_len >= 0) {
-         slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
-         RETURN0;
-      }
-      slang_type_specifier_ctr(&p);
-      if (!slang_type_specifier_copy(&p, &param->type.specifier)) {
-         slang_type_specifier_dtr(&p);
-         RETURN0;
-      }
-      if (!convert_to_array(C, param, &p)) {
-         slang_type_specifier_dtr(&p);
-         RETURN0;
-      }
-      slang_type_specifier_dtr(&p);
-      if (!parse_array_len(C, O, &param->array_len))
-         RETURN0;
-   }
-
-#if 0
-   /* calculate the parameter size */
-   if (!calculate_var_size(C, O, param))
-      RETURN0;
-#endif
-   /* TODO: allocate the local address here? */
-   return 1;
-}
-
-/* function type */
-#define FUNCTION_ORDINARY 0
-#define FUNCTION_CONSTRUCTOR 1
-#define FUNCTION_OPERATOR 2
-
-/* function parameter */
-#define PARAMETER_NONE 0
-#define PARAMETER_NEXT 1
-
-/* operator type */
-#define OPERATOR_ADDASSIGN 1
-#define OPERATOR_SUBASSIGN 2
-#define OPERATOR_MULASSIGN 3
-#define OPERATOR_DIVASSIGN 4
-/*#define OPERATOR_MODASSIGN 5*/
-/*#define OPERATOR_LSHASSIGN 6*/
-/*#define OPERATOR_RSHASSIGN 7*/
-/*#define OPERATOR_ANDASSIGN 8*/
-/*#define OPERATOR_XORASSIGN 9*/
-/*#define OPERATOR_ORASSIGN 10*/
-#define OPERATOR_LOGICALXOR 11
-/*#define OPERATOR_BITOR 12*/
-/*#define OPERATOR_BITXOR 13*/
-/*#define OPERATOR_BITAND 14*/
-#define OPERATOR_LESS 15
-#define OPERATOR_GREATER 16
-#define OPERATOR_LESSEQUAL 17
-#define OPERATOR_GREATEREQUAL 18
-/*#define OPERATOR_LSHIFT 19*/
-/*#define OPERATOR_RSHIFT 20*/
-#define OPERATOR_MULTIPLY 21
-#define OPERATOR_DIVIDE 22
-/*#define OPERATOR_MODULUS 23*/
-#define OPERATOR_INCREMENT 24
-#define OPERATOR_DECREMENT 25
-#define OPERATOR_PLUS 26
-#define OPERATOR_MINUS 27
-/*#define OPERATOR_COMPLEMENT 28*/
-#define OPERATOR_NOT 29
-
-static const struct
-{
-   unsigned int o_code;
-   const char *o_name;
-} operator_names[] = {
-   {OPERATOR_INCREMENT, "++"},
-   {OPERATOR_ADDASSIGN, "+="},
-   {OPERATOR_PLUS, "+"},
-   {OPERATOR_DECREMENT, "--"},
-   {OPERATOR_SUBASSIGN, "-="},
-   {OPERATOR_MINUS, "-"},
-   {OPERATOR_NOT, "!"},
-   {OPERATOR_MULASSIGN, "*="},
-   {OPERATOR_MULTIPLY, "*"},
-   {OPERATOR_DIVASSIGN, "/="},
-   {OPERATOR_DIVIDE, "/"},
-   {OPERATOR_LESSEQUAL, "<="},
-   /*{ OPERATOR_LSHASSIGN, "<<=" }, */
-   /*{ OPERATOR_LSHIFT, "<<" }, */
-   {OPERATOR_LESS, "<"},
-   {OPERATOR_GREATEREQUAL, ">="},
-   /*{ OPERATOR_RSHASSIGN, ">>=" }, */
-   /*{ OPERATOR_RSHIFT, ">>" }, */
-   {OPERATOR_GREATER, ">"},
-   /*{ OPERATOR_MODASSIGN, "%=" }, */
-   /*{ OPERATOR_MODULUS, "%" }, */
-   /*{ OPERATOR_ANDASSIGN, "&=" }, */
-   /*{ OPERATOR_BITAND, "&" }, */
-   /*{ OPERATOR_ORASSIGN, "|=" }, */
-   /*{ OPERATOR_BITOR, "|" }, */
-   /*{ OPERATOR_COMPLEMENT, "~" }, */
-   /*{ OPERATOR_XORASSIGN, "^=" }, */
-   {OPERATOR_LOGICALXOR, "^^"},
-   /*{ OPERATOR_BITXOR, "^" } */
-};
-
-static slang_atom
-parse_operator_name(slang_parse_ctx * C)
-{
-   unsigned int i;
-
-   for (i = 0; i < sizeof(operator_names) / sizeof(*operator_names); i++) {
-      if (operator_names[i].o_code == (unsigned int) (*C->I)) {
-         slang_atom atom =
-            slang_atom_pool_atom(C->atoms, operator_names[i].o_name);
-         if (atom == SLANG_ATOM_NULL) {
-            slang_info_log_memory(C->L);
-            RETURN0;
-         }
-         C->I++;
-         return atom;
-      }
-   }
-   RETURN0;
-}
-
-
-static int
-parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O,
-                         slang_function * func)
-{
-   GLuint functype;
-   /* parse function type and name */
-   if (!parse_fully_specified_type(C, O, &func->header.type))
-      RETURN0;
-
-   functype = *C->I++;
-   switch (functype) {
-   case FUNCTION_ORDINARY:
-      func->kind = SLANG_FUNC_ORDINARY;
-      func->header.a_name = parse_identifier(C);
-      if (func->header.a_name == SLANG_ATOM_NULL)
-         RETURN0;
-      break;
-   case FUNCTION_CONSTRUCTOR:
-      func->kind = SLANG_FUNC_CONSTRUCTOR;
-      if (func->header.type.specifier.type == SLANG_SPEC_STRUCT)
-         RETURN0;
-      func->header.a_name =
-         slang_atom_pool_atom(C->atoms,
-                              slang_type_specifier_type_to_string
-                              (func->header.type.specifier.type));
-      if (func->header.a_name == SLANG_ATOM_NULL) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      break;
-   case FUNCTION_OPERATOR:
-      func->kind = SLANG_FUNC_OPERATOR;
-      func->header.a_name = parse_operator_name(C);
-      if (func->header.a_name == SLANG_ATOM_NULL)
-         RETURN0;
-      break;
-   default:
-      RETURN0;
-   }
-
-   if (!legal_identifier(func->header.a_name)) {
-      slang_info_log_error(C->L, "illegal function name '%s'",
-                           (char *) func->header.a_name);
-      RETURN0;
-   }
-
-   /* parse function parameters */
-   while (*C->I++ == PARAMETER_NEXT) {
-      slang_variable *p = slang_variable_scope_grow(func->parameters);
-      if (!p) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      if (!parse_parameter_declaration(C, O, p))
-         RETURN0;
-   }
-
-   /* if the function returns a value, append a hidden __retVal 'out'
-    * parameter that corresponds to the return value.
-    */
-   if (_slang_function_has_return_value(func)) {
-      slang_variable *p = slang_variable_scope_grow(func->parameters);
-      slang_atom a_retVal = slang_atom_pool_atom(C->atoms, "__retVal");
-      assert(a_retVal);
-      p->a_name = a_retVal;
-      p->type = func->header.type;
-      p->type.qualifier = SLANG_QUAL_OUT;
-   }
-
-   /* function formal parameters and local variables share the same
-    * scope, so save the information about param count in a seperate
-    * place also link the scope to the global variable scope so when a
-    * given identifier is not found here, the search process continues
-    * in the global space
-    */
-   func->param_count = func->parameters->num_variables;
-   func->parameters->outer_scope = O->vars;
-
-   return 1;
-}
-
-static int
-parse_function_definition(slang_parse_ctx * C, slang_output_ctx * O,
-                          slang_function * func)
-{
-   slang_output_ctx o = *O;
-
-   if (!parse_function_prototype(C, O, func))
-      RETURN0;
-
-   /* create function's body operation */
-   func->body = (slang_operation *) _slang_alloc(sizeof(slang_operation));
-   if (func->body == NULL) {
-      slang_info_log_memory(C->L);
-      RETURN0;
-   }
-   if (!slang_operation_construct(func->body)) {
-      _slang_free(func->body);
-      func->body = NULL;
-      slang_info_log_memory(C->L);
-      RETURN0;
-   }
-
-   /* to parse the body the parse context is modified in order to
-    * capture parsed variables into function's local variable scope
-    */
-   C->global_scope = GL_FALSE;
-   o.vars = func->parameters;
-   if (!parse_statement(C, &o, func->body))
-      RETURN0;
-
-   C->global_scope = GL_TRUE;
-   return 1;
-}
-
-static GLboolean
-initialize_global(slang_assemble_ctx * A, slang_variable * var)
-{
-   slang_operation op_id, op_assign;
-   GLboolean result;
-
-   /* construct the left side of assignment */
-   if (!slang_operation_construct(&op_id))
-      return GL_FALSE;
-   op_id.type = SLANG_OPER_IDENTIFIER;
-   op_id.a_id = var->a_name;
-
-   /* put the variable into operation's scope */
-   op_id.locals->variables =
-      (slang_variable **) _slang_alloc(sizeof(slang_variable *));
-   if (op_id.locals->variables == NULL) {
-      slang_operation_destruct(&op_id);
-      return GL_FALSE;
-   }
-   op_id.locals->num_variables = 1;
-   op_id.locals->variables[0] = var;
-
-   /* construct the assignment expression */
-   if (!slang_operation_construct(&op_assign)) {
-      op_id.locals->num_variables = 0;
-      slang_operation_destruct(&op_id);
-      return GL_FALSE;
-   }
-   op_assign.type = SLANG_OPER_ASSIGN;
-   op_assign.children =
-      (slang_operation *) _slang_alloc(2 * sizeof(slang_operation));
-   if (op_assign.children == NULL) {
-      slang_operation_destruct(&op_assign);
-      op_id.locals->num_variables = 0;
-      slang_operation_destruct(&op_id);
-      return GL_FALSE;
-   }
-   op_assign.num_children = 2;
-   op_assign.children[0] = op_id;
-   op_assign.children[1] = *var->initializer;
-
-   result = 1;
-
-   /* carefully destroy the operations */
-   op_assign.num_children = 0;
-   _slang_free(op_assign.children);
-   op_assign.children = NULL;
-   slang_operation_destruct(&op_assign);
-   op_id.locals->num_variables = 0;
-   slang_operation_destruct(&op_id);
-
-   if (!result)
-      return GL_FALSE;
-
-   return GL_TRUE;
-}
-
-/* init declarator list */
-#define DECLARATOR_NONE 0
-#define DECLARATOR_NEXT 1
-
-/* variable declaration */
-#define VARIABLE_NONE 0
-#define VARIABLE_IDENTIFIER 1
-#define VARIABLE_INITIALIZER 2
-#define VARIABLE_ARRAY_EXPLICIT 3
-#define VARIABLE_ARRAY_UNKNOWN 4
-
-
-/**
- * Check if it's OK to re-declare a variable with the given new type.
- * This happens when applying layout qualifiers to gl_FragCoord or
- * (re)setting an array size.
- * If redeclaration is OK, return a pointer to the incoming variable
- * updated with new type info.  Else return NULL;
- */
-static slang_variable *
-redeclare_variable(slang_variable *var, 
-                   const slang_fully_specified_type *type)
-{
-   if (slang_fully_specified_types_compatible(&var->type, type)) {
-      /* replace orig var layout with new layout */
-      var->type.layout = type->layout;
-
-      /* XXX there may be other type updates in the future here */
-
-      return var;
-   }
-   else
-      return NULL;
-}
-
-
-/**
- * Parse the initializer for a variable declaration.
- */
-static int
-parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
-                      const slang_fully_specified_type * type)
-{
-   GET_CURRENT_CONTEXT(ctx); /* a hack */
-   slang_variable *var = NULL, *prevDecl;
-   slang_atom a_name;
-
-   /* empty init declatator (without name, e.g. "float ;") */
-   if (*C->I++ == VARIABLE_NONE)
-      return 1;
-
-   a_name = parse_identifier(C);
-
-   /* check if name is already in this scope */
-   prevDecl = _slang_variable_locate(O->vars, a_name, C->global_scope);
-   if (prevDecl) {
-      /* A var with this name has already been declared.
-       * Check if redeclaring the var with a different type/layout is legal.
-       */
-      if (C->global_scope) {
-         var = redeclare_variable(prevDecl, type);
-      }
-      if (!var) {
-         slang_info_log_error(C->L,
-                   "declaration of '%s' conflicts with previous declaration",
-                   (char *) a_name);
-         RETURN0;
-      }
-   }
-
-   if (!var) {
-      /* make room for a new variable and initialize it */
-      var = slang_variable_scope_grow(O->vars);
-      if (!var) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-
-      /* copy the declarator type qualifier/etc info, parse the identifier */
-      var->type.qualifier = type->qualifier;
-      var->type.centroid = type->centroid;
-      var->type.precision = type->precision;
-      var->type.specifier = type->specifier;/*new*/
-      var->type.variant = type->variant;
-      var->type.layout = type->layout;
-      var->type.array_len = type->array_len;
-      var->a_name = a_name;
-      if (var->a_name == SLANG_ATOM_NULL)
-         RETURN0;
-   }
-
-   switch (*C->I++) {
-   case VARIABLE_NONE:
-      /* simple variable declarator - just copy the specifier */
-      if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
-         RETURN0;
-      break;
-   case VARIABLE_INITIALIZER:
-      /* initialized variable - copy the specifier and parse the expression */
-      if (0 && type->array_len >= 0) {
-         /* The type was something like "float[4]" */
-         convert_to_array(C, var, &type->specifier);
-         var->array_len = type->array_len;
-      }
-      else {
-         if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
-            RETURN0;
-      }
-      var->initializer =
-         (slang_operation *) _slang_alloc(sizeof(slang_operation));
-      if (var->initializer == NULL) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      if (!slang_operation_construct(var->initializer)) {
-         _slang_free(var->initializer);
-         var->initializer = NULL;
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      if (!parse_expression(C, O, var->initializer))
-         RETURN0;
-      break;
-   case VARIABLE_ARRAY_UNKNOWN:
-      /* unsized array - mark it as array and copy the specifier to
-       * the array element
-       */
-      if (type->array_len >= 0) {
-         slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
-         RETURN0;
-      }
-      if (!convert_to_array(C, var, &type->specifier))
-         return GL_FALSE;
-      break;
-   case VARIABLE_ARRAY_EXPLICIT:
-      if (type->array_len >= 0) {
-         /* the user is trying to do something like: float[2] x[3]; */
-         slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
-         RETURN0;
-      }
-      if (!convert_to_array(C, var, &type->specifier))
-         return GL_FALSE;
-      if (!parse_array_len(C, O, &var->array_len))
-         return GL_FALSE;
-      break;
-   default:
-      RETURN0;
-   }
-
-   /* allocate global address space for a variable with a known size */
-   if (C->global_scope
-       && !(var->type.specifier.type == SLANG_SPEC_ARRAY
-            && var->array_len == 0)) {
-      if (!calculate_var_size(C, O, var))
-         return GL_FALSE;
-   }
-
-   /* emit code for global var decl */
-   if (C->global_scope) {
-      slang_assemble_ctx A;
-      memset(&A, 0, sizeof(slang_assemble_ctx));
-      A.allow_uniform_initializers = C->version > 110;
-      A.atoms = C->atoms;
-      A.space.funcs = O->funs;
-      A.space.structs = O->structs;
-      A.space.vars = O->vars;
-      A.program = O->program;
-      A.pragmas = O->pragmas;
-      A.vartable = O->vartable;
-      A.log = C->L;
-      A.curFuncEndLabel = NULL;
-      A.EmitContReturn = ctx->Shader.EmitContReturn;
-      if (!_slang_codegen_global_variable(&A, var, C->type))
-         RETURN0;
-   }
-
-   /* initialize global variable */
-   if (C->global_scope) {
-      if (var->initializer != NULL) {
-         slang_assemble_ctx A;
-         memset(&A, 0, sizeof(slang_assemble_ctx));
-         A.allow_uniform_initializers = C->version > 110;
-         A.atoms = C->atoms;
-         A.space.funcs = O->funs;
-         A.space.structs = O->structs;
-         A.space.vars = O->vars;
-         if (!initialize_global(&A, var))
-            RETURN0;
-      }
-   }
-
-   if (var->type.qualifier == SLANG_QUAL_FIXEDINPUT &&
-       var->a_name == slang_atom_pool_atom(C->atoms, "gl_FragCoord")) {
-      /* set the program's PixelCenterInteger, OriginUpperLeft fields */
-      struct gl_fragment_program *fragProg =
-         (struct gl_fragment_program *) O->program;
-
-      if (var->type.layout & SLANG_LAYOUT_UPPER_LEFT_BIT) {
-         fragProg->OriginUpperLeft = GL_TRUE;
-      }
-      if (var->type.layout & SLANG_LAYOUT_PIXEL_CENTER_INTEGER_BIT) {
-         fragProg->PixelCenterInteger = GL_TRUE;
-      }
-   }
-
-   return 1;
-}
-
-/**
- * Parse a list of variable declarations.  Each variable may have an
- * initializer.
- */
-static int
-parse_init_declarator_list(slang_parse_ctx * C, slang_output_ctx * O)
-{
-   slang_fully_specified_type type;
-
-   /* parse the fully specified type, common to all declarators */
-   if (!slang_fully_specified_type_construct(&type))
-      RETURN0;
-   if (!parse_fully_specified_type(C, O, &type)) {
-      slang_fully_specified_type_destruct(&type);
-      RETURN0;
-   }
-
-   /* parse declarators, pass-in the parsed type */
-   do {
-      if (!parse_init_declarator(C, O, &type)) {
-         slang_fully_specified_type_destruct(&type);
-         RETURN0;
-      }
-   }
-   while (*C->I++ == DECLARATOR_NEXT);
-
-   slang_fully_specified_type_destruct(&type);
-   return 1;
-}
-
-
-/**
- * Parse a function definition or declaration.
- * \param C  parsing context
- * \param O  output context
- * \param definition if non-zero expect a definition, else a declaration
- * \param parsed_func_ret  returns the parsed function
- * \return GL_TRUE if success, GL_FALSE if failure
- */
-static GLboolean
-parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
-               slang_function ** parsed_func_ret)
-{
-   slang_function parsed_func, *found_func;
-
-   /* parse function definition/declaration */
-   if (!slang_function_construct(&parsed_func))
-      return GL_FALSE;
-   if (definition) {
-      if (!parse_function_definition(C, O, &parsed_func)) {
-         slang_function_destruct(&parsed_func);
-         return GL_FALSE;
-      }
-   }
-   else {
-      if (!parse_function_prototype(C, O, &parsed_func)) {
-         slang_function_destruct(&parsed_func);
-         return GL_FALSE;
-      }
-   }
-
-   /* find a function with a prototype matching the parsed one - only
-    * the current scope is being searched to allow built-in function
-    * overriding
-    */
-   found_func = slang_function_scope_find(O->funs, &parsed_func, 0);
-   if (found_func == NULL) {
-      /* New function, add it to the function list */
-      O->funs->functions =
-         (slang_function *) _slang_realloc(O->funs->functions,
-                                           O->funs->num_functions
-                                           * sizeof(slang_function),
-                                           (O->funs->num_functions + 1)
-                                           * sizeof(slang_function));
-      if (O->funs->functions == NULL) {
-         /* Make sure that there are no functions marked, as the
-          * allocation is currently NULL, in order to avoid
-          * a potental segfault as we clean up later.
-          */
-         O->funs->num_functions = 0;
-
-         slang_info_log_memory(C->L);
-         slang_function_destruct(&parsed_func);
-         return GL_FALSE;
-      }
-      O->funs->functions[O->funs->num_functions] = parsed_func;
-      O->funs->num_functions++;
-
-      /* return the newly parsed function */
-      *parsed_func_ret = &O->funs->functions[O->funs->num_functions - 1];
-   }
-   else {
-      /* previously defined or declared */
-      /* TODO: check function return type qualifiers and specifiers */
-      if (definition) {
-         if (found_func->body != NULL) {
-            slang_info_log_error(C->L, "%s: function already has a body.",
-                                 slang_atom_pool_id(C->atoms,
-                                                    parsed_func.header.
-                                                    a_name));
-            slang_function_destruct(&parsed_func);
-            return GL_FALSE;
-         }
-
-         /* destroy the existing function declaration and replace it
-          * with the new one
-          */
-         slang_function_destruct(found_func);
-         *found_func = parsed_func;
-      }
-      else {
-         /* another declaration of the same function prototype - ignore it */
-         slang_function_destruct(&parsed_func);
-      }
-
-      /* return the found function */
-      *parsed_func_ret = found_func;
-   }
-
-   return GL_TRUE;
-}
-
-/* declaration */
-#define DECLARATION_FUNCTION_PROTOTYPE 1
-#define DECLARATION_INIT_DECLARATOR_LIST 2
-
-static int
-parse_declaration(slang_parse_ctx * C, slang_output_ctx * O)
-{
-   switch (*C->I++) {
-   case DECLARATION_INIT_DECLARATOR_LIST:
-      if (!parse_init_declarator_list(C, O))
-         RETURN0;
-      break;
-   case DECLARATION_FUNCTION_PROTOTYPE:
-      {
-         slang_function *dummy_func;
-
-         if (!parse_function(C, O, 0, &dummy_func))
-            RETURN0;
-      }
-      break;
-   default:
-      RETURN0;
-   }
-   return 1;
-}
-
-static int
-parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O)
-{
-   int precision, type;
-
-   if (!O->allow_precision) {
-      slang_info_log_error(C->L, "syntax error at \"precision\"");
-      RETURN0;
-   }
-
-   precision = *C->I++;
-   switch (precision) {
-   case PRECISION_LOW:
-   case PRECISION_MEDIUM:
-   case PRECISION_HIGH:
-      /* OK */
-      break;
-   default:
-      _mesa_problem(NULL, "unexpected precision %d at %s:%d\n",
-                    precision, __FILE__, __LINE__);
-      RETURN0;
-   }
-
-   type = *C->I++;
-   switch (type) {
-   case TYPE_SPECIFIER_FLOAT:
-   case TYPE_SPECIFIER_INT:
-   case TYPE_SPECIFIER_SAMPLER1D:
-   case TYPE_SPECIFIER_SAMPLER2D:
-   case TYPE_SPECIFIER_SAMPLER3D:
-   case TYPE_SPECIFIER_SAMPLERCUBE:
-   case TYPE_SPECIFIER_SAMPLER1DSHADOW:
-   case TYPE_SPECIFIER_SAMPLER2DSHADOW:
-   case TYPE_SPECIFIER_SAMPLER2DRECT:
-   case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW:
-   case TYPE_SPECIFIER_SAMPLER_1D_ARRAY:
-   case TYPE_SPECIFIER_SAMPLER_2D_ARRAY:
-   case TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW:
-   case TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW:
-      /* OK */
-      break;
-   default:
-      _mesa_problem(NULL, "unexpected type %d at %s:%d\n",
-                    type, __FILE__, __LINE__);
-      RETURN0;
-   }
-
-   assert(type < TYPE_SPECIFIER_COUNT);
-   O->default_precision[type] = precision;
-
-   return 1;
-}
-
-
-/**
- * Initialize the default precision for all types.
- * XXX this info isn't used yet.
- */
-static void
-init_default_precision(slang_output_ctx *O, slang_unit_type type)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLuint i;
-   for (i = 0; i < TYPE_SPECIFIER_COUNT; i++) {
-#if FEATURE_es2_glsl
-      if (ctx->API == API_OPENGLES2)
-        O->default_precision[i] = PRECISION_LOW;
-      else
-        O->default_precision[i] = PRECISION_HIGH;
-#else
-      (void) ctx;
-      O->default_precision[i] = PRECISION_HIGH;
-#endif
-   }
-
-   if (type == SLANG_UNIT_VERTEX_SHADER) {
-      O->default_precision[TYPE_SPECIFIER_FLOAT] = PRECISION_HIGH;
-      O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_HIGH;
-   }
-   else {
-      O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_MEDIUM;
-   }
-}
-
-
-static int
-parse_invariant(slang_parse_ctx * C, slang_output_ctx * O)
-{
-   if (O->allow_invariant) {
-      slang_atom *a = parse_identifier(C);
-      /* XXX not doing anything with this var yet */
-      /*printf("ID: %s\n", (char*) a);*/
-      return a ? 1 : 0;
-   }
-   else {
-      slang_info_log_error(C->L, "syntax error at \"invariant\"");
-      RETURN0;
-   }
-}
-      
-
-/* external declaration or default precision specifier */
-#define EXTERNAL_NULL 0
-#define EXTERNAL_FUNCTION_DEFINITION 1
-#define EXTERNAL_DECLARATION 2
-#define DEFAULT_PRECISION 3
-#define INVARIANT_STMT 4
-
-
-static GLboolean
-parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
-                struct gl_shader *shader)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   slang_output_ctx o;
-   GLboolean success;
-   GLuint maxRegs;
-   slang_function *mainFunc = NULL;
-
-   if (unit->type == SLANG_UNIT_FRAGMENT_BUILTIN ||
-       unit->type == SLANG_UNIT_FRAGMENT_SHADER) {
-      maxRegs = ctx->Const.FragmentProgram.MaxTemps;
-   }
-   else {
-      assert(unit->type == SLANG_UNIT_VERTEX_BUILTIN ||
-             unit->type == SLANG_UNIT_VERTEX_SHADER);
-      maxRegs = ctx->Const.VertexProgram.MaxTemps;
-   }
-
-   /* setup output context */
-   o.funs = &unit->funs;
-   o.structs = &unit->structs;
-   o.vars = &unit->vars;
-   o.program = shader ? shader->Program : NULL;
-   o.pragmas = shader ? &shader->Pragmas : NULL;
-   o.vartable = _slang_new_var_table(maxRegs);
-   _slang_push_var_table(o.vartable);
-
-   /* allow 'invariant' keyword? */
-#if FEATURE_es2_glsl
-   o.allow_invariant =
-      (ctx->API == API_OPENGLES2 || C->version >= 120) ? GL_TRUE : GL_FALSE;
-#else
-   o.allow_invariant = (C->version >= 120) ? GL_TRUE : GL_FALSE;
-#endif
-
-   /* allow 'centroid' keyword? */
-   o.allow_centroid = (C->version >= 120) ? GL_TRUE : GL_FALSE;
-
-   /* allow 'lowp/mediump/highp' keywords? */
-#if FEATURE_es2_glsl
-   o.allow_precision =
-      (ctx->API == API_OPENGLES2 || C->version >= 120) ? GL_TRUE : GL_FALSE;
-#else
-   o.allow_precision = (C->version >= 120) ? GL_TRUE : GL_FALSE;
-#endif
-   init_default_precision(&o, unit->type);
-
-   /* allow 'float[]' keyword? */
-   o.allow_array_types = (C->version >= 120) ? GL_TRUE : GL_FALSE;
-
-   /* parse individual functions and declarations */
-   while (*C->I != EXTERNAL_NULL) {
-      switch (*C->I++) {
-      case EXTERNAL_FUNCTION_DEFINITION:
-         {
-            slang_function *func;
-            success = parse_function(C, &o, 1, &func);
-            if (success && strcmp((char *) func->header.a_name, "main") == 0) {
-               /* found main() */
-               mainFunc = func;
-            }
-         }
-         break;
-      case EXTERNAL_DECLARATION:
-         success = parse_declaration(C, &o);
-         break;
-      case DEFAULT_PRECISION:
-         success = parse_default_precision(C, &o);
-         break;
-      case INVARIANT_STMT:
-         success = parse_invariant(C, &o);
-         break;
-      default:
-         success = GL_FALSE;
-      }
-
-      if (!success) {
-         /* xxx free codegen */
-         _slang_pop_var_table(o.vartable);
-         return GL_FALSE;
-      }
-   }
-   C->I++;
-
-   if (mainFunc) {
-      /* assemble (generate code) for main() */
-      slang_assemble_ctx A;
-      memset(&A, 0, sizeof(slang_assemble_ctx));
-      A.atoms = C->atoms;
-      A.space.funcs = o.funs;
-      A.space.structs = o.structs;
-      A.space.vars = o.vars;
-      A.program = o.program;
-      A.pragmas = &shader->Pragmas;
-      A.vartable = o.vartable;
-      A.EmitContReturn = ctx->Shader.EmitContReturn;
-      A.log = C->L;
-      A.allow_uniform_initializers = C->version > 110;
-
-      /* main() takes no parameters */
-      if (mainFunc->param_count > 0) {
-         slang_info_log_error(A.log, "main() takes no arguments");
-         return GL_FALSE;
-      }
-
-      _slang_codegen_function(&A, mainFunc);
-
-      shader->Main = GL_TRUE; /* this shader defines main() */
-
-      shader->UnresolvedRefs = A.UnresolvedRefs;
-   }
-
-   _slang_pop_var_table(o.vartable);
-   _slang_delete_var_table(o.vartable);
-
-   return GL_TRUE;
-}
-
-static GLboolean
-compile_binary(const unsigned char * prod, slang_code_unit * unit,
-               GLuint version,
-               slang_unit_type type, slang_info_log * infolog,
-               slang_code_unit * builtin, slang_code_unit * downlink,
-               struct gl_shader *shader)
-{
-   slang_parse_ctx C;
-
-   unit->type = type;
-
-   /* setup parse context */
-   C.I = prod;
-   C.L = infolog;
-   C.parsing_builtin = (builtin == NULL);
-   C.global_scope = GL_TRUE;
-   C.atoms = &unit->object->atompool;
-   C.type = type;
-   C.version = version;
-
-   if (!check_revision(&C))
-      return GL_FALSE;
-
-   if (downlink != NULL) {
-      unit->vars.outer_scope = &downlink->vars;
-      unit->funs.outer_scope = &downlink->funs;
-      unit->structs.outer_scope = &downlink->structs;
-   }
-
-   /* parse translation unit */
-   return parse_code_unit(&C, unit, shader);
-}
-
-static GLboolean
-compile_with_grammar(const char *source,
-                     slang_code_unit *unit,
-                     slang_unit_type type,
-                     slang_info_log *infolog,
-                     slang_code_unit *builtin,
-                     struct gl_shader *shader,
-                     struct gl_sl_pragmas *pragmas,
-                     unsigned int shader_type,
-                     unsigned int parsing_builtin)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct sl_pp_purify_options options;
-   struct sl_pp_context *context;
-   unsigned char *prod;
-   GLuint size;
-   unsigned int version;
-   unsigned int maxVersion;
-   int result;
-   char errmsg[200] = "";
-
-   assert(shader_type == 1 || shader_type == 2);
-
-   memset(&options, 0, sizeof(options));
-
-   context = sl_pp_context_create(source, &options);
-   if (!context) {
-      slang_info_log_error(infolog, "out of memory");
-      return GL_FALSE;
-   }
-
-   if (sl_pp_version(context, &version)) {
-      slang_info_log_error(infolog, "%s", sl_pp_context_error_message(context));
-      sl_pp_context_destroy(context);
-      return GL_FALSE;
-   }
-
-   if (sl_pp_context_add_extension(context, "GL_ARB_draw_buffers") ||
-       sl_pp_context_add_extension(context, "GL_ARB_texture_rectangle")) {
-      slang_info_log_error(infolog, "%s", sl_pp_context_error_message(context));
-      sl_pp_context_destroy(context);
-      return GL_FALSE;
-   }
-
-   if (type == SLANG_UNIT_FRAGMENT_SHADER) {
-      sl_pp_context_add_extension(context, "GL_ARB_fragment_coord_conventions");
-   }
-
-
-#if FEATURE_es2_glsl
-   if (ctx->API == API_OPENGLES2) {
-      if (sl_pp_context_add_predefined(context, "GL_ES", "1") ||
-         sl_pp_context_add_predefined(context, "GL_FRAGMENT_PRECISION_HIGH", "1")) {
-        slang_info_log_error(infolog, "%s", sl_pp_context_error_message(context));
-        sl_pp_context_destroy(context);
-        return GL_FALSE;
-      }
-   }
-#else
-   (void) ctx;
-#endif
-
-#if FEATURE_ARB_shading_language_120
-   maxVersion = 120;
-#elif FEATURE_es2_glsl
-   maxVersion = 100;
-#else
-   maxVersion = 110;
-#endif
-
-   if (version > maxVersion ||
-       (version != 100 && version != 110 && version != 120)) {
-      slang_info_log_error(infolog,
-                           "language version %.2f is not supported.",
-                           version * 0.01);
-      sl_pp_context_destroy(context);
-      return GL_FALSE;
-   }
-
-   /* Finally check the syntax and generate its binary representation. */
-   result = sl_cl_compile(context,
-                          shader_type,
-                          parsing_builtin,
-                          &prod,
-                          &size,
-                          errmsg,
-                          sizeof(errmsg));
-
-   sl_pp_context_destroy(context);
-
-   if (result) {
-      /*GLint pos;*/
-
-      slang_info_log_error(infolog, errmsg);
-      /* syntax error (possibly in library code) */
-#if 0
-      {
-         int line, col;
-         char *s;
-         s = (char *) _mesa_find_line_column((const GLubyte *) source,
-                                             (const GLubyte *) source + pos,
-                                             &line, &col);
-         printf("Error on line %d, col %d: %s\n", line, col, s);
-      }
-#endif
-      return GL_FALSE;
-   }
-
-   /* Syntax is okay - translate it to internal representation. */
-   if (!compile_binary(prod, unit, version, type, infolog, builtin,
-                       &builtin[SLANG_BUILTIN_TOTAL - 1],
-                       shader)) {
-      free(prod);
-      return GL_FALSE;
-   }
-   free(prod);
-   return GL_TRUE;
-}
-
-static const unsigned char slang_core_gc[] = {
-#include "library/slang_core_gc.h"
-};
-
-static const unsigned char slang_120_core_gc[] = {
-#include "library/slang_120_core_gc.h"
-};
-
-static const unsigned char slang_120_fragment_gc[] = {
-#include "library/slang_builtin_120_fragment_gc.h"
-};
-
-static const unsigned char slang_common_builtin_gc[] = {
-#include "library/slang_common_builtin_gc.h"
-};
-
-static const unsigned char slang_fragment_builtin_gc[] = {
-#include "library/slang_fragment_builtin_gc.h"
-};
-
-static const unsigned char slang_vertex_builtin_gc[] = {
-#include "library/slang_vertex_builtin_gc.h"
-};
-
-static GLboolean
-compile_object(const char *source,
-               slang_code_object *object,
-               slang_unit_type type,
-               slang_info_log *infolog,
-               struct gl_shader *shader,
-               struct gl_sl_pragmas *pragmas)
-{
-   slang_code_unit *builtins = NULL;
-   GLuint base_version = 110;
-   unsigned int shader_type;
-   unsigned int parsing_builtin;
-
-   /* set shader type - the syntax is slightly different for different shaders */
-   if (type == SLANG_UNIT_FRAGMENT_SHADER || type == SLANG_UNIT_FRAGMENT_BUILTIN) {
-      shader_type = 1;
-   } else {
-      shader_type = 2;
-   }
-
-   /* enable language extensions */
-   parsing_builtin = 1;
-
-   /* if parsing user-specified shader, load built-in library */
-   if (type == SLANG_UNIT_FRAGMENT_SHADER || type == SLANG_UNIT_VERTEX_SHADER) {
-      /* compile core functionality first */
-      if (!compile_binary(slang_core_gc,
-                          &object->builtin[SLANG_BUILTIN_CORE],
-                          base_version,
-                          SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
-                          NULL, NULL, NULL))
-         return GL_FALSE;
-
-#if FEATURE_ARB_shading_language_120
-      if (!compile_binary(slang_120_core_gc,
-                          &object->builtin[SLANG_BUILTIN_120_CORE],
-                          120,
-                          SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
-                          NULL, &object->builtin[SLANG_BUILTIN_CORE], NULL))
-         return GL_FALSE;
-#endif
-
-      /* compile common functions and variables, link to core */
-      if (!compile_binary(slang_common_builtin_gc,
-                          &object->builtin[SLANG_BUILTIN_COMMON],
-#if FEATURE_ARB_shading_language_120
-                          120,
-#else
-                          base_version,
-#endif
-                          SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
-#if FEATURE_ARB_shading_language_120
-                          &object->builtin[SLANG_BUILTIN_120_CORE],
-#else
-                          &object->builtin[SLANG_BUILTIN_CORE],
-#endif
-                          NULL))
-         return GL_FALSE;
-
-      /* compile target-specific functions and variables, link to common */
-      if (type == SLANG_UNIT_FRAGMENT_SHADER) {
-         if (!compile_binary(slang_fragment_builtin_gc,
-                             &object->builtin[SLANG_BUILTIN_TARGET],
-                             base_version,
-                             SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
-                             &object->builtin[SLANG_BUILTIN_COMMON], NULL))
-            return GL_FALSE;
-#if FEATURE_ARB_shading_language_120
-         if (!compile_binary(slang_120_fragment_gc,
-                             &object->builtin[SLANG_BUILTIN_TARGET],
-                             120,
-                             SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
-                             &object->builtin[SLANG_BUILTIN_COMMON], NULL))
-            return GL_FALSE;
-#endif
-      }
-      else if (type == SLANG_UNIT_VERTEX_SHADER) {
-         if (!compile_binary(slang_vertex_builtin_gc,
-                             &object->builtin[SLANG_BUILTIN_TARGET],
-                             base_version,
-                             SLANG_UNIT_VERTEX_BUILTIN, infolog, NULL,
-                             &object->builtin[SLANG_BUILTIN_COMMON], NULL))
-            return GL_FALSE;
-      }
-
-      /* disable language extensions */
-      parsing_builtin = 0;
-
-      builtins = object->builtin;
-   }
-
-   /* compile the actual shader - pass-in built-in library for external shader */
-   return compile_with_grammar(source,
-                               &object->unit,
-                               type,
-                               infolog,
-                               builtins,
-                               shader,
-                               pragmas,
-                               shader_type,
-                               parsing_builtin);
-}
-
-
-GLboolean
-_slang_compile(GLcontext *ctx, struct gl_shader *shader)
-{
-   GLboolean success;
-   slang_info_log info_log;
-   slang_code_object obj;
-   slang_unit_type type;
-   GLenum progTarget;
-
-   if (shader->Type == GL_VERTEX_SHADER) {
-      type = SLANG_UNIT_VERTEX_SHADER;
-   }
-   else {
-      assert(shader->Type == GL_FRAGMENT_SHADER);
-      type = SLANG_UNIT_FRAGMENT_SHADER;
-   }
-
-   if (!shader->Source)
-      return GL_FALSE;
-
-   ctx->Shader.MemPool = _slang_new_mempool(1024*1024);
-
-   shader->Main = GL_FALSE;
-
-   /* free the shader's old instructions, etc */
-   _mesa_reference_program(ctx, &shader->Program, NULL);
-
-   /* allocate new GPU program, parameter lists, etc. */
-   if (shader->Type == GL_VERTEX_SHADER)
-      progTarget = GL_VERTEX_PROGRAM_ARB;
-   else
-      progTarget = GL_FRAGMENT_PROGRAM_ARB;
-   shader->Program = ctx->Driver.NewProgram(ctx, progTarget, 1);
-   shader->Program->Parameters = _mesa_new_parameter_list();
-   shader->Program->Varying = _mesa_new_parameter_list();
-   shader->Program->Attributes = _mesa_new_parameter_list();
-
-   slang_info_log_construct(&info_log);
-   _slang_code_object_ctr(&obj);
-
-   success = compile_object(shader->Source,
-                            &obj,
-                            type,
-                            &info_log,
-                            shader,
-                            &shader->Pragmas);
-
-   /* free shader's prev info log */
-   if (shader->InfoLog) {
-      free(shader->InfoLog);
-      shader->InfoLog = NULL;
-   }
-
-   if (info_log.text) {
-      /* copy info-log string to shader object */
-      shader->InfoLog = _mesa_strdup(info_log.text);
-   }
-
-   if (info_log.error_flag) {
-      success = GL_FALSE;
-   }
-
-   slang_info_log_destruct(&info_log);
-   _slang_code_object_dtr(&obj);
-
-   _slang_delete_mempool((slang_mempool *) ctx->Shader.MemPool);
-   ctx->Shader.MemPool = NULL;
-
-   /* remove any reads of output registers */
-#if 0
-   printf("Pre-remove output reads:\n");
-   _mesa_print_program(shader->Program);
-#endif
-   _mesa_remove_output_reads(shader->Program, PROGRAM_OUTPUT);
-   if (shader->Type == GL_VERTEX_SHADER) {
-      /* and remove writes to varying vars in vertex programs */
-      _mesa_remove_output_reads(shader->Program, PROGRAM_VARYING);
-   }
-#if 0
-   printf("Post-remove output reads:\n");
-   _mesa_print_program(shader->Program);
-#endif
-
-   shader->CompileStatus = success;
-
-   if (success) {
-      if (shader->Pragmas.Optimize &&
-          (ctx->Shader.Flags & GLSL_NO_OPT) == 0) {
-         _mesa_optimize_program(ctx, shader->Program);
-      }
-      if ((ctx->Shader.Flags & GLSL_NOP_VERT) &&
-          shader->Program->Target == GL_VERTEX_PROGRAM_ARB) {
-         _mesa_nop_vertex_program(ctx,
-                                  (struct gl_vertex_program *) shader->Program);
-      }
-      if ((ctx->Shader.Flags & GLSL_NOP_FRAG) &&
-          shader->Program->Target == GL_FRAGMENT_PROGRAM_ARB) {
-         _mesa_nop_fragment_program(ctx,
-                                (struct gl_fragment_program *) shader->Program);
-      }
-   }
-
-   if (ctx->Shader.Flags & GLSL_LOG) {
-      _mesa_write_shader_to_file(shader);
-   }
-
-   return success;
-}
-
diff --git a/src/mesa/shader/slang/slang_compile.h b/src/mesa/shader/slang/slang_compile.h
deleted file mode 100644 (file)
index 7fb549d..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#if !defined SLANG_COMPILE_H
-#define SLANG_COMPILE_H
-
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "slang_typeinfo.h"
-#include "slang_compile_variable.h"
-#include "slang_compile_struct.h"
-#include "slang_compile_operation.h"
-#include "slang_compile_function.h"
-
-#if defined __cplusplus
-extern "C" {
-#endif
-
-typedef struct slang_name_space_
-{
-   struct slang_function_scope_ *funcs;
-   struct slang_struct_scope_ *structs;
-   struct slang_variable_scope_ *vars;
-} slang_name_space;
-
-typedef enum slang_unit_type_
-{
-   SLANG_UNIT_FRAGMENT_SHADER,
-   SLANG_UNIT_VERTEX_SHADER,
-   SLANG_UNIT_FRAGMENT_BUILTIN,
-   SLANG_UNIT_VERTEX_BUILTIN
-} slang_unit_type;
-
-
-typedef struct slang_code_unit_
-{
-   slang_variable_scope vars;
-   slang_function_scope funs;
-   slang_struct_scope structs;
-   slang_unit_type type;
-   struct slang_code_object_ *object;
-} slang_code_unit;
-
-
-extern GLvoid
-_slang_code_unit_ctr (slang_code_unit *, struct slang_code_object_ *);
-
-extern GLvoid
-_slang_code_unit_dtr (slang_code_unit *);
-
-#define SLANG_BUILTIN_CORE   0
-#define SLANG_BUILTIN_120_CORE   1
-#define SLANG_BUILTIN_COMMON 2
-#define SLANG_BUILTIN_TARGET 3
-
-#define SLANG_BUILTIN_TOTAL  4
-
-typedef struct slang_code_object_
-{
-   slang_code_unit builtin[SLANG_BUILTIN_TOTAL];
-   slang_code_unit unit;
-   slang_atom_pool atompool;
-} slang_code_object;
-
-extern GLvoid
-_slang_code_object_ctr (slang_code_object *);
-
-extern GLvoid
-_slang_code_object_dtr (slang_code_object *);
-
-extern GLboolean
-_slang_compile (GLcontext *ctx, struct gl_shader *shader);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/src/mesa/shader/slang/slang_compile_function.c b/src/mesa/shader/slang/slang_compile_function.c
deleted file mode 100644 (file)
index 4dd8851..0000000
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_compile_function.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_mem.h"
-
-
-int
-slang_function_construct(slang_function * func)
-{
-   func->kind = SLANG_FUNC_ORDINARY;
-   if (!slang_variable_construct(&func->header))
-      return 0;
-
-   func->parameters = (slang_variable_scope *)
-      _slang_alloc(sizeof(slang_variable_scope));
-   if (func->parameters == NULL) {
-      slang_variable_destruct(&func->header);
-      return 0;
-   }
-
-   _slang_variable_scope_ctr(func->parameters);
-   func->param_count = 0;
-   func->body = NULL;
-   return 1;
-}
-
-void
-slang_function_destruct(slang_function * func)
-{
-   slang_variable_destruct(&func->header);
-   slang_variable_scope_destruct(func->parameters);
-   _slang_free(func->parameters);
-   if (func->body != NULL) {
-      slang_operation_destruct(func->body);
-      _slang_free(func->body);
-   }
-}
-
-
-slang_function *
-slang_function_new(slang_function_kind kind)
-{
-   slang_function *fun = (slang_function *)
-      _slang_alloc(sizeof(slang_function));
-   if (fun) {
-      slang_function_construct(fun);
-      fun->kind = kind;
-   }
-   return fun;
-}
-
-
-/*
- * slang_function_scope
- */
-
-GLvoid
-_slang_function_scope_ctr(slang_function_scope * self)
-{
-   self->functions = NULL;
-   self->num_functions = 0;
-   self->outer_scope = NULL;
-}
-
-void
-slang_function_scope_destruct(slang_function_scope * scope)
-{
-   unsigned int i;
-
-   for (i = 0; i < scope->num_functions; i++)
-      slang_function_destruct(scope->functions + i);
-   _slang_free(scope->functions);
-}
-
-
-/**
- * Does this function have a non-void return value?
- */
-GLboolean
-_slang_function_has_return_value(const slang_function *fun)
-{
-   return fun->header.type.specifier.type != SLANG_SPEC_VOID;
-}
-
-
-/**
- * Search a list of functions for a particular function by name.
- * \param funcs  the list of functions to search
- * \param a_name  the name to search for
- * \param all_scopes  if non-zero, search containing scopes too.
- * \return pointer to found function, or NULL.
- */
-int
-slang_function_scope_find_by_name(slang_function_scope * funcs,
-                                  slang_atom a_name, int all_scopes)
-{
-   unsigned int i;
-
-   for (i = 0; i < funcs->num_functions; i++)
-      if (a_name == funcs->functions[i].header.a_name)
-         return 1;
-   if (all_scopes && funcs->outer_scope != NULL)
-      return slang_function_scope_find_by_name(funcs->outer_scope, a_name, 1);
-   return 0;
-}
-
-
-/**
- * Search a list of functions for a particular function (for implementing
- * function calls.  Matching is done by first comparing the function's name,
- * then the function's parameter list.
- *
- * \param funcs  the list of functions to search
- * \param fun  the function to search for
- * \param all_scopes  if non-zero, search containing scopes too.
- * \return pointer to found function, or NULL.
- */
-slang_function *
-slang_function_scope_find(slang_function_scope * funcs, slang_function * fun,
-                          int all_scopes)
-{
-   unsigned int i;
-
-   for (i = 0; i < funcs->num_functions; i++) {
-      slang_function *f = &funcs->functions[i];
-      const GLuint haveRetValue = 0;
-#if 0
-         = (f->header.type.specifier.type != SLANG_SPEC_VOID);
-#endif
-      unsigned int j;
-
-      /*
-      printf("Compare name %s to %s  (ret %u, %d, %d)\n",
-             (char *) fun->header.a_name, (char *) f->header.a_name,
-             haveRetValue,
-             fun->param_count, f->param_count);
-      */
-
-      if (fun->header.a_name != f->header.a_name)
-         continue;
-      if (fun->param_count != f->param_count)
-         continue;
-      for (j = haveRetValue; j < fun->param_count; j++) {
-         if (!slang_type_specifier_equal
-             (&fun->parameters->variables[j]->type.specifier,
-              &f->parameters->variables[j]->type.specifier))
-            break;
-      }
-      if (j == fun->param_count) {
-         /*
-         printf("Found match\n");
-         */
-         return f;
-      }
-   }
-   /*
-   printf("Not found\n");
-   */
-   if (all_scopes && funcs->outer_scope != NULL)
-      return slang_function_scope_find(funcs->outer_scope, fun, 1);
-   return NULL;
-}
-
-
-/**
- * Lookup a function according to name and parameter count/types.
- */
-slang_function *
-_slang_function_locate(const slang_function_scope * funcs, slang_atom a_name,
-                       slang_operation * args, GLuint num_args,
-                       const slang_name_space * space, slang_atom_pool * atoms,
-                       slang_info_log *log, GLboolean *error)
-{
-   slang_typeinfo arg_ti[100];
-   GLuint i;
-
-   *error = GL_FALSE;
-
-   /* determine type of each argument */
-   assert(num_args < 100);
-   for (i = 0; i < num_args; i++) {
-      if (!slang_typeinfo_construct(&arg_ti[i]))
-         return NULL;
-      if (!_slang_typeof_operation(&args[i], space, &arg_ti[i], atoms, log)) {
-         return NULL;
-      }
-   }
-
-   /* loop over function scopes */
-   while (funcs) {
-
-      /* look for function with matching name and argument/param types */
-      for (i = 0; i < funcs->num_functions; i++) {
-         slang_function *f = &funcs->functions[i];
-         const GLuint haveRetValue = _slang_function_has_return_value(f);
-         GLuint j;
-
-         if (a_name != f->header.a_name)
-            continue;
-         if (f->param_count - haveRetValue != num_args)
-            continue;
-
-         /* compare parameter / argument types */
-         for (j = 0; j < num_args; j++) {
-            if (!slang_type_specifier_compatible(&arg_ti[j].spec,
-                              &f->parameters->variables[j]->type.specifier)) {
-               /* param/arg types don't match */
-               break;
-            }
-
-            /* "out" and "inout" formal parameter requires the actual
-             * argument to be an l-value.
-             */
-            if (!arg_ti[j].can_be_referenced &&
-                (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT ||
-                 f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT)) {
-               /* param is not an lvalue! */
-               *error = GL_TRUE;
-               return NULL;
-            }
-         }
-
-         if (j == num_args) {
-            /* name and args match! */
-            return f;
-         }
-      }
-
-      funcs = funcs->outer_scope;
-   }
-
-   return NULL;
-}
diff --git a/src/mesa/shader/slang/slang_compile_function.h b/src/mesa/shader/slang/slang_compile_function.h
deleted file mode 100644 (file)
index a5445ec..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.2
- *
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_COMPILE_FUNCTION_H
-#define SLANG_COMPILE_FUNCTION_H
-
-
-/**
- * Types of functions.
- */
-typedef enum slang_function_kind_
-{
-   SLANG_FUNC_ORDINARY,
-   SLANG_FUNC_CONSTRUCTOR,
-   SLANG_FUNC_OPERATOR
-} slang_function_kind;
-
-
-/**
- * Description of a compiled shader function.
- */
-typedef struct slang_function_
-{
-   slang_function_kind kind;
-   slang_variable header;      /**< The function's name and return type */
-   slang_variable_scope *parameters; /**< formal parameters AND local vars */
-   unsigned int param_count;   /**< number of formal params (no locals) */
-   slang_operation *body;      /**< The instruction tree */
-} slang_function;
-
-extern int slang_function_construct(slang_function *);
-extern void slang_function_destruct(slang_function *);
-extern slang_function *slang_function_new(slang_function_kind kind);
-
-extern GLboolean
-_slang_function_has_return_value(const slang_function *fun);
-
-
-/**
- * Basically, a list of compiled functions.
- */
-typedef struct slang_function_scope_
-{
-   slang_function *functions;
-   GLuint num_functions;
-   struct slang_function_scope_ *outer_scope;
-} slang_function_scope;
-
-
-extern GLvoid
-_slang_function_scope_ctr(slang_function_scope *);
-
-extern void
-slang_function_scope_destruct(slang_function_scope *);
-
-extern int
-slang_function_scope_find_by_name(slang_function_scope *, slang_atom, int);
-
-extern slang_function *
-slang_function_scope_find(slang_function_scope *, slang_function *, int);
-
-extern struct slang_function_ *
-_slang_function_locate(const struct slang_function_scope_ *funcs,
-                       slang_atom name, struct slang_operation_ *params,
-                       GLuint num_params,
-                       const struct slang_name_space_ *space,
-                       slang_atom_pool *atoms, slang_info_log *log,
-                       GLboolean *error);
-
-
-#endif /* SLANG_COMPILE_FUNCTION_H */
diff --git a/src/mesa/shader/slang/slang_compile_operation.c b/src/mesa/shader/slang/slang_compile_operation.c
deleted file mode 100644 (file)
index 5441d60..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.2
- *
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_compile_operation.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_mem.h"
-
-
-/**
- * Init a slang_operation object
- */
-GLboolean
-slang_operation_construct(slang_operation * oper)
-{
-   oper->type = SLANG_OPER_NONE;
-   oper->children = NULL;
-   oper->num_children = 0;
-   oper->literal[0] = 0.0;
-   oper->literal_size = 1;
-   oper->array_constructor = GL_FALSE;
-   oper->a_id = SLANG_ATOM_NULL;
-   oper->a_obj = SLANG_ATOM_NULL;
-   oper->locals = _slang_variable_scope_new(NULL);
-   if (oper->locals == NULL)
-      return GL_FALSE;
-   _slang_variable_scope_ctr(oper->locals);
-   oper->fun = NULL;
-   oper->var = NULL;
-   oper->label = NULL;
-   return GL_TRUE;
-}
-
-void
-slang_operation_destruct(slang_operation * oper)
-{
-   GLuint i;
-
-   for (i = 0; i < oper->num_children; i++)
-      slang_operation_destruct(oper->children + i);
-   _slang_free(oper->children);
-   slang_variable_scope_destruct(oper->locals);
-   _slang_free(oper->locals);
-   oper->children = NULL;
-   oper->num_children = 0;
-   oper->locals = NULL;
-}
-
-
-/**
- * Recursively traverse 'oper', replacing occurances of 'oldScope' with
- * 'newScope' in the oper->locals->outer_scope field.
- */
-void
-slang_replace_scope(slang_operation *oper,
-                    slang_variable_scope *oldScope,
-                    slang_variable_scope *newScope)
-{
-   GLuint i;
-
-   if (oper->locals != newScope &&
-       oper->locals->outer_scope == oldScope) {
-      /* found.  replace old w/ new */
-      oper->locals->outer_scope = newScope;
-   }
-
-   if (oper->type == SLANG_OPER_VARIABLE_DECL) {
-      /* search/replace in the initializer */
-      slang_variable *var;
-      var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
-      if (var && var->initializer) {
-         slang_replace_scope(var->initializer, oldScope, newScope);
-      }
-   }
-
-   /* search/replace in children */
-   for (i = 0; i < oper->num_children; i++) {
-      slang_replace_scope(&oper->children[i], oldScope, newScope);
-   }
-}
-
-
-/**
- * Recursively copy a slang_operation node.
- * \param x  copy target
- * \param y  copy source
- * \return GL_TRUE for success, GL_FALSE if failure
- */
-GLboolean
-slang_operation_copy(slang_operation * x, const slang_operation * y)
-{
-   slang_operation z;
-   GLuint i;
-
-   if (!slang_operation_construct(&z))
-      return GL_FALSE;
-   z.type = y->type;
-   if (y->num_children > 0) {
-      z.children = (slang_operation *)
-         _slang_alloc(y->num_children * sizeof(slang_operation));
-      if (z.children == NULL) {
-         slang_operation_destruct(&z);
-         return GL_FALSE;
-      }
-   }
-   for (z.num_children = 0; z.num_children < y->num_children;
-        z.num_children++) {
-      if (!slang_operation_construct(&z.children[z.num_children])) {
-         slang_operation_destruct(&z);
-         return GL_FALSE;
-      }
-   }
-   for (i = 0; i < z.num_children; i++) {
-      if (!slang_operation_copy(&z.children[i], &y->children[i])) {
-         slang_operation_destruct(&z);
-         return GL_FALSE;
-      }
-   }
-   z.literal[0] = y->literal[0];
-   z.literal[1] = y->literal[1];
-   z.literal[2] = y->literal[2];
-   z.literal[3] = y->literal[3];
-   z.literal_size = y->literal_size;
-   assert(y->literal_size >= 1);
-   assert(y->literal_size <= 4);
-   z.a_id = y->a_id;
-   if (y->locals) {
-      if (!slang_variable_scope_copy(z.locals, y->locals)) {
-         slang_operation_destruct(&z);
-         return GL_FALSE;
-      }
-   }
-
-   /* update scoping for children */
-   for (i = 0; i < y->num_children; i++) {
-      if (y->children[i].locals &&
-          y->children[i].locals->outer_scope == y->locals) {
-         z.children[i].locals->outer_scope = z.locals;
-      }
-   }
-
-#if 0
-   z.var = y->var;
-   z.fun = y->fun;
-#endif
-   slang_operation_destruct(x);
-   *x = z;
-
-   /* If this operation declares a new scope, we need to make sure
-    * all children point to it, not the original operation's scope!
-    */
-   if (x->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
-       x->type == SLANG_OPER_WHILE ||
-       x->type == SLANG_OPER_FOR) {
-      slang_replace_scope(x, y->locals, x->locals);
-   }
-
-   return GL_TRUE;
-}
-
-
-slang_operation *
-slang_operation_new(GLuint count)
-{
-   slang_operation *ops
-       = (slang_operation *) _slang_alloc(count * sizeof(slang_operation));
-   assert(count > 0);
-   if (ops) {
-      GLuint i;
-      for (i = 0; i < count; i++)
-         slang_operation_construct(ops + i);
-   }
-   return ops;
-}
-
-
-/**
- * Delete operation and all children
- */
-void
-slang_operation_delete(slang_operation *oper)
-{
-   slang_operation_destruct(oper);
-   _slang_free(oper);
-}
-
-
-void
-slang_operation_free_children(slang_operation *oper)
-{
-   GLuint i;
-   for (i = 0; i < slang_oper_num_children(oper); i++) {
-      slang_operation *child = slang_oper_child(oper, i);
-      slang_operation_destruct(child);
-   }
-   _slang_free(oper->children);
-   oper->children = NULL;
-   oper->num_children = 0;
-}
-
-
-slang_operation *
-slang_operation_grow(GLuint *numChildren, slang_operation **children)
-{
-   slang_operation *ops;
-
-   ops = (slang_operation *)
-      _slang_realloc(*children,
-                     *numChildren * sizeof(slang_operation),
-                     (*numChildren + 1) * sizeof(slang_operation));
-   if (ops) {
-      slang_operation *newOp = ops + *numChildren;
-      if (!slang_operation_construct(newOp)) {
-         _slang_free(ops);
-         *children = NULL;
-         return NULL;
-      }
-      *children = ops;
-      (*numChildren)++;
-      return newOp;
-   }
-   return NULL;
-}
-
-/**
- * Insert a new slang_operation into an array.
- * \param numElements  pointer to current array size (in/out)
- * \param array  address of the array (in/out)
- * \param pos  position to insert new element
- * \return  pointer to the new operation/element
- */
-slang_operation *
-slang_operation_insert(GLuint *numElements, slang_operation **array,
-                       GLuint pos)
-{
-   slang_operation *ops;
-
-   assert(pos <= *numElements);
-
-   ops = (slang_operation *)
-      _slang_alloc((*numElements + 1) * sizeof(slang_operation));
-   if (ops) {
-      slang_operation *newOp;
-      newOp = ops + pos;
-      if (pos > 0)
-         memcpy(ops, *array, pos * sizeof(slang_operation));
-      if (pos < *numElements)
-         memcpy(newOp + 1, (*array) + pos,
-                (*numElements - pos) * sizeof(slang_operation));
-
-      if (!slang_operation_construct(newOp)) {
-         _slang_free(ops);
-         *numElements = 0;
-         *array = NULL;
-         return NULL;
-      }
-      if (*array)
-         _slang_free(*array);
-      *array = ops;
-      (*numElements)++;
-      return newOp;
-   }
-   return NULL;
-}
-
-
-/**
- * Add/insert new child into given node at given position.
- * \return pointer to the new child node
- */
-slang_operation *
-slang_operation_insert_child(slang_operation *oper, GLuint pos)
-{
-   slang_operation *newOp;
-
-   newOp = slang_operation_insert(&oper->num_children,
-                                  &oper->children,
-                                  pos);
-   if (newOp) {
-      newOp->locals->outer_scope = oper->locals;
-   }
-
-   return newOp;
-}
-
-
-void
-_slang_operation_swap(slang_operation *oper0, slang_operation *oper1)
-{
-   slang_operation tmp = *oper0;
-   *oper0 = *oper1;
-   *oper1 = tmp;
-}
-
-
-void
-slang_operation_add_children(slang_operation *oper, GLuint num_children)
-{
-   GLuint i;
-   assert(oper->num_children == 0);
-   assert(oper->children == NULL);
-   oper->num_children = num_children;
-   oper->children = slang_operation_new(num_children);
-   for (i = 0; i < num_children; i++) {
-      oper->children[i].locals = _slang_variable_scope_new(oper->locals);
-   }
-}
-
diff --git a/src/mesa/shader/slang/slang_compile_operation.h b/src/mesa/shader/slang/slang_compile_operation.h
deleted file mode 100644 (file)
index 1f15c19..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.2
- *
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_COMPILE_OPERATION_H
-#define SLANG_COMPILE_OPERATION_H
-
-
-/**
- * Types of slang operations.
- * These are the types of the AST (abstract syntax tree) nodes.
- * [foo] indicates a sub-tree or reference to another type of node
- */
-typedef enum slang_operation_type_
-{
-   SLANG_OPER_NONE,
-   SLANG_OPER_BLOCK_NO_NEW_SCOPE,       /* "{" sequence "}" */
-   SLANG_OPER_BLOCK_NEW_SCOPE,  /* "{" sequence "}" */
-   SLANG_OPER_VARIABLE_DECL,    /* [type] [var] or [var] = [expr] */
-   SLANG_OPER_ASM,
-   SLANG_OPER_BREAK,            /* "break" statement */
-   SLANG_OPER_CONTINUE,         /* "continue" statement */
-   SLANG_OPER_DISCARD,          /* "discard" (kill fragment) statement */
-   SLANG_OPER_RETURN,           /* "return" [expr]  */
-   SLANG_OPER_RETURN_INLINED,   /* "return" [expr] from inlined function  */
-   SLANG_OPER_LABEL,            /* a jump target */
-   SLANG_OPER_EXPRESSION,       /* [expr] */
-   SLANG_OPER_IF,               /* "if" [0] then [1] else [2] */
-   SLANG_OPER_WHILE,            /* "while" [cond] [body] */
-   SLANG_OPER_DO,               /* "do" [body] "while" [cond] */
-   SLANG_OPER_FOR,              /* "for" [init] [while] [incr] [body] */
-   SLANG_OPER_VOID,             /* nop */
-   SLANG_OPER_LITERAL_BOOL,     /* "true" or "false" */
-   SLANG_OPER_LITERAL_INT,      /* integer literal */
-   SLANG_OPER_LITERAL_FLOAT,    /* float literal */
-   SLANG_OPER_IDENTIFIER,       /* var name, func name, etc */
-   SLANG_OPER_SEQUENCE,         /* [expr] "," [expr] "," etc */
-   SLANG_OPER_ASSIGN,           /* [var] "=" [expr] */
-   SLANG_OPER_ADDASSIGN,        /* [var] "+=" [expr] */
-   SLANG_OPER_SUBASSIGN,        /* [var] "-=" [expr] */
-   SLANG_OPER_MULASSIGN,        /* [var] "*=" [expr] */
-   SLANG_OPER_DIVASSIGN,        /* [var] "/=" [expr] */
-   /*SLANG_OPER_MODASSIGN, */
-   /*SLANG_OPER_LSHASSIGN, */
-   /*SLANG_OPER_RSHASSIGN, */
-   /*SLANG_OPER_ORASSIGN, */
-   /*SLANG_OPER_XORASSIGN, */
-   /*SLANG_OPER_ANDASSIGN, */
-   SLANG_OPER_SELECT,           /* [expr] "?" [expr] ":" [expr] */
-   SLANG_OPER_LOGICALOR,        /* [expr] "||" [expr] */
-   SLANG_OPER_LOGICALXOR,       /* [expr] "^^" [expr] */
-   SLANG_OPER_LOGICALAND,       /* [expr] "&&" [expr] */
-   /*SLANG_OPER_BITOR, */
-   /*SLANG_OPER_BITXOR, */
-   /*SLANG_OPER_BITAND, */
-   SLANG_OPER_EQUAL,            /* [expr] "==" [expr] */
-   SLANG_OPER_NOTEQUAL,         /* [expr] "!=" [expr] */
-   SLANG_OPER_LESS,             /* [expr] "<" [expr] */
-   SLANG_OPER_GREATER,          /* [expr] ">" [expr] */
-   SLANG_OPER_LESSEQUAL,        /* [expr] "<=" [expr] */
-   SLANG_OPER_GREATEREQUAL,     /* [expr] ">=" [expr] */
-   /*SLANG_OPER_LSHIFT, */
-   /*SLANG_OPER_RSHIFT, */
-   SLANG_OPER_ADD,              /* [expr] "+" [expr] */
-   SLANG_OPER_SUBTRACT,         /* [expr] "-" [expr] */
-   SLANG_OPER_MULTIPLY,         /* [expr] "*" [expr] */
-   SLANG_OPER_DIVIDE,           /* [expr] "/" [expr] */
-   /*SLANG_OPER_MODULUS, */
-   SLANG_OPER_PREINCREMENT,     /* "++" [var] */
-   SLANG_OPER_PREDECREMENT,     /* "--" [var] */
-   SLANG_OPER_PLUS,             /* "-" [expr] */
-   SLANG_OPER_MINUS,            /* "+" [expr] */
-   /*SLANG_OPER_COMPLEMENT, */
-   SLANG_OPER_NOT,              /* "!" [expr] */
-   SLANG_OPER_SUBSCRIPT,        /* [expr] "[" [expr] "]" */
-   SLANG_OPER_CALL,             /* [func name] [param] [param] [...] */
-   SLANG_OPER_NON_INLINED_CALL, /* a real function call */
-   SLANG_OPER_METHOD,           /* method call, such as  v.length() */
-   SLANG_OPER_FIELD,            /* i.e.: ".next" or ".xzy" or ".xxx" etc */
-   SLANG_OPER_POSTINCREMENT,    /* [var] "++" */
-   SLANG_OPER_POSTDECREMENT     /* [var] "--" */
-} slang_operation_type;
-
-
-/**
- * A slang_operation is basically a compiled instruction (such as assignment,
- * a while-loop, a conditional, a multiply, a function call, etc).
- * The AST (abstract syntax tree) is built from these nodes.
- * NOTE: This structure could have been implemented as a union of simpler
- * structs which would correspond to the operation types above.
- */
-typedef struct slang_operation_
-{
-   slang_operation_type type;
-   struct slang_operation_ *children;
-   GLuint num_children;
-   GLfloat literal[4];           /**< Used for float, int and bool values */
-   GLuint literal_size;          /**< 1, 2, 3, or 4 */
-   slang_atom a_id;              /**< type: asm, identifier, call, field */
-   slang_atom a_obj;             /**< object in a method call */
-   slang_variable_scope *locals; /**< local vars for scope */
-   struct slang_function_ *fun;  /**< If type == SLANG_OPER_CALL */
-   struct slang_variable_ *var;  /**< If type == slang_oper_identier */
-   struct slang_label_ *label;   /**< If type == SLANG_OPER_LABEL */
-   /** If type==SLANG_OPER_CALL and we're calling an array constructor,
-    * for which there's no real function, we need to have a flag to
-    * indicate such.  num_children indicates number of elements.
-    */
-   GLboolean array_constructor;
-} slang_operation;
-
-
-extern GLboolean
-slang_operation_construct(slang_operation *);
-
-extern void
-slang_operation_destruct(slang_operation *);
-
-extern void
-slang_replace_scope(slang_operation *oper,
-                    slang_variable_scope *oldScope,
-                    slang_variable_scope *newScope);
-
-extern GLboolean
-slang_operation_copy(slang_operation *, const slang_operation *);
-
-extern slang_operation *
-slang_operation_new(GLuint count);
-
-extern void
-slang_operation_delete(slang_operation *oper);
-
-extern void
-slang_operation_free_children(slang_operation *oper);
-
-extern slang_operation *
-slang_operation_grow(GLuint *numChildren, slang_operation **children);
-
-extern slang_operation *
-slang_operation_insert(GLuint *numChildren, slang_operation **children,
-                       GLuint pos);
-
-extern slang_operation *
-slang_operation_insert_child(slang_operation *oper, GLuint pos);
-
-extern void
-_slang_operation_swap(slang_operation *oper0, slang_operation *oper1);
-
-
-extern void
-slang_operation_add_children(slang_operation *oper, GLuint num_children);
-
-
-/** Return number of children of given node */
-static INLINE GLuint
-slang_oper_num_children(const slang_operation *oper)
-{
-   return oper->num_children;
-}
-
-/** Return child of given operation node */
-static INLINE slang_operation *
-slang_oper_child(slang_operation *oper, GLuint child)
-{
-   assert(child < oper->num_children);
-   return &oper->children[child];
-}
-
-
-/** Return child of given operation node, const version */
-static INLINE const slang_operation *
-slang_oper_child_const(const slang_operation *oper, GLuint child)
-{
-   assert(child < oper->num_children);
-   return &oper->children[child];
-}
-
-
-/** Init oper to a boolean literal. */
-static INLINE void
-slang_operation_literal_bool(slang_operation *oper, GLboolean value)
-{
-   oper->type = SLANG_OPER_LITERAL_BOOL;
-   oper->literal[0] =
-   oper->literal[1] =
-   oper->literal[2] =
-   oper->literal[3] = (float) value;
-   oper->literal_size = 1;
-}
-
-
-/** Init oper to an int literal. */
-static INLINE void
-slang_operation_literal_int(slang_operation *oper, GLint value)
-{
-   oper->type = SLANG_OPER_LITERAL_INT;
-   oper->literal[0] =
-   oper->literal[1] =
-   oper->literal[2] =
-   oper->literal[3] = (float) value;
-   oper->literal_size = 1;
-}
-
-
-#endif /* SLANG_COMPILE_OPERATION_H */
diff --git a/src/mesa/shader/slang/slang_compile_struct.c b/src/mesa/shader/slang/slang_compile_struct.c
deleted file mode 100644 (file)
index e6c3873..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_compile_struct.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_mem.h"
-#include "slang_compile.h"
-
-
-GLvoid
-_slang_struct_scope_ctr(slang_struct_scope * self)
-{
-   self->structs = NULL;
-   self->num_structs = 0;
-   self->outer_scope = NULL;
-}
-
-void
-slang_struct_scope_destruct(slang_struct_scope * scope)
-{
-   GLuint i;
-
-   for (i = 0; i < scope->num_structs; i++)
-      slang_struct_destruct(scope->structs + i);
-   _slang_free(scope->structs);
-   /* do not free scope->outer_scope */
-}
-
-int
-slang_struct_scope_copy(slang_struct_scope * x, const slang_struct_scope * y)
-{
-   slang_struct_scope z;
-   GLuint i;
-
-   _slang_struct_scope_ctr(&z);
-   z.structs = (slang_struct *)
-      _slang_alloc(y->num_structs * sizeof(slang_struct));
-   if (z.structs == NULL) {
-      slang_struct_scope_destruct(&z);
-      return 0;
-   }
-   for (z.num_structs = 0; z.num_structs < y->num_structs; z.num_structs++)
-      if (!slang_struct_construct(&z.structs[z.num_structs])) {
-         slang_struct_scope_destruct(&z);
-         return 0;
-      }
-   for (i = 0; i < z.num_structs; i++)
-      if (!slang_struct_copy(&z.structs[i], &y->structs[i])) {
-         slang_struct_scope_destruct(&z);
-         return 0;
-      }
-   z.outer_scope = y->outer_scope;
-   slang_struct_scope_destruct(x);
-   *x = z;
-   return 1;
-}
-
-slang_struct *
-slang_struct_scope_find(slang_struct_scope * stru, slang_atom a_name,
-                        int all_scopes)
-{
-   GLuint i;
-
-   for (i = 0; i < stru->num_structs; i++)
-      if (a_name == stru->structs[i].a_name)
-         return &stru->structs[i];
-   if (all_scopes && stru->outer_scope != NULL)
-      return slang_struct_scope_find(stru->outer_scope, a_name, 1);
-   return NULL;
-}
-
-/* slang_struct */
-
-int
-slang_struct_construct(slang_struct * stru)
-{
-   stru->a_name = SLANG_ATOM_NULL;
-   stru->fields = (slang_variable_scope *)
-      _slang_alloc(sizeof(slang_variable_scope));
-   if (stru->fields == NULL)
-      return 0;
-   _slang_variable_scope_ctr(stru->fields);
-
-   stru->structs =
-      (slang_struct_scope *) _slang_alloc(sizeof(slang_struct_scope));
-   if (stru->structs == NULL) {
-      slang_variable_scope_destruct(stru->fields);
-      _slang_free(stru->fields);
-      return 0;
-   }
-   _slang_struct_scope_ctr(stru->structs);
-   stru->constructor = NULL;
-   return 1;
-}
-
-void
-slang_struct_destruct(slang_struct * stru)
-{
-   slang_variable_scope_destruct(stru->fields);
-   _slang_free(stru->fields);
-   slang_struct_scope_destruct(stru->structs);
-   _slang_free(stru->structs);
-}
-
-int
-slang_struct_copy(slang_struct * x, const slang_struct * y)
-{
-   slang_struct z;
-
-   if (!slang_struct_construct(&z))
-      return 0;
-   z.a_name = y->a_name;
-   if (!slang_variable_scope_copy(z.fields, y->fields)) {
-      slang_struct_destruct(&z);
-      return 0;
-   }
-   if (!slang_struct_scope_copy(z.structs, y->structs)) {
-      slang_struct_destruct(&z);
-      return 0;
-   }
-   slang_struct_destruct(x);
-   *x = z;
-   return 1;
-}
-
-int
-slang_struct_equal(const slang_struct * x, const slang_struct * y)
-{
-   GLuint i;
-
-   if (x->fields->num_variables != y->fields->num_variables)
-      return 0;
-
-   for (i = 0; i < x->fields->num_variables; i++) {
-      const slang_variable *varx = x->fields->variables[i];
-      const slang_variable *vary = y->fields->variables[i];
-
-      if (varx->a_name != vary->a_name)
-         return 0;
-      if (!slang_type_specifier_equal(&varx->type.specifier,
-                                      &vary->type.specifier))
-         return 0;
-      if (varx->type.specifier.type == SLANG_SPEC_ARRAY)
-         if (varx->array_len != vary->array_len)
-            return GL_FALSE;
-   }
-   return 1;
-}
diff --git a/src/mesa/shader/slang/slang_compile_struct.h b/src/mesa/shader/slang/slang_compile_struct.h
deleted file mode 100644 (file)
index 90c5512..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#if !defined SLANG_COMPILE_STRUCT_H
-#define SLANG_COMPILE_STRUCT_H
-
-#if defined __cplusplus
-extern "C" {
-#endif
-
-struct slang_function_;
-
-typedef struct slang_struct_scope_
-{
-   struct slang_struct_ *structs;
-   GLuint num_structs;
-   struct slang_struct_scope_ *outer_scope;
-} slang_struct_scope;
-
-extern GLvoid
-_slang_struct_scope_ctr (slang_struct_scope *);
-
-void slang_struct_scope_destruct (slang_struct_scope *);
-int slang_struct_scope_copy (slang_struct_scope *, const slang_struct_scope *);
-struct slang_struct_ *slang_struct_scope_find (slang_struct_scope *, slang_atom, int);
-
-typedef struct slang_struct_
-{
-   slang_atom a_name;
-   struct slang_variable_scope_ *fields;
-   slang_struct_scope *structs;
-   struct slang_function_ *constructor;
-} slang_struct;
-
-int slang_struct_construct (slang_struct *);
-void slang_struct_destruct (slang_struct *);
-int slang_struct_copy (slang_struct *, const slang_struct *);
-int slang_struct_equal (const slang_struct *, const slang_struct *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/src/mesa/shader/slang/slang_compile_variable.c b/src/mesa/shader/slang/slang_compile_variable.c
deleted file mode 100644 (file)
index 23c08a9..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_compile_variable.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_mem.h"
-
-
-static slang_variable *
-slang_variable_new(void)
-{
-   slang_variable *v = (slang_variable *) _slang_alloc(sizeof(slang_variable));
-   if (v) {
-      if (!slang_variable_construct(v)) {
-         _slang_free(v);
-         v = NULL;
-      }
-   }
-   return v;
-}
-
-
-static void
-slang_variable_delete(slang_variable * var)
-{
-   slang_variable_destruct(var);
-   _slang_free(var);
-}
-
-
-/*
- * slang_variable_scope
- */
-
-slang_variable_scope *
-_slang_variable_scope_new(slang_variable_scope *parent)
-{
-   slang_variable_scope *s;
-   s = (slang_variable_scope *) _slang_alloc(sizeof(slang_variable_scope));
-   if (s)
-      s->outer_scope = parent;
-   return s;
-}
-
-
-GLvoid
-_slang_variable_scope_ctr(slang_variable_scope * self)
-{
-   self->variables = NULL;
-   self->num_variables = 0;
-   self->outer_scope = NULL;
-}
-
-void
-slang_variable_scope_destruct(slang_variable_scope * scope)
-{
-   unsigned int i;
-
-   if (!scope)
-      return;
-   for (i = 0; i < scope->num_variables; i++) {
-      if (scope->variables[i])
-         slang_variable_delete(scope->variables[i]);
-   }
-   _slang_free(scope->variables);
-   /* do not free scope->outer_scope */
-}
-
-int
-slang_variable_scope_copy(slang_variable_scope * x,
-                          const slang_variable_scope * y)
-{
-   slang_variable_scope z;
-   unsigned int i;
-
-   _slang_variable_scope_ctr(&z);
-   z.variables = (slang_variable **)
-      _slang_alloc(y->num_variables * sizeof(slang_variable *));
-   if (z.variables == NULL) {
-      slang_variable_scope_destruct(&z);
-      return 0;
-   }
-   for (z.num_variables = 0; z.num_variables < y->num_variables;
-        z.num_variables++) {
-      z.variables[z.num_variables] = slang_variable_new();
-      if (!z.variables[z.num_variables]) {
-         slang_variable_scope_destruct(&z);
-         return 0;
-      }
-   }
-   for (i = 0; i < z.num_variables; i++) {
-      if (!slang_variable_copy(z.variables[i], y->variables[i])) {
-         slang_variable_scope_destruct(&z);
-         return 0;
-      }
-   }
-   z.outer_scope = y->outer_scope;
-   slang_variable_scope_destruct(x);
-   *x = z;
-   return 1;
-}
-
-
-/**
- * Grow the variable list by one.
- * \return  pointer to space for the new variable (will be initialized)
- */
-slang_variable *
-slang_variable_scope_grow(slang_variable_scope *scope)
-{
-   const int n = scope->num_variables;
-   scope->variables = (slang_variable **)
-         _slang_realloc(scope->variables,
-                        n * sizeof(slang_variable *),
-                        (n + 1) * sizeof(slang_variable *));
-   if (!scope->variables)
-      return NULL;
-
-   scope->num_variables++;
-
-   scope->variables[n] = slang_variable_new();
-   if (!scope->variables[n])
-      return NULL;
-
-   return scope->variables[n];
-}
-
-
-
-/* slang_variable */
-
-int
-slang_variable_construct(slang_variable * var)
-{
-   if (!slang_fully_specified_type_construct(&var->type))
-      return 0;
-   var->a_name = SLANG_ATOM_NULL;
-   var->array_len = 0;
-   var->initializer = NULL;
-   var->size = 0;
-   var->isTemp = GL_FALSE;
-   var->store = NULL;
-   var->declared = 0;
-   return 1;
-}
-
-
-void
-slang_variable_destruct(slang_variable * var)
-{
-   slang_fully_specified_type_destruct(&var->type);
-   if (var->initializer != NULL) {
-      slang_operation_destruct(var->initializer);
-      _slang_free(var->initializer);
-   }
-#if 0
-   if (var->aux) {
-      free(var->aux);
-   }
-#endif
-}
-
-
-int
-slang_variable_copy(slang_variable * x, const slang_variable * y)
-{
-   slang_variable z;
-
-   if (!slang_variable_construct(&z))
-      return 0;
-   if (!slang_fully_specified_type_copy(&z.type, &y->type)) {
-      slang_variable_destruct(&z);
-      return 0;
-   }
-   z.a_name = y->a_name;
-   z.array_len = y->array_len;
-   if (y->initializer != NULL) {
-      z.initializer
-         = (slang_operation *) _slang_alloc(sizeof(slang_operation));
-      if (z.initializer == NULL) {
-         slang_variable_destruct(&z);
-         return 0;
-      }
-      if (!slang_operation_construct(z.initializer)) {
-         _slang_free(z.initializer);
-         slang_variable_destruct(&z);
-         return 0;
-      }
-      if (!slang_operation_copy(z.initializer, y->initializer)) {
-         slang_variable_destruct(&z);
-         return 0;
-      }
-   }
-   z.size = y->size;
-   slang_variable_destruct(x);
-   *x = z;
-   return 1;
-}
-
-
-/**
- * Search for named variable in given scope.
- * \param all  if true, search parent scopes too.
- */
-slang_variable *
-_slang_variable_locate(const slang_variable_scope * scope,
-                       const slang_atom a_name, GLboolean all)
-{
-   while (scope) {
-      GLuint i;
-      for (i = 0; i < scope->num_variables; i++)
-         if (a_name == scope->variables[i]->a_name)
-            return scope->variables[i];
-      if (all)
-         scope = scope->outer_scope;
-      else
-         scope = NULL;
-   }
-   return NULL;
-}
diff --git a/src/mesa/shader/slang/slang_compile_variable.h b/src/mesa/shader/slang/slang_compile_variable.h
deleted file mode 100644 (file)
index 5c9d248..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.2
- *
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_COMPILE_VARIABLE_H
-#define SLANG_COMPILE_VARIABLE_H
-
-
-struct slang_ir_storage_;
-
-
-/**
- * A shading language program variable.
- */
-typedef struct slang_variable_
-{
-   slang_fully_specified_type type; /**< Variable's data type */
-   slang_atom a_name;               /**< The variable's name (char *) */
-   GLuint array_len;                /**< only if type == SLANG_SPEC_ARRAy */
-   struct slang_operation_ *initializer; /**< Optional initializer code */
-   GLuint size;                     /**< Variable's size in bytes */
-   GLboolean is_global;
-   GLboolean isTemp;                /**< a named temporary (__resultTmp) */
-   GLboolean declared;              /**< has the var been declared? */
-   struct slang_ir_storage_ *store; /**< Storage for this var */
-} slang_variable;
-
-
-/**
- * Basically a list of variables, with a pointer to the parent scope.
- */
-typedef struct slang_variable_scope_
-{
-   slang_variable **variables;  /**< Array [num_variables] of ptrs to vars */
-   GLuint num_variables;
-   struct slang_variable_scope_ *outer_scope;
-} slang_variable_scope;
-
-
-extern slang_variable_scope *
-_slang_variable_scope_new(slang_variable_scope *parent);
-
-extern GLvoid
-_slang_variable_scope_ctr(slang_variable_scope *);
-
-extern void
-slang_variable_scope_destruct(slang_variable_scope *);
-
-extern int
-slang_variable_scope_copy(slang_variable_scope *,
-                          const slang_variable_scope *);
-
-extern slang_variable *
-slang_variable_scope_grow(slang_variable_scope *);
-
-extern int
-slang_variable_construct(slang_variable *);
-
-extern void
-slang_variable_destruct(slang_variable *);
-
-extern int
-slang_variable_copy(slang_variable *, const slang_variable *);
-
-extern slang_variable *
-_slang_variable_locate(const slang_variable_scope *, const slang_atom a_name,
-                       GLboolean all);
-
-
-#endif /* SLANG_COMPILE_VARIABLE_H */
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
deleted file mode 100644 (file)
index 4d4c611..0000000
+++ /dev/null
@@ -1,2666 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
- * Copyright (C) 2008 VMware, Inc.   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_emit.c
- * Emit program instructions (PI code) from IR trees.
- * \author Brian Paul
- */
-
-/***
- *** NOTES
- ***
- *** To emit GPU instructions, we basically just do an in-order traversal
- *** of the IR tree.
- ***/
-
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "shader/program.h"
-#include "shader/prog_instruction.h"
-#include "shader/prog_parameter.h"
-#include "shader/prog_print.h"
-#include "slang_builtin.h"
-#include "slang_emit.h"
-#include "slang_mem.h"
-
-
-#define PEEPHOLE_OPTIMIZATIONS 1
-#define ANNOTATE 0
-
-
-typedef struct
-{
-   slang_info_log *log;
-   slang_var_table *vt;
-   struct gl_program *prog;
-   struct gl_program **Subroutines;
-   GLuint NumSubroutines;
-
-   GLuint MaxInstructions;  /**< size of prog->Instructions[] buffer */
-
-   GLboolean UnresolvedFunctions;
-
-   /* code-gen options */
-   GLboolean EmitHighLevelInstructions;
-   GLboolean EmitCondCodes;
-   GLboolean EmitComments;
-   GLboolean EmitBeginEndSub; /* XXX TEMPORARY */
-} slang_emit_info;
-
-
-
-static struct gl_program *
-new_subroutine(slang_emit_info *emitInfo, GLuint *id)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   const GLuint n = emitInfo->NumSubroutines;
-
-   emitInfo->Subroutines = (struct gl_program **)
-      _mesa_realloc(emitInfo->Subroutines,
-                    n * sizeof(struct gl_program *),
-                    (n + 1) * sizeof(struct gl_program *));
-   emitInfo->Subroutines[n] = ctx->Driver.NewProgram(ctx, emitInfo->prog->Target, 0);
-   emitInfo->Subroutines[n]->Parameters = emitInfo->prog->Parameters;
-   emitInfo->NumSubroutines++;
-   *id = n;
-   return emitInfo->Subroutines[n];
-}
-
-
-/**
- * Convert a writemask to a swizzle.  Used for testing cond codes because
- * we only want to test the cond code component(s) that was set by the
- * previous instruction.
- */
-static GLuint
-writemask_to_swizzle(GLuint writemask)
-{
-   if (writemask == WRITEMASK_X)
-      return SWIZZLE_XXXX;
-   if (writemask == WRITEMASK_Y)
-      return SWIZZLE_YYYY;
-   if (writemask == WRITEMASK_Z)
-      return SWIZZLE_ZZZZ;
-   if (writemask == WRITEMASK_W)
-      return SWIZZLE_WWWW;
-   return SWIZZLE_XYZW;  /* shouldn't be hit */
-}
-
-
-/**
- * Convert a swizzle mask to a writemask.
- * Note that the slang_ir_storage->Swizzle field can represent either a
- * swizzle mask or a writemask, depending on how it's used.  For example,
- * when we parse "direction.yz" alone, we don't know whether .yz is a
- * writemask or a swizzle.  In this case, we encode ".yz" in store->Swizzle
- * as a swizzle mask (.yz?? actually).  Later, if direction.yz is used as
- * an R-value, we use store->Swizzle as-is.  Otherwise, if direction.yz is
- * used as an L-value, we convert it to a writemask.
- */
-static GLuint
-swizzle_to_writemask(GLuint swizzle)
-{
-   GLuint i, writemask = 0x0;
-   for (i = 0; i < 4; i++) {
-      GLuint swz = GET_SWZ(swizzle, i);
-      if (swz <= SWIZZLE_W) {
-         writemask |= (1 << swz);
-      }
-   }
-   return writemask;
-}
-
-
-/**
- * Swizzle a swizzle (function composition).
- * That is, return swz2(swz1), or said another way: swz1.szw2
- * Example: swizzle_swizzle(".zwxx", ".xxyw") yields ".zzwx"
- */
-GLuint
-_slang_swizzle_swizzle(GLuint swz1, GLuint swz2)
-{
-   GLuint i, swz, s[4];
-   for (i = 0; i < 4; i++) {
-      GLuint c = GET_SWZ(swz2, i);
-      if (c <= SWIZZLE_W)
-         s[i] = GET_SWZ(swz1, c);
-      else
-         s[i] = c;
-   }
-   swz = MAKE_SWIZZLE4(s[0], s[1], s[2], s[3]);
-   return swz;
-}
-
-
-/**
- * Return the default swizzle mask for accessing a variable of the
- * given size (in floats).  If size = 1, comp is used to identify
- * which component [0..3] of the register holds the variable.
- */
-GLuint
-_slang_var_swizzle(GLint size, GLint comp)
-{
-   switch (size) {
-   case 1:
-      return MAKE_SWIZZLE4(comp, SWIZZLE_NIL, SWIZZLE_NIL, SWIZZLE_NIL);
-   case 2:
-      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL);
-   case 3:
-      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_NIL);
-   default:
-      return SWIZZLE_XYZW;
-   }
-}
-
-
-
-/**
- * Allocate storage for the given node (if it hasn't already been allocated).
- *
- * Typically this is temporary storage for an intermediate result (such as
- * for a multiply or add, etc).
- *
- * If n->Store does not exist it will be created and will be of the size
- * specified by defaultSize.
- */
-static GLboolean
-alloc_node_storage(slang_emit_info *emitInfo, slang_ir_node *n,
-                   GLint defaultSize)
-{
-   assert(!n->Var);
-   if (!n->Store) {
-      assert(defaultSize > 0);
-      n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, defaultSize);
-      if (!n->Store) {
-         return GL_FALSE;
-      }
-   }
-
-   /* now allocate actual register(s).  I.e. set n->Store->Index >= 0 */
-   if (n->Store->Index < 0) {
-      if (!_slang_alloc_temp(emitInfo->vt, n->Store)) {
-         slang_info_log_error(emitInfo->log,
-                              "Ran out of registers, too many temporaries");
-         _slang_free(n->Store);
-         n->Store = NULL;
-         return GL_FALSE;
-      }
-   }
-   return GL_TRUE;
-}
-
-
-/**
- * Free temporary storage, if n->Store is, in fact, temp storage.
- * Otherwise, no-op.
- */
-static void
-free_node_storage(slang_var_table *vt, slang_ir_node *n)
-{
-   if (n->Store->File == PROGRAM_TEMPORARY &&
-       n->Store->Index >= 0 &&
-       n->Opcode != IR_SWIZZLE) {
-      if (_slang_is_temp(vt, n->Store)) {
-         _slang_free_temp(vt, n->Store);
-         n->Store->Index = -1;
-         n->Store = NULL; /* XXX this may not be needed */
-      }
-   }
-}
-
-
-/**
- * Helper function to allocate a short-term temporary.
- * Free it with _slang_free_temp().
- */
-static GLboolean
-alloc_local_temp(slang_emit_info *emitInfo, slang_ir_storage *temp, GLint size)
-{
-   assert(size >= 1);
-   assert(size <= 4);
-   memset(temp, 0, sizeof(*temp));
-   temp->Size = size;
-   temp->File = PROGRAM_TEMPORARY;
-   temp->Index = -1;
-   return _slang_alloc_temp(emitInfo->vt, temp);
-}
-
-
-/**
- * Remove any SWIZZLE_NIL terms from given swizzle mask.
- * For a swizzle like .z??? generate .zzzz (replicate single component).
- * Else, for .wx?? generate .wxzw (insert default component for the position).
- */
-static GLuint
-fix_swizzle(GLuint swizzle)
-{
-   GLuint c0 = GET_SWZ(swizzle, 0),
-      c1 = GET_SWZ(swizzle, 1),
-      c2 = GET_SWZ(swizzle, 2),
-      c3 = GET_SWZ(swizzle, 3);
-   if (c1 == SWIZZLE_NIL && c2 == SWIZZLE_NIL && c3 == SWIZZLE_NIL) {
-      /* smear first component across all positions */
-      c1 = c2 = c3 = c0;
-   }
-   else {
-      /* insert default swizzle components */
-      if (c0 == SWIZZLE_NIL)
-         c0 = SWIZZLE_X;
-      if (c1 == SWIZZLE_NIL)
-         c1 = SWIZZLE_Y;
-      if (c2 == SWIZZLE_NIL)
-         c2 = SWIZZLE_Z;
-      if (c3 == SWIZZLE_NIL)
-         c3 = SWIZZLE_W;
-   }
-   return MAKE_SWIZZLE4(c0, c1, c2, c3);
-}
-
-
-
-/**
- * Convert IR storage to an instruction dst register.
- */
-static void
-storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st)
-{
-   const GLboolean relAddr = st->RelAddr;
-   const GLint size = st->Size;
-   GLint index = st->Index;
-   GLuint swizzle = st->Swizzle;
-
-   assert(index >= 0);
-   /* if this is storage relative to some parent storage, walk up the tree */
-   while (st->Parent) {
-      st = st->Parent;
-      assert(st->Index >= 0);
-      index += st->Index;
-      swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
-   }
-
-   assert(st->File != PROGRAM_UNDEFINED);
-   dst->File = st->File;
-
-   assert(index >= 0);
-   dst->Index = index;
-
-   assert(size >= 1);
-   assert(size <= 4);
-
-   if (swizzle != SWIZZLE_XYZW) {
-      dst->WriteMask = swizzle_to_writemask(swizzle);
-   }
-   else {
-      switch (size) {
-      case 1:
-         dst->WriteMask = WRITEMASK_X << GET_SWZ(st->Swizzle, 0);
-         break;
-      case 2:
-         dst->WriteMask = WRITEMASK_XY;
-         break;
-      case 3:
-         dst->WriteMask = WRITEMASK_XYZ;
-         break;
-      case 4:
-         dst->WriteMask = WRITEMASK_XYZW;
-         break;
-      default:
-         ; /* error would have been caught above */
-      }
-   }
-
-   dst->RelAddr = relAddr;
-}
-
-
-/**
- * Convert IR storage to an instruction src register.
- */
-static void
-storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
-{
-   const GLboolean relAddr = st->RelAddr;
-   GLint index = st->Index;
-   GLuint swizzle = st->Swizzle;
-
-   /* if this is storage relative to some parent storage, walk up the tree */
-   assert(index >= 0);
-   while (st->Parent) {
-      st = st->Parent;
-      if (st->Index < 0) {
-         /* an error should have been reported already */
-         return;
-      }
-      assert(st->Index >= 0);
-      index += st->Index;
-      swizzle = _slang_swizzle_swizzle(fix_swizzle(st->Swizzle), swizzle);
-   }
-
-   assert(st->File >= 0);
-#if 1 /* XXX temporary */
-   if (st->File == PROGRAM_UNDEFINED) {
-      slang_ir_storage *st0 = (slang_ir_storage *) st;
-      st0->File = PROGRAM_TEMPORARY;
-   }
-#endif
-   assert(st->File < PROGRAM_FILE_MAX);
-   src->File = st->File;
-
-   assert(index >= 0);
-   src->Index = index;
-
-   swizzle = fix_swizzle(swizzle);
-   assert(GET_SWZ(swizzle, 0) <= SWIZZLE_W);
-   assert(GET_SWZ(swizzle, 1) <= SWIZZLE_W);
-   assert(GET_SWZ(swizzle, 2) <= SWIZZLE_W);
-   assert(GET_SWZ(swizzle, 3) <= SWIZZLE_W);
-   src->Swizzle = swizzle;
-
-   src->RelAddr = relAddr;
-}
-
-
-/*
- * Setup storage pointing to a scalar constant/literal.
- */
-static void
-constant_to_storage(slang_emit_info *emitInfo,
-                    GLfloat val,
-                    slang_ir_storage *store)
-{
-   GLuint swizzle;
-   GLint reg;
-   GLfloat value[4];
-
-   value[0] = val;
-   reg = _mesa_add_unnamed_constant(emitInfo->prog->Parameters,
-                                        value, 1, &swizzle);
-
-   memset(store, 0, sizeof(*store));
-   store->File = PROGRAM_CONSTANT;
-   store->Index = reg;
-   store->Swizzle = swizzle;
-}
-
-
-/**
- * Add new instruction at end of given program.
- * \param prog  the program to append instruction onto
- * \param opcode  opcode for the new instruction
- * \return pointer to the new instruction
- */
-static struct prog_instruction *
-new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode)
-{
-   struct gl_program *prog = emitInfo->prog;
-   struct prog_instruction *inst;
-
-#if 0
-   /* print prev inst */
-   if (prog->NumInstructions > 0) {
-      _mesa_print_instruction(prog->Instructions + prog->NumInstructions - 1);
-   }
-#endif
-   assert(prog->NumInstructions <= emitInfo->MaxInstructions);
-
-   if (prog->NumInstructions == emitInfo->MaxInstructions) {
-      /* grow the instruction buffer */
-      emitInfo->MaxInstructions += 20;
-      prog->Instructions =
-         _mesa_realloc_instructions(prog->Instructions,
-                                    prog->NumInstructions,
-                                    emitInfo->MaxInstructions);
-      if (!prog->Instructions) {
-         return NULL;
-      }
-   }
-
-   inst = prog->Instructions + prog->NumInstructions;
-   prog->NumInstructions++;
-   _mesa_init_instructions(inst, 1);
-   inst->Opcode = opcode;
-   inst->BranchTarget = -1; /* invalid */
-   /*
-   printf("New inst %d: %p %s\n", prog->NumInstructions-1,(void*)inst,
-          _mesa_opcode_string(inst->Opcode));
-   */
-   return inst;
-}
-
-
-static struct prog_instruction *
-emit_arl_load(slang_emit_info *emitInfo,
-              gl_register_file file, GLint index, GLuint swizzle)
-{
-   struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ARL);
-   if (inst) {
-      inst->SrcReg[0].File = file;
-      inst->SrcReg[0].Index = index;
-      inst->SrcReg[0].Swizzle = fix_swizzle(swizzle);
-      inst->DstReg.File = PROGRAM_ADDRESS;
-      inst->DstReg.Index = 0;
-      inst->DstReg.WriteMask = WRITEMASK_X;
-   }
-   return inst;
-}
-
-
-/**
- * Emit a new instruction with given opcode, operands.
- * At this point the instruction may have multiple indirect register
- * loads/stores.  We convert those into ARL loads and address-relative
- * operands.  See comments inside.
- * At some point in the future we could directly emit indirectly addressed
- * registers in Mesa GPU instructions.
- */
-static struct prog_instruction *
-emit_instruction(slang_emit_info *emitInfo,
-                 gl_inst_opcode opcode,
-                 const slang_ir_storage *dst,
-                 const slang_ir_storage *src0,
-                 const slang_ir_storage *src1,
-                 const slang_ir_storage *src2)
-{
-   struct prog_instruction *inst;
-   GLuint numIndirect = 0;
-   const slang_ir_storage *src[3];
-   slang_ir_storage newSrc[3], newDst;
-   GLuint i;
-   GLboolean isTemp[3];
-
-   isTemp[0] = isTemp[1] = isTemp[2] = GL_FALSE;
-
-   src[0] = src0;
-   src[1] = src1;
-   src[2] = src2;
-
-   /* count up how many operands are indirect loads */
-   for (i = 0; i < 3; i++) {
-      if (src[i] && src[i]->IsIndirect)
-         numIndirect++;
-   }
-   if (dst && dst->IsIndirect)
-      numIndirect++;
-
-   /* Take special steps for indirect register loads.
-    * If we had multiple address registers this would be simpler.
-    * For example, this GLSL code:
-    *    x[i] = y[j] + z[k];
-    * would translate into something like:
-    *    ARL ADDR.x, i;
-    *    ARL ADDR.y, j;
-    *    ARL ADDR.z, k;
-    *    ADD TEMP[ADDR.x+5], TEMP[ADDR.y+9], TEMP[ADDR.z+4];
-    * But since we currently only have one address register we have to do this:
-    *    ARL ADDR.x, i;
-    *    MOV t1, TEMP[ADDR.x+9];
-    *    ARL ADDR.x, j;
-    *    MOV t2, TEMP[ADDR.x+4];
-    *    ARL ADDR.x, k;
-    *    ADD TEMP[ADDR.x+5], t1, t2;
-    * The code here figures this out...
-    */
-   if (numIndirect > 0) {
-      for (i = 0; i < 3; i++) {
-         if (src[i] && src[i]->IsIndirect) {
-            /* load the ARL register with the indirect register */
-            emit_arl_load(emitInfo,
-                          src[i]->IndirectFile,
-                          src[i]->IndirectIndex,
-                          src[i]->IndirectSwizzle);
-
-            if (numIndirect > 1) {
-               /* Need to load src[i] into a temporary register */
-               slang_ir_storage srcRelAddr;
-               alloc_local_temp(emitInfo, &newSrc[i], src[i]->Size);
-               isTemp[i] = GL_TRUE;
-
-               /* set RelAddr flag on src register */
-               srcRelAddr = *src[i];
-               srcRelAddr.RelAddr = GL_TRUE;
-               srcRelAddr.IsIndirect = GL_FALSE; /* not really needed */
-
-               /* MOV newSrc, srcRelAddr; */
-               inst = emit_instruction(emitInfo,
-                                       OPCODE_MOV,
-                                       &newSrc[i],
-                                       &srcRelAddr,
-                                       NULL,
-                                       NULL);
-               if (!inst) {
-                  return NULL;
-               }
-
-               src[i] = &newSrc[i];
-            }
-            else {
-               /* just rewrite the src[i] storage to be ARL-relative */
-               newSrc[i] = *src[i];
-               newSrc[i].RelAddr = GL_TRUE;
-               newSrc[i].IsIndirect = GL_FALSE; /* not really needed */
-               src[i] = &newSrc[i];
-            }
-         }
-      }
-   }
-
-   /* Take special steps for indirect dest register write */
-   if (dst && dst->IsIndirect) {
-      /* load the ARL register with the indirect register */
-      emit_arl_load(emitInfo,
-                    dst->IndirectFile,
-                    dst->IndirectIndex,
-                    dst->IndirectSwizzle);
-      newDst = *dst;
-      newDst.RelAddr = GL_TRUE;
-      newDst.IsIndirect = GL_FALSE;
-      dst = &newDst;
-   }
-
-   /* OK, emit the instruction and its dst, src regs */
-   inst = new_instruction(emitInfo, opcode);
-   if (!inst)
-      return NULL;
-
-   if (dst)
-      storage_to_dst_reg(&inst->DstReg, dst);
-
-   for (i = 0; i < 3; i++) {
-      if (src[i])
-         storage_to_src_reg(&inst->SrcReg[i], src[i]);
-   }
-
-   /* Free any temp registers that we allocated above */
-   for (i = 0; i < 3; i++) {
-      if (isTemp[i])
-         _slang_free_temp(emitInfo->vt, &newSrc[i]);
-   }
-
-   return inst;
-}
-
-
-
-/**
- * Put a comment on the given instruction.
- */
-static void
-inst_comment(struct prog_instruction *inst, const char *comment)
-{
-   if (inst)
-      inst->Comment = _mesa_strdup(comment);
-}
-
-
-
-/**
- * Return pointer to last instruction in program.
- */
-static struct prog_instruction *
-prev_instruction(slang_emit_info *emitInfo)
-{
-   struct gl_program *prog = emitInfo->prog;
-   if (prog->NumInstructions == 0)
-      return NULL;
-   else
-      return prog->Instructions + prog->NumInstructions - 1;
-}
-
-
-static struct prog_instruction *
-emit(slang_emit_info *emitInfo, slang_ir_node *n);
-
-
-/**
- * Return an annotation string for given node's storage.
- */
-static char *
-storage_annotation(const slang_ir_node *n, const struct gl_program *prog)
-{
-#if ANNOTATE
-   const slang_ir_storage *st = n->Store;
-   static char s[100] = "";
-
-   if (!st)
-      return _mesa_strdup("");
-
-   switch (st->File) {
-   case PROGRAM_CONSTANT:
-      if (st->Index >= 0) {
-         const GLfloat *val = prog->Parameters->ParameterValues[st->Index];
-         if (st->Swizzle == SWIZZLE_NOOP)
-            _mesa_snprintf(s, sizeof(s), "{%g, %g, %g, %g}", val[0], val[1], val[2], val[3]);
-         else {
-            _mesa_snprintf(s, sizeof(s), "%g", val[GET_SWZ(st->Swizzle, 0)]);
-         }
-      }
-      break;
-   case PROGRAM_TEMPORARY:
-      if (n->Var)
-         _mesa_snprintf(s, sizeof(s), "%s", (char *) n->Var->a_name);
-      else
-         _mesa_snprintf(s, sizeof(s), "t[%d]", st->Index);
-      break;
-   case PROGRAM_STATE_VAR:
-   case PROGRAM_UNIFORM:
-      _mesa_snprintf(s, sizeof(s), "%s", prog->Parameters->Parameters[st->Index].Name);
-      break;
-   case PROGRAM_VARYING:
-      _mesa_snprintf(s, sizeof(s), "%s", prog->Varying->Parameters[st->Index].Name);
-      break;
-   case PROGRAM_INPUT:
-      _mesa_snprintf(s, sizeof(s), "input[%d]", st->Index);
-      break;
-   case PROGRAM_OUTPUT:
-      _mesa_snprintf(s, sizeof(s), "output[%d]", st->Index);
-      break;
-   default:
-      s[0] = 0;
-   }
-   return _mesa_strdup(s);
-#else
-   return NULL;
-#endif
-}
-
-
-/**
- * Return an annotation string for an instruction.
- */
-static char *
-instruction_annotation(gl_inst_opcode opcode, char *dstAnnot,
-                       char *srcAnnot0, char *srcAnnot1, char *srcAnnot2)
-{
-#if ANNOTATE
-   const char *operator;
-   char *s;
-   int len = 50;
-
-   if (dstAnnot)
-      len += strlen(dstAnnot);
-   else
-      dstAnnot = _mesa_strdup("");
-
-   if (srcAnnot0)
-      len += strlen(srcAnnot0);
-   else
-      srcAnnot0 = _mesa_strdup("");
-
-   if (srcAnnot1)
-      len += strlen(srcAnnot1);
-   else
-      srcAnnot1 = _mesa_strdup("");
-
-   if (srcAnnot2)
-      len += strlen(srcAnnot2);
-   else
-      srcAnnot2 = _mesa_strdup("");
-
-   switch (opcode) {
-   case OPCODE_ADD:
-      operator = "+";
-      break;
-   case OPCODE_SUB:
-      operator = "-";
-      break;
-   case OPCODE_MUL:
-      operator = "*";
-      break;
-   case OPCODE_DP2:
-      operator = "DP2";
-      break;
-   case OPCODE_DP3:
-      operator = "DP3";
-      break;
-   case OPCODE_DP4:
-      operator = "DP4";
-      break;
-   case OPCODE_XPD:
-      operator = "XPD";
-      break;
-   case OPCODE_RSQ:
-      operator = "RSQ";
-      break;
-   case OPCODE_SGT:
-      operator = ">";
-      break;
-   default:
-      operator = ",";
-   }
-
-   s = (char *) malloc(len);
-   _mesa_snprintf(s, len, "%s = %s %s %s %s", dstAnnot,
-                  srcAnnot0, operator, srcAnnot1, srcAnnot2);
-
-   free(dstAnnot);
-   free(srcAnnot0);
-   free(srcAnnot1);
-   free(srcAnnot2);
-
-   return s;
-#else
-   return NULL;
-#endif
-}
-
-
-/**
- * Emit an instruction that's just a comment.
- */
-static struct prog_instruction *
-emit_comment(slang_emit_info *emitInfo, const char *comment)
-{
-   struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_NOP);
-   if (inst) {
-      inst_comment(inst, comment);
-   }
-   return inst;
-}
-
-
-/**
- * Generate code for a simple arithmetic instruction.
- * Either 1, 2 or 3 operands.
- */
-static struct prog_instruction *
-emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   const slang_ir_info *info = _slang_ir_info(n->Opcode);
-   struct prog_instruction *inst;
-   GLuint i;
-
-   assert(info);
-   assert(info->InstOpcode != OPCODE_NOP);
-
-#if PEEPHOLE_OPTIMIZATIONS
-   /* Look for MAD opportunity */
-   if (info->NumParams == 2 &&
-       n->Opcode == IR_ADD && n->Children[0]->Opcode == IR_MUL) {
-      /* found pattern IR_ADD(IR_MUL(A, B), C) */
-      emit(emitInfo, n->Children[0]->Children[0]);  /* A */
-      emit(emitInfo, n->Children[0]->Children[1]);  /* B */
-      emit(emitInfo, n->Children[1]);  /* C */
-      if (!alloc_node_storage(emitInfo, n, -1)) {  /* dest */
-         return NULL;
-      }
-
-      inst = emit_instruction(emitInfo,
-                              OPCODE_MAD,
-                              n->Store,
-                              n->Children[0]->Children[0]->Store,
-                              n->Children[0]->Children[1]->Store,
-                              n->Children[1]->Store);
-
-      free_node_storage(emitInfo->vt, n->Children[0]->Children[0]);
-      free_node_storage(emitInfo->vt, n->Children[0]->Children[1]);
-      free_node_storage(emitInfo->vt, n->Children[1]);
-      return inst;
-   }
-
-   if (info->NumParams == 2 &&
-       n->Opcode == IR_ADD && n->Children[1]->Opcode == IR_MUL) {
-      /* found pattern IR_ADD(A, IR_MUL(B, C)) */
-      emit(emitInfo, n->Children[0]);  /* A */
-      emit(emitInfo, n->Children[1]->Children[0]);  /* B */
-      emit(emitInfo, n->Children[1]->Children[1]);  /* C */
-      if (!alloc_node_storage(emitInfo, n, -1)) {  /* dest */
-         return NULL;
-      }
-
-      inst = emit_instruction(emitInfo,
-                              OPCODE_MAD,
-                              n->Store,
-                              n->Children[1]->Children[0]->Store,
-                              n->Children[1]->Children[1]->Store,
-                              n->Children[0]->Store);
-
-      free_node_storage(emitInfo->vt, n->Children[1]->Children[0]);
-      free_node_storage(emitInfo->vt, n->Children[1]->Children[1]);
-      free_node_storage(emitInfo->vt, n->Children[0]);
-      return inst;
-   }
-#endif
-
-   /* gen code for children, may involve temp allocation */
-   for (i = 0; i < info->NumParams; i++) {
-      emit(emitInfo, n->Children[i]);
-      if (!n->Children[i] || !n->Children[i]->Store) {
-         /* error recovery */
-         return NULL;
-      }
-   }
-
-   /* result storage */
-   if (!alloc_node_storage(emitInfo, n, -1)) {
-      return NULL;
-   }
-
-   inst = emit_instruction(emitInfo,
-                           info->InstOpcode,
-                           n->Store,  /* dest */
-                           (info->NumParams > 0 ? n->Children[0]->Store : NULL),
-                           (info->NumParams > 1 ? n->Children[1]->Store : NULL),
-                           (info->NumParams > 2 ? n->Children[2]->Store : NULL)
-                           );
-
-   /* free temps */
-   for (i = 0; i < info->NumParams; i++)
-      free_node_storage(emitInfo->vt, n->Children[i]);
-
-   return inst;
-}
-
-
-/**
- * Emit code for == and != operators.  These could normally be handled
- * by emit_arith() except we need to be able to handle structure comparisons.
- */
-static struct prog_instruction *
-emit_compare(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst = NULL;
-   GLint size;
-
-   assert(n->Opcode == IR_EQUAL || n->Opcode == IR_NOTEQUAL);
-
-   /* gen code for children */
-   emit(emitInfo, n->Children[0]);
-   emit(emitInfo, n->Children[1]);
-
-   if (n->Children[0]->Store->Size != n->Children[1]->Store->Size) {
-      /* XXX this error should have been caught in slang_codegen.c */
-      slang_info_log_error(emitInfo->log, "invalid operands to == or !=");
-      n->Store = NULL;
-      return NULL;
-   }
-
-   /* final result is 1 bool */
-   if (!alloc_node_storage(emitInfo, n, 1))
-      return NULL;
-
-   size = n->Children[0]->Store->Size;
-
-   if (size == 1) {
-      gl_inst_opcode opcode = n->Opcode == IR_EQUAL ? OPCODE_SEQ : OPCODE_SNE;
-      inst =  emit_instruction(emitInfo,
-                               opcode,
-                               n->Store, /* dest */
-                               n->Children[0]->Store,
-                               n->Children[1]->Store,
-                               NULL);
-   }
-   else if (size <= 4) {
-      /* compare two vectors.
-       * Unfortunately, there's no instruction to compare vectors and
-       * return a scalar result.  Do it with some compare and dot product
-       * instructions...
-       */
-      GLuint swizzle;
-      gl_inst_opcode dotOp;
-      slang_ir_storage tempStore;
-
-      if (!alloc_local_temp(emitInfo, &tempStore, 4)) {
-         n->Store = NULL;
-         return NULL;
-         /* out of temps */
-      }
-
-      if (size == 4) {
-         dotOp = OPCODE_DP4;
-         swizzle = SWIZZLE_XYZW;
-      }
-      else if (size == 3) {
-         dotOp = OPCODE_DP3;
-         swizzle = SWIZZLE_XYZW;
-      }
-      else {
-         assert(size == 2);
-         dotOp = OPCODE_DP3; /* XXX use OPCODE_DP2 eventually */
-         swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y);
-      }
-
-      /* Compute inequality (temp = (A != B)) */
-      inst = emit_instruction(emitInfo,
-                              OPCODE_SNE,
-                              &tempStore,
-                              n->Children[0]->Store,
-                              n->Children[1]->Store,
-                              NULL);
-      if (!inst) {
-         return NULL;
-      }
-      inst_comment(inst, "Compare values");
-
-      /* Compute val = DOT(temp, temp)  (reduction) */
-      inst = emit_instruction(emitInfo,
-                              dotOp,
-                              n->Store,
-                              &tempStore,
-                              &tempStore,
-                              NULL);
-      if (!inst) {
-         return NULL;
-      }
-      inst->SrcReg[0].Swizzle = inst->SrcReg[1].Swizzle = swizzle; /*override*/
-      inst_comment(inst, "Reduce vec to bool");
-
-      _slang_free_temp(emitInfo->vt, &tempStore); /* free temp */
-
-      if (n->Opcode == IR_EQUAL) {
-         /* compute val = !val.x  with SEQ val, val, 0; */
-         slang_ir_storage zero;
-         constant_to_storage(emitInfo, 0.0, &zero);
-         inst = emit_instruction(emitInfo,
-                                 OPCODE_SEQ,
-                                 n->Store, /* dest */
-                                 n->Store,
-                                 &zero,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-         inst_comment(inst, "Invert true/false");
-      }
-   }
-   else {
-      /* size > 4, struct or array compare.
-       * XXX this won't work reliably for structs with padding!!
-       */
-      GLint i, num = (n->Children[0]->Store->Size + 3) / 4;
-      slang_ir_storage accTemp, sneTemp;
-
-      if (!alloc_local_temp(emitInfo, &accTemp, 4))
-         return NULL;
-
-      if (!alloc_local_temp(emitInfo, &sneTemp, 4))
-         return NULL;
-
-      for (i = 0; i < num; i++) {
-         slang_ir_storage srcStore0 = *n->Children[0]->Store;
-         slang_ir_storage srcStore1 = *n->Children[1]->Store;
-         srcStore0.Index += i;
-         srcStore1.Index += i;
-
-         if (i == 0) {
-            /* SNE accTemp, left[i], right[i] */
-            inst = emit_instruction(emitInfo, OPCODE_SNE,
-                                    &accTemp, /* dest */
-                                    &srcStore0,
-                                    &srcStore1,
-                                    NULL);
-            if (!inst) {
-               return NULL;
-            }
-            inst_comment(inst, "Begin struct/array comparison");
-         }
-         else {
-            /* SNE sneTemp, left[i], right[i] */
-            inst = emit_instruction(emitInfo, OPCODE_SNE,
-                                    &sneTemp, /* dest */
-                                    &srcStore0,
-                                    &srcStore1,
-                                    NULL);
-            if (!inst) {
-               return NULL;
-            }
-            /* ADD accTemp, accTemp, sneTemp; # like logical-OR */
-            inst = emit_instruction(emitInfo, OPCODE_ADD,
-                                    &accTemp, /* dest */
-                                    &accTemp,
-                                    &sneTemp,
-                                    NULL);
-            if (!inst) {
-               return NULL;
-            }
-         }
-      }
-
-      /* compute accTemp.x || accTemp.y || accTemp.z || accTemp.w with DOT4 */
-      inst = emit_instruction(emitInfo, OPCODE_DP4,
-                              n->Store,
-                              &accTemp,
-                              &accTemp,
-                              NULL);
-      if (!inst) {
-         return NULL;
-      }
-      inst_comment(inst, "End struct/array comparison");
-
-      if (n->Opcode == IR_EQUAL) {
-         /* compute tmp.x = !tmp.x  via tmp.x = (tmp.x == 0) */
-         slang_ir_storage zero;
-         constant_to_storage(emitInfo, 0.0, &zero);
-         inst = emit_instruction(emitInfo, OPCODE_SEQ,
-                                 n->Store, /* dest */
-                                 n->Store,
-                                 &zero,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-         inst_comment(inst, "Invert true/false");
-      }
-
-      _slang_free_temp(emitInfo->vt, &accTemp);
-      _slang_free_temp(emitInfo->vt, &sneTemp);
-   }
-
-   /* free temps */
-   free_node_storage(emitInfo->vt, n->Children[0]);
-   free_node_storage(emitInfo->vt, n->Children[1]);
-
-   return inst;
-}
-
-
-
-/**
- * Generate code for an IR_CLAMP instruction.
- */
-static struct prog_instruction *
-emit_clamp(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-   slang_ir_node tmpNode;
-
-   assert(n->Opcode == IR_CLAMP);
-   /* ch[0] = value
-    * ch[1] = min limit
-    * ch[2] = max limit
-    */
-
-   inst = emit(emitInfo, n->Children[0]);
-
-   /* If lower limit == 0.0 and upper limit == 1.0,
-    *    set prev instruction's SaturateMode field to SATURATE_ZERO_ONE.
-    * Else,
-    *    emit OPCODE_MIN, OPCODE_MAX sequence.
-    */
-#if 0
-   /* XXX this isn't quite finished yet */
-   if (n->Children[1]->Opcode == IR_FLOAT &&
-       n->Children[1]->Value[0] == 0.0 &&
-       n->Children[1]->Value[1] == 0.0 &&
-       n->Children[1]->Value[2] == 0.0 &&
-       n->Children[1]->Value[3] == 0.0 &&
-       n->Children[2]->Opcode == IR_FLOAT &&
-       n->Children[2]->Value[0] == 1.0 &&
-       n->Children[2]->Value[1] == 1.0 &&
-       n->Children[2]->Value[2] == 1.0 &&
-       n->Children[2]->Value[3] == 1.0) {
-      if (!inst) {
-         inst = prev_instruction(prog);
-      }
-      if (inst && inst->Opcode != OPCODE_NOP) {
-         /* and prev instruction's DstReg matches n->Children[0]->Store */
-         inst->SaturateMode = SATURATE_ZERO_ONE;
-         n->Store = n->Children[0]->Store;
-         return inst;
-      }
-   }
-#else
-   (void) inst;
-#endif
-
-   if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
-      return NULL;
-
-   emit(emitInfo, n->Children[1]);
-   emit(emitInfo, n->Children[2]);
-
-   /* Some GPUs don't allow reading from output registers.  So if the
-    * dest for this clamp() is an output reg, we can't use that reg for
-    * the intermediate result.  Use a temp register instead.
-    */
-   memset(&tmpNode, 0, sizeof(tmpNode));
-   if (!alloc_node_storage(emitInfo, &tmpNode, n->Store->Size)) {
-      return NULL;
-   }
-
-   /* tmp = max(ch[0], ch[1]) */
-   inst = emit_instruction(emitInfo, OPCODE_MAX,
-                           tmpNode.Store, /* dest */
-                           n->Children[0]->Store,
-                           n->Children[1]->Store,
-                           NULL);
-   if (!inst) {
-      return NULL;
-   }
-
-   /* n->dest = min(tmp, ch[2]) */
-   inst = emit_instruction(emitInfo, OPCODE_MIN,
-                           n->Store, /* dest */
-                           tmpNode.Store,
-                           n->Children[2]->Store,
-                           NULL);
-
-   free_node_storage(emitInfo->vt, &tmpNode);
-
-   return inst;
-}
-
-
-static struct prog_instruction *
-emit_negation(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   /* Implement as MOV dst, -src; */
-   /* XXX we could look at the previous instruction and in some circumstances
-    * modify it to accomplish the negation.
-    */
-   struct prog_instruction *inst;
-
-   emit(emitInfo, n->Children[0]);
-
-   if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
-      return NULL;
-
-   inst = emit_instruction(emitInfo,
-                           OPCODE_MOV,
-                           n->Store, /* dest */
-                           n->Children[0]->Store,
-                           NULL,
-                           NULL);
-   if (inst) {
-      inst->SrcReg[0].Negate = NEGATE_XYZW;
-   }
-   return inst;
-}
-
-
-static struct prog_instruction *
-emit_label(slang_emit_info *emitInfo, const slang_ir_node *n)
-{
-   assert(n->Label);
-#if 0
-   /* XXX this fails in loop tail code - investigate someday */
-   assert(_slang_label_get_location(n->Label) < 0);
-   _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
-                             emitInfo->prog);
-#else
-   if (_slang_label_get_location(n->Label) < 0)
-      _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
-                                emitInfo->prog);
-#endif
-   return NULL;
-}
-
-
-/**
- * Emit code for a function call.
- * Note that for each time a function is called, we emit the function's
- * body code again because the set of available registers may be different.
- */
-static struct prog_instruction *
-emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct gl_program *progSave;
-   struct prog_instruction *inst;
-   GLuint subroutineId;
-   GLuint maxInstSave;
-
-   assert(n->Opcode == IR_CALL);
-   assert(n->Label);
-
-   /* save/push cur program */
-   maxInstSave = emitInfo->MaxInstructions;
-   progSave = emitInfo->prog;
-
-   emitInfo->prog = new_subroutine(emitInfo, &subroutineId);
-   emitInfo->MaxInstructions = emitInfo->prog->NumInstructions;
-
-   _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
-                             emitInfo->prog);
-
-   if (emitInfo->EmitBeginEndSub) {
-      /* BGNSUB isn't a real instruction.
-       * We require a label (i.e. "foobar:") though, if we're going to
-       * print the program in the NV format.  The BNGSUB instruction is
-       * really just a NOP to attach the label to.
-       */
-      inst = new_instruction(emitInfo, OPCODE_BGNSUB);
-      if (!inst) {
-         return NULL;
-      }
-      inst_comment(inst, n->Label->Name);
-   }
-
-   /* body of function: */
-   emit(emitInfo, n->Children[0]);
-   n->Store = n->Children[0]->Store;
-
-   /* add RET instruction now, if needed */
-   inst = prev_instruction(emitInfo);
-   if (inst && inst->Opcode != OPCODE_RET) {
-      inst = new_instruction(emitInfo, OPCODE_RET);
-      if (!inst) {
-         return NULL;
-      }
-   }
-
-   if (emitInfo->EmitBeginEndSub) {
-      inst = new_instruction(emitInfo, OPCODE_ENDSUB);
-      if (!inst) {
-         return NULL;
-      }
-      inst_comment(inst, n->Label->Name);
-   }
-
-   /* pop/restore cur program */
-   emitInfo->prog = progSave;
-   emitInfo->MaxInstructions = maxInstSave;
-
-   /* emit the function call */
-   inst = new_instruction(emitInfo, OPCODE_CAL);
-   if (!inst) {
-      return NULL;
-   }
-   /* The branch target is just the subroutine number (changed later) */
-   inst->BranchTarget = subroutineId;
-   inst_comment(inst, n->Label->Name);
-   assert(inst->BranchTarget >= 0);
-
-   return inst;
-}
-
-
-/**
- * Emit code for a 'return' statement.
- */
-static struct prog_instruction *
-emit_return(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-   assert(n);
-   assert(n->Opcode == IR_RETURN);
-   assert(n->Label);
-   inst = new_instruction(emitInfo, OPCODE_RET);
-   if (inst) {
-      inst->DstReg.CondMask = COND_TR;  /* always return */
-   }
-   return inst;
-}
-
-
-static struct prog_instruction *
-emit_kill(slang_emit_info *emitInfo)
-{
-   struct gl_fragment_program *fp;
-   struct prog_instruction *inst;
-   /* NV-KILL - discard fragment depending on condition code.
-    * Note that ARB-KILL depends on sign of vector operand.
-    */
-   inst = new_instruction(emitInfo, OPCODE_KIL_NV);
-   if (!inst) {
-      return NULL;
-   }
-   inst->DstReg.CondMask = COND_TR;  /* always kill */
-
-   assert(emitInfo->prog->Target == GL_FRAGMENT_PROGRAM_ARB);
-   fp = (struct gl_fragment_program *) emitInfo->prog;
-   fp->UsesKill = GL_TRUE;
-
-   return inst;
-}
-
-
-static struct prog_instruction *
-emit_tex(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-   gl_inst_opcode opcode;
-   GLboolean shadow = GL_FALSE;
-
-   switch (n->Opcode) {
-   case IR_TEX:
-      opcode = OPCODE_TEX;
-      break;
-   case IR_TEX_SH:
-      opcode = OPCODE_TEX;
-      shadow = GL_TRUE;
-      break;
-   case IR_TEXB:
-      opcode = OPCODE_TXB;
-      break;
-   case IR_TEXB_SH:
-      opcode = OPCODE_TXB;
-      shadow = GL_TRUE;
-      break;
-   case IR_TEXP:
-      opcode = OPCODE_TXP;
-      break;
-   case IR_TEXP_SH:
-      opcode = OPCODE_TXP;
-      shadow = GL_TRUE;
-      break;
-   default:
-      _mesa_problem(NULL, "Bad IR TEX code");
-      return NULL;
-   }
-
-   if (n->Children[0]->Opcode == IR_ELEMENT) {
-      /* array is the sampler (a uniform which'll indicate the texture unit) */
-      assert(n->Children[0]->Children[0]->Store);
-      assert(n->Children[0]->Children[0]->Store->File == PROGRAM_SAMPLER);
-
-      emit(emitInfo, n->Children[0]);
-
-      n->Children[0]->Var = n->Children[0]->Children[0]->Var;
-   } else {
-      /* this is the sampler (a uniform which'll indicate the texture unit) */
-      assert(n->Children[0]->Store);
-      assert(n->Children[0]->Store->File == PROGRAM_SAMPLER);
-   }
-
-   /* emit code for the texcoord operand */
-   (void) emit(emitInfo, n->Children[1]);
-
-   /* alloc storage for result of texture fetch */
-   if (!alloc_node_storage(emitInfo, n, 4))
-      return NULL;
-
-   /* emit TEX instruction;  Child[1] is the texcoord */
-   inst = emit_instruction(emitInfo,
-                           opcode,
-                           n->Store,
-                           n->Children[1]->Store,
-                           NULL,
-                           NULL);
-   if (!inst) {
-      return NULL;
-   }
-
-   inst->TexShadow = shadow;
-
-   /* Store->Index is the uniform/sampler index */
-   assert(n->Children[0]->Store->Index >= 0);
-   inst->TexSrcUnit = n->Children[0]->Store->Index;
-   inst->TexSrcTarget = n->Children[0]->Store->TexTarget;
-
-   /* mark the sampler as being used */
-   _mesa_use_uniform(emitInfo->prog->Parameters,
-                     (char *) n->Children[0]->Var->a_name);
-
-   return inst;
-}
-
-
-/**
- * Assignment/copy
- */
-static struct prog_instruction *
-emit_copy(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-
-   assert(n->Opcode == IR_COPY);
-
-   /* lhs */
-   emit(emitInfo, n->Children[0]);
-   if (!n->Children[0]->Store || n->Children[0]->Store->Index < 0) {
-      /* an error should have been already recorded */
-      return NULL;
-   }
-
-   /* rhs */
-   assert(n->Children[1]);
-   inst = emit(emitInfo, n->Children[1]);
-
-   if (!n->Children[1]->Store || n->Children[1]->Store->Index < 0) {
-      if (!emitInfo->log->text && !emitInfo->UnresolvedFunctions) {
-         /* XXX this error should have been caught in slang_codegen.c */
-         slang_info_log_error(emitInfo->log, "invalid assignment");
-      }
-      return NULL;
-   }
-
-   assert(n->Children[1]->Store->Index >= 0);
-
-   /*assert(n->Children[0]->Store->Size == n->Children[1]->Store->Size);*/
-
-   n->Store = n->Children[0]->Store;
-
-   if (n->Store->File == PROGRAM_SAMPLER) {
-      /* no code generated for sampler assignments,
-       * just copy the sampler index/target at compile time.
-       */
-      n->Store->Index = n->Children[1]->Store->Index;
-      n->Store->TexTarget = n->Children[1]->Store->TexTarget;
-      return NULL;
-   }
-
-#if PEEPHOLE_OPTIMIZATIONS
-   if (inst &&
-       (n->Children[1]->Opcode != IR_SWIZZLE) &&
-       _slang_is_temp(emitInfo->vt, n->Children[1]->Store) &&
-       (inst->DstReg.File == n->Children[1]->Store->File) &&
-       (inst->DstReg.Index == n->Children[1]->Store->Index) &&
-       !n->Children[0]->Store->IsIndirect &&
-       n->Children[0]->Store->Size <= 4) {
-      /* Peephole optimization:
-       * The Right-Hand-Side has its results in a temporary place.
-       * Modify the RHS (and the prev instruction) to store its results
-       * in the destination specified by n->Children[0].
-       * Then, this MOVE is a no-op.
-       * Ex:
-       *   MUL tmp, x, y;
-       *   MOV a, tmp;
-       * becomes:
-       *   MUL a, x, y;
-       */
-
-      /* fixup the previous instruction (which stored the RHS result) */
-      assert(n->Children[0]->Store->Index >= 0);
-      storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store);
-      return inst;
-   }
-   else
-#endif
-   {
-      if (n->Children[0]->Store->Size > 4) {
-         /* move matrix/struct etc (block of registers) */
-         slang_ir_storage dstStore = *n->Children[0]->Store;
-         slang_ir_storage srcStore = *n->Children[1]->Store;
-         GLint size = srcStore.Size;
-         ASSERT(n->Children[1]->Store->Swizzle == SWIZZLE_NOOP);
-         dstStore.Size = 4;
-         srcStore.Size = 4;
-         while (size >= 4) {
-            inst = emit_instruction(emitInfo, OPCODE_MOV,
-                                    &dstStore,
-                                    &srcStore,
-                                    NULL,
-                                    NULL);
-            if (!inst) {
-               return NULL;
-            }
-            inst_comment(inst, "IR_COPY block");
-            srcStore.Index++;
-            dstStore.Index++;
-            size -= 4;
-         }
-      }
-      else {
-         /* single register move */
-         char *srcAnnot, *dstAnnot;
-         assert(n->Children[0]->Store->Index >= 0);
-         inst = emit_instruction(emitInfo, OPCODE_MOV,
-                                 n->Children[0]->Store, /* dest */
-                                 n->Children[1]->Store,
-                                 NULL,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-         dstAnnot = storage_annotation(n->Children[0], emitInfo->prog);
-         srcAnnot = storage_annotation(n->Children[1], emitInfo->prog);
-         inst->Comment = instruction_annotation(inst->Opcode, dstAnnot,
-                                                srcAnnot, NULL, NULL);
-      }
-      free_node_storage(emitInfo->vt, n->Children[1]);
-      return inst;
-   }
-}
-
-
-/**
- * An IR_COND node wraps a boolean expression which is used by an
- * IF or WHILE test.  This is where we'll set condition codes, if needed.
- */
-static struct prog_instruction *
-emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-
-   assert(n->Opcode == IR_COND);
-
-   if (!n->Children[0])
-      return NULL;
-
-   /* emit code for the expression */
-   inst = emit(emitInfo, n->Children[0]);
-
-   if (!n->Children[0]->Store) {
-      /* error recovery */
-      return NULL;
-   }
-
-   assert(n->Children[0]->Store);
-   /*assert(n->Children[0]->Store->Size == 1);*/
-
-   if (emitInfo->EmitCondCodes) {
-      if (inst &&
-          n->Children[0]->Store &&
-          inst->DstReg.File == n->Children[0]->Store->File &&
-          inst->DstReg.Index == n->Children[0]->Store->Index) {
-         /* The previous instruction wrote to the register who's value
-          * we're testing.  Just fix that instruction so that the
-          * condition codes are computed.
-          */
-         inst->CondUpdate = GL_TRUE;
-         n->Store = n->Children[0]->Store;
-         return inst;
-      }
-      else {
-         /* This'll happen for things like "if (i) ..." where no code
-          * is normally generated for the expression "i".
-          * Generate a move instruction just to set condition codes.
-          */
-         if (!alloc_node_storage(emitInfo, n, 1))
-            return NULL;
-         inst = emit_instruction(emitInfo, OPCODE_MOV,
-                                 n->Store, /* dest */
-                                 n->Children[0]->Store,
-                                 NULL,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-         inst->CondUpdate = GL_TRUE;
-         inst_comment(inst, "COND expr");
-         _slang_free_temp(emitInfo->vt, n->Store);
-         return inst;
-      }
-   }
-   else {
-      /* No-op: the boolean result of the expression is in a regular reg */
-      n->Store = n->Children[0]->Store;
-      return inst;
-   }
-}
-
-
-/**
- * Logical-NOT
- */
-static struct prog_instruction *
-emit_not(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   static const struct {
-      gl_inst_opcode op, opNot;
-   } operators[] = {
-      { OPCODE_SLT, OPCODE_SGE },
-      { OPCODE_SLE, OPCODE_SGT },
-      { OPCODE_SGT, OPCODE_SLE },
-      { OPCODE_SGE, OPCODE_SLT },
-      { OPCODE_SEQ, OPCODE_SNE },
-      { OPCODE_SNE, OPCODE_SEQ },
-      { 0, 0 }
-   };
-   struct prog_instruction *inst;
-   slang_ir_storage zero;
-   GLuint i;
-
-   /* child expr */
-   inst = emit(emitInfo, n->Children[0]);
-
-#if PEEPHOLE_OPTIMIZATIONS
-   if (inst) {
-      /* if the prev instruction was a comparison instruction, invert it */
-      for (i = 0; operators[i].op; i++) {
-         if (inst->Opcode == operators[i].op) {
-            inst->Opcode = operators[i].opNot;
-            n->Store = n->Children[0]->Store;
-            return inst;
-         }
-      }
-   }
-#endif
-
-   /* else, invert using SEQ (v = v == 0) */
-   if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
-      return NULL;
-
-   constant_to_storage(emitInfo, 0.0, &zero);
-   inst = emit_instruction(emitInfo,
-                           OPCODE_SEQ,
-                           n->Store,
-                           n->Children[0]->Store,
-                           &zero,
-                           NULL);
-   if (!inst) {
-      return NULL;
-   }
-   inst_comment(inst, "NOT");
-
-   free_node_storage(emitInfo->vt, n->Children[0]);
-
-   return inst;
-}
-
-
-static struct prog_instruction *
-emit_if(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct gl_program *prog = emitInfo->prog;
-   GLuint ifInstLoc, elseInstLoc = 0;
-   GLuint condWritemask = 0;
-
-   /* emit condition expression code */
-   {
-      struct prog_instruction *inst;
-      inst = emit(emitInfo, n->Children[0]);
-      if (emitInfo->EmitCondCodes) {
-         if (!inst) {
-            /* error recovery */
-            return NULL;
-         }
-         condWritemask = inst->DstReg.WriteMask;
-      }
-   }
-
-   if (!n->Children[0]->Store)
-      return NULL;
-
-#if 0
-   assert(n->Children[0]->Store->Size == 1); /* a bool! */
-#endif
-
-   ifInstLoc = prog->NumInstructions;
-   if (emitInfo->EmitHighLevelInstructions) {
-      if (emitInfo->EmitCondCodes) {
-         /* IF condcode THEN ... */
-         struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_IF);
-         if (!ifInst) {
-            return NULL;
-         }
-         ifInst->DstReg.CondMask = COND_NE;  /* if cond is non-zero */
-         /* only test the cond code (1 of 4) that was updated by the
-          * previous instruction.
-          */
-         ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
-      }
-      else {
-         struct prog_instruction *inst;
-
-         /* IF src[0] THEN ... */
-         inst = emit_instruction(emitInfo, OPCODE_IF,
-                                 NULL, /* dst */
-                                 n->Children[0]->Store, /* op0 */
-                                 NULL,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-      }
-   }
-   else {
-      /* conditional jump to else, or endif */
-      struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_BRA);
-      if (!ifInst) {
-         return NULL;
-      }
-      ifInst->DstReg.CondMask = COND_EQ;  /* BRA if cond is zero */
-      inst_comment(ifInst, "if zero");
-      ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
-   }
-
-   /* if body */
-   emit(emitInfo, n->Children[1]);
-
-   if (n->Children[2]) {
-      /* have else body */
-      elseInstLoc = prog->NumInstructions;
-      if (emitInfo->EmitHighLevelInstructions) {
-         struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ELSE);
-         if (!inst) {
-            return NULL;
-         }
-         prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions - 1;
-      }
-      else {
-         /* jump to endif instruction */
-         struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_BRA);
-         if (!inst) {
-            return NULL;
-         }
-         inst_comment(inst, "else");
-         inst->DstReg.CondMask = COND_TR;  /* always branch */
-         prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions;
-      }
-      emit(emitInfo, n->Children[2]);
-   }
-   else {
-      /* no else body */
-      prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions;
-   }
-
-   if (emitInfo->EmitHighLevelInstructions) {
-      struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ENDIF);
-      if (!inst) {
-         return NULL;
-      }
-   }
-
-   if (elseInstLoc) {
-      /* point ELSE instruction BranchTarget at ENDIF */
-      if (emitInfo->EmitHighLevelInstructions) {
-         prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions - 1;
-      }
-      else {
-         prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions;
-      }
-   }
-   return NULL;
-}
-
-
-static struct prog_instruction *
-emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct gl_program *prog = emitInfo->prog;
-   struct prog_instruction *endInst;
-   GLuint beginInstLoc, tailInstLoc, endInstLoc;
-   slang_ir_node *ir;
-
-   /* emit OPCODE_BGNLOOP */
-   beginInstLoc = prog->NumInstructions;
-   if (emitInfo->EmitHighLevelInstructions) {
-      struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_BGNLOOP);
-      if (!inst) {
-         return NULL;
-      }
-   }
-
-   /* body */
-   emit(emitInfo, n->Children[0]);
-
-   /* tail */
-   tailInstLoc = prog->NumInstructions;
-   if (n->Children[1]) {
-      if (emitInfo->EmitComments)
-         emit_comment(emitInfo, "Loop tail code:");
-      emit(emitInfo, n->Children[1]);
-   }
-
-   endInstLoc = prog->NumInstructions;
-   if (emitInfo->EmitHighLevelInstructions) {
-      /* emit OPCODE_ENDLOOP */
-      endInst = new_instruction(emitInfo, OPCODE_ENDLOOP);
-      if (!endInst) {
-         return NULL;
-      }
-   }
-   else {
-      /* emit unconditional BRA-nch */
-      endInst = new_instruction(emitInfo, OPCODE_BRA);
-      if (!endInst) {
-         return NULL;
-      }
-      endInst->DstReg.CondMask = COND_TR;  /* always true */
-   }
-   /* ENDLOOP's BranchTarget points to the BGNLOOP inst */
-   endInst->BranchTarget = beginInstLoc;
-
-   if (emitInfo->EmitHighLevelInstructions) {
-      /* BGNLOOP's BranchTarget points to the ENDLOOP inst */
-      prog->Instructions[beginInstLoc].BranchTarget = prog->NumInstructions -1;
-   }
-
-   /* Done emitting loop code.  Now walk over the loop's linked list of
-    * BREAK and CONT nodes, filling in their BranchTarget fields (which
-    * will point to the corresponding ENDLOOP instruction.
-    */
-   for (ir = n->List; ir; ir = ir->List) {
-      struct prog_instruction *inst = prog->Instructions + ir->InstLocation;
-      assert(inst->BranchTarget < 0);
-      if (ir->Opcode == IR_BREAK ||
-          ir->Opcode == IR_BREAK_IF_TRUE) {
-         assert(inst->Opcode == OPCODE_BRK ||
-                inst->Opcode == OPCODE_BRA);
-         /* go to instruction at end of loop */
-         if (emitInfo->EmitHighLevelInstructions) {
-            inst->BranchTarget = endInstLoc;
-         }
-         else {
-            inst->BranchTarget = endInstLoc + 1;
-         }
-      }
-      else {
-         assert(ir->Opcode == IR_CONT ||
-                ir->Opcode == IR_CONT_IF_TRUE);
-         assert(inst->Opcode == OPCODE_CONT ||
-                inst->Opcode == OPCODE_BRA);
-         /* go to instruction at tail of loop */
-         inst->BranchTarget = endInstLoc;
-      }
-   }
-   return NULL;
-}
-
-
-/**
- * Unconditional "continue" or "break" statement.
- * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted.
- */
-static struct prog_instruction *
-emit_cont_break(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   gl_inst_opcode opcode;
-   struct prog_instruction *inst;
-
-   if (n->Opcode == IR_CONT) {
-      /* we need to execute the loop's tail code before doing CONT */
-      assert(n->Parent);
-      assert(n->Parent->Opcode == IR_LOOP);
-      if (n->Parent->Children[1]) {
-         /* emit tail code */
-         if (emitInfo->EmitComments) {
-            emit_comment(emitInfo, "continue - tail code:");
-         }
-         emit(emitInfo, n->Parent->Children[1]);
-      }
-   }
-
-   /* opcode selection */
-   if (emitInfo->EmitHighLevelInstructions) {
-      opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
-   }
-   else {
-      opcode = OPCODE_BRA;
-   }
-   n->InstLocation = emitInfo->prog->NumInstructions;
-   inst = new_instruction(emitInfo, opcode);
-   if (inst) {
-      inst->DstReg.CondMask = COND_TR;  /* always true */
-   }
-   return inst;
-}
-
-
-/**
- * Conditional "continue" or "break" statement.
- * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted.
- */
-static struct prog_instruction *
-emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-
-   assert(n->Opcode == IR_CONT_IF_TRUE ||
-          n->Opcode == IR_BREAK_IF_TRUE);
-
-   /* evaluate condition expr, setting cond codes */
-   inst = emit(emitInfo, n->Children[0]);
-   if (emitInfo->EmitCondCodes) {
-      assert(inst);
-      inst->CondUpdate = GL_TRUE;
-   }
-
-   n->InstLocation = emitInfo->prog->NumInstructions;
-
-   /* opcode selection */
-   if (emitInfo->EmitHighLevelInstructions) {
-      const gl_inst_opcode opcode
-         = (n->Opcode == IR_CONT_IF_TRUE) ? OPCODE_CONT : OPCODE_BRK;
-      if (emitInfo->EmitCondCodes) {
-         /* Get the writemask from the previous instruction which set
-          * the condcodes.  Use that writemask as the CondSwizzle.
-          */
-         const GLuint condWritemask = inst->DstReg.WriteMask;
-         inst = new_instruction(emitInfo, opcode);
-         if (inst) {
-            inst->DstReg.CondMask = COND_NE;
-            inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
-         }
-         return inst;
-      }
-      else {
-         /* IF reg
-          *    BRK/CONT;
-          * ENDIF
-          */
-         GLint ifInstLoc;
-         ifInstLoc = emitInfo->prog->NumInstructions;
-         inst = emit_instruction(emitInfo, OPCODE_IF,
-                                 NULL, /* dest */
-                                 n->Children[0]->Store,
-                                 NULL,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-         n->InstLocation = emitInfo->prog->NumInstructions;
-
-         inst = new_instruction(emitInfo, opcode);
-         if (!inst) {
-            return NULL;
-         }
-         inst = new_instruction(emitInfo, OPCODE_ENDIF);
-         if (!inst) {
-            return NULL;
-         }
-
-         emitInfo->prog->Instructions[ifInstLoc].BranchTarget
-            = emitInfo->prog->NumInstructions - 1;
-         return inst;
-      }
-   }
-   else {
-      const GLuint condWritemask = inst->DstReg.WriteMask;
-      assert(emitInfo->EmitCondCodes);
-      inst = new_instruction(emitInfo, OPCODE_BRA);
-      if (inst) {
-         inst->DstReg.CondMask = COND_NE;
-         inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
-      }
-      return inst;
-   }
-}
-
-
-/**
- * Return the size of a swizzle mask given that some swizzle components
- * may be NIL/undefined.  For example:
- *  swizzle_size(".zzxx") = 4
- *  swizzle_size(".xy??") = 2
- *  swizzle_size(".w???") = 1
- */
-static GLuint
-swizzle_size(GLuint swizzle)
-{
-   GLuint i;
-   for (i = 0; i < 4; i++) {
-      if (GET_SWZ(swizzle, i) == SWIZZLE_NIL)
-         return i;
-   }
-   return 4;
-}
-
-
-static struct prog_instruction *
-emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-
-   inst = emit(emitInfo, n->Children[0]);
-
-   if (!n->Store->Parent) {
-      /* this covers a case such as "(b ? p : q).x" */
-      n->Store->Parent = n->Children[0]->Store;
-      assert(n->Store->Parent);
-   }
-
-   {
-      const GLuint swizzle = n->Store->Swizzle;
-      /* new storage is parent storage with updated Swizzle + Size fields */
-      _slang_copy_ir_storage(n->Store, n->Store->Parent);
-      /* Apply this node's swizzle to parent's storage */
-      n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle);
-      /* Update size */
-      n->Store->Size = swizzle_size(n->Store->Swizzle);
-   }
-
-   assert(!n->Store->Parent);
-   assert(n->Store->Index >= 0);
-
-   return inst;
-}
-
-
-/**
- * Dereference array element:  element == array[index]
- * This basically involves emitting code for computing the array index
- * and updating the node/element's storage info.
- */
-static struct prog_instruction *
-emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   slang_ir_storage *arrayStore, *indexStore;
-   const int elemSize = n->Store->Size;           /* number of floats */
-   const GLint elemSizeVec = (elemSize + 3) / 4;  /* number of vec4 */
-   struct prog_instruction *inst;
-
-   assert(n->Opcode == IR_ELEMENT);
-   assert(elemSize > 0);
-
-   /* special case for built-in state variables, like light state */
-   {
-      slang_ir_storage *root = n->Store;
-      assert(!root->Parent);
-      while (root->Parent)
-         root = root->Parent;
-
-      if (root->File == PROGRAM_STATE_VAR) {
-         GLboolean direct;
-         GLint index =
-            _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
-         if (index < 0) {
-            /* error */
-            return NULL;
-         }
-         if (direct) {
-            n->Store->Index = index;
-            return NULL; /* all done */
-         }
-      }
-   }
-
-   /* do codegen for array itself */
-   emit(emitInfo, n->Children[0]);
-   arrayStore = n->Children[0]->Store;
-
-   /* The initial array element storage is the array's storage,
-    * then modified below.
-    */
-   _slang_copy_ir_storage(n->Store, arrayStore);
-
-
-   if (n->Children[1]->Opcode == IR_FLOAT) {
-      /* Constant array index */
-      const GLint element = (GLint) n->Children[1]->Value[0];
-
-      /* this element's storage is the array's storage, plus constant offset */
-      n->Store->Index += elemSizeVec * element;
-   }
-   else {
-      /* Variable array index */
-
-      /* do codegen for array index expression */
-      emit(emitInfo, n->Children[1]);
-      indexStore = n->Children[1]->Store;
-
-      if (indexStore->IsIndirect) {
-         /* need to put the array index into a temporary since we can't
-          * directly support a[b[i]] constructs.
-          */
-
-
-         /*indexStore = tempstore();*/
-      }
-
-
-      if (elemSize > 4) {
-         /* need to multiply array index by array element size */
-         struct prog_instruction *inst;
-         slang_ir_storage *indexTemp;
-         slang_ir_storage elemSizeStore;
-
-         /* allocate 1 float indexTemp */
-         indexTemp = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
-         _slang_alloc_temp(emitInfo->vt, indexTemp);
-
-         /* allocate a constant containing the element size */
-         constant_to_storage(emitInfo, (float) elemSizeVec, &elemSizeStore);
-
-         /* multiply array index by element size */
-         inst = emit_instruction(emitInfo,
-                                 OPCODE_MUL,
-                                 indexTemp, /* dest */
-                                 indexStore, /* the index */
-                                 &elemSizeStore,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-
-         indexStore = indexTemp;
-      }
-
-      if (arrayStore->IsIndirect) {
-         /* ex: in a[i][j], a[i] (the arrayStore) is indirect */
-         /* Need to add indexStore to arrayStore->Indirect store */
-         slang_ir_storage indirectArray;
-         slang_ir_storage *indexTemp;
-
-         _slang_init_ir_storage(&indirectArray,
-                                arrayStore->IndirectFile,
-                                arrayStore->IndirectIndex,
-                                1,
-                                arrayStore->IndirectSwizzle);
-
-         /* allocate 1 float indexTemp */
-         indexTemp = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
-         _slang_alloc_temp(emitInfo->vt, indexTemp);
-
-         inst = emit_instruction(emitInfo,
-                                 OPCODE_ADD,
-                                 indexTemp,      /* dest */
-                                 indexStore,     /* the index */
-                                 &indirectArray, /* indirect array base */
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-
-         indexStore = indexTemp;
-      }
-
-      /* update the array element storage info */
-      n->Store->IsIndirect = GL_TRUE;
-      n->Store->IndirectFile = indexStore->File;
-      n->Store->IndirectIndex = indexStore->Index;
-      n->Store->IndirectSwizzle = indexStore->Swizzle;
-   }
-
-   n->Store->Size = elemSize;
-   n->Store->Swizzle = _slang_var_swizzle(elemSize, 0);
-
-   return NULL; /* no instruction */
-}
-
-
-/**
- * Resolve storage for accessing a structure field.
- */
-static struct prog_instruction *
-emit_struct_field(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   slang_ir_storage *root = n->Store;
-   GLint fieldOffset, fieldSize;
-
-   assert(n->Opcode == IR_FIELD);
-
-   assert(!root->Parent);
-   while (root->Parent)
-      root = root->Parent;
-
-   /* If this is the field of a state var, allocate constant/uniform
-    * storage for it now if we haven't already.
-    * Note that we allocate storage (uniform/constant slots) for state
-    * variables here rather than at declaration time so we only allocate
-    * space for the ones that we actually use!
-    */
-   if (root->File == PROGRAM_STATE_VAR) {
-      GLboolean direct;
-      GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
-      if (index < 0) {
-         slang_info_log_error(emitInfo->log, "Error parsing state variable");
-         return NULL;
-      }
-      if (direct) {
-         root->Index = index;
-         return NULL; /* all done */
-      }
-   }
-
-   /* do codegen for struct */
-   emit(emitInfo, n->Children[0]);
-   assert(n->Children[0]->Store->Index >= 0);
-
-
-   fieldOffset = n->Store->Index;
-   fieldSize = n->Store->Size;
-
-   _slang_copy_ir_storage(n->Store, n->Children[0]->Store);
-
-   n->Store->Index = n->Children[0]->Store->Index + fieldOffset / 4;
-   n->Store->Size = fieldSize;
-
-   switch (fieldSize) {
-   case 1:
-      {
-         GLint swz = fieldOffset % 4;
-         n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz);
-      }
-      break;
-   case 2:
-      n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
-                                        SWIZZLE_NIL, SWIZZLE_NIL);
-      break;
-   case 3:
-      n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
-                                        SWIZZLE_Z, SWIZZLE_NIL);
-      break;
-   default:
-      n->Store->Swizzle = SWIZZLE_XYZW;
-   }
-
-   assert(n->Store->Index >= 0);
-
-   return NULL; /* no instruction */
-}
-
-
-/**
- * Emit code for a variable declaration.
- * This usually doesn't result in any code generation, but just
- * memory allocation.
- */
-static struct prog_instruction *
-emit_var_decl(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   assert(n->Store);
-   assert(n->Store->File != PROGRAM_UNDEFINED);
-   assert(n->Store->Size > 0);
-   /*assert(n->Store->Index < 0);*/
-
-   if (!n->Var || n->Var->isTemp) {
-      /* a nameless/temporary variable, will be freed after first use */
-      /*NEW*/
-      if (n->Store->Index < 0 && !_slang_alloc_temp(emitInfo->vt, n->Store)) {
-         slang_info_log_error(emitInfo->log,
-                              "Ran out of registers, too many temporaries");
-         return NULL;
-      }
-   }
-   else {
-      /* a regular variable */
-      _slang_add_variable(emitInfo->vt, n->Var);
-      if (!_slang_alloc_var(emitInfo->vt, n->Store)) {
-         slang_info_log_error(emitInfo->log,
-                              "Ran out of registers, too many variables");
-         return NULL;
-      }
-      /*
-        printf("IR_VAR_DECL %s %d store %p\n",
-        (char*) n->Var->a_name, n->Store->Index, (void*) n->Store);
-      */
-      assert(n->Var->store == n->Store);
-   }
-   if (emitInfo->EmitComments) {
-      /* emit NOP with comment describing the variable's storage location */
-      char s[1000];
-      _mesa_snprintf(s, sizeof(s), "TEMP[%d]%s = variable %s (size %d)",
-                     n->Store->Index,
-                     _mesa_swizzle_string(n->Store->Swizzle, 0, GL_FALSE), 
-                     (n->Var ? (char *) n->Var->a_name : "anonymous"),
-                     n->Store->Size);
-      emit_comment(emitInfo, s);
-   }
-   return NULL;
-}
-
-
-/**
- * Emit code for a reference to a variable.
- * Actually, no code is generated but we may do some memory allocation.
- * In particular, state vars (uniforms) are allocated on an as-needed basis.
- */
-static struct prog_instruction *
-emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   assert(n->Store);
-   assert(n->Store->File != PROGRAM_UNDEFINED);
-
-   if (n->Store->File == PROGRAM_STATE_VAR && n->Store->Index < 0) {
-      GLboolean direct;
-      GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
-      if (index < 0) {
-         /* error */
-         char s[100];
-         /* XXX isn't this really an out of memory/resources error? */
-         _mesa_snprintf(s, sizeof(s), "Undefined variable '%s'",
-                 (char *) n->Var->a_name);
-         slang_info_log_error(emitInfo->log, s);
-         return NULL;
-      }
-
-      n->Store->Index = index;
-   }
-   else if (n->Store->File == PROGRAM_UNIFORM ||
-            n->Store->File == PROGRAM_SAMPLER) {
-      /* mark var as used */
-      _mesa_use_uniform(emitInfo->prog->Parameters, (char *) n->Var->a_name);
-   }
-   else if (n->Store->File == PROGRAM_INPUT) {
-      assert(n->Store->Index >= 0);
-      emitInfo->prog->InputsRead |= (1 << n->Store->Index);
-   }
-
-   if (n->Store->Index < 0) {
-      /* probably ran out of registers */
-      return NULL;
-   }
-   assert(n->Store->Size > 0);
-
-   return NULL;
-}
-
-
-static struct prog_instruction *
-emit(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-   if (!n)
-      return NULL;
-
-   if (emitInfo->log->error_flag) {
-      return NULL;
-   }
-
-   if (n->Comment) {
-      inst = new_instruction(emitInfo, OPCODE_NOP);
-      if (inst) {
-         inst->Comment = _mesa_strdup(n->Comment);
-      }
-      inst = NULL;
-   }
-
-   switch (n->Opcode) {
-   case IR_SEQ:
-      /* sequence of two sub-trees */
-      assert(n->Children[0]);
-      assert(n->Children[1]);
-      emit(emitInfo, n->Children[0]);
-      if (emitInfo->log->error_flag)
-         return NULL;
-      inst = emit(emitInfo, n->Children[1]);
-#if 0
-      assert(!n->Store);
-#endif
-      n->Store = n->Children[1]->Store;
-      return inst;
-
-   case IR_SCOPE:
-      /* new variable scope */
-      _slang_push_var_table(emitInfo->vt);
-      inst = emit(emitInfo, n->Children[0]);
-      _slang_pop_var_table(emitInfo->vt);
-      return inst;
-
-   case IR_VAR_DECL:
-      /* Variable declaration - allocate a register for it */
-      inst = emit_var_decl(emitInfo, n);
-      return inst;
-
-   case IR_VAR:
-      /* Reference to a variable
-       * Storage should have already been resolved/allocated.
-       */
-      return emit_var_ref(emitInfo, n);
-
-   case IR_ELEMENT:
-      return emit_array_element(emitInfo, n);
-   case IR_FIELD:
-      return emit_struct_field(emitInfo, n);
-   case IR_SWIZZLE:
-      return emit_swizzle(emitInfo, n);
-
-   /* Simple arithmetic */
-   /* unary */
-   case IR_MOVE:
-   case IR_RSQ:
-   case IR_RCP:
-   case IR_FLOOR:
-   case IR_FRAC:
-   case IR_F_TO_I:
-   case IR_I_TO_F:
-   case IR_ABS:
-   case IR_SIN:
-   case IR_COS:
-   case IR_DDX:
-   case IR_DDY:
-   case IR_EXP:
-   case IR_EXP2:
-   case IR_LOG2:
-   case IR_NOISE1:
-   case IR_NOISE2:
-   case IR_NOISE3:
-   case IR_NOISE4:
-   case IR_NRM4:
-   case IR_NRM3:
-   /* binary */
-   case IR_ADD:
-   case IR_SUB:
-   case IR_MUL:
-   case IR_DOT4:
-   case IR_DOT3:
-   case IR_DOT2:
-   case IR_CROSS:
-   case IR_MIN:
-   case IR_MAX:
-   case IR_SEQUAL:
-   case IR_SNEQUAL:
-   case IR_SGE:
-   case IR_SGT:
-   case IR_SLE:
-   case IR_SLT:
-   case IR_POW:
-   /* trinary operators */
-   case IR_LRP:
-   case IR_CMP:
-      return emit_arith(emitInfo, n);
-
-   case IR_EQUAL:
-   case IR_NOTEQUAL:
-      return emit_compare(emitInfo, n);
-
-   case IR_CLAMP:
-      return emit_clamp(emitInfo, n);
-   case IR_TEX:
-   case IR_TEXB:
-   case IR_TEXP:
-   case IR_TEX_SH:
-   case IR_TEXB_SH:
-   case IR_TEXP_SH:
-      return emit_tex(emitInfo, n);
-   case IR_NEG:
-      return emit_negation(emitInfo, n);
-   case IR_FLOAT:
-      /* find storage location for this float constant */
-      n->Store->Index = _mesa_add_unnamed_constant(emitInfo->prog->Parameters,
-                                                   n->Value,
-                                                   n->Store->Size,
-                                                   &n->Store->Swizzle);
-      if (n->Store->Index < 0) {
-         slang_info_log_error(emitInfo->log, "Ran out of space for constants");
-         return NULL;
-      }
-      return NULL;
-
-   case IR_COPY:
-      return emit_copy(emitInfo, n);
-
-   case IR_COND:
-      return emit_cond(emitInfo, n);
-
-   case IR_NOT:
-      return emit_not(emitInfo, n);
-
-   case IR_LABEL:
-      return emit_label(emitInfo, n);
-
-   case IR_KILL:
-      return emit_kill(emitInfo);
-
-   case IR_CALL:
-      /* new variable scope for subroutines/function calls */
-      _slang_push_var_table(emitInfo->vt);
-      inst = emit_fcall(emitInfo, n);
-      _slang_pop_var_table(emitInfo->vt);
-      return inst;
-
-   case IR_IF:
-      return emit_if(emitInfo, n);
-
-   case IR_LOOP:
-      return emit_loop(emitInfo, n);
-   case IR_BREAK_IF_TRUE:
-   case IR_CONT_IF_TRUE:
-      return emit_cont_break_if_true(emitInfo, n);
-   case IR_BREAK:
-      /* fall-through */
-   case IR_CONT:
-      return emit_cont_break(emitInfo, n);
-
-   case IR_BEGIN_SUB:
-      return new_instruction(emitInfo, OPCODE_BGNSUB);
-   case IR_END_SUB:
-      return new_instruction(emitInfo, OPCODE_ENDSUB);
-   case IR_RETURN:
-      return emit_return(emitInfo, n);
-
-   case IR_NOP:
-      return NULL;
-
-   default:
-      _mesa_problem(NULL, "Unexpected IR opcode in emit()\n");
-   }
-   return NULL;
-}
-
-
-/**
- * After code generation, any subroutines will be in separate program
- * objects.  This function appends all the subroutines onto the main
- * program and resolves the linking of all the branch/call instructions.
- * XXX this logic should really be part of the linking process...
- */
-static void
-_slang_resolve_subroutines(slang_emit_info *emitInfo)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_program *mainP = emitInfo->prog;
-   GLuint *subroutineLoc, i, total;
-
-   subroutineLoc
-      = (GLuint *) malloc(emitInfo->NumSubroutines * sizeof(GLuint));
-
-   /* total number of instructions */
-   total = mainP->NumInstructions;
-   for (i = 0; i < emitInfo->NumSubroutines; i++) {
-      subroutineLoc[i] = total;
-      total += emitInfo->Subroutines[i]->NumInstructions;
-   }
-
-   /* adjust BranchTargets within the functions */
-   for (i = 0; i < emitInfo->NumSubroutines; i++) {
-      struct gl_program *sub = emitInfo->Subroutines[i];
-      GLuint j;
-      for (j = 0; j < sub->NumInstructions; j++) {
-         struct prog_instruction *inst = sub->Instructions + j;
-         if (inst->Opcode != OPCODE_CAL && inst->BranchTarget >= 0) {
-            inst->BranchTarget += subroutineLoc[i];
-         }
-      }
-   }
-
-   /* append subroutines' instructions after main's instructions */
-   mainP->Instructions = _mesa_realloc_instructions(mainP->Instructions,
-                                                    mainP->NumInstructions,
-                                                    total);
-   mainP->NumInstructions = total;
-   for (i = 0; i < emitInfo->NumSubroutines; i++) {
-      struct gl_program *sub = emitInfo->Subroutines[i];
-      _mesa_copy_instructions(mainP->Instructions + subroutineLoc[i],
-                              sub->Instructions,
-                              sub->NumInstructions);
-      /* delete subroutine code */
-      sub->Parameters = NULL; /* prevent double-free */
-      _mesa_reference_program(ctx, &emitInfo->Subroutines[i], NULL);
-   }
-
-   /* free subroutine list */
-   if (emitInfo->Subroutines) {
-      free(emitInfo->Subroutines);
-      emitInfo->Subroutines = NULL;
-   }
-   emitInfo->NumSubroutines = 0;
-
-   /* Examine CAL instructions.
-    * At this point, the BranchTarget field of the CAL instruction is
-    * the number/id of the subroutine to call (an index into the
-    * emitInfo->Subroutines list).
-    * Translate that into an actual instruction location now.
-    */
-   for (i = 0; i < mainP->NumInstructions; i++) {
-      struct prog_instruction *inst = mainP->Instructions + i;
-      if (inst->Opcode == OPCODE_CAL) {
-         const GLuint f = inst->BranchTarget;
-         inst->BranchTarget = subroutineLoc[f];
-      }
-   }
-
-   free(subroutineLoc);
-}
-
-
-
-/**
- * Convert the IR tree into GPU instructions.
- * \param n  root of IR tree
- * \param vt  variable table
- * \param prog  program to put GPU instructions into
- * \param pragmas  controls codegen options
- * \param withEnd  if true, emit END opcode at end
- * \param log  log for emitting errors/warnings/info
- */
-GLboolean
-_slang_emit_code(slang_ir_node *n, slang_var_table *vt,
-                 struct gl_program *prog,
-                 const struct gl_sl_pragmas *pragmas,
-                 GLboolean withEnd,
-                 slang_info_log *log)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLboolean success;
-   slang_emit_info emitInfo;
-   GLuint maxUniforms;
-
-   emitInfo.log = log;
-   emitInfo.vt = vt;
-   emitInfo.prog = prog;
-   emitInfo.Subroutines = NULL;
-   emitInfo.NumSubroutines = 0;
-   emitInfo.MaxInstructions = prog->NumInstructions;
-
-   emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
-   emitInfo.EmitCondCodes = ctx->Shader.EmitCondCodes;
-   emitInfo.EmitComments = ctx->Shader.EmitComments || pragmas->Debug;
-   emitInfo.EmitBeginEndSub = GL_TRUE;
-
-   if (!emitInfo.EmitCondCodes) {
-      emitInfo.EmitHighLevelInstructions = GL_TRUE;
-   }      
-
-   /* Check uniform/constant limits */
-   if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
-      maxUniforms = ctx->Const.FragmentProgram.MaxUniformComponents / 4;
-   }
-   else {
-      assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
-      maxUniforms = ctx->Const.VertexProgram.MaxUniformComponents / 4;
-   }
-   if (prog->Parameters->NumParameters > maxUniforms) {
-      slang_info_log_error(log, "Constant/uniform register limit exceeded "
-                           "(max=%u vec4)", maxUniforms);
-
-      return GL_FALSE;
-   }
-
-   (void) emit(&emitInfo, n);
-
-   /* finish up by adding the END opcode to program */
-   if (withEnd) {
-      struct prog_instruction *inst;
-      inst = new_instruction(&emitInfo, OPCODE_END);
-      if (!inst) {
-         return GL_FALSE;
-      }
-   }
-
-   _slang_resolve_subroutines(&emitInfo);
-
-   success = GL_TRUE;
-
-#if 0
-   printf("*********** End emit code (%u inst):\n", prog->NumInstructions);
-   _mesa_print_program(prog);
-   _mesa_print_program_parameters(ctx,prog);
-#endif
-
-   return success;
-}
diff --git a/src/mesa/shader/slang/slang_emit.h b/src/mesa/shader/slang/slang_emit.h
deleted file mode 100644 (file)
index ab4c202..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.1
- *
- * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_EMIT_H
-#define SLANG_EMIT_H
-
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_ir.h"
-#include "main/mtypes.h"
-
-
-extern GLuint
-_slang_swizzle_swizzle(GLuint swz1, GLuint swz2);
-
-
-extern GLuint
-_slang_var_swizzle(GLint size, GLint comp);
-
-
-extern GLboolean
-_slang_emit_code(slang_ir_node *n, slang_var_table *vartable,
-                 struct gl_program *prog,
-                 const struct gl_sl_pragmas *pragmas,
-                 GLboolean withEnd,
-                 slang_info_log *log);
-
-
-#endif /* SLANG_EMIT_H */
diff --git a/src/mesa/shader/slang/slang_ir.c b/src/mesa/shader/slang/slang_ir.c
deleted file mode 100644 (file)
index c223004..0000000
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
- * Copyright (C) 2009  VMware, Inc.   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "slang_ir.h"
-#include "slang_mem.h"
-#include "shader/prog_instruction.h"
-#include "shader/prog_print.h"
-
-
-static const slang_ir_info IrInfo[] = {
-   /* binary ops */
-   { IR_ADD, "IR_ADD", OPCODE_ADD, 4, 2 },
-   { IR_SUB, "IR_SUB", OPCODE_SUB, 4, 2 },
-   { IR_MUL, "IR_MUL", OPCODE_MUL, 4, 2 },
-   { IR_DIV, "IR_DIV", OPCODE_NOP, 0, 2 }, /* XXX broke */
-   { IR_DOT4, "IR_DOT4", OPCODE_DP4, 1, 2 },
-   { IR_DOT3, "IR_DOT3", OPCODE_DP3, 1, 2 },
-   { IR_DOT2, "IR_DOT2", OPCODE_DP2, 1, 2 },
-   { IR_NRM4, "IR_NRM4", OPCODE_NRM4, 1, 1 },
-   { IR_NRM3, "IR_NRM3", OPCODE_NRM3, 1, 1 },
-   { IR_CROSS, "IR_CROSS", OPCODE_XPD, 3, 2 },
-   { IR_LRP, "IR_LRP", OPCODE_LRP, 4, 3 },
-   { IR_MIN, "IR_MIN", OPCODE_MIN, 4, 2 },
-   { IR_MAX, "IR_MAX", OPCODE_MAX, 4, 2 },
-   { IR_CLAMP, "IR_CLAMP", OPCODE_NOP, 4, 3 }, /* special case: emit_clamp() */
-   { IR_SEQUAL, "IR_SEQUAL", OPCODE_SEQ, 4, 2 },
-   { IR_SNEQUAL, "IR_SNEQUAL", OPCODE_SNE, 4, 2 },
-   { IR_SGE, "IR_SGE", OPCODE_SGE, 4, 2 },
-   { IR_SGT, "IR_SGT", OPCODE_SGT, 4, 2 },
-   { IR_SLE, "IR_SLE", OPCODE_SLE, 4, 2 },
-   { IR_SLT, "IR_SLT", OPCODE_SLT, 4, 2 },
-   { IR_POW, "IR_POW", OPCODE_POW, 1, 2 },
-   { IR_EQUAL, "IR_EQUAL", OPCODE_NOP, 1, 2 },
-   { IR_NOTEQUAL, "IR_NOTEQUAL", OPCODE_NOP, 1, 2 },
-
-   /* unary ops */
-   { IR_MOVE, "IR_MOVE", OPCODE_MOV, 4, 1 },
-   { IR_I_TO_F, "IR_I_TO_F", OPCODE_MOV, 4, 1 },  /* int[4] to float[4] */
-   { IR_F_TO_I, "IR_F_TO_I", OPCODE_TRUNC, 4, 1 },
-   { IR_EXP, "IR_EXP", OPCODE_EXP, 1, 1 },
-   { IR_EXP2, "IR_EXP2", OPCODE_EX2, 1, 1 },
-   { IR_LOG2, "IR_LOG2", OPCODE_LG2, 1, 1 },
-   { IR_RSQ, "IR_RSQ", OPCODE_RSQ, 1, 1 },
-   { IR_RCP, "IR_RCP", OPCODE_RCP, 1, 1 },
-   { IR_FLOOR, "IR_FLOOR", OPCODE_FLR, 4, 1 },
-   { IR_FRAC, "IR_FRAC", OPCODE_FRC, 4, 1 },
-   { IR_ABS, "IR_ABS", OPCODE_ABS, 4, 1 },
-   { IR_NEG, "IR_NEG", OPCODE_NOP, 4, 1 }, /* special case: emit_negation() */
-   { IR_DDX, "IR_DDX", OPCODE_DDX, 4, 1 },
-   { IR_DDY, "IR_DDY", OPCODE_DDY, 4, 1 },
-   { IR_SIN, "IR_SIN", OPCODE_SIN, 1, 1 },
-   { IR_COS, "IR_COS", OPCODE_COS, 1, 1 },
-   { IR_NOISE1, "IR_NOISE1", OPCODE_NOISE1, 1, 1 },
-   { IR_NOISE2, "IR_NOISE2", OPCODE_NOISE2, 1, 1 },
-   { IR_NOISE3, "IR_NOISE3", OPCODE_NOISE3, 1, 1 },
-   { IR_NOISE4, "IR_NOISE4", OPCODE_NOISE4, 1, 1 },
-
-   /* other */
-   { IR_CMP, "IR_CMP", OPCODE_CMP, 4, 3 },  /* compare/select */
-   { IR_SEQ, "IR_SEQ", OPCODE_NOP, 0, 0 },
-   { IR_SCOPE, "IR_SCOPE", OPCODE_NOP, 0, 0 },
-   { IR_LABEL, "IR_LABEL", OPCODE_NOP, 0, 0 },
-   { IR_IF, "IR_IF", OPCODE_NOP, 0, 0 },
-   { IR_KILL, "IR_KILL", OPCODE_NOP, 0, 0 },
-   { IR_COND, "IR_COND", OPCODE_NOP, 0, 0 },
-   { IR_CALL, "IR_CALL", OPCODE_NOP, 0, 0 },
-   { IR_COPY, "IR_COPY", OPCODE_NOP, 0, 1 },
-   { IR_NOT, "IR_NOT", OPCODE_NOP, 1, 1 },
-   { IR_VAR, "IR_VAR", OPCODE_NOP, 0, 0 },
-   { IR_VAR_DECL, "IR_VAR_DECL", OPCODE_NOP, 0, 0 },
-   { IR_TEX, "IR_TEX", OPCODE_TEX, 4, 1 },
-   { IR_TEXB, "IR_TEXB", OPCODE_TXB, 4, 1 },
-   { IR_TEXP, "IR_TEXP", OPCODE_TXP, 4, 1 },
-   { IR_TEX_SH, "IR_TEX_SH", OPCODE_TEX, 4, 1 },
-   { IR_TEXB_SH, "IR_TEXB_SH", OPCODE_TXB, 4, 1 },
-   { IR_TEXP_SH, "IR_TEXP_SH", OPCODE_TXP, 4, 1 },
-   { IR_FLOAT, "IR_FLOAT", OPCODE_NOP, 0, 0 }, /* float literal */
-   { IR_FIELD, "IR_FIELD", OPCODE_NOP, 0, 0 },
-   { IR_ELEMENT, "IR_ELEMENT", OPCODE_NOP, 0, 0 },
-   { IR_SWIZZLE, "IR_SWIZZLE", OPCODE_NOP, 0, 0 },
-   { IR_NOP, "IR_NOP", OPCODE_NOP, 0, 0 },
-   { 0, NULL, 0, 0, 0 }
-};
-
-
-const slang_ir_info *
-_slang_ir_info(slang_ir_opcode opcode)
-{
-   GLuint i;
-   for (i = 0; IrInfo[i].IrName; i++) {
-      if (IrInfo[i].IrOpcode == opcode) {
-        return IrInfo + i;
-      }
-   }
-   return NULL;
-}
-
-
-void
-_slang_init_ir_storage(slang_ir_storage *st,
-                       gl_register_file file, GLint index, GLint size,
-                       GLuint swizzle)
-{
-   st->File = file;
-   st->Index = index;
-   st->Size = size;
-   st->Swizzle = swizzle;
-   st->Parent = NULL;
-   st->IsIndirect = GL_FALSE;
-}
-
-
-/**
- * Return a new slang_ir_storage object.
- */
-slang_ir_storage *
-_slang_new_ir_storage(gl_register_file file, GLint index, GLint size)
-{
-   slang_ir_storage *st;
-   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
-   if (st) {
-      st->File = file;
-      st->Index = index;
-      st->Size = size;
-      st->Swizzle = SWIZZLE_NOOP;
-      st->Parent = NULL;
-      st->IsIndirect = GL_FALSE;
-   }
-   return st;
-}
-
-
-/**
- * Return a new slang_ir_storage object.
- */
-slang_ir_storage *
-_slang_new_ir_storage_swz(gl_register_file file, GLint index, GLint size,
-                          GLuint swizzle)
-{
-   slang_ir_storage *st;
-   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
-   if (st) {
-      st->File = file;
-      st->Index = index;
-      st->Size = size;
-      st->Swizzle = swizzle;
-      st->Parent = NULL;
-      st->IsIndirect = GL_FALSE;
-   }
-   return st;
-}
-
-
-/**
- * Return a new slang_ir_storage object.
- */
-slang_ir_storage *
-_slang_new_ir_storage_relative(GLint index, GLint size,
-                               slang_ir_storage *parent)
-{
-   slang_ir_storage *st;
-   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
-   if (st) {
-      st->File = PROGRAM_UNDEFINED;
-      st->Index = index;
-      st->Size = size;
-      st->Swizzle = SWIZZLE_NOOP;
-      st->Parent = parent;
-      st->IsIndirect = GL_FALSE;
-   }
-   return st;
-}
-
-
-slang_ir_storage *
-_slang_new_ir_storage_indirect(gl_register_file file,
-                               GLint index,
-                               GLint size,
-                               gl_register_file indirectFile,
-                               GLint indirectIndex,
-                               GLuint indirectSwizzle)
-{
-   slang_ir_storage *st;
-   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
-   if (st) {
-      st->File = file;
-      st->Index = index;
-      st->Size = size;
-      st->Swizzle = SWIZZLE_NOOP;
-      st->IsIndirect = GL_TRUE;
-      st->IndirectFile = indirectFile;
-      st->IndirectIndex = indirectIndex;
-      st->IndirectSwizzle = indirectSwizzle;
-   }
-   return st;
-}
-
-
-/**
- * Allocate IR storage for a texture sampler.
- * \param sampNum  the sampler number/index
- * \param texTarget  one of TEXTURE_x_INDEX values
- * \param size  number of samplers (in case of sampler array)
- */
-slang_ir_storage *
-_slang_new_ir_storage_sampler(GLint sampNum, GLuint texTarget, GLint size)
-{
-   slang_ir_storage *st;
-   assert(texTarget < NUM_TEXTURE_TARGETS);
-   st = _slang_new_ir_storage(PROGRAM_SAMPLER, sampNum, size);
-   if (st) {
-      st->TexTarget = texTarget;
-   }
-   return st;
-}
-
-
-
-/* XXX temporary function */
-void
-_slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src)
-{
-   *dst = *src;
-   dst->Parent = NULL;
-}
-
-
-
-static const char *
-_slang_ir_name(slang_ir_opcode opcode)
-{
-   return _slang_ir_info(opcode)->IrName;
-}
-
-
-
-#if 0 /* no longer needed with mempool */
-/**
- * Since many IR nodes might point to the same IR storage info, we need
- * to be careful when deleting things.
- * Before deleting an IR tree, traverse it and do refcounting on the
- * IR storage nodes.  Use the refcount info during delete to free things
- * properly.
- */
-static void
-_slang_refcount_storage(slang_ir_node *n)
-{
-   GLuint i;
-   if (!n)
-      return;
-   if (n->Store)
-      n->Store->RefCount++;
-   for (i = 0; i < 3; i++)
-      _slang_refcount_storage(n->Children[i]);
-}
-#endif
-
-
-static void
-_slang_free_ir(slang_ir_node *n)
-{
-   GLuint i;
-   if (!n)
-      return;
-
-#if 0
-   if (n->Store) {
-      n->Store->RefCount--;
-      if (n->Store->RefCount == 0) {
-         _slang_free(n->Store);
-         n->Store = NULL;
-      }
-   }
-#endif
-
-   for (i = 0; i < 3; i++)
-      _slang_free_ir(n->Children[i]);
-   /* Do not free n->List since it's a child elsewhere */
-   _slang_free(n);
-}
-
-
-/**
- * Recursively free an IR tree.
- */
-void
-_slang_free_ir_tree(slang_ir_node *n)
-{
-#if 0
-   _slang_refcount_storage(n);
-#endif
-   _slang_free_ir(n);
-}
-
-
-static const char *
-storage_string(const slang_ir_storage *st)
-{
-   static const char *files[] = {
-      "TEMP",
-      "LOCAL_PARAM",
-      "ENV_PARAM",
-      "STATE",
-      "INPUT",
-      "OUTPUT",
-      "NAMED_PARAM",
-      "CONSTANT",
-      "UNIFORM",
-      "VARYING",
-      "WRITE_ONLY",
-      "ADDRESS",
-      "SAMPLER",
-      "UNDEFINED"
-   };
-   static char s[100];
-   assert(Elements(files) == PROGRAM_FILE_MAX);
-#if 0
-   if (st->Size == 1)
-      _mesa_snprintf(s, "%s[%d]", files[st->File], st->Index);
-   else
-      _mesa_snprintf(s, "%s[%d..%d]", files[st->File], st->Index,
-                     st->Index + st->Size - 1);
-#endif
-   assert(st->File < (GLint) (sizeof(files) / sizeof(files[0])));
-   _mesa_snprintf(s, sizeof(s), "%s[%d]", files[st->File], st->Index);
-   return s;
-}
-
-
-static void
-spaces(int n)
-{
-   while (n-- > 0) {
-      printf(" ");
-   }
-}
-
-
-void
-_slang_print_ir_tree(const slang_ir_node *n, int indent)
-{
-#define IND 0
-
-   if (!n)
-      return;
-#if !IND
-   if (n->Opcode != IR_SEQ)
-#else
-      printf("%3d:", indent);
-#endif
-      spaces(indent);
-
-   switch (n->Opcode) {
-   case IR_SEQ:
-#if IND
-      printf("SEQ  at %p\n", (void*) n);
-#endif
-      assert(n->Children[0]);
-      assert(n->Children[1]);
-      _slang_print_ir_tree(n->Children[0], indent + IND);
-      _slang_print_ir_tree(n->Children[1], indent + IND);
-      break;
-   case IR_SCOPE:
-      printf("NEW SCOPE\n");
-      assert(!n->Children[1]);
-      _slang_print_ir_tree(n->Children[0], indent + 3);
-      break;
-   case IR_COPY:
-      printf("COPY\n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      _slang_print_ir_tree(n->Children[1], indent+3);
-      break;
-   case IR_LABEL:
-      printf("LABEL: %s\n", n->Label->Name);
-      break;
-   case IR_COND:
-      printf("COND\n");
-      _slang_print_ir_tree(n->Children[0], indent + 3);
-      break;
-
-   case IR_IF:
-      printf("IF \n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      spaces(indent);
-      printf("THEN\n");
-      _slang_print_ir_tree(n->Children[1], indent+3);
-      if (n->Children[2]) {
-         spaces(indent);
-         printf("ELSE\n");
-         _slang_print_ir_tree(n->Children[2], indent+3);
-      }
-      spaces(indent);
-      printf("ENDIF\n");
-      break;
-
-   case IR_BEGIN_SUB:
-      printf("BEGIN_SUB\n");
-      break;
-   case IR_END_SUB:
-      printf("END_SUB\n");
-      break;
-   case IR_RETURN:
-      printf("RETURN\n");
-      break;
-   case IR_CALL:
-      printf("CALL %s\n", n->Label->Name);
-      break;
-
-   case IR_LOOP:
-      printf("LOOP\n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      if (n->Children[1]) {
-         spaces(indent);
-         printf("TAIL:\n");
-         _slang_print_ir_tree(n->Children[1], indent+3);
-      }
-      spaces(indent);
-      printf("ENDLOOP\n");
-      break;
-   case IR_CONT:
-      printf("CONT\n");
-      break;
-   case IR_BREAK:
-      printf("BREAK\n");
-      break;
-   case IR_BREAK_IF_TRUE:
-      printf("BREAK_IF_TRUE\n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      break;
-   case IR_CONT_IF_TRUE:
-      printf("CONT_IF_TRUE\n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      break;
-
-   case IR_VAR:
-      printf("VAR %s%s at %s  store %p\n",
-             (n->Var ? (char *) n->Var->a_name : "TEMP"),
-             _mesa_swizzle_string(n->Store->Swizzle, 0, 0),
-             storage_string(n->Store), (void*) n->Store);
-      break;
-   case IR_VAR_DECL:
-      printf("VAR_DECL %s (%p) at %s  store %p\n",
-             (n->Var ? (char *) n->Var->a_name : "TEMP"),
-             (void*) n->Var, storage_string(n->Store),
-             (void*) n->Store);
-      break;
-   case IR_FIELD:
-      printf("FIELD %s of\n", n->Field);
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      break;
-   case IR_FLOAT:
-      printf("FLOAT %g %g %g %g\n",
-             n->Value[0], n->Value[1], n->Value[2], n->Value[3]);
-      break;
-   case IR_I_TO_F:
-      printf("INT_TO_FLOAT\n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      break;
-   case IR_F_TO_I:
-      printf("FLOAT_TO_INT\n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      break;
-   case IR_SWIZZLE:
-      printf("SWIZZLE %s of  (store %p) \n",
-             _mesa_swizzle_string(n->Store->Swizzle, 0, 0), (void*) n->Store);
-      _slang_print_ir_tree(n->Children[0], indent + 3);
-      break;
-   default:
-      printf("%s (%p, %p)  (store %p)\n", _slang_ir_name(n->Opcode),
-             (void*) n->Children[0], (void*) n->Children[1], (void*) n->Store);
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      _slang_print_ir_tree(n->Children[1], indent+3);
-   }
-}
diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h
deleted file mode 100644 (file)
index 166b4e8..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
- * Copyright (C) 2009  VMware, Inc.   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_ir.h
- * Mesa GLSL Intermediate Representation tree types and constants.
- * \author Brian Paul
- */
-
-
-#ifndef SLANG_IR_H
-#define SLANG_IR_H
-
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_label.h"
-#include "main/mtypes.h"
-
-
-/**
- * Intermediate Representation opcodes
- */
-typedef enum
-{
-   IR_NOP = 0,
-   IR_SEQ,     /* sequence (eval left, then right) */
-   IR_SCOPE,   /* new variable scope (one child) */
-
-   IR_LABEL,   /* target of a jump or cjump */
-
-   IR_COND,    /* conditional expression/predicate */
-
-   IR_IF,      /* high-level IF/then/else */
-               /* Children[0] = conditional expression */
-               /* Children[1] = if-true part */
-               /* Children[2] = if-else part, or NULL */
-
-   IR_BEGIN_SUB, /* begin subroutine */
-   IR_END_SUB,   /* end subroutine */
-   IR_RETURN,    /* return from subroutine */
-   IR_CALL,      /* call subroutine */
-
-   IR_LOOP,      /* high-level loop-begin / loop-end */
-                 /* Children[0] = loop body */
-                 /* Children[1] = loop tail code, or NULL */
-
-   IR_CONT,      /* continue loop */
-                 /* n->Parent = ptr to parent IR_LOOP Node */
-   IR_BREAK,     /* break loop */
-
-   IR_BREAK_IF_TRUE, /**< Children[0] = the condition expression */
-   IR_CONT_IF_TRUE,
-
-   IR_COPY,       /**< assignment/copy */
-   IR_MOVE,       /**< assembly MOV instruction */
-
-   /* vector ops: */
-   IR_ADD,        /**< assembly ADD instruction */
-   IR_SUB,
-   IR_MUL,
-   IR_DIV,
-   IR_DOT4,
-   IR_DOT3,
-   IR_DOT2,
-   IR_NRM4,
-   IR_NRM3,
-   IR_CROSS,   /* vec3 cross product */
-   IR_LRP,
-   IR_CLAMP,
-   IR_MIN,
-   IR_MAX,
-   IR_CMP,     /* = (op0 < 0) ? op1 : op2 */
-   IR_SEQUAL,  /* Set if args are equal (vector) */
-   IR_SNEQUAL, /* Set if args are not equal (vector) */
-   IR_SGE,     /* Set if greater or equal (vector) */
-   IR_SGT,     /* Set if greater than (vector) */
-   IR_SLE,     /* Set if less or equal (vector) */
-   IR_SLT,     /* Set if less than (vector) */
-   IR_POW,     /* x^y */
-   IR_EXP,     /* e^x */
-   IR_EXP2,    /* 2^x */
-   IR_LOG2,    /* log base 2 */
-   IR_RSQ,     /* 1/sqrt() */
-   IR_RCP,     /* reciprocol */
-   IR_FLOOR,
-   IR_FRAC,
-   IR_ABS,     /* absolute value */
-   IR_NEG,     /* negate */
-   IR_DDX,     /* derivative w.r.t. X */
-   IR_DDY,     /* derivative w.r.t. Y */
-   IR_SIN,     /* sine */
-   IR_COS,     /* cosine */
-   IR_NOISE1,  /* noise(x) */
-   IR_NOISE2,  /* noise(x, y) */
-   IR_NOISE3,  /* noise(x, y, z) */
-   IR_NOISE4,  /* noise(x, y, z, w) */
-
-   IR_EQUAL,   /* boolean equality */
-   IR_NOTEQUAL,/* boolean inequality */
-   IR_NOT,     /* boolean not */
-
-   IR_VAR,     /* variable reference */
-   IR_VAR_DECL,/* var declaration */
-
-   IR_ELEMENT, /* array element */
-   IR_FIELD,   /* struct field */
-   IR_SWIZZLE, /* swizzled storage access */
-
-   IR_TEX,     /* texture lookup */
-   IR_TEXB,    /* texture lookup with LOD bias */
-   IR_TEXP,    /* texture lookup with projection */
-
-   IR_TEX_SH,     /* texture lookup, shadow compare */
-   IR_TEXB_SH,    /* texture lookup with LOD bias, shadow compare */
-   IR_TEXP_SH,    /* texture lookup with projection, shadow compare */
-
-   IR_FLOAT,
-   IR_I_TO_F,  /* int[4] to float[4] conversion */
-   IR_F_TO_I,  /* float[4] to int[4] conversion */
-
-   IR_KILL     /* fragment kill/discard */
-} slang_ir_opcode;
-
-
-/**
- * Describes where data/variables are stored in the various register files.
- *
- * In the simple case, the File, Index and Size fields indicate where
- * a variable is stored.  For example, a vec3 variable may be stored
- * as (File=PROGRAM_TEMPORARY, Index=6, Size=3).  Or, File[Index].
- * Or, a program input like color may be stored as
- * (File=PROGRAM_INPUT,Index=3,Size=4);
- *
- * For single-float values, the Swizzle field indicates which component
- * of the vector contains the float.
- *
- * If IsIndirect is set, the storage is accessed through an indirect
- * register lookup.  The value in question will be located at:
- *   File[Index + IndirectFile[IndirectIndex]]
- *
- * This is primary used for indexing arrays.  For example, consider this
- * GLSL code:
- *   uniform int i;
- *   float a[10];
- *   float x = a[i];
- *
- * here, storage for a[i] would be described by (File=PROGRAM_TEMPORAY,
- * Index=aPos, IndirectFile=PROGRAM_UNIFORM, IndirectIndex=iPos), which
- * would mean TEMP[aPos + UNIFORM[iPos]]
- */
-struct slang_ir_storage_
-{
-   gl_register_file File;  /**< PROGRAM_TEMPORARY, PROGRAM_INPUT, etc */
-   GLint Index;    /**< -1 means unallocated */
-   GLint Size;     /**< number of floats or ints */
-   GLuint Swizzle; /**< Swizzle AND writemask info */
-   GLint RefCount; /**< Used during IR tree delete */
-
-   GLboolean RelAddr; /* we'll remove this eventually */
-
-   GLboolean IsIndirect;
-   gl_register_file IndirectFile;
-   GLint IndirectIndex;
-   GLuint IndirectSwizzle;
-   GLuint TexTarget;  /**< If File==PROGRAM_SAMPLER, one of TEXTURE_x_INDEX */
-
-   /** If Parent is non-null, Index is relative to parent.
-    * The other fields are ignored.
-    */
-   struct slang_ir_storage_ *Parent;
-};
-
-typedef struct slang_ir_storage_ slang_ir_storage;
-
-
-/**
- * Intermediate Representation (IR) tree node
- * Basically a binary tree, but IR_LRP and IR_CLAMP have three children.
- */
-typedef struct slang_ir_node_
-{
-   slang_ir_opcode Opcode;
-   struct slang_ir_node_ *Children[3];
-   slang_ir_storage *Store;  /**< location of result of this operation */
-   GLint InstLocation;  /**< Location of instruction emitted for this node */
-
-   /** special fields depending on Opcode: */
-   const char *Field;  /**< If Opcode == IR_FIELD */
-   GLfloat Value[4];    /**< If Opcode == IR_FLOAT */
-   slang_variable *Var;  /**< If Opcode == IR_VAR or IR_VAR_DECL */
-   struct slang_ir_node_ *List;  /**< For various linked lists */
-   struct slang_ir_node_ *Parent;  /**< Pointer to logical parent (ie. loop) */
-   slang_label *Label;  /**< Used for branches */
-   const char *Comment; /**< If Opcode == IR_COMMENT */
-} slang_ir_node;
-
-
-
-/**
- * Assembly and IR info
- */
-typedef struct
-{
-   slang_ir_opcode IrOpcode;
-   const char *IrName;
-   gl_inst_opcode InstOpcode;
-   GLuint ResultSize, NumParams;
-} slang_ir_info;
-
-
-
-extern const slang_ir_info *
-_slang_ir_info(slang_ir_opcode opcode);
-
-
-extern void
-_slang_init_ir_storage(slang_ir_storage *st,
-                       gl_register_file file, GLint index, GLint size,
-                       GLuint swizzle);
-
-extern slang_ir_storage *
-_slang_new_ir_storage(gl_register_file file, GLint index, GLint size);
-
-
-extern slang_ir_storage *
-_slang_new_ir_storage_swz(gl_register_file file, GLint index, GLint size,
-                          GLuint swizzle);
-
-extern slang_ir_storage *
-_slang_new_ir_storage_relative(GLint index, GLint size,
-                               slang_ir_storage *parent);
-
-
-extern slang_ir_storage *
-_slang_new_ir_storage_indirect(gl_register_file file,
-                               GLint index,
-                               GLint size,
-                               gl_register_file indirectFile,
-                               GLint indirectIndex,
-                               GLuint indirectSwizzle);
-
-extern slang_ir_storage *
-_slang_new_ir_storage_sampler(GLint sampNum, GLuint texTarget, GLint size);
-
-
-extern void
-_slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src);
-
-
-extern void
-_slang_free_ir_tree(slang_ir_node *n);
-
-
-extern void
-_slang_print_ir_tree(const slang_ir_node *n, int indent);
-
-
-#endif /* SLANG_IR_H */
diff --git a/src/mesa/shader/slang/slang_label.c b/src/mesa/shader/slang/slang_label.c
deleted file mode 100644 (file)
index 8e3a8eb..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-
-
-/**
- * Functions for managing instruction labels.
- * Basically, this is used to manage the problem of forward branches where
- * we have a branch instruciton but don't know the target address yet.
- */
-
-
-#include "slang_label.h"
-#include "slang_mem.h"
-
-
-
-slang_label *
-_slang_label_new(const char *name)
-{
-   slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label));
-   if (l) {
-      l->Name = _slang_strdup(name);
-      l->Location = -1;
-   }
-   return l;
-}
-
-/**
- * As above, but suffix the name with a unique number.
- */
-slang_label *
-_slang_label_new_unique(const char *name)
-{
-   static int id = 1;
-   slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label));
-   if (l) {
-      l->Name = (char *) _slang_alloc(strlen(name) + 10);
-      if (!l->Name) {
-         free(l);
-         return NULL;
-      }
-      _mesa_snprintf(l->Name, strlen(name) + 10, "%s_%d", name, id);
-      id++;
-      l->Location = -1;
-   }
-   return l;
-}
-
-void
-_slang_label_delete(slang_label *l)
-{
-   if (l->Name) {
-      _slang_free(l->Name);
-      l->Name = NULL;
-   }
-   if (l->References) {
-      _slang_free(l->References);
-      l->References = NULL;
-   }
-   _slang_free(l);
-}
-
-
-void
-_slang_label_add_reference(slang_label *l, GLuint inst)
-{
-   const GLuint oldSize = l->NumReferences * sizeof(GLuint);
-   assert(l->Location < 0);
-   l->References = _slang_realloc(l->References,
-                                  oldSize, oldSize + sizeof(GLuint));
-   if (l->References) {
-      l->References[l->NumReferences] = inst;
-      l->NumReferences++;
-   }
-}
-
-
-GLint
-_slang_label_get_location(const slang_label *l)
-{
-   return l->Location;
-}
-
-
-void
-_slang_label_set_location(slang_label *l, GLint location,
-                          struct gl_program *prog)
-{
-   GLuint i;
-
-   assert(l->Location < 0);
-   assert(location >= 0);
-
-   l->Location = location;
-
-   /* for the instructions that were waiting to learn the label's location: */
-   for (i = 0; i < l->NumReferences; i++) {
-      const GLuint j = l->References[i];
-      prog->Instructions[j].BranchTarget = location;
-   }
-
-   if (l->References) {
-      _slang_free(l->References);
-      l->References = NULL;
-   }
-}
diff --git a/src/mesa/shader/slang/slang_label.h b/src/mesa/shader/slang/slang_label.h
deleted file mode 100644 (file)
index 87068ae..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef SLANG_LABEL_H
-#define SLANG_LABEL_H 1
-
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "shader/prog_instruction.h"
-
-
-struct slang_label_
-{
-   char *Name;
-   GLint Location;
-   /**
-    * List of instruction references (numbered starting at zero) which need
-    * their BranchTarget field filled in with the location eventually
-    * assigned to the label.
-    */
-   GLuint NumReferences;
-   GLuint *References;   /** Array [NumReferences] */
-};
-
-typedef struct slang_label_ slang_label;
-
-
-extern slang_label *
-_slang_label_new(const char *name);
-
-extern slang_label *
-_slang_label_new_unique(const char *name);
-
-extern void
-_slang_label_delete(slang_label *l);
-
-extern void
-_slang_label_add_reference(slang_label *l, GLuint inst);
-
-extern GLint
-_slang_label_get_location(const slang_label *l);
-
-extern void
-_slang_label_set_location(slang_label *l, GLint location,
-                          struct gl_program *prog);
-
-
-#endif /* SLANG_LABEL_H */
diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c
deleted file mode 100644 (file)
index 56d42ca..0000000
+++ /dev/null
@@ -1,1124 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.3
- *
- * Copyright (C) 2008  Brian Paul   All Rights Reserved.
- * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_link.c
- * GLSL linker
- * \author Brian Paul
- */
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/macros.h"
-#include "main/shaderapi.h"
-#include "main/shaderobj.h"
-#include "main/uniforms.h"
-#include "shader/program.h"
-#include "shader/prog_instruction.h"
-#include "shader/prog_parameter.h"
-#include "shader/prog_print.h"
-#include "shader/prog_statevars.h"
-#include "shader/prog_uniform.h"
-#include "slang_builtin.h"
-#include "slang_link.h"
-
-
-/** cast wrapper */
-static struct gl_vertex_program *
-vertex_program(struct gl_program *prog)
-{
-   assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
-   return (struct gl_vertex_program *) prog;
-}
-
-
-/** cast wrapper */
-static struct gl_fragment_program *
-fragment_program(struct gl_program *prog)
-{
-   assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
-   return (struct gl_fragment_program *) prog;
-}
-
-
-/**
- * Record a linking error.
- */
-static void
-link_error(struct gl_shader_program *shProg, const char *msg)
-{
-   if (shProg->InfoLog) {
-      free(shProg->InfoLog);
-   }
-   shProg->InfoLog = _mesa_strdup(msg);
-   shProg->LinkStatus = GL_FALSE;
-}
-
-
-
-/**
- * Check if the given bit is either set or clear in both bitfields.
- */
-static GLboolean
-bits_agree(GLbitfield flags1, GLbitfield flags2, GLbitfield bit)
-{
-   return (flags1 & bit) == (flags2 & bit);
-}
-
-
-/**
- * Examine the outputs/varyings written by the vertex shader and
- * append the names of those outputs onto the Varyings list.
- * This will only capture the pre-defined/built-in varyings like
- * gl_Position, not user-defined varyings.
- */
-static void
-update_varying_var_list(GLcontext *ctx, struct gl_shader_program *shProg)
-{
-   if (shProg->VertexProgram) {
-      GLbitfield64 written = shProg->VertexProgram->Base.OutputsWritten;
-      GLuint i;
-      for (i = 0; written && i < VERT_RESULT_MAX; i++) {
-         if (written & BITFIELD64_BIT(i)) {
-            const char *name = _slang_vertex_output_name(i);            
-            if (name)
-               _mesa_add_varying(shProg->Varying, name, 1, GL_FLOAT_VEC4, 0x0);
-            written &= ~BITFIELD64_BIT(i);
-         }
-      }
-   }
-}
-
-
-/**
- * Do link error checking related to transform feedback.
- */
-static GLboolean
-link_transform_feedback(GLcontext *ctx, struct gl_shader_program *shProg)
-{
-   GLbitfield varyingMask;
-   GLuint totalComps, maxComps, i;
-
-   if (shProg->TransformFeedback.NumVarying == 0) {
-      /* nothing to do */
-      return GL_TRUE;
-   }
-
-   /* Check that there's a vertex shader */
-   if (shProg->TransformFeedback.NumVarying > 0 &&
-       !shProg->VertexProgram) {
-      link_error(shProg, "Transform feedback without vertex shader");
-      return GL_FALSE;
-   }
-
-   /* Check that all named variables exist, and that none are duplicated.
-    * Also, build a count of the number of varying components to feedback.
-    */
-   totalComps = 0;
-   varyingMask = 0x0;
-   for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
-      const GLchar *name = shProg->TransformFeedback.VaryingNames[i];
-      GLint v = _mesa_lookup_parameter_index(shProg->Varying, -1, name);
-      struct gl_program_parameter *p;
-
-      if (v < 0) {
-         char msg[100];
-         _mesa_snprintf(msg, sizeof(msg),
-                        "vertex shader does not emit %s", name);
-         link_error(shProg, msg);
-         return GL_FALSE;
-      }
-
-      assert(v < MAX_VARYING);
-
-      /* already seen this varying name? */
-      if (varyingMask & (1 << v)) {
-         char msg[100];
-         _mesa_snprintf(msg, sizeof(msg),
-                        "duplicated transform feedback varying name: %s",
-                        name);
-         link_error(shProg, msg);
-         return GL_FALSE;
-      }
-
-      varyingMask |= (1 << v);
-
-      p = &shProg->Varying->Parameters[v];
-      
-      totalComps += _mesa_sizeof_glsl_type(p->DataType);
-   }
-
-   if (shProg->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS)
-      maxComps = ctx->Const.MaxTransformFeedbackInterleavedComponents;
-   else
-      maxComps = ctx->Const.MaxTransformFeedbackSeparateComponents;
-
-   /* check max varying components against the limit */
-   if (totalComps > maxComps) {
-      char msg[100];
-      _mesa_snprintf(msg, sizeof(msg),
-                     "Too many feedback components: %u, max is %u",
-                     totalComps, maxComps);
-      link_error(shProg, msg);
-      return GL_FALSE;
-   }
-
-   return GL_TRUE;
-}
-
-
-/**
- * Linking varying vars involves rearranging varying vars so that the
- * vertex program's output varyings matches the order of the fragment
- * program's input varyings.
- * We'll then rewrite instructions to replace PROGRAM_VARYING with either
- * PROGRAM_INPUT or PROGRAM_OUTPUT depending on whether it's a vertex or
- * fragment shader.
- * This is also where we set program Input/OutputFlags to indicate
- * which inputs are centroid-sampled, invariant, etc.
- */
-static GLboolean
-link_varying_vars(GLcontext *ctx,
-                  struct gl_shader_program *shProg, struct gl_program *prog)
-{
-   GLuint *map, i, firstVarying, newFile;
-   GLbitfield *inOutFlags;
-
-   map = (GLuint *) malloc(prog->Varying->NumParameters * sizeof(GLuint));
-   if (!map)
-      return GL_FALSE;
-
-   /* Varying variables are treated like other vertex program outputs
-    * (and like other fragment program inputs).  The position of the
-    * first varying differs for vertex/fragment programs...
-    * Also, replace File=PROGRAM_VARYING with File=PROGRAM_INPUT/OUTPUT.
-    */
-   if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
-      firstVarying = VERT_RESULT_VAR0;
-      newFile = PROGRAM_OUTPUT;
-      inOutFlags = prog->OutputFlags;
-   }
-   else {
-      assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
-      firstVarying = FRAG_ATTRIB_VAR0;
-      newFile = PROGRAM_INPUT;
-      inOutFlags = prog->InputFlags;
-   }
-
-   for (i = 0; i < prog->Varying->NumParameters; i++) {
-      /* see if this varying is in the linked varying list */
-      const struct gl_program_parameter *var = prog->Varying->Parameters + i;
-      GLint j = _mesa_lookup_parameter_index(shProg->Varying, -1, var->Name);
-      if (j >= 0) {
-         /* varying is already in list, do some error checking */
-         const struct gl_program_parameter *v =
-            &shProg->Varying->Parameters[j];
-         if (var->Size != v->Size) {
-            link_error(shProg, "mismatched varying variable types");
-            free(map);
-            return GL_FALSE;
-         }
-         if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_CENTROID)) {
-            char msg[100];
-            _mesa_snprintf(msg, sizeof(msg),
-                    "centroid modifier mismatch for '%s'", var->Name);
-            link_error(shProg, msg);
-            free(map);
-            return GL_FALSE;
-         }
-         if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_INVARIANT)) {
-            char msg[100];
-            _mesa_snprintf(msg, sizeof(msg),
-                    "invariant modifier mismatch for '%s'", var->Name);
-            link_error(shProg, msg);
-            free(map);
-            return GL_FALSE;
-         }
-      }
-      else {
-         /* not already in linked list */
-         j = _mesa_add_varying(shProg->Varying, var->Name, var->Size,
-                               var->DataType, var->Flags);
-      }
-
-      if (shProg->Varying->NumParameters > ctx->Const.MaxVarying) {
-         link_error(shProg, "Too many varying variables");
-         free(map);
-         return GL_FALSE;
-      }
-
-      /* Map varying[i] to varying[j].
-       * Note: the loop here takes care of arrays or large (sz>4) vars.
-       */
-      {
-         GLint sz = var->Size;
-         while (sz > 0) {
-            inOutFlags[firstVarying + j] = var->Flags;
-            /*printf("Link varying from %d to %d\n", i, j);*/
-            map[i++] = j++;
-            sz -= 4;
-         }
-         i--; /* go back one */
-      }
-   }
-
-
-   /* OK, now scan the program/shader instructions looking for varying vars,
-    * replacing the old index with the new index.
-    */
-   for (i = 0; i < prog->NumInstructions; i++) {
-      struct prog_instruction *inst = prog->Instructions + i;
-      GLuint j;
-
-      if (inst->DstReg.File == PROGRAM_VARYING) {
-         inst->DstReg.File = newFile;
-         inst->DstReg.Index = map[ inst->DstReg.Index ] + firstVarying;
-      }
-
-      for (j = 0; j < 3; j++) {
-         if (inst->SrcReg[j].File == PROGRAM_VARYING) {
-            inst->SrcReg[j].File = newFile;
-            inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ] + firstVarying;
-         }
-      }
-   }
-
-   free(map);
-
-   /* these will get recomputed before linking is completed */
-   prog->InputsRead = 0x0;
-   prog->OutputsWritten = 0x0;
-
-   return GL_TRUE;
-}
-
-
-/**
- * Build the shProg->Uniforms list.
- * This is basically a list/index of all uniforms found in either/both of
- * the vertex and fragment shaders.
- *
- * About uniforms:
- * Each uniform has two indexes, one that points into the vertex
- * program's parameter array and another that points into the fragment
- * program's parameter array.  When the user changes a uniform's value
- * we have to change the value in the vertex and/or fragment program's
- * parameter array.
- *
- * This function will be called twice to set up the two uniform->parameter
- * mappings.
- *
- * If a uniform is only present in the vertex program OR fragment program
- * then the fragment/vertex parameter index, respectively, will be -1.
- */
-static GLboolean
-link_uniform_vars(GLcontext *ctx,
-                  struct gl_shader_program *shProg,
-                  struct gl_program *prog,
-                  GLuint *numSamplers)
-{
-   GLuint samplerMap[200]; /* max number of samplers declared, not used */
-   GLuint i;
-
-   for (i = 0; i < prog->Parameters->NumParameters; i++) {
-      const struct gl_program_parameter *p = prog->Parameters->Parameters + i;
-
-      /*
-       * XXX FIX NEEDED HERE
-       * We should also be adding a uniform if p->Type == PROGRAM_STATE_VAR.
-       * For example, modelview matrix, light pos, etc.
-       * Also, we need to update the state-var name-generator code to
-       * generate GLSL-style names, like "gl_LightSource[0].position".
-       * Furthermore, we'll need to fix the state-var's size/datatype info.
-       */
-
-      if ((p->Type == PROGRAM_UNIFORM || p->Type == PROGRAM_SAMPLER)
-          && p->Used) {
-         /* add this uniform, indexing into the target's Parameters list */
-         struct gl_uniform *uniform =
-            _mesa_append_uniform(shProg->Uniforms, p->Name, prog->Target, i);
-         if (uniform)
-            uniform->Initialized = p->Initialized;
-      }
-
-      /* The samplerMap[] table we build here is used to remap/re-index
-       * sampler references by TEX instructions.
-       */
-      if (p->Type == PROGRAM_SAMPLER && p->Used) {
-         /* Allocate a new sampler index */
-         GLuint oldSampNum = (GLuint) prog->Parameters->ParameterValues[i][0];
-         GLuint newSampNum = *numSamplers;
-         if (newSampNum >= ctx->Const.MaxTextureImageUnits) {
-            char s[100];
-            _mesa_snprintf(s, sizeof(s),
-                           "Too many texture samplers (%u, max is %u)",
-                           newSampNum, ctx->Const.MaxTextureImageUnits);
-            link_error(shProg, s);
-            return GL_FALSE;
-         }
-         /* save old->new mapping in the table */
-         if (oldSampNum < Elements(samplerMap))
-            samplerMap[oldSampNum] = newSampNum;
-         /* update parameter's sampler index */
-         prog->Parameters->ParameterValues[i][0] = (GLfloat) newSampNum;
-         (*numSamplers)++;
-      }
-   }
-
-   /* OK, now scan the program/shader instructions looking for texture
-    * instructions using sampler vars.  Replace old sampler indexes with
-    * new ones.
-    */
-   prog->SamplersUsed = 0x0;
-   for (i = 0; i < prog->NumInstructions; i++) {
-      struct prog_instruction *inst = prog->Instructions + i;
-      if (_mesa_is_tex_instruction(inst->Opcode)) {
-         /* here, inst->TexSrcUnit is really the sampler unit */
-         const GLint oldSampNum = inst->TexSrcUnit;
-
-#if 0
-         printf("====== remap sampler from %d to %d\n",
-                inst->TexSrcUnit, samplerMap[ inst->TexSrcUnit ]);
-#endif
-
-         if (oldSampNum < Elements(samplerMap)) {
-            const GLuint newSampNum = samplerMap[oldSampNum];
-            inst->TexSrcUnit = newSampNum;
-            prog->SamplerTargets[newSampNum] = inst->TexSrcTarget;
-            prog->SamplersUsed |= (1 << newSampNum);
-            if (inst->TexShadow) {
-               prog->ShadowSamplers |= (1 << newSampNum);
-            }
-         }
-      }
-   }
-
-   return GL_TRUE;
-}
-
-
-/**
- * Resolve binding of generic vertex attributes.
- * For example, if the vertex shader declared "attribute vec4 foobar" we'll
- * allocate a generic vertex attribute for "foobar" and plug that value into
- * the vertex program instructions.
- * But if the user called glBindAttributeLocation(), those bindings will
- * have priority.
- */
-static GLboolean
-_slang_resolve_attributes(struct gl_shader_program *shProg,
-                          const struct gl_program *origProg,
-                          struct gl_program *linkedProg)
-{
-   GLint attribMap[MAX_VERTEX_GENERIC_ATTRIBS];
-   GLuint i, j;
-   GLbitfield usedAttributes; /* generics only, not legacy attributes */
-   GLbitfield inputsRead = 0x0;
-
-   assert(origProg != linkedProg);
-   assert(origProg->Target == GL_VERTEX_PROGRAM_ARB);
-   assert(linkedProg->Target == GL_VERTEX_PROGRAM_ARB);
-
-   if (!shProg->Attributes)
-      shProg->Attributes = _mesa_new_parameter_list();
-
-   if (linkedProg->Attributes) {
-      _mesa_free_parameter_list(linkedProg->Attributes);
-   }
-   linkedProg->Attributes = _mesa_new_parameter_list();
-
-
-   /* Build a bitmask indicating which attribute indexes have been
-    * explicitly bound by the user with glBindAttributeLocation().
-    */
-   usedAttributes = 0x0;
-   for (i = 0; i < shProg->Attributes->NumParameters; i++) {
-      GLint attr = shProg->Attributes->Parameters[i].StateIndexes[0];
-      usedAttributes |= (1 << attr);
-   }
-
-   /* If gl_Vertex is used, that actually counts against the limit
-    * on generic vertex attributes.  This avoids the ambiguity of
-    * whether glVertexAttrib4fv(0, v) sets legacy attribute 0 (vert pos)
-    * or generic attribute[0].  If gl_Vertex is used, we want the former.
-    */
-   if (origProg->InputsRead & VERT_BIT_POS) {
-      usedAttributes |= 0x1;
-   }
-
-   /* initialize the generic attribute map entries to -1 */
-   for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
-      attribMap[i] = -1;
-   }
-
-   /*
-    * Scan program for generic attribute references
-    */
-   for (i = 0; i < linkedProg->NumInstructions; i++) {
-      struct prog_instruction *inst = linkedProg->Instructions + i;
-      for (j = 0; j < 3; j++) {
-         if (inst->SrcReg[j].File == PROGRAM_INPUT) {
-            inputsRead |= (1 << inst->SrcReg[j].Index);
-         }
-
-         if (inst->SrcReg[j].File == PROGRAM_INPUT &&
-             inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) {
-            /*
-             * OK, we've found a generic vertex attribute reference.
-             */
-            const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0;
-
-            GLint attr = attribMap[k];
-
-            if (attr < 0) {
-               /* Need to figure out attribute mapping now.
-                */
-               const char *name = origProg->Attributes->Parameters[k].Name;
-               const GLint size = origProg->Attributes->Parameters[k].Size;
-               const GLenum type =origProg->Attributes->Parameters[k].DataType;
-               GLint index;
-
-               /* See if there's a user-defined attribute binding for
-                * this name.
-                */
-               index = _mesa_lookup_parameter_index(shProg->Attributes,
-                                                    -1, name);
-               if (index >= 0) {
-                  /* Found a user-defined binding */
-                  attr = shProg->Attributes->Parameters[index].StateIndexes[0];
-               }
-               else {
-                  /* No user-defined binding, choose our own attribute number.
-                   * Start at 1 since generic attribute 0 always aliases
-                   * glVertex/position.
-                   */
-                  for (attr = 0; attr < MAX_VERTEX_GENERIC_ATTRIBS; attr++) {
-                     if (((1 << attr) & usedAttributes) == 0)
-                        break;
-                  }
-                  if (attr == MAX_VERTEX_GENERIC_ATTRIBS) {
-                     link_error(shProg, "Too many vertex attributes");
-                     return GL_FALSE;
-                  }
-
-                  /* mark this attribute as used */
-                  usedAttributes |= (1 << attr);
-               }
-
-               attribMap[k] = attr;
-
-               /* Save the final name->attrib binding so it can be queried
-                * with glGetAttributeLocation().
-                */
-               _mesa_add_attribute(linkedProg->Attributes, name,
-                                   size, type, attr);
-            }
-
-            assert(attr >= 0);
-
-            /* update the instruction's src reg */
-            inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + attr;
-         }
-      }
-   }
-
-   /* Handle pre-defined attributes here (gl_Vertex, gl_Normal, etc).
-    * When the user queries the active attributes we need to include both
-    * the user-defined attributes and the built-in ones.
-    */
-   for (i = VERT_ATTRIB_POS; i < VERT_ATTRIB_GENERIC0; i++) {
-      if (inputsRead & (1 << i)) {
-         _mesa_add_attribute(linkedProg->Attributes,
-                             _slang_vert_attrib_name(i),
-                             4, /* size in floats */
-                             _slang_vert_attrib_type(i),
-                             -1 /* attrib/input */);
-      }
-   }
-
-   return GL_TRUE;
-}
-
-
-/**
- * Scan program instructions to update the program's NumTemporaries field.
- * Note: this implemenation relies on the code generator allocating
- * temps in increasing order (0, 1, 2, ... ).
- */
-static void
-_slang_count_temporaries(struct gl_program *prog)
-{
-   GLuint i, j;
-   GLint maxIndex = -1;
-
-   for (i = 0; i < prog->NumInstructions; i++) {
-      const struct prog_instruction *inst = prog->Instructions + i;
-      const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
-      for (j = 0; j < numSrc; j++) {
-         if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
-            if (maxIndex < inst->SrcReg[j].Index)
-               maxIndex = inst->SrcReg[j].Index;
-         }
-         if (inst->DstReg.File == PROGRAM_TEMPORARY) {
-            if (maxIndex < (GLint) inst->DstReg.Index)
-               maxIndex = inst->DstReg.Index;
-         }
-      }
-   }
-
-   prog->NumTemporaries = (GLuint) (maxIndex + 1);
-}
-
-
-/**
- * If an input attribute is indexed with relative addressing we have
- * to compute a gl_program::InputsRead bitmask which reflects the fact
- * that any input may be referenced by array element.  Ex: gl_TexCoord[i].
- * This function computes the bitmask of potentially read inputs.
- */
-static GLbitfield
-get_inputs_read_mask(GLenum target, GLuint index, GLboolean relAddr)
-{
-   GLbitfield mask;
-
-   mask = 1 << index;
-
-   if (relAddr) {
-      if (target == GL_VERTEX_PROGRAM_ARB) {
-         switch (index) {
-         case VERT_ATTRIB_TEX0:
-            mask = ((1U << (VERT_ATTRIB_TEX7 + 1)) - 1)
-                 - ((1U << VERT_ATTRIB_TEX0) - 1);
-            break;
-         case VERT_ATTRIB_GENERIC0:
-            /* different code to avoid uint overflow */
-            mask = ~0x0U - ((1U << VERT_ATTRIB_GENERIC0) - 1);
-            break;
-         default:
-            ; /* a non-array input attribute */
-         }
-      }
-      else if (target == GL_FRAGMENT_PROGRAM_ARB) {
-         switch (index) {
-         case FRAG_ATTRIB_TEX0:
-            mask = ((1U << (FRAG_ATTRIB_TEX7 + 1)) - 1)
-                 - ((1U << FRAG_ATTRIB_TEX0) - 1);
-            break;
-         case FRAG_ATTRIB_VAR0:
-            mask = ((1U << (FRAG_ATTRIB_VAR0 + MAX_VARYING)) - 1)
-                 - ((1U << FRAG_ATTRIB_VAR0) - 1);
-            break;
-         default:
-            ; /* a non-array input attribute */
-         }
-      }
-      else {
-         assert(0 && "bad program target");
-      }
-   }
-   else {
-   }
-
-   return mask;
-}
-
-
-/**
- * If an output attribute is indexed with relative addressing we have
- * to compute a gl_program::OutputsWritten bitmask which reflects the fact
- * that any output may be referenced by array element.  Ex: gl_TexCoord[i].
- * This function computes the bitmask of potentially written outputs.
- */
-static GLbitfield64
-get_outputs_written_mask(GLenum target, GLuint index, GLboolean relAddr)
-{
-   GLbitfield64 mask;
-
-   mask = BITFIELD64_BIT(index);
-
-   if (relAddr) {
-      if (target == GL_VERTEX_PROGRAM_ARB) {
-         switch (index) {
-         case VERT_RESULT_TEX0:
-            mask = BITFIELD64_RANGE(VERT_RESULT_TEX0,
-                                    (VERT_RESULT_TEX0
-                                     + MAX_TEXTURE_COORD_UNITS - 1));
-            break;
-         case VERT_RESULT_VAR0:
-            mask = BITFIELD64_RANGE(VERT_RESULT_VAR0,
-                                    (VERT_RESULT_VAR0 + MAX_VARYING - 1));
-            break;
-         default:
-            ; /* a non-array output attribute */
-         }
-      }
-      else if (target == GL_FRAGMENT_PROGRAM_ARB) {
-         switch (index) {
-         case FRAG_RESULT_DATA0:
-            mask = BITFIELD64_RANGE(FRAG_RESULT_DATA0,
-                                    (FRAG_RESULT_DATA0
-                                     + MAX_DRAW_BUFFERS - 1));
-            break;
-         default:
-            ; /* a non-array output attribute */
-         }
-      }
-      else {
-         assert(0 && "bad program target");
-      }
-   }
-
-   return mask;
-}
-
-
-/**
- * Scan program instructions to update the program's InputsRead and
- * OutputsWritten fields.
- */
-static void
-_slang_update_inputs_outputs(struct gl_program *prog)
-{
-   GLuint i, j;
-   GLuint maxAddrReg = 0;
-
-   prog->InputsRead = 0x0;
-   prog->OutputsWritten = 0x0;
-
-   for (i = 0; i < prog->NumInstructions; i++) {
-      const struct prog_instruction *inst = prog->Instructions + i;
-      const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
-      for (j = 0; j < numSrc; j++) {
-         if (inst->SrcReg[j].File == PROGRAM_INPUT) {
-            prog->InputsRead |= get_inputs_read_mask(prog->Target,
-                                                     inst->SrcReg[j].Index,
-                                                     inst->SrcReg[j].RelAddr);
-         }
-         else if (inst->SrcReg[j].File == PROGRAM_ADDRESS) {
-            maxAddrReg = MAX2(maxAddrReg, (GLuint) (inst->SrcReg[j].Index + 1));
-         }
-      }
-
-      if (inst->DstReg.File == PROGRAM_OUTPUT) {
-         prog->OutputsWritten |= get_outputs_written_mask(prog->Target,
-                                                          inst->DstReg.Index,
-                                                          inst->DstReg.RelAddr);
-      }
-      else if (inst->DstReg.File == PROGRAM_ADDRESS) {
-         maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1);
-      }
-   }
-   prog->NumAddressRegs = maxAddrReg;
-}
-
-
-
-/**
- * Remove extra #version directives from the concatenated source string.
- * Disable the extra ones by converting first two chars to //, a comment.
- * This is a bit of hack to work around a preprocessor bug that only
- * allows one #version directive per source.
- */
-static void
-remove_extra_version_directives(GLchar *source)
-{
-   GLuint verCount = 0;
-   while (1) {
-      char *ver = strstr(source, "#version");
-      if (ver) {
-         verCount++;
-         if (verCount > 1) {
-            ver[0] = '/';
-            ver[1] = '/';
-         }
-         source += 8;
-      }
-      else {
-         break;
-      }
-   }
-}
-
-
-
-/**
- * Return a new shader whose source code is the concatenation of
- * all the shader sources of the given type.
- */
-static struct gl_shader *
-concat_shaders(struct gl_shader_program *shProg, GLenum shaderType)
-{
-   struct gl_shader *newShader;
-   const struct gl_shader *firstShader = NULL;
-   GLuint *shaderLengths;
-   GLchar *source;
-   GLuint totalLen = 0, len = 0;
-   GLuint i;
-
-   shaderLengths = (GLuint *)malloc(shProg->NumShaders * sizeof(GLuint));
-   if (!shaderLengths) {
-      return NULL;
-   }
-
-   /* compute total size of new shader source code */
-   for (i = 0; i < shProg->NumShaders; i++) {
-      const struct gl_shader *shader = shProg->Shaders[i];
-      if (shader->Type == shaderType) {
-         shaderLengths[i] = strlen(shader->Source);
-         totalLen += shaderLengths[i];
-         if (!firstShader)
-            firstShader = shader;
-      }
-   }
-
-   if (totalLen == 0) {
-      free(shaderLengths);
-      return NULL;
-   }
-
-   source = (GLchar *) malloc(totalLen + 1);
-   if (!source) {
-      free(shaderLengths);
-      return NULL;
-   }
-
-   /* concatenate shaders */
-   for (i = 0; i < shProg->NumShaders; i++) {
-      const struct gl_shader *shader = shProg->Shaders[i];
-      if (shader->Type == shaderType) {
-         memcpy(source + len, shader->Source, shaderLengths[i]);
-         len += shaderLengths[i];
-      }
-   }
-   source[len] = '\0';
-   /*
-   printf("---NEW CONCATENATED SHADER---:\n%s\n------------\n", source);
-   */
-
-   free(shaderLengths);
-
-   remove_extra_version_directives(source);
-
-   newShader = CALLOC_STRUCT(gl_shader);
-   if (!newShader) {
-      free(source);
-      return NULL;
-   }
-
-   newShader->Type = shaderType;
-   newShader->Source = source;
-   newShader->Pragmas = firstShader->Pragmas;
-
-   return newShader;
-}
-
-
-/**
- * Search the shader program's list of shaders to find the one that
- * defines main().
- * This will involve shader concatenation and recompilation if needed.
- */
-static struct gl_shader *
-get_main_shader(GLcontext *ctx,
-                struct gl_shader_program *shProg, GLenum type)
-{
-   struct gl_shader *shader = NULL;
-   GLuint i;
-
-   /*
-    * Look for a shader that defines main() and has no unresolved references.
-    */
-   for (i = 0; i < shProg->NumShaders; i++) {
-      shader = shProg->Shaders[i];
-      if (shader->Type == type &&
-          shader->Main &&
-          !shader->UnresolvedRefs) {
-         /* All set! */
-         return shader;
-      }
-   }
-
-   /*
-    * There must have been unresolved references during the original
-    * compilation.  Try concatenating all the shaders of the given type
-    * and recompile that.
-    */
-   shader = concat_shaders(shProg, type);
-
-   if (shader) {
-      _slang_compile(ctx, shader);
-
-      /* Finally, check if recompiling failed */
-      if (!shader->CompileStatus ||
-          !shader->Main ||
-          shader->UnresolvedRefs) {
-         link_error(shProg, "Unresolved symbols");
-         ctx->Driver.DeleteShader(ctx, shader);
-         return NULL;
-      }
-   }
-
-   return shader;
-}
-
-
-/**
- * Shader linker.  Currently:
- *
- * 1. The last attached vertex shader and fragment shader are linked.
- * 2. Varying vars in the two shaders are combined so their locations
- *    agree between the vertex and fragment stages.  They're treated as
- *    vertex program output attribs and as fragment program input attribs.
- * 3. The vertex and fragment programs are cloned and modified to update
- *    src/dst register references so they use the new, linked varying
- *    storage locations.
- */
-void
-_slang_link(GLcontext *ctx,
-            GLhandleARB programObj,
-            struct gl_shader_program *shProg)
-{
-   const struct gl_vertex_program *vertProg = NULL;
-   const struct gl_fragment_program *fragProg = NULL;
-   GLboolean vertNotify = GL_TRUE, fragNotify = GL_TRUE;
-   GLuint numSamplers = 0;
-   GLuint i;
-
-   _mesa_clear_shader_program_data(ctx, shProg);
-
-   /* Initialize LinkStatus to "success".  Will be cleared if error. */
-   shProg->LinkStatus = GL_TRUE;
-
-   /* check that all programs compiled successfully */
-   for (i = 0; i < shProg->NumShaders; i++) {
-      if (!shProg->Shaders[i]->CompileStatus) {
-         link_error(shProg, "linking with uncompiled shader\n");
-         return;
-      }
-   }
-
-   shProg->Uniforms = _mesa_new_uniform_list();
-   shProg->Varying = _mesa_new_parameter_list();
-
-   /*
-    * Find the vertex and fragment shaders which define main()
-    */
-   {
-      struct gl_shader *vertShader, *fragShader;
-      vertShader = get_main_shader(ctx, shProg, GL_VERTEX_SHADER);
-      fragShader = get_main_shader(ctx, shProg, GL_FRAGMENT_SHADER);
-      if (vertShader)
-         vertProg = vertex_program(vertShader->Program);
-      if (fragShader)
-         fragProg = fragment_program(fragShader->Program);
-      if (!shProg->LinkStatus)
-         return;
-   }
-
-#if FEATURE_es2_glsl
-   /* must have both a vertex and fragment program for ES2 */
-   if (ctx->API == API_OPENGLES2) {
-      if (!vertProg) {
-        link_error(shProg, "missing vertex shader\n");
-        return;
-      }
-      if (!fragProg) {
-        link_error(shProg, "missing fragment shader\n");
-        return;
-      }
-   }
-#endif
-
-   /*
-    * Make copies of the vertex/fragment programs now since we'll be
-    * changing src/dst registers after merging the uniforms and varying vars.
-    */
-   _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
-   if (vertProg) {
-      struct gl_vertex_program *linked_vprog =
-         _mesa_clone_vertex_program(ctx, vertProg);
-      shProg->VertexProgram = linked_vprog; /* refcount OK */
-      /* vertex program ID not significant; just set Id for debugging purposes */
-      shProg->VertexProgram->Base.Id = shProg->Name;
-      ASSERT(shProg->VertexProgram->Base.RefCount == 1);
-   }
-
-   _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
-   if (fragProg) {
-      struct gl_fragment_program *linked_fprog = 
-         _mesa_clone_fragment_program(ctx, fragProg);
-      shProg->FragmentProgram = linked_fprog; /* refcount OK */
-      /* vertex program ID not significant; just set Id for debugging purposes */
-      shProg->FragmentProgram->Base.Id = shProg->Name;
-      ASSERT(shProg->FragmentProgram->Base.RefCount == 1);
-   }
-
-   /* link varying vars */
-   if (shProg->VertexProgram) {
-      if (!link_varying_vars(ctx, shProg, &shProg->VertexProgram->Base))
-         return;
-   }
-   if (shProg->FragmentProgram) {
-      if (!link_varying_vars(ctx, shProg, &shProg->FragmentProgram->Base))
-         return;
-   }
-
-   /* link uniform vars */
-   if (shProg->VertexProgram) {
-      if (!link_uniform_vars(ctx, shProg, &shProg->VertexProgram->Base,
-                             &numSamplers)) {
-         return;
-      }
-   }
-   if (shProg->FragmentProgram) {
-      if (!link_uniform_vars(ctx, shProg, &shProg->FragmentProgram->Base,
-                             &numSamplers)) {
-         return;
-      }
-   }
-
-   /*_mesa_print_uniforms(shProg->Uniforms);*/
-
-   if (shProg->VertexProgram) {
-      if (!_slang_resolve_attributes(shProg, &vertProg->Base,
-                                     &shProg->VertexProgram->Base)) {
-         return;
-      }
-   }
-
-   if (shProg->VertexProgram) {
-      _slang_update_inputs_outputs(&shProg->VertexProgram->Base);
-      _slang_count_temporaries(&shProg->VertexProgram->Base);
-      if (!(shProg->VertexProgram->Base.OutputsWritten
-           & BITFIELD64_BIT(VERT_RESULT_HPOS))) {
-         /* the vertex program did not compute a vertex position */
-         link_error(shProg,
-                    "gl_Position was not written by vertex shader\n");
-         return;
-      }
-   }
-   if (shProg->FragmentProgram) {
-      _slang_count_temporaries(&shProg->FragmentProgram->Base);
-      _slang_update_inputs_outputs(&shProg->FragmentProgram->Base);
-   }
-
-   /* Check that all the varying vars needed by the fragment shader are
-    * actually produced by the vertex shader.
-    */
-   if (shProg->FragmentProgram) {
-      const GLbitfield varyingRead
-         = shProg->FragmentProgram->Base.InputsRead >> FRAG_ATTRIB_VAR0;
-      const GLbitfield64 varyingWritten = shProg->VertexProgram ?
-         shProg->VertexProgram->Base.OutputsWritten >> VERT_RESULT_VAR0 : 0x0;
-      if ((varyingRead & varyingWritten) != varyingRead) {
-         link_error(shProg,
-          "Fragment program using varying vars not written by vertex shader\n");
-         return;
-      }         
-   }
-
-   /* check that gl_FragColor and gl_FragData are not both written to */
-   if (shProg->FragmentProgram) {
-      const GLbitfield64 outputsWritten =
-        shProg->FragmentProgram->Base.OutputsWritten;
-      if ((outputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) &&
-          (outputsWritten >= BITFIELD64_BIT(FRAG_RESULT_DATA0))) {
-         link_error(shProg, "Fragment program cannot write both gl_FragColor"
-                    " and gl_FragData[].\n");
-         return;
-      }         
-   }
-
-   update_varying_var_list(ctx, shProg);
-
-   /* checks related to transform feedback */
-   if (!link_transform_feedback(ctx, shProg)) {
-      return;
-   }
-
-   if (fragProg && shProg->FragmentProgram) {
-      /* Compute initial program's TexturesUsed info */
-      _mesa_update_shader_textures_used(&shProg->FragmentProgram->Base);
-
-      /* notify driver that a new fragment program has been compiled/linked */
-      vertNotify = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
-                                                 &shProg->FragmentProgram->Base);
-      if (ctx->Shader.Flags & GLSL_DUMP) {
-         printf("Mesa pre-link fragment program:\n");
-         _mesa_print_program(&fragProg->Base);
-         _mesa_print_program_parameters(ctx, &fragProg->Base);
-
-         printf("Mesa post-link fragment program:\n");
-         _mesa_print_program(&shProg->FragmentProgram->Base);
-         _mesa_print_program_parameters(ctx, &shProg->FragmentProgram->Base);
-      }
-   }
-
-   if (vertProg && shProg->VertexProgram) {
-      /* Compute initial program's TexturesUsed info */
-      _mesa_update_shader_textures_used(&shProg->VertexProgram->Base);
-
-      /* notify driver that a new vertex program has been compiled/linked */
-      fragNotify = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
-                                                   &shProg->VertexProgram->Base);
-      if (ctx->Shader.Flags & GLSL_DUMP) {
-         printf("Mesa pre-link vertex program:\n");
-         _mesa_print_program(&vertProg->Base);
-         _mesa_print_program_parameters(ctx, &vertProg->Base);
-
-         printf("Mesa post-link vertex program:\n");
-         _mesa_print_program(&shProg->VertexProgram->Base);
-         _mesa_print_program_parameters(ctx, &shProg->VertexProgram->Base);
-      }
-   }
-
-   /* Debug: */
-   if (0) {
-      if (shProg->VertexProgram)
-         _mesa_postprocess_program(ctx, &shProg->VertexProgram->Base);
-      if (shProg->FragmentProgram)
-         _mesa_postprocess_program(ctx, &shProg->FragmentProgram->Base);
-   }
-
-   if (ctx->Shader.Flags & GLSL_DUMP) {
-      printf("Varying vars:\n");
-      _mesa_print_parameter_list(shProg->Varying);
-      if (shProg->InfoLog) {
-         printf("Info Log: %s\n", shProg->InfoLog);
-      }
-   }
-
-   if (!vertNotify || !fragNotify) {
-      /* driver rejected one/both of the vertex/fragment programs */
-      if (!shProg->InfoLog) {
-        link_error(shProg,
-                   "Vertex and/or fragment program rejected by driver\n");
-      }
-   }
-   else {
-      shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram);
-   }
-}
-
diff --git a/src/mesa/shader/slang/slang_link.h b/src/mesa/shader/slang/slang_link.h
deleted file mode 100644 (file)
index 2b44d20..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.2
- *
- * Copyright (C) 2008  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_LINK_H
-#define SLANG_LINK_H 1
-
-#include "slang_compile.h"
-
-
-extern void
-_slang_link(GLcontext *ctx, GLhandleARB h,
-            struct gl_shader_program *shProg);
-
-
-#endif
-
diff --git a/src/mesa/shader/slang/slang_log.c b/src/mesa/shader/slang/slang_log.c
deleted file mode 100644 (file)
index 9ff2141..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.3
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "main/imports.h"
-#include "slang_log.h"
-#include "slang_utility.h"
-
-
-
-static char *out_of_memory = "Error: Out of memory.\n";
-
-void
-slang_info_log_construct(slang_info_log * log)
-{
-   log->text = NULL;
-   log->dont_free_text = GL_FALSE;
-   log->error_flag = GL_FALSE;
-}
-
-void
-slang_info_log_destruct(slang_info_log * log)
-{
-   if (!log->dont_free_text)
-      free(log->text);
-}
-
-static int
-slang_info_log_message(slang_info_log * log, const char *prefix,
-                       const char *msg)
-{
-   GLuint size;
-
-   if (log->dont_free_text)
-      return 0;
-   size = slang_string_length(msg) + 2;
-   if (prefix != NULL)
-      size += slang_string_length(prefix) + 2;
-   if (log->text != NULL) {
-      GLuint old_len = slang_string_length(log->text);
-      log->text = (char *)
-        _mesa_realloc(log->text, old_len + 1, old_len + size);
-   }
-   else {
-      log->text = (char *) (malloc(size));
-      if (log->text != NULL)
-         log->text[0] = '\0';
-   }
-   if (log->text == NULL)
-      return 0;
-   if (prefix != NULL) {
-      slang_string_concat(log->text, prefix);
-      slang_string_concat(log->text, ": ");
-   }
-   slang_string_concat(log->text, msg);
-   slang_string_concat(log->text, "\n");
-
-   return 1;
-}
-
-int
-slang_info_log_print(slang_info_log * log, const char *msg, ...)
-{
-   va_list va;
-   char buf[1024];
-
-   va_start(va, msg);
-   vsprintf(buf, msg, va);
-   va_end(va);
-   return slang_info_log_message(log, NULL, buf);
-}
-
-int
-slang_info_log_error(slang_info_log * log, const char *msg, ...)
-{
-   va_list va;
-   char buf[1024];
-
-   va_start(va, msg);
-   vsprintf(buf, msg, va);
-   va_end(va);
-   log->error_flag = GL_TRUE;
-   if (slang_info_log_message(log, "Error", buf))
-      return 1;
-   slang_info_log_memory(log);
-   return 0;
-}
-
-int
-slang_info_log_warning(slang_info_log * log, const char *msg, ...)
-{
-   va_list va;
-   char buf[1024];
-
-   va_start(va, msg);
-   vsprintf(buf, msg, va);
-   va_end(va);
-   if (slang_info_log_message(log, "Warning", buf))
-      return 1;
-   slang_info_log_memory(log);
-   return 0;
-}
-
-void
-slang_info_log_memory(slang_info_log * log)
-{
-   if (!slang_info_log_message(log, "Error", "Out of memory.")) {
-      log->dont_free_text = GL_TRUE;
-      log->error_flag = GL_TRUE;
-      log->text = out_of_memory;
-   }
-}
diff --git a/src/mesa/shader/slang/slang_log.h b/src/mesa/shader/slang/slang_log.h
deleted file mode 100644 (file)
index dcaba02..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef SLANG_LOG_H
-#define SLANG_LOG_H
-
-
-typedef struct slang_info_log_
-{
-   char *text;
-   GLboolean dont_free_text;
-   GLboolean error_flag;
-} slang_info_log;
-
-
-extern void
-slang_info_log_construct(slang_info_log *);
-
-extern void
-slang_info_log_destruct(slang_info_log *);
-
-extern int
-slang_info_log_print(slang_info_log *, const char *, ...);
-
-extern int
-slang_info_log_error(slang_info_log *, const char *, ...);
-
-extern int
-slang_info_log_warning(slang_info_log *, const char *, ...);
-
-extern void
-slang_info_log_memory(slang_info_log *);
-
-
-#endif /* SLANG_LOG_H */
diff --git a/src/mesa/shader/slang/slang_mem.c b/src/mesa/shader/slang/slang_mem.c
deleted file mode 100644 (file)
index 5eaa7c4..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_mem.c
- *
- * Memory manager for GLSL compiler.  The general idea is to do all
- * allocations out of a large pool then just free the pool when done
- * compiling to avoid intricate malloc/free tracking and memory leaks.
- *
- * \author Brian Paul
- */
-
-#include "main/context.h"
-#include "main/macros.h"
-#include "slang_mem.h"
-
-
-#define GRANULARITY 8
-#define ROUND_UP(B)  ( ((B) + (GRANULARITY - 1)) & ~(GRANULARITY - 1) )
-
-
-/** If 1, use conventional malloc/free.  Helpful for debugging */
-#define USE_MALLOC_FREE 0
-
-
-struct slang_mempool_
-{
-   GLuint Size, Used, Count, Largest;
-   char *Data;
-   struct slang_mempool_ *Next;
-};
-
-
-slang_mempool *
-_slang_new_mempool(GLuint initialSize)
-{
-   slang_mempool *pool = (slang_mempool *) calloc(1, sizeof(slang_mempool));
-   if (pool) {
-      pool->Data = (char *) calloc(1, initialSize);
-      /*printf("ALLOC MEMPOOL %d at %p\n", initialSize, pool->Data);*/
-      if (!pool->Data) {
-         free(pool);
-         return NULL;
-      }
-      pool->Size = initialSize;
-      pool->Used = 0;
-   }
-   return pool;
-}
-
-
-void
-_slang_delete_mempool(slang_mempool *pool)
-{
-   GLuint total = 0;
-   while (pool) {
-      slang_mempool *next = pool->Next;
-      /*
-      printf("DELETE MEMPOOL %u / %u  count=%u largest=%u\n",
-             pool->Used, pool->Size, pool->Count, pool->Largest);
-      */
-      total += pool->Used;
-      free(pool->Data);
-      free(pool);
-      pool = next;
-   }
-   /*printf("TOTAL ALLOCATED: %u\n", total);*/
-}
-
-
-#ifdef DEBUG
-static void
-check_zero(const char *addr, GLuint n)
-{
-   GLuint i;
-   for (i = 0; i < n; i++) {
-      assert(addr[i]==0);
-   }
-}
-#endif
-
-
-#ifdef DEBUG
-static GLboolean
-is_valid_address(const slang_mempool *pool, void *addr)
-{
-   while (pool) {
-      if ((char *) addr >= pool->Data &&
-          (char *) addr < pool->Data + pool->Used)
-         return GL_TRUE;
-
-      pool = pool->Next;
-   }
-   return GL_FALSE;
-}
-#endif
-
-
-/**
- * Alloc 'bytes' from shader mempool.
- */
-void *
-_slang_alloc(GLuint bytes)
-{
-#if USE_MALLOC_FREE
-   return calloc(1, bytes);
-#else
-   slang_mempool *pool;
-   GET_CURRENT_CONTEXT(ctx);
-   pool = (slang_mempool *) ctx->Shader.MemPool;
-
-   if (bytes == 0)
-      bytes = 1;
-
-   while (pool) {
-      if (pool->Used + bytes <= pool->Size) {
-         /* found room */
-         void *addr = (void *) (pool->Data + pool->Used);
-#ifdef DEBUG
-         check_zero((char*) addr, bytes);
-#endif
-         pool->Used += ROUND_UP(bytes);
-         pool->Largest = MAX2(pool->Largest, bytes);
-         pool->Count++;
-         /*printf("alloc %u  Used %u\n", bytes, pool->Used);*/
-         return addr;
-      }
-      else if (pool->Next) {
-         /* try next block */
-         pool = pool->Next;
-      }
-      else {
-         /* alloc new pool */
-         const GLuint sz = MAX2(bytes, pool->Size);
-         pool->Next = _slang_new_mempool(sz);
-         if (!pool->Next) {
-            /* we're _really_ out of memory */
-            return NULL;
-         }
-         else {
-            pool = pool->Next;
-            pool->Largest = bytes;
-            pool->Count++;
-            pool->Used = ROUND_UP(bytes);
-#ifdef DEBUG
-            check_zero((char*) pool->Data, bytes);
-#endif
-            return (void *) pool->Data;
-         }
-      }
-   }
-   return NULL;
-#endif
-}
-
-
-void *
-_slang_realloc(void *oldBuffer, GLuint oldSize, GLuint newSize)
-{
-#if USE_MALLOC_FREE
-   return _mesa_realloc(oldBuffer, oldSize, newSize);
-#else
-   GET_CURRENT_CONTEXT(ctx);
-   slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool;
-   (void) pool;
-
-   if (newSize < oldSize) {
-      return oldBuffer;
-   }
-   else {
-      const GLuint copySize = (oldSize < newSize) ? oldSize : newSize;
-      void *newBuffer = _slang_alloc(newSize);
-
-      if (oldBuffer)
-         ASSERT(is_valid_address(pool, oldBuffer));
-
-      if (newBuffer && oldBuffer && copySize > 0)
-         memcpy(newBuffer, oldBuffer, copySize);
-
-      return newBuffer;
-   }
-#endif
-}
-
-
-/**
- * Clone string, storing in current mempool.
- */
-char *
-_slang_strdup(const char *s)
-{
-   if (s) {
-      size_t l = strlen(s);
-      char *s2 = (char *) _slang_alloc(l + 1);
-      if (s2)
-         strcpy(s2, s);
-      return s2;
-   }
-   else {
-      return NULL;
-   }
-}
-
-
-/**
- * Don't actually free memory, but mark it (for debugging).
- */
-void
-_slang_free(void *addr)
-{
-#if USE_MALLOC_FREE
-   free(addr);
-#else
-   if (addr) {
-      GET_CURRENT_CONTEXT(ctx);
-      slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool;
-      (void) pool;
-      ASSERT(is_valid_address(pool, addr));
-   }
-#endif
-}
diff --git a/src/mesa/shader/slang/slang_mem.h b/src/mesa/shader/slang/slang_mem.h
deleted file mode 100644 (file)
index b5bfae2..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef SLANG_MEM_H
-#define SLANG_MEM_H
-
-
-#include "main/imports.h"
-
-
-typedef struct slang_mempool_ slang_mempool;
-
-
-extern slang_mempool *
-_slang_new_mempool(GLuint initialSize);
-
-extern void
-_slang_delete_mempool(slang_mempool *pool);
-
-extern void *
-_slang_alloc(GLuint bytes);
-
-extern void *
-_slang_realloc(void *oldBuffer, GLuint oldSize, GLuint newSize);
-
-extern char *
-_slang_strdup(const char *s);
-
-extern void
-_slang_free(void *addr);
-
-
-#endif
diff --git a/src/mesa/shader/slang/slang_print.c b/src/mesa/shader/slang/slang_print.c
deleted file mode 100644 (file)
index 6b34f39..0000000
+++ /dev/null
@@ -1,883 +0,0 @@
-
-/**
- * Dump/print a slang_operation tree
- */
-
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_print.h"
-
-
-static void
-spaces(int n)
-{
-   while (n--)
-      printf(" ");
-}
-
-
-static void
-print_type(const slang_fully_specified_type *t)
-{
-   switch (t->qualifier) {
-   case SLANG_QUAL_NONE:
-      /*printf("");*/
-      break;
-   case SLANG_QUAL_CONST:
-      printf("const ");
-      break;
-   case SLANG_QUAL_ATTRIBUTE:
-      printf("attrib ");
-      break;
-   case SLANG_QUAL_VARYING:
-      printf("varying ");
-      break;
-   case SLANG_QUAL_UNIFORM:
-      printf("uniform ");
-      break;
-   case SLANG_QUAL_OUT:
-      printf("output ");
-      break;
-   case SLANG_QUAL_INOUT:
-      printf("inout ");
-      break;
-   case SLANG_QUAL_FIXEDOUTPUT:
-      printf("fixedoutput");
-      break;
-   case SLANG_QUAL_FIXEDINPUT:
-      printf("fixedinput");
-      break;
-   default:
-      printf("unknown qualifer!");
-   }
-
-   switch (t->specifier.type) {
-   case SLANG_SPEC_VOID:
-      printf("void");
-      break;
-   case SLANG_SPEC_BOOL:
-      printf("bool");
-      break;
-   case SLANG_SPEC_BVEC2:
-      printf("bvec2");
-      break;
-   case SLANG_SPEC_BVEC3:
-      printf("bvec3");
-      break;
-   case SLANG_SPEC_BVEC4:
-      printf("bvec4");
-      break;
-   case SLANG_SPEC_INT:
-      printf("int");
-      break;
-   case SLANG_SPEC_IVEC2:
-      printf("ivec2");
-      break;
-   case SLANG_SPEC_IVEC3:
-      printf("ivec3");
-      break;
-   case SLANG_SPEC_IVEC4:
-      printf("ivec4");
-      break;
-   case SLANG_SPEC_FLOAT:
-      printf("float");
-      break;
-   case SLANG_SPEC_VEC2:
-      printf("vec2");
-      break;
-   case SLANG_SPEC_VEC3:
-      printf("vec3");
-      break;
-   case SLANG_SPEC_VEC4:
-      printf("vec4");
-      break;
-   case SLANG_SPEC_MAT2:
-      printf("mat2");
-      break;
-   case SLANG_SPEC_MAT3:
-      printf("mat3");
-      break;
-   case SLANG_SPEC_MAT4:
-      printf("mat4");
-      break;
-   case SLANG_SPEC_MAT23:
-      printf("mat2x3");
-      break;
-   case SLANG_SPEC_MAT32:
-      printf("mat3x2");
-      break;
-   case SLANG_SPEC_MAT24:
-      printf("mat2x4");
-      break;
-   case SLANG_SPEC_MAT42:
-      printf("mat4x2");
-      break;
-   case SLANG_SPEC_MAT34:
-      printf("mat3x4");
-      break;
-   case SLANG_SPEC_MAT43:
-      printf("mat4x3");
-      break;
-   case SLANG_SPEC_SAMPLER_1D:
-      printf("sampler1D");
-      break;
-   case SLANG_SPEC_SAMPLER_2D:
-      printf("sampler2D");
-      break;
-   case SLANG_SPEC_SAMPLER_3D:
-      printf("sampler3D");
-      break;
-   case SLANG_SPEC_SAMPLER_CUBE:
-      printf("samplerCube");
-      break;
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-      printf("sampler1DShadow");
-      break;
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-      printf("sampler2DShadow");
-      break;
-   case SLANG_SPEC_STRUCT:
-      printf("struct");
-      break;
-   case SLANG_SPEC_ARRAY:
-      printf("array");
-      break;
-   default:
-      printf("unknown type");
-   }
-   /*printf("\n");*/
-}
-
-
-static void
-print_variable(const slang_variable *v, int indent)
-{
-   spaces(indent);
-   printf("VAR ");
-   print_type(&v->type);
-   printf(" %s (at %p)", (char *) v->a_name, (void *) v);
-   if (v->initializer) {
-      printf(" :=\n");
-      slang_print_tree(v->initializer, indent + 3);
-   }
-   else {
-      printf(";\n");
-   }
-}
-
-
-static void
-print_binary(const slang_operation *op, const char *oper, int indent)
-{
-   assert(op->num_children == 2);
-#if 0
-   printf("binary at %p locals=%p outer=%p\n",
-          (void *) op,
-          (void *) op->locals,
-          (void *) op->locals->outer_scope);
-#endif
-   slang_print_tree(&op->children[0], indent + 3);
-   spaces(indent);
-   printf("%s at %p locals=%p outer=%p\n",
-          oper, (void *) op, (void *) op->locals,
-          (void *) op->locals->outer_scope);
-   slang_print_tree(&op->children[1], indent + 3);
-}
-
-
-static void
-print_generic2(const slang_operation *op, const char *oper,
-               const char *s, int indent)
-{
-   GLuint i;
-   if (oper) {
-      spaces(indent);
-      printf("%s %s at %p locals=%p outer=%p\n",
-             oper, s, (void *) op, (void *) op->locals, 
-             (void *) op->locals->outer_scope);
-   }
-   for (i = 0; i < op->num_children; i++) {
-      spaces(indent);
-      printf("//child %u of %u:\n", i, op->num_children);
-      slang_print_tree(&op->children[i], indent);
-   }
-}
-
-static void
-print_generic(const slang_operation *op, const char *oper, int indent)
-{
-   print_generic2(op, oper, "", indent);
-}
-
-
-static const slang_variable_scope *
-find_scope(const slang_variable_scope *s, slang_atom name)
-{
-   GLuint i;
-   for (i = 0; i < s->num_variables; i++) {
-      if (s->variables[i]->a_name == name)
-         return s;
-   }
-   if (s->outer_scope)
-      return find_scope(s->outer_scope, name);
-   else
-      return NULL;
-}
-
-static const slang_variable *
-find_var(const slang_variable_scope *s, slang_atom name)
-{
-   GLuint i;
-   for (i = 0; i < s->num_variables; i++) {
-      if (s->variables[i]->a_name == name)
-         return s->variables[i];
-   }
-   if (s->outer_scope)
-      return find_var(s->outer_scope, name);
-   else
-      return NULL;
-}
-
-
-void
-slang_print_tree(const slang_operation *op, int indent)
-{
-   GLuint i;
-
-   switch (op->type) {
-
-   case SLANG_OPER_NONE:
-      spaces(indent);
-      printf("SLANG_OPER_NONE\n");
-      break;
-
-   case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
-      spaces(indent);
-      printf("{ locals=%p  outer=%p\n", (void*)op->locals, (void*)op->locals->outer_scope);
-      print_generic(op, NULL, indent+3);
-      spaces(indent);
-      printf("}\n");
-      break;
-
-   case SLANG_OPER_BLOCK_NEW_SCOPE:
-   case SLANG_OPER_NON_INLINED_CALL:
-      spaces(indent);
-      printf("{{ // new scope  locals=%p outer=%p: ",
-             (void *) op->locals,
-             (void *) op->locals->outer_scope);
-      for (i = 0; i < op->locals->num_variables; i++) {
-         printf("%s ", (char *) op->locals->variables[i]->a_name);
-      }
-      printf("\n");
-      print_generic(op, NULL, indent+3);
-      spaces(indent);
-      printf("}}\n");
-      break;
-
-   case SLANG_OPER_VARIABLE_DECL:
-      assert(op->num_children == 0 || op->num_children == 1);
-      {
-         slang_variable *v;
-         v = _slang_variable_locate(op->locals, op->a_id, GL_TRUE);
-         if (v) {
-            const slang_variable_scope *scope;
-            spaces(indent);
-            printf("DECL (locals=%p outer=%p) ", (void*)op->locals, (void*) op->locals->outer_scope);
-            print_type(&v->type);
-            printf(" %s (%p)", (char *) op->a_id,
-                   (void *) find_var(op->locals, op->a_id));
-
-            scope = find_scope(op->locals, op->a_id);
-            printf(" (in scope %p) ", (void *) scope);
-            assert(scope);
-            if (op->num_children == 1) {
-               printf(" :=\n");
-               slang_print_tree(&op->children[0], indent + 3);
-            }
-            else if (v->initializer) {
-               printf(" := INITIALIZER\n");
-               slang_print_tree(v->initializer, indent + 3);
-            }
-            else {
-               printf(";\n");
-            }
-            /*
-            spaces(indent);
-            printf("TYPE: ");
-            print_type(&v->type);
-            spaces(indent);
-            printf("ADDR: %d  size: %d\n", v->address, v->size);
-            */
-         }
-         else {
-            spaces(indent);
-            printf("DECL %s (anonymous variable!!!!)\n", (char *) op->a_id);
-         }
-      }
-      break;
-
-   case SLANG_OPER_ASM:
-      spaces(indent);
-      printf("ASM: %s at %p locals=%p outer=%p\n",
-             (char *) op->a_id,
-             (void *) op,
-             (void *) op->locals,
-             (void *) op->locals->outer_scope);
-      print_generic(op, "ASM", indent+3);
-      break;
-
-   case SLANG_OPER_BREAK:
-      spaces(indent);
-      printf("BREAK\n");
-      break;
-
-   case SLANG_OPER_CONTINUE:
-      spaces(indent);
-      printf("CONTINUE\n");
-      break;
-
-   case SLANG_OPER_DISCARD:
-      spaces(indent);
-      printf("DISCARD\n");
-      break;
-
-   case SLANG_OPER_RETURN:
-      spaces(indent);
-      printf("RETURN\n");
-      if (op->num_children > 0)
-         slang_print_tree(&op->children[0], indent + 3);
-      break;
-
-   case SLANG_OPER_RETURN_INLINED:
-      spaces(indent);
-      printf("RETURN_INLINED\n");
-      if (op->num_children > 0)
-         slang_print_tree(&op->children[0], indent + 3);
-      break;
-
-   case SLANG_OPER_LABEL:
-      spaces(indent);
-      printf("LABEL %s\n", (char *) op->a_id);
-      break;
-
-   case SLANG_OPER_EXPRESSION:
-      spaces(indent);
-      printf("EXPR:  locals=%p outer=%p\n",
-             (void *) op->locals,
-             (void *) op->locals->outer_scope);
-      /*print_generic(op, "SLANG_OPER_EXPRESSION", indent);*/
-      slang_print_tree(&op->children[0], indent + 3);
-      break;
-
-   case SLANG_OPER_IF:
-      spaces(indent);
-      printf("IF\n");
-      slang_print_tree(&op->children[0], indent + 3);
-      spaces(indent);
-      printf("THEN\n");
-      slang_print_tree(&op->children[1], indent + 3);
-      spaces(indent);
-      printf("ELSE\n");
-      slang_print_tree(&op->children[2], indent + 3);
-      spaces(indent);
-      printf("ENDIF\n");
-      break;
-
-   case SLANG_OPER_WHILE:
-      assert(op->num_children == 2);
-      spaces(indent);
-      printf("WHILE LOOP: locals = %p\n", (void *) op->locals);
-      indent += 3;
-      spaces(indent);
-      printf("WHILE cond:\n");
-      slang_print_tree(&op->children[0], indent + 3);
-      spaces(indent);
-      printf("WHILE body:\n");
-      slang_print_tree(&op->children[1], indent + 3);
-      indent -= 3;
-      spaces(indent);
-      printf("END WHILE LOOP\n");
-      break;
-
-   case SLANG_OPER_DO:
-      spaces(indent);
-      printf("DO LOOP: locals = %p\n", (void *) op->locals);
-      indent += 3;
-      spaces(indent);
-      printf("DO body:\n");
-      slang_print_tree(&op->children[0], indent + 3);
-      spaces(indent);
-      printf("DO cond:\n");
-      slang_print_tree(&op->children[1], indent + 3);
-      indent -= 3;
-      spaces(indent);
-      printf("END DO LOOP\n");
-      break;
-
-   case SLANG_OPER_FOR:
-      spaces(indent);
-      printf("FOR LOOP: locals = %p\n", (void *) op->locals);
-      indent += 3;
-      spaces(indent);
-      printf("FOR init:\n");
-      slang_print_tree(&op->children[0], indent + 3);
-      spaces(indent);
-      printf("FOR condition:\n");
-      slang_print_tree(&op->children[1], indent + 3);
-      spaces(indent);
-      printf("FOR step:\n");
-      slang_print_tree(&op->children[2], indent + 3);
-      spaces(indent);
-      printf("FOR body:\n");
-      slang_print_tree(&op->children[3], indent + 3);
-      indent -= 3;
-      spaces(indent);
-      printf("ENDFOR\n");
-      /*
-      print_generic(op, "FOR", indent + 3);
-      */
-      break;
-
-   case SLANG_OPER_VOID:
-      spaces(indent);
-      printf("(oper-void)\n");
-      break;
-
-   case SLANG_OPER_LITERAL_BOOL:
-      spaces(indent);
-      printf("LITERAL (");
-      for (i = 0; i < op->literal_size; i++)
-         printf("%s ", op->literal[0] ? "TRUE" : "FALSE");
-      printf(")\n");
-
-      break;
-
-   case SLANG_OPER_LITERAL_INT:
-      spaces(indent);
-      printf("LITERAL (");
-      for (i = 0; i < op->literal_size; i++)
-         printf("%d ", (int) op->literal[i]);
-      printf(")\n");
-      break;
-
-   case SLANG_OPER_LITERAL_FLOAT:
-      spaces(indent);
-      printf("LITERAL (");
-      for (i = 0; i < op->literal_size; i++)
-         printf("%f ", op->literal[i]);
-      printf(")\n");
-      break;
-
-   case SLANG_OPER_IDENTIFIER:
-      {
-         const slang_variable_scope *scope;
-         spaces(indent);
-         if (op->var && op->var->a_name) {
-            scope = find_scope(op->locals, op->var->a_name);
-            printf("VAR %s  (in scope %p)\n", (char *) op->var->a_name,
-                   (void *) scope);
-            assert(scope);
-         }
-         else {
-            scope = find_scope(op->locals, op->a_id);
-            printf("VAR' %s  (in scope %p) locals=%p outer=%p\n",
-                   (char *) op->a_id,
-                   (void *) scope,
-                   (void *) op->locals,
-                   (void *) op->locals->outer_scope);
-            /*assert(scope);*/
-         }
-      }
-      break;
-
-   case SLANG_OPER_SEQUENCE:
-      print_generic(op, "COMMA-SEQ", indent+3);
-      break;
-
-   case SLANG_OPER_ASSIGN:
-      spaces(indent);
-      printf("ASSIGNMENT  locals=%p outer=%p\n",
-             (void *) op->locals,
-             (void *) op->locals->outer_scope);
-      print_binary(op, ":=", indent);
-      break;
-
-   case SLANG_OPER_ADDASSIGN:
-      spaces(indent);
-      printf("ASSIGN\n");
-      print_binary(op, "+=", indent);
-      break;
-
-   case SLANG_OPER_SUBASSIGN:
-      spaces(indent);
-      printf("ASSIGN\n");
-      print_binary(op, "-=", indent);
-      break;
-
-   case SLANG_OPER_MULASSIGN:
-      spaces(indent);
-      printf("ASSIGN\n");
-      print_binary(op, "*=", indent);
-      break;
-
-   case SLANG_OPER_DIVASSIGN:
-      spaces(indent);
-      printf("ASSIGN\n");
-      print_binary(op, "/=", indent);
-      break;
-
-       /*SLANG_OPER_MODASSIGN,*/
-       /*SLANG_OPER_LSHASSIGN,*/
-       /*SLANG_OPER_RSHASSIGN,*/
-       /*SLANG_OPER_ORASSIGN,*/
-       /*SLANG_OPER_XORASSIGN,*/
-       /*SLANG_OPER_ANDASSIGN,*/
-   case SLANG_OPER_SELECT:
-      spaces(indent);
-      printf("SLANG_OPER_SELECT n=%d\n", op->num_children);
-      assert(op->num_children == 3);
-      slang_print_tree(&op->children[0], indent+3);
-      spaces(indent);
-      printf("?\n");
-      slang_print_tree(&op->children[1], indent+3);
-      spaces(indent);
-      printf(":\n");
-      slang_print_tree(&op->children[2], indent+3);
-      break;
-
-   case SLANG_OPER_LOGICALOR:
-      print_binary(op, "||", indent);
-      break;
-
-   case SLANG_OPER_LOGICALXOR:
-      print_binary(op, "^^", indent);
-      break;
-
-   case SLANG_OPER_LOGICALAND:
-      print_binary(op, "&&", indent);
-      break;
-
-   /*SLANG_OPER_BITOR*/
-   /*SLANG_OPER_BITXOR*/
-   /*SLANG_OPER_BITAND*/
-   case SLANG_OPER_EQUAL:
-      print_binary(op, "==", indent);
-      break;
-
-   case SLANG_OPER_NOTEQUAL:
-      print_binary(op, "!=", indent);
-      break;
-
-   case SLANG_OPER_LESS:
-      print_binary(op, "<", indent);
-      break;
-
-   case SLANG_OPER_GREATER:
-      print_binary(op, ">", indent);
-      break;
-
-   case SLANG_OPER_LESSEQUAL:
-      print_binary(op, "<=", indent);
-      break;
-
-   case SLANG_OPER_GREATEREQUAL:
-      print_binary(op, ">=", indent);
-      break;
-
-   /*SLANG_OPER_LSHIFT*/
-   /*SLANG_OPER_RSHIFT*/
-   case SLANG_OPER_ADD:
-      print_binary(op, "+", indent);
-      break;
-
-   case SLANG_OPER_SUBTRACT:
-      print_binary(op, "-", indent);
-      break;
-
-   case SLANG_OPER_MULTIPLY:
-      print_binary(op, "*", indent);
-      break;
-
-   case SLANG_OPER_DIVIDE:
-      print_binary(op, "/", indent);
-      break;
-
-   /*SLANG_OPER_MODULUS*/
-   case SLANG_OPER_PREINCREMENT:
-      spaces(indent);
-      printf("PRE++\n");
-      slang_print_tree(&op->children[0], indent+3);
-      break;
-
-   case SLANG_OPER_PREDECREMENT:
-      spaces(indent);
-      printf("PRE--\n");
-      slang_print_tree(&op->children[0], indent+3);
-      break;
-
-   case SLANG_OPER_PLUS:
-      spaces(indent);
-      printf("SLANG_OPER_PLUS\n");
-      break;
-
-   case SLANG_OPER_MINUS:
-      spaces(indent);
-      printf("SLANG_OPER_MINUS\n");
-      break;
-
-   /*SLANG_OPER_COMPLEMENT*/
-   case SLANG_OPER_NOT:
-      spaces(indent);
-      printf("NOT\n");
-      slang_print_tree(&op->children[0], indent+3);
-      break;
-
-   case SLANG_OPER_SUBSCRIPT:
-      spaces(indent);
-      printf("SLANG_OPER_SUBSCRIPT locals=%p outer=%p\n",
-             (void *) op->locals,
-             (void *) op->locals->outer_scope);
-      print_generic(op, NULL, indent+3);
-      break;
-
-   case SLANG_OPER_CALL:
-#if 0
-         slang_function *fun
-            = _slang_function_locate(A->space.funcs, oper->a_id,
-                                     oper->children,
-                                     oper->num_children, &A->space, A->atoms);
-#endif
-      spaces(indent);
-      printf("CALL %s(\n", (char *) op->a_id);
-      for (i = 0; i < op->num_children; i++) {
-         slang_print_tree(&op->children[i], indent+3);
-         if (i + 1 < op->num_children) {
-            spaces(indent + 3);
-            printf(",\n");
-         }
-      }
-      spaces(indent);
-      printf(")\n");
-      break;
-
-   case SLANG_OPER_METHOD:
-      spaces(indent);
-      printf("METHOD CALL %s.%s\n", (char *) op->a_obj, (char *) op->a_id);
-      break;
-
-   case SLANG_OPER_FIELD:
-      spaces(indent);
-      printf("FIELD %s of\n", (char*) op->a_id);
-      slang_print_tree(&op->children[0], indent+3);
-      break;
-
-   case SLANG_OPER_POSTINCREMENT:
-      spaces(indent);
-      printf("POST++\n");
-      slang_print_tree(&op->children[0], indent+3);
-      break;
-
-   case SLANG_OPER_POSTDECREMENT:
-      spaces(indent);
-      printf("POST--\n");
-      slang_print_tree(&op->children[0], indent+3);
-      break;
-
-   default:
-      printf("unknown op->type %d\n", (int) op->type);
-   }
-
-}
-
-
-
-void
-slang_print_function(const slang_function *f, GLboolean body)
-{
-   GLuint i;
-
-#if 0
-   if (strcmp((char *) f->header.a_name, "main") != 0)
-     return;
-#endif
-
-   printf("FUNCTION %s ( scope=%p\n",
-          (char *) f->header.a_name, (void *) f->parameters);
-
-   for (i = 0; i < f->param_count; i++) {
-      print_variable(f->parameters->variables[i], 3);
-   }
-
-   printf(") param scope = %p\n", (void *) f->parameters);
-
-   if (body && f->body)
-      slang_print_tree(f->body, 0);
-}
-
-
-
-
-
-const char *
-slang_type_qual_string(slang_type_qualifier q)
-{
-   switch (q) {
-   case SLANG_QUAL_NONE:
-      return "none";
-   case SLANG_QUAL_CONST:
-      return "const";
-   case SLANG_QUAL_ATTRIBUTE:
-      return "attribute";
-   case SLANG_QUAL_VARYING:
-      return "varying";
-   case SLANG_QUAL_UNIFORM:
-      return "uniform";
-   case SLANG_QUAL_OUT:
-      return "out";
-   case SLANG_QUAL_INOUT:
-      return "inout";
-   case SLANG_QUAL_FIXEDOUTPUT:
-      return "fixedoutput";
-   case SLANG_QUAL_FIXEDINPUT:
-      return "fixedinputk";
-   default:
-      return "qual?";
-   }
-}
-
-
-static const char *
-slang_type_string(slang_type_specifier_type t)
-{
-   switch (t) {
-   case SLANG_SPEC_VOID:
-      return "void";
-   case SLANG_SPEC_BOOL:
-      return "bool";
-   case SLANG_SPEC_BVEC2:
-      return "bvec2";
-   case SLANG_SPEC_BVEC3:
-      return "bvec3";
-   case SLANG_SPEC_BVEC4:
-      return "bvec4";
-   case SLANG_SPEC_INT:
-      return "int";
-   case SLANG_SPEC_IVEC2:
-      return "ivec2";
-   case SLANG_SPEC_IVEC3:
-      return "ivec3";
-   case SLANG_SPEC_IVEC4:
-      return "ivec4";
-   case SLANG_SPEC_FLOAT:
-      return "float";
-   case SLANG_SPEC_VEC2:
-      return "vec2";
-   case SLANG_SPEC_VEC3:
-      return "vec3";
-   case SLANG_SPEC_VEC4:
-      return "vec4";
-   case SLANG_SPEC_MAT2:
-      return "mat2";
-   case SLANG_SPEC_MAT3:
-      return "mat3";
-   case SLANG_SPEC_MAT4:
-      return "mat4";
-   case SLANG_SPEC_SAMPLER_1D:
-      return "sampler1D";
-   case SLANG_SPEC_SAMPLER_2D:
-      return "sampler2D";
-   case SLANG_SPEC_SAMPLER_3D:
-      return "sampler3D";
-   case SLANG_SPEC_SAMPLER_CUBE:
-      return "samplerCube";
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-      return "sampler1DShadow";
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-      return "sampler2DShadow";
-   case SLANG_SPEC_SAMPLER_RECT:
-      return "sampler2DRect";
-   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
-      return "sampler2DRectShadow";
-   case SLANG_SPEC_STRUCT:
-      return "struct";
-   case SLANG_SPEC_ARRAY:
-      return "array";
-   default:
-      return "type?";
-   }
-}
-
-
-static const char *
-slang_fq_type_string(const slang_fully_specified_type *t)
-{
-   static char str[1000];
-   _mesa_snprintf(str, sizeof(str), "%s %s", slang_type_qual_string(t->qualifier),
-      slang_type_string(t->specifier.type));
-   return str;
-}
-
-
-void
-slang_print_type(const slang_fully_specified_type *t)
-{
-   printf("%s %s", slang_type_qual_string(t->qualifier),
-      slang_type_string(t->specifier.type));
-}
-
-
-#if 0
-static char *
-slang_var_string(const slang_variable *v)
-{
-   static char str[1000];
-   _mesa_snprintf(str, sizeof(str), "%s : %s",
-                  (char *) v->a_name,
-                  slang_fq_type_string(&v->type));
-   return str;
-}
-#endif
-
-
-void
-slang_print_variable(const slang_variable *v)
-{
-   printf("Name: %s\n", (char *) v->a_name);
-   printf("Type: %s\n", slang_fq_type_string(&v->type));
-}
-
-
-void
-_slang_print_var_scope(const slang_variable_scope *vars, int indent)
-{
-   GLuint i;
-
-   spaces(indent);
-   printf("Var scope %p  %d vars:\n", (void *) vars, vars->num_variables);
-   for (i = 0; i < vars->num_variables; i++) {
-      spaces(indent + 3);
-      printf("%s (at %p)\n", (char *) vars->variables[i]->a_name, (void*) (vars->variables + i));
-   }
-   spaces(indent + 3);
-   printf("outer_scope = %p\n", (void*) vars->outer_scope);
-
-   if (vars->outer_scope) {
-      /*spaces(indent + 3);*/
-      _slang_print_var_scope(vars->outer_scope, indent + 3);
-   }
-}
-
-
-
-int
-slang_checksum_tree(const slang_operation *op)
-{
-   int s = op->num_children;
-   GLuint i;
-
-   for (i = 0; i < op->num_children; i++) {
-      s += slang_checksum_tree(&op->children[i]);
-   }
-   return s;
-}
diff --git a/src/mesa/shader/slang/slang_print.h b/src/mesa/shader/slang/slang_print.h
deleted file mode 100644 (file)
index 46605c8..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-#ifndef SLANG_PRINT
-#define SLANG_PRINT
-
-extern void
-slang_print_function(const slang_function *f, GLboolean body);
-
-extern void
-slang_print_tree(const slang_operation *op, int indent);
-
-extern const char *
-slang_type_qual_string(slang_type_qualifier q);
-
-extern void
-slang_print_type(const slang_fully_specified_type *t);
-
-extern void
-slang_print_variable(const slang_variable *v);
-
-extern void
-_slang_print_var_scope(const slang_variable_scope *s, int indent);
-
-
-extern int
-slang_checksum_tree(const slang_operation *op);
-
-#endif /* SLANG_PRINT */
-
diff --git a/src/mesa/shader/slang/slang_simplify.c b/src/mesa/shader/slang/slang_simplify.c
deleted file mode 100644 (file)
index 13b9ca3..0000000
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.1
- *
- * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * Functions for constant folding, built-in constant lookup, and function
- * call casting.
- */
-
-
-#include "main/imports.h"
-#include "main/macros.h"
-#include "main/get.h"
-#include "slang_compile.h"
-#include "slang_codegen.h"
-#include "slang_simplify.h"
-#include "slang_print.h"
-
-
-#ifndef GL_MAX_FRAGMENT_UNIFORM_VECTORS
-#define GL_MAX_FRAGMENT_UNIFORM_VECTORS     0x8DFD
-#endif
-#ifndef GL_MAX_VERTEX_UNIFORM_VECTORS
-#define GL_MAX_VERTEX_UNIFORM_VECTORS       0x8DFB
-#endif
-#ifndef GL_MAX_VARYING_VECTORS
-#define GL_MAX_VARYING_VECTORS              0x8DFC
-#endif
-
-
-/**
- * Lookup the value of named constant, such as gl_MaxLights.
- * \return value of constant, or -1 if unknown
- */
-GLint
-_slang_lookup_constant(const char *name)
-{
-   struct constant_info {
-      const char *Name;
-      const GLenum Token;
-   };
-   static const struct constant_info info[] = {
-      { "gl_MaxClipPlanes", GL_MAX_CLIP_PLANES },
-      { "gl_MaxCombinedTextureImageUnits", GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS },
-      { "gl_MaxDrawBuffers", GL_MAX_DRAW_BUFFERS },
-      { "gl_MaxFragmentUniformComponents", GL_MAX_FRAGMENT_UNIFORM_COMPONENTS },
-      { "gl_MaxLights", GL_MAX_LIGHTS },
-      { "gl_MaxTextureUnits", GL_MAX_TEXTURE_UNITS },
-      { "gl_MaxTextureCoords", GL_MAX_TEXTURE_COORDS },
-      { "gl_MaxVertexAttribs", GL_MAX_VERTEX_ATTRIBS },
-      { "gl_MaxVertexUniformComponents", GL_MAX_VERTEX_UNIFORM_COMPONENTS },
-      { "gl_MaxVaryingFloats", GL_MAX_VARYING_FLOATS },
-      { "gl_MaxVertexTextureImageUnits", GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS },
-      { "gl_MaxTextureImageUnits", GL_MAX_TEXTURE_IMAGE_UNITS },
-#if FEATURE_es2_glsl
-      { "gl_MaxVertexUniformVectors", GL_MAX_VERTEX_UNIFORM_VECTORS },
-      { "gl_MaxVaryingVectors", GL_MAX_VARYING_VECTORS },
-      { "gl_MaxFragmentUniformVectors", GL_MAX_FRAGMENT_UNIFORM_VECTORS },
-#endif
-      { NULL, 0 }
-   };
-   GLuint i;
-
-   for (i = 0; info[i].Name; i++) {
-      if (strcmp(info[i].Name, name) == 0) {
-         /* found */
-         GLint values[16];
-         values[0] = -1;
-         _mesa_GetIntegerv(info[i].Token, values);
-         ASSERT(values[0] >= 0);  /* sanity check that glGetFloatv worked */
-         return values[0];
-      }
-   }
-   return -1;
-}
-
-
-static slang_operation_type
-literal_type(slang_operation_type t1, slang_operation_type t2)
-{
-   if (t1 == SLANG_OPER_LITERAL_FLOAT || t2 == SLANG_OPER_LITERAL_FLOAT)
-      return SLANG_OPER_LITERAL_FLOAT;
-   else
-      return SLANG_OPER_LITERAL_INT;
-}
-
-
-/**
- * Recursively traverse an AST tree, applying simplifications wherever
- * possible.
- * At the least, we do constant folding.  We need to do that much so that
- * compile-time expressions can be evaluated for things like array
- * declarations.  I.e.:  float foo[3 + 5];
- */
-void
-_slang_simplify(slang_operation *oper,
-                const slang_name_space * space,
-                slang_atom_pool * atoms)
-{
-   GLboolean isFloat[4];
-   GLboolean isBool[4];
-   GLuint i, n;
-
-   if (oper->type == SLANG_OPER_IDENTIFIER) {
-      /* see if it's a named constant */
-      GLint value = _slang_lookup_constant((char *) oper->a_id);
-      /*printf("value[%s] = %d\n", (char*) oper->a_id, value);*/
-      if (value >= 0) {
-         oper->literal[0] =
-         oper->literal[1] =
-         oper->literal[2] =
-         oper->literal[3] = (GLfloat) value;
-         oper->type = SLANG_OPER_LITERAL_INT;
-         return;
-      }
-      /* look for user-defined constant */
-      {
-         slang_variable *var;
-         var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
-         if (var) {
-            if (var->type.qualifier == SLANG_QUAL_CONST &&
-                var->initializer &&
-                (var->initializer->type == SLANG_OPER_LITERAL_INT ||
-                 var->initializer->type == SLANG_OPER_LITERAL_FLOAT)) {
-               oper->literal[0] = var->initializer->literal[0];
-               oper->literal[1] = var->initializer->literal[1];
-               oper->literal[2] = var->initializer->literal[2];
-               oper->literal[3] = var->initializer->literal[3];
-               oper->literal_size = var->initializer->literal_size;
-               oper->type = var->initializer->type;
-               /*
-               printf("value[%s] = %f\n",
-                      (char*) oper->a_id, oper->literal[0]);
-               */
-               return;
-            }
-         }
-      }
-   }
-
-   /* first, simplify children */
-   for (i = 0; i < oper->num_children; i++) {
-      _slang_simplify(&oper->children[i], space, atoms);
-   }
-
-   /* examine children */
-   n = MIN2(oper->num_children, 4);
-   for (i = 0; i < n; i++) {
-      isFloat[i] = (oper->children[i].type == SLANG_OPER_LITERAL_FLOAT ||
-                   oper->children[i].type == SLANG_OPER_LITERAL_INT);
-      isBool[i] = (oper->children[i].type == SLANG_OPER_LITERAL_BOOL);
-   }
-                              
-   if (oper->num_children == 2 && isFloat[0] && isFloat[1]) {
-      /* probably simple arithmetic */
-      switch (oper->type) {
-      case SLANG_OPER_ADD:
-         for (i = 0; i < 4; i++) {
-            oper->literal[i]
-               = oper->children[0].literal[i] + oper->children[1].literal[i];
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         oper->type = literal_type(oper->children[0].type, 
-                                   oper->children[1].type);
-         slang_operation_destruct(oper);  /* frees unused children */
-         return;
-      case SLANG_OPER_SUBTRACT:
-         for (i = 0; i < 4; i++) {
-            oper->literal[i]
-               = oper->children[0].literal[i] - oper->children[1].literal[i];
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         oper->type = literal_type(oper->children[0].type, 
-                                   oper->children[1].type);
-         slang_operation_destruct(oper);
-         return;
-      case SLANG_OPER_MULTIPLY:
-         for (i = 0; i < 4; i++) {
-            oper->literal[i]
-               = oper->children[0].literal[i] * oper->children[1].literal[i];
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         oper->type = literal_type(oper->children[0].type, 
-                                   oper->children[1].type);
-         slang_operation_destruct(oper);
-         return;
-      case SLANG_OPER_DIVIDE:
-         for (i = 0; i < 4; i++) {
-            oper->literal[i]
-               = oper->children[0].literal[i] / oper->children[1].literal[i];
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         oper->type = literal_type(oper->children[0].type, 
-                                   oper->children[1].type);
-         slang_operation_destruct(oper);
-         return;
-      default:
-         ; /* nothing */
-      }
-   }
-
-   if (oper->num_children == 1 && isFloat[0]) {
-      switch (oper->type) {
-      case SLANG_OPER_MINUS:
-         for (i = 0; i < 4; i++) {
-            oper->literal[i] = -oper->children[0].literal[i];
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         slang_operation_destruct(oper);
-         oper->type = SLANG_OPER_LITERAL_FLOAT;
-         return;
-      case SLANG_OPER_PLUS:
-         COPY_4V(oper->literal, oper->children[0].literal);
-         oper->literal_size = oper->children[0].literal_size;
-         slang_operation_destruct(oper);
-         oper->type = SLANG_OPER_LITERAL_FLOAT;
-         return;
-      default:
-         ; /* nothing */
-      }
-   }
-
-   if (oper->num_children == 2 && isBool[0] && isBool[1]) {
-      /* simple boolean expression */
-      switch (oper->type) {
-      case SLANG_OPER_LOGICALAND:
-         for (i = 0; i < 4; i++) {
-            const GLint a = oper->children[0].literal[i] ? 1 : 0;
-            const GLint b = oper->children[1].literal[i] ? 1 : 0;
-            oper->literal[i] = (GLfloat) (a && b);
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         slang_operation_destruct(oper);
-         oper->type = SLANG_OPER_LITERAL_BOOL;
-         return;
-      case SLANG_OPER_LOGICALOR:
-         for (i = 0; i < 4; i++) {
-            const GLint a = oper->children[0].literal[i] ? 1 : 0;
-            const GLint b = oper->children[1].literal[i] ? 1 : 0;
-            oper->literal[i] = (GLfloat) (a || b);
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         slang_operation_destruct(oper);
-         oper->type = SLANG_OPER_LITERAL_BOOL;
-         return;
-      case SLANG_OPER_LOGICALXOR:
-         for (i = 0; i < 4; i++) {
-            const GLint a = oper->children[0].literal[i] ? 1 : 0;
-            const GLint b = oper->children[1].literal[i] ? 1 : 0;
-            oper->literal[i] = (GLfloat) (a ^ b);
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         slang_operation_destruct(oper);
-         oper->type = SLANG_OPER_LITERAL_BOOL;
-         return;
-      default:
-         ; /* nothing */
-      }
-   }
-
-   if (oper->num_children == 4
-       && isFloat[0] && isFloat[1] && isFloat[2] && isFloat[3]) {
-      /* vec4(flt, flt, flt, flt) constructor */
-      if (oper->type == SLANG_OPER_CALL) {
-         if (strcmp((char *) oper->a_id, "vec4") == 0) {
-            oper->literal[0] = oper->children[0].literal[0];
-            oper->literal[1] = oper->children[1].literal[0];
-            oper->literal[2] = oper->children[2].literal[0];
-            oper->literal[3] = oper->children[3].literal[0];
-            oper->literal_size = 4;
-            slang_operation_destruct(oper);
-            oper->type = SLANG_OPER_LITERAL_FLOAT;
-            return;
-         }
-      }
-   }
-
-   if (oper->num_children == 3 && isFloat[0] && isFloat[1] && isFloat[2]) {
-      /* vec3(flt, flt, flt) constructor */
-      if (oper->type == SLANG_OPER_CALL) {
-         if (strcmp((char *) oper->a_id, "vec3") == 0) {
-            oper->literal[0] = oper->children[0].literal[0];
-            oper->literal[1] = oper->children[1].literal[0];
-            oper->literal[2] = oper->children[2].literal[0];
-            oper->literal[3] = oper->literal[2];
-            oper->literal_size = 3;
-            slang_operation_destruct(oper);
-            oper->type = SLANG_OPER_LITERAL_FLOAT;
-            return;
-         }
-      }
-   }
-
-   if (oper->num_children == 2 && isFloat[0] && isFloat[1]) {
-      /* vec2(flt, flt) constructor */
-      if (oper->type == SLANG_OPER_CALL) {
-         if (strcmp((char *) oper->a_id, "vec2") == 0) {
-            oper->literal[0] = oper->children[0].literal[0];
-            oper->literal[1] = oper->children[1].literal[0];
-            oper->literal[2] = oper->literal[1];
-            oper->literal[3] = oper->literal[1];
-            oper->literal_size = 2;
-            slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */
-            oper->type = SLANG_OPER_LITERAL_FLOAT;
-            assert(oper->num_children == 0);
-            return;
-         }
-      }
-   }
-
-   if (oper->num_children == 1 && isFloat[0]) {
-      /* vec2/3/4(flt, flt) constructor */
-      if (oper->type == SLANG_OPER_CALL) {
-         const char *func = (const char *) oper->a_id;
-         if (strncmp(func, "vec", 3) == 0 && func[3] >= '2' && func[3] <= '4') {
-            oper->literal[0] =
-            oper->literal[1] =
-            oper->literal[2] =
-            oper->literal[3] = oper->children[0].literal[0];
-            oper->literal_size = func[3] - '0';
-            assert(oper->literal_size >= 2);
-            assert(oper->literal_size <= 4);
-            slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */
-            oper->type = SLANG_OPER_LITERAL_FLOAT;
-            assert(oper->num_children == 0);
-            return;
-         }
-      }
-   }
-}
-
-
-
-/**
- * Insert casts to try to adapt actual parameters to formal parameters for a
- * function call when an exact match for the parameter types is not found.
- * Example:
- *   void foo(int i, bool b) {}
- *   x = foo(3.15, 9);
- * Gets translated into:
- *   x = foo(int(3.15), bool(9))
- */
-GLboolean
-_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
-                        const slang_name_space * space,
-                        slang_atom_pool * atoms, slang_info_log *log)
-{
-   const GLboolean haveRetValue = _slang_function_has_return_value(fun);
-   const int numParams = fun->param_count - haveRetValue;
-   int i;
-   int dbg = 0;
-
-   if (dbg)
-      printf("Adapt call of %d args to func %s (%d params)\n",
-             callOper->num_children, (char*) fun->header.a_name, numParams);
-
-   for (i = 0; i < numParams; i++) {
-      slang_typeinfo argType;
-      slang_variable *paramVar = fun->parameters->variables[i];
-
-      /* Get type of arg[i] */
-      if (!slang_typeinfo_construct(&argType))
-         return GL_FALSE;
-      if (!_slang_typeof_operation(&callOper->children[i], space,
-                                    &argType, atoms, log)) {
-         slang_typeinfo_destruct(&argType);
-         return GL_FALSE;
-      }
-
-      /* see if arg type matches parameter type */
-      if (!slang_type_specifier_equal(&argType.spec,
-                                      &paramVar->type.specifier)) {
-         /* need to adapt arg type to match param type */
-         const char *constructorName =
-            slang_type_specifier_type_to_string(paramVar->type.specifier.type);
-         slang_operation *child = slang_operation_new(1);
-
-         if (dbg)
-            printf("Need to adapt types of arg %d\n", i);
-
-         slang_operation_copy(child, &callOper->children[i]);
-         child->locals->outer_scope = callOper->children[i].locals;
-
-#if 0
-         if (_slang_sizeof_type_specifier(&argType.spec) >
-             _slang_sizeof_type_specifier(&paramVar->type.specifier)) {
-         }
-#endif
-
-         callOper->children[i].type = SLANG_OPER_CALL;
-         callOper->children[i].a_id = slang_atom_pool_atom(atoms, constructorName);
-         callOper->children[i].num_children = 1;
-         callOper->children[i].children = child;
-      }
-
-      slang_typeinfo_destruct(&argType);
-   }
-
-   if (dbg) {
-      printf("===== New call to %s with cast arguments ===============\n",
-             (char*) fun->header.a_name);
-      slang_print_tree(callOper, 5);
-   }
-
-   return GL_TRUE;
-}
-
-
-/**
- * Adapt the arguments for a function call to match the parameters of
- * the given function.
- * This is for:
- * 1. converting/casting argument types to match parameters
- * 2. breaking up vector/matrix types into individual components to
- *    satisfy constructors.
- */
-GLboolean
-_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
-                  const slang_name_space * space,
-                  slang_atom_pool * atoms, slang_info_log *log)
-{
-   const GLboolean haveRetValue = _slang_function_has_return_value(fun);
-   const int numParams = fun->param_count - haveRetValue;
-   int i;
-   int dbg = 0;
-
-   if (dbg)
-      printf("Adapt %d args to %d parameters for %s\n",
-             callOper->num_children, numParams, (char *) fun->header.a_name);
-
-   /* Only try adapting for constructors */
-   if (fun->kind != SLANG_FUNC_CONSTRUCTOR)
-      return GL_FALSE;
-
-   if (callOper->num_children != numParams) {
-      /* number of arguments doesn't match number of parameters */
-
-      /* For constructor calls, we can try to unroll vector/matrix args
-       * into individual floats/ints and try to match the function params.
-       */
-      for (i = 0; i < numParams; i++) {
-         slang_typeinfo argType;
-         GLint argSz, j;
-
-         /* Get type of arg[i] */
-         if (!slang_typeinfo_construct(&argType))
-            return GL_FALSE;
-         if (!_slang_typeof_operation(&callOper->children[i], space,
-                                       &argType, atoms, log)) {
-            slang_typeinfo_destruct(&argType);
-            return GL_FALSE;
-         }
-
-         /*
-           paramSz = _slang_sizeof_type_specifier(&paramVar->type.specifier);
-           assert(paramSz == 1);
-         */
-         argSz = _slang_sizeof_type_specifier(&argType.spec);
-         if (argSz > 1) {
-            slang_operation origArg;
-            /* break up arg[i] into components */
-            if (dbg)
-               printf("Break up arg %d from 1 to %d elements\n", i, argSz);
-
-            slang_operation_construct(&origArg);
-            slang_operation_copy(&origArg, &callOper->children[i]);
-
-            /* insert argSz-1 new children/args */
-            for (j = 0; j < argSz - 1; j++) {
-               (void) slang_operation_insert(&callOper->num_children,
-                                             &callOper->children, i);
-            }
-
-            /* replace arg[i+j] with subscript/index oper */
-            for (j = 0; j < argSz; j++) {
-               callOper->children[i + j].type = SLANG_OPER_SUBSCRIPT;
-               callOper->children[i + j].locals = _slang_variable_scope_new(callOper->locals);
-               callOper->children[i + j].num_children = 2;
-               callOper->children[i + j].children = slang_operation_new(2);
-               slang_operation_copy(&callOper->children[i + j].children[0],
-                                    &origArg);
-               callOper->children[i + j].children[1].type
-                  = SLANG_OPER_LITERAL_INT;
-               callOper->children[i + j].children[1].literal[0] = (GLfloat) j;
-            }
-         }
-      }
-   }
-
-   if (callOper->num_children < (GLuint) numParams) {
-      /* still not enough args for all params */
-      return GL_FALSE;
-   }
-   else if (callOper->num_children > (GLuint) numParams) {
-      /* now too many arguments */
-      /* just truncate */
-      callOper->num_children = (GLuint) numParams;
-   }
-
-   if (dbg) {
-      printf("===== New call to %s with adapted arguments ===============\n",
-             (char*) fun->header.a_name);
-      slang_print_tree(callOper, 5);
-   }
-
-   return GL_TRUE;
-}
diff --git a/src/mesa/shader/slang/slang_simplify.h b/src/mesa/shader/slang/slang_simplify.h
deleted file mode 100644 (file)
index 8689c23..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.1
- *
- * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_SIMPLIFY_H
-#define SLANG_SIMPLIFY_H
-
-
-extern GLint
-_slang_lookup_constant(const char *name);
-
-
-extern void
-_slang_simplify(slang_operation *oper,
-                const slang_name_space * space,
-                slang_atom_pool * atoms);
-
-
-extern GLboolean
-_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
-                        const slang_name_space * space,
-                        slang_atom_pool * atoms, slang_info_log *log);
-
-extern GLboolean
-_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
-                  const slang_name_space * space,
-                  slang_atom_pool * atoms, slang_info_log *log);
-
-
-#endif /* SLANG_SIMPLIFY_H */
diff --git a/src/mesa/shader/slang/slang_storage.c b/src/mesa/shader/slang/slang_storage.c
deleted file mode 100644 (file)
index 656e156..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_storage.c
- * slang variable storage
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_storage.h"
-#include "slang_mem.h"
-
-/* slang_storage_array */
-
-GLboolean
-slang_storage_array_construct(slang_storage_array * arr)
-{
-   arr->type = SLANG_STORE_AGGREGATE;
-   arr->aggregate = NULL;
-   arr->length = 0;
-   return GL_TRUE;
-}
-
-GLvoid
-slang_storage_array_destruct(slang_storage_array * arr)
-{
-   if (arr->aggregate != NULL) {
-      slang_storage_aggregate_destruct(arr->aggregate);
-      _slang_free(arr->aggregate);
-   }
-}
-
-/* slang_storage_aggregate */
-
-GLboolean
-slang_storage_aggregate_construct(slang_storage_aggregate * agg)
-{
-   agg->arrays = NULL;
-   agg->count = 0;
-   return GL_TRUE;
-}
-
-GLvoid
-slang_storage_aggregate_destruct(slang_storage_aggregate * agg)
-{
-   GLuint i;
-
-   for (i = 0; i < agg->count; i++)
-      slang_storage_array_destruct(agg->arrays + i);
-   _slang_free(agg->arrays);
-}
-
-static slang_storage_array *
-slang_storage_aggregate_push_new(slang_storage_aggregate * agg)
-{
-   slang_storage_array *arr = NULL;
-
-   agg->arrays = (slang_storage_array *)
-      _slang_realloc(agg->arrays,
-                     agg->count * sizeof(slang_storage_array),
-                     (agg->count + 1) * sizeof(slang_storage_array));
-   if (agg->arrays != NULL) {
-      arr = agg->arrays + agg->count;
-      if (!slang_storage_array_construct(arr))
-         return NULL;
-      agg->count++;
-   }
-   return arr;
-}
-
-/* _slang_aggregate_variable() */
-
-static GLboolean
-aggregate_vector(slang_storage_aggregate * agg, slang_storage_type basic_type,
-                 GLuint row_count)
-{
-   slang_storage_array *arr = slang_storage_aggregate_push_new(agg);
-   if (arr == NULL)
-      return GL_FALSE;
-   arr->type = basic_type;
-   arr->length = row_count;
-   return GL_TRUE;
-}
-
-static GLboolean
-aggregate_matrix(slang_storage_aggregate * agg, slang_storage_type basic_type,
-                 GLuint columns, GLuint rows)
-{
-   slang_storage_array *arr = slang_storage_aggregate_push_new(agg);
-   if (arr == NULL)
-      return GL_FALSE;
-   arr->type = SLANG_STORE_AGGREGATE;
-   arr->length = columns;
-   arr->aggregate = (slang_storage_aggregate *)
-      _slang_alloc(sizeof(slang_storage_aggregate));
-   if (arr->aggregate == NULL)
-      return GL_FALSE;
-   if (!slang_storage_aggregate_construct(arr->aggregate)) {
-      _slang_free(arr->aggregate);
-      arr->aggregate = NULL;
-      return GL_FALSE;
-   }
-   if (!aggregate_vector(arr->aggregate, basic_type, rows))
-      return GL_FALSE;
-   return GL_TRUE;
-}
-
-
-static GLboolean
-aggregate_variables(slang_storage_aggregate * agg,
-                    slang_variable_scope * vars, slang_function_scope * funcs,
-                    slang_struct_scope * structs,
-                    slang_variable_scope * globals,
-                    slang_atom_pool * atoms)
-{
-   GLuint i;
-
-   for (i = 0; i < vars->num_variables; i++)
-      if (!_slang_aggregate_variable(agg, &vars->variables[i]->type.specifier,
-                                     vars->variables[i]->array_len, funcs,
-                                     structs, globals, atoms))
-         return GL_FALSE;
-   return GL_TRUE;
-}
-
-
-GLboolean
-_slang_aggregate_variable(slang_storage_aggregate * agg,
-                          slang_type_specifier * spec, GLuint array_len,
-                          slang_function_scope * funcs,
-                          slang_struct_scope * structs,
-                          slang_variable_scope * vars,
-                          slang_atom_pool * atoms)
-{
-   switch (spec->type) {
-   case SLANG_SPEC_BOOL:
-      return aggregate_vector(agg, SLANG_STORE_BOOL, 1);
-   case SLANG_SPEC_BVEC2:
-      return aggregate_vector(agg, SLANG_STORE_BOOL, 2);
-   case SLANG_SPEC_BVEC3:
-      return aggregate_vector(agg, SLANG_STORE_BOOL, 3);
-   case SLANG_SPEC_BVEC4:
-      return aggregate_vector(agg, SLANG_STORE_BOOL, 4);
-   case SLANG_SPEC_INT:
-      return aggregate_vector(agg, SLANG_STORE_INT, 1);
-   case SLANG_SPEC_IVEC2:
-      return aggregate_vector(agg, SLANG_STORE_INT, 2);
-   case SLANG_SPEC_IVEC3:
-      return aggregate_vector(agg, SLANG_STORE_INT, 3);
-   case SLANG_SPEC_IVEC4:
-      return aggregate_vector(agg, SLANG_STORE_INT, 4);
-   case SLANG_SPEC_FLOAT:
-      return aggregate_vector(agg, SLANG_STORE_FLOAT, 1);
-   case SLANG_SPEC_VEC2:
-      return aggregate_vector(agg, SLANG_STORE_FLOAT, 2);
-   case SLANG_SPEC_VEC3:
-      return aggregate_vector(agg, SLANG_STORE_FLOAT, 3);
-   case SLANG_SPEC_VEC4:
-      return aggregate_vector(agg, SLANG_STORE_FLOAT, 4);
-   case SLANG_SPEC_MAT2:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 2);
-   case SLANG_SPEC_MAT3:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 3);
-   case SLANG_SPEC_MAT4:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 4);
-
-   case SLANG_SPEC_MAT23:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 3);
-   case SLANG_SPEC_MAT32:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 2);
-   case SLANG_SPEC_MAT24:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 4);
-   case SLANG_SPEC_MAT42:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 2);
-   case SLANG_SPEC_MAT34:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 4);
-   case SLANG_SPEC_MAT43:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 3);
-
-   case SLANG_SPEC_SAMPLER_1D:
-   case SLANG_SPEC_SAMPLER_2D:
-   case SLANG_SPEC_SAMPLER_3D:
-   case SLANG_SPEC_SAMPLER_CUBE:
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-   case SLANG_SPEC_SAMPLER_RECT:
-   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
-   case SLANG_SPEC_SAMPLER_1D_ARRAY:
-   case SLANG_SPEC_SAMPLER_2D_ARRAY:
-   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
-   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
-
-      return aggregate_vector(agg, SLANG_STORE_INT, 1);
-   case SLANG_SPEC_STRUCT:
-      return aggregate_variables(agg, spec->_struct->fields, funcs, structs,
-                                 vars, atoms);
-   case SLANG_SPEC_ARRAY:
-      {
-         slang_storage_array *arr;
-
-         arr = slang_storage_aggregate_push_new(agg);
-         if (arr == NULL)
-            return GL_FALSE;
-         arr->type = SLANG_STORE_AGGREGATE;
-         arr->aggregate = (slang_storage_aggregate *)
-            _slang_alloc(sizeof(slang_storage_aggregate));
-         if (arr->aggregate == NULL)
-            return GL_FALSE;
-         if (!slang_storage_aggregate_construct(arr->aggregate)) {
-            _slang_free(arr->aggregate);
-            arr->aggregate = NULL;
-            return GL_FALSE;
-         }
-         if (!_slang_aggregate_variable(arr->aggregate, spec->_array, 0,
-                                        funcs, structs, vars, atoms))
-            return GL_FALSE;
-         arr->length = array_len;
-         /* TODO: check if 0 < arr->length <= 65535 */
-      }
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-GLuint
-_slang_sizeof_type(slang_storage_type type)
-{
-   if (type == SLANG_STORE_AGGREGATE)
-      return 0;
-   if (type == SLANG_STORE_VEC4)
-      return 4 * sizeof(GLfloat);
-   return sizeof(GLfloat);
-}
-
-
-GLuint
-_slang_sizeof_aggregate(const slang_storage_aggregate * agg)
-{
-   GLuint i, size = 0;
-
-   for (i = 0; i < agg->count; i++) {
-      slang_storage_array *arr = &agg->arrays[i];
-      GLuint element_size;
-
-      if (arr->type == SLANG_STORE_AGGREGATE)
-         element_size = _slang_sizeof_aggregate(arr->aggregate);
-      else
-         element_size = _slang_sizeof_type(arr->type);
-      size += element_size * arr->length;
-   }
-   return size;
-}
-
-
-#if 0
-GLboolean
-_slang_flatten_aggregate(slang_storage_aggregate * flat,
-                         const slang_storage_aggregate * agg)
-{
-   GLuint i;
-
-   for (i = 0; i < agg->count; i++) {
-      GLuint j;
-
-      for (j = 0; j < agg->arrays[i].length; j++) {
-         if (agg->arrays[i].type == SLANG_STORE_AGGREGATE) {
-            if (!_slang_flatten_aggregate(flat, agg->arrays[i].aggregate))
-               return GL_FALSE;
-         }
-         else {
-            GLuint k, count;
-            slang_storage_type type;
-
-            if (agg->arrays[i].type == SLANG_STORE_VEC4) {
-               count = 4;
-               type = SLANG_STORE_FLOAT;
-            }
-            else {
-               count = 1;
-               type = agg->arrays[i].type;
-            }
-
-            for (k = 0; k < count; k++) {
-               slang_storage_array *arr;
-
-               arr = slang_storage_aggregate_push_new(flat);
-               if (arr == NULL)
-                  return GL_FALSE;
-               arr->type = type;
-               arr->length = 1;
-            }
-         }
-      }
-   }
-   return GL_TRUE;
-}
-#endif
diff --git a/src/mesa/shader/slang/slang_storage.h b/src/mesa/shader/slang/slang_storage.h
deleted file mode 100644 (file)
index 1876a36..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_STORAGE_H
-#define SLANG_STORAGE_H
-
-#include "slang_compile.h"
-
-
-/*
- * Program variable data storage is kept completely transparent to the
- * front-end compiler. It is up to the back-end how the data is
- * actually allocated. The slang_storage_type enum provides the basic
- * information about how the memory is interpreted. This abstract
- * piece of memory is called a data slot. A data slot of a particular
- * type has a fixed size.
- *
- * For now, only the three basic types are supported, that is bool,
- * int and float. Other built-in types like vector or matrix can
- * easily be decomposed into a series of basic types.
- *
- * If the vec4 module is enabled, 4-component vectors of floats are
- * used when possible. 4x4 matrices are constructed of 4 vec4 slots.
- */
-typedef enum slang_storage_type_
-{
-   /* core */
-   SLANG_STORE_AGGREGATE,
-   SLANG_STORE_BOOL,
-   SLANG_STORE_INT,
-   SLANG_STORE_FLOAT,
-   /* vec4 */
-   SLANG_STORE_VEC4
-} slang_storage_type;
-
-
-/**
- * The slang_storage_array structure groups data slots of the same
- * type into an array. This array has a fixed length. Arrays are
- * required to have a size equal to the sum of sizes of its
- * elements. They are also required to support indirect
- * addressing. That is, if B references first data slot in the array,
- * S is the size of the data slot and I is the integral index that is
- * not known at compile time, B+I*S references I-th data slot.
- *
- * This structure is also used to break down built-in data types that
- * are not supported directly.  Vectors, like vec3, are constructed
- * from arrays of their basic types. Matrices are formed of an array
- * of column vectors, which are in turn processed as other vectors.
- */
-typedef struct slang_storage_array_
-{
-   slang_storage_type type;
-   struct slang_storage_aggregate_ *aggregate;
-   GLuint length;
-} slang_storage_array;
-
-GLboolean slang_storage_array_construct (slang_storage_array *);
-GLvoid slang_storage_array_destruct (slang_storage_array *);
-
-
-/**
- * The slang_storage_aggregate structure relaxes the indirect
- * addressing requirement for slang_storage_array
- * structure. Aggregates are always accessed statically - its member
- * addresses are well-known at compile time. For example, user-defined
- * types are implemented as aggregates. Aggregates can collect data of
- * a different type.
- */
-typedef struct slang_storage_aggregate_
-{
-   slang_storage_array *arrays;
-   GLuint count;
-} slang_storage_aggregate;
-
-GLboolean slang_storage_aggregate_construct (slang_storage_aggregate *);
-GLvoid slang_storage_aggregate_destruct (slang_storage_aggregate *);
-
-
-extern GLboolean
-_slang_aggregate_variable(slang_storage_aggregate *agg,
-                          slang_type_specifier *spec,
-                          GLuint array_len,
-                          slang_function_scope *funcs,
-                          slang_struct_scope *structs,
-                          slang_variable_scope *vars,
-                          slang_atom_pool *atoms);
-
-/*
- * Returns the size (in machine units) of the given storage type.
- * It is an error to pass-in SLANG_STORE_AGGREGATE.
- * Returns 0 on error.
- */
-extern GLuint
-_slang_sizeof_type (slang_storage_type);
-
-
-/**
- * Returns total size (in machine units) of the given aggregate.
- * Returns 0 on error.
- */
-extern GLuint
-_slang_sizeof_aggregate (const slang_storage_aggregate *);
-
-
-#if 0
-/**
- * Converts structured aggregate to a flat one, with arrays of generic
- * type being one-element long.  Returns GL_TRUE on success.  Returns
- * GL_FALSE otherwise.
- */
-extern GLboolean
-_slang_flatten_aggregate (slang_storage_aggregate *,
-                          const slang_storage_aggregate *);
-
-#endif
-
-#endif /* SLANG_STORAGE_H */
diff --git a/src/mesa/shader/slang/slang_typeinfo.c b/src/mesa/shader/slang/slang_typeinfo.c
deleted file mode 100644 (file)
index 0f96768..0000000
+++ /dev/null
@@ -1,1177 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_typeinfo.c
- * slang type info
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "shader/prog_instruction.h"
-#include "slang_typeinfo.h"
-#include "slang_compile.h"
-#include "slang_log.h"
-#include "slang_mem.h"
-
-
-/**
- * Checks if a field selector is a general swizzle (an r-value swizzle
- * with replicated components or an l-value swizzle mask) for a
- * vector.  Returns GL_TRUE if this is the case, <swz> is filled with
- * swizzle information.  Returns GL_FALSE otherwise.
- */
-GLboolean
-_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz)
-{
-   GLuint i;
-   GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE;
-
-   /* init to undefined.
-    * We rely on undefined/nil values to distinguish between
-    * regular swizzles and writemasks.
-    * For example, the swizzle ".xNNN" is the writemask ".x".
-    * That's different than the swizzle ".xxxx".
-    */
-   for (i = 0; i < 4; i++)
-      swz->swizzle[i] = SWIZZLE_NIL;
-
-   /* the swizzle can be at most 4-component long */
-   swz->num_components = slang_string_length(field);
-   if (swz->num_components > 4)
-      return GL_FALSE;
-
-   for (i = 0; i < swz->num_components; i++) {
-      /* mark which swizzle group is used */
-      switch (field[i]) {
-      case 'x':
-      case 'y':
-      case 'z':
-      case 'w':
-         xyzw = GL_TRUE;
-         break;
-      case 'r':
-      case 'g':
-      case 'b':
-      case 'a':
-         rgba = GL_TRUE;
-         break;
-      case 's':
-      case 't':
-      case 'p':
-      case 'q':
-         stpq = GL_TRUE;
-         break;
-      default:
-         return GL_FALSE;
-      }
-
-      /* collect swizzle component */
-      switch (field[i]) {
-      case 'x':
-      case 'r':
-      case 's':
-         swz->swizzle[i] = 0;
-         break;
-      case 'y':
-      case 'g':
-      case 't':
-         swz->swizzle[i] = 1;
-         break;
-      case 'z':
-      case 'b':
-      case 'p':
-         swz->swizzle[i] = 2;
-         break;
-      case 'w':
-      case 'a':
-      case 'q':
-         swz->swizzle[i] = 3;
-         break;
-      }
-
-      /* check if the component is valid for given vector's row count */
-      if (rows <= swz->swizzle[i])
-         return GL_FALSE;
-   }
-
-   /* only one swizzle group can be used */
-   if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
-      return GL_FALSE;
-
-   return GL_TRUE;
-}
-
-
-
-/**
- * Checks if a general swizzle is an l-value swizzle - these swizzles
- * do not have duplicated fields.  Returns GL_TRUE if this is a
- * swizzle mask.  Returns GL_FALSE otherwise
- */
-static GLboolean
-_slang_is_swizzle_mask(const slang_swizzle * swz, GLuint rows)
-{
-   GLuint i, c = 0;
-
-   /* the swizzle may not be longer than the vector dim */
-   if (swz->num_components > rows)
-      return GL_FALSE;
-
-   /* the swizzle components cannot be duplicated */
-   for (i = 0; i < swz->num_components; i++) {
-      if ((c & (1 << swz->swizzle[i])) != 0)
-         return GL_FALSE;
-      c |= 1 << swz->swizzle[i];
-   }
-
-   return GL_TRUE;
-}
-
-
-/**
- * Combines (multiplies) two swizzles to form single swizzle.
- * Example: "vec.wzyx.yx" --> "vec.zw".
- */
-static void
-_slang_multiply_swizzles(slang_swizzle * dst, const slang_swizzle * left,
-                         const slang_swizzle * right)
-{
-   GLuint i;
-
-   dst->num_components = right->num_components;
-   for (i = 0; i < right->num_components; i++)
-      dst->swizzle[i] = left->swizzle[right->swizzle[i]];
-}
-
-
-typedef struct
-{
-   const char *name;
-   slang_type_specifier_type type;
-} type_specifier_type_name;
-
-static const type_specifier_type_name type_specifier_type_names[] = {
-   {"void", SLANG_SPEC_VOID},
-   {"bool", SLANG_SPEC_BOOL},
-   {"bvec2", SLANG_SPEC_BVEC2},
-   {"bvec3", SLANG_SPEC_BVEC3},
-   {"bvec4", SLANG_SPEC_BVEC4},
-   {"int", SLANG_SPEC_INT},
-   {"ivec2", SLANG_SPEC_IVEC2},
-   {"ivec3", SLANG_SPEC_IVEC3},
-   {"ivec4", SLANG_SPEC_IVEC4},
-   {"float", SLANG_SPEC_FLOAT},
-   {"vec2", SLANG_SPEC_VEC2},
-   {"vec3", SLANG_SPEC_VEC3},
-   {"vec4", SLANG_SPEC_VEC4},
-   {"mat2", SLANG_SPEC_MAT2},
-   {"mat3", SLANG_SPEC_MAT3},
-   {"mat4", SLANG_SPEC_MAT4},
-   {"mat2x3", SLANG_SPEC_MAT23},
-   {"mat3x2", SLANG_SPEC_MAT32},
-   {"mat2x4", SLANG_SPEC_MAT24},
-   {"mat4x2", SLANG_SPEC_MAT42},
-   {"mat3x4", SLANG_SPEC_MAT34},
-   {"mat4x3", SLANG_SPEC_MAT43},
-   {"sampler1D", SLANG_SPEC_SAMPLER_1D},
-   {"sampler2D", SLANG_SPEC_SAMPLER_2D},
-   {"sampler3D", SLANG_SPEC_SAMPLER_3D},
-   {"samplerCube", SLANG_SPEC_SAMPLER_CUBE},
-   {"sampler1DShadow", SLANG_SPEC_SAMPLER_1D_SHADOW},
-   {"sampler2DShadow", SLANG_SPEC_SAMPLER_2D_SHADOW},
-   {"sampler2DRect", SLANG_SPEC_SAMPLER_RECT},
-   {"sampler2DRectShadow", SLANG_SPEC_SAMPLER_RECT_SHADOW},
-   {"sampler1DArray", SLANG_SPEC_SAMPLER_1D_ARRAY},
-   {"sampler2DArray", SLANG_SPEC_SAMPLER_2D_ARRAY},
-   {"sampler1DArrayShadow", SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW},
-   {"sampler2DArrayShadow", SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW},
-   {NULL, SLANG_SPEC_VOID}
-};
-
-slang_type_specifier_type
-slang_type_specifier_type_from_string(const char *name)
-{
-   const type_specifier_type_name *p = type_specifier_type_names;
-   while (p->name != NULL) {
-      if (slang_string_compare(p->name, name) == 0)
-         break;
-      p++;
-   }
-   return p->type;
-}
-
-const char *
-slang_type_specifier_type_to_string(slang_type_specifier_type type)
-{
-   const type_specifier_type_name *p = type_specifier_type_names;
-   while (p->name != NULL) {
-      if (p->type == type)
-         break;
-      p++;
-   }
-   return p->name;
-}
-
-/* slang_fully_specified_type */
-
-int
-slang_fully_specified_type_construct(slang_fully_specified_type * type)
-{
-   type->qualifier = SLANG_QUAL_NONE;
-   slang_type_specifier_ctr(&type->specifier);
-   return 1;
-}
-
-void
-slang_fully_specified_type_destruct(slang_fully_specified_type * type)
-{
-   slang_type_specifier_dtr(&type->specifier);
-}
-
-int
-slang_fully_specified_type_copy(slang_fully_specified_type * x,
-                                const slang_fully_specified_type * y)
-{
-   slang_fully_specified_type z;
-
-   if (!slang_fully_specified_type_construct(&z))
-      return 0;
-   z.qualifier = y->qualifier;
-   z.precision = y->precision;
-   z.variant = y->variant;
-   z.centroid = y->centroid;
-   z.layout = y->layout;
-   z.array_len = y->array_len;
-   if (!slang_type_specifier_copy(&z.specifier, &y->specifier)) {
-      slang_fully_specified_type_destruct(&z);
-      return 0;
-   }
-   slang_fully_specified_type_destruct(x);
-   *x = z;
-   return 1;
-}
-
-
-/**
- * Test if two fully specified types are compatible.  This is a bit
- * looser than testing for equality.  We don't check the precision,
- * variant, centroid, etc. information.
- * XXX this may need some tweaking.
- */
-GLboolean
-slang_fully_specified_types_compatible(const slang_fully_specified_type * x,
-                                       const slang_fully_specified_type * y)
-{
-   if (!slang_type_specifier_equal(&x->specifier, &y->specifier))
-      return GL_FALSE;
-
-   if (x->qualifier == SLANG_QUAL_FIXEDINPUT &&
-       y->qualifier == SLANG_QUAL_VARYING)
-      ; /* ok */
-   else if (x->qualifier != y->qualifier)
-      return GL_FALSE;
-
-   /* Note: don't compare precision, variant, centroid */
-
-   /* XXX array length? */
-
-   return GL_TRUE;
-}
-
-
-GLvoid
-slang_type_specifier_ctr(slang_type_specifier * self)
-{
-   self->type = SLANG_SPEC_VOID;
-   self->_struct = NULL;
-   self->_array = NULL;
-}
-
-GLvoid
-slang_type_specifier_dtr(slang_type_specifier * self)
-{
-   if (self->_struct != NULL) {
-      slang_struct_destruct(self->_struct);
-      _slang_free(self->_struct);
-   }
-   if (self->_array != NULL) {
-      slang_type_specifier_dtr(self->_array);
-      _slang_free(self->_array);
-   }
-}
-
-slang_type_specifier *
-slang_type_specifier_new(slang_type_specifier_type type,
-                         struct slang_struct_ *_struct,
-                         struct slang_type_specifier_ *_array)
-{
-   slang_type_specifier *spec =
-      (slang_type_specifier *) _slang_alloc(sizeof(slang_type_specifier));
-   if (spec) {
-      spec->type = type;
-      spec->_struct = _struct;
-      spec->_array = _array;
-   }
-   return spec;
-}
-
-GLboolean
-slang_type_specifier_copy(slang_type_specifier * x,
-                          const slang_type_specifier * y)
-{
-   slang_type_specifier z;
-
-   slang_type_specifier_ctr(&z);
-   z.type = y->type;
-   if (z.type == SLANG_SPEC_STRUCT) {
-      z._struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
-      if (z._struct == NULL) {
-         slang_type_specifier_dtr(&z);
-         return GL_FALSE;
-      }
-      if (!slang_struct_construct(z._struct)) {
-         _slang_free(z._struct);
-         slang_type_specifier_dtr(&z);
-         return GL_FALSE;
-      }
-      if (!slang_struct_copy(z._struct, y->_struct)) {
-         slang_type_specifier_dtr(&z);
-         return GL_FALSE;
-      }
-   }
-   else if (z.type == SLANG_SPEC_ARRAY) {
-      z._array = (slang_type_specifier *)
-         _slang_alloc(sizeof(slang_type_specifier));
-      if (z._array == NULL) {
-         slang_type_specifier_dtr(&z);
-         return GL_FALSE;
-      }
-      slang_type_specifier_ctr(z._array);
-      if (!slang_type_specifier_copy(z._array, y->_array)) {
-         slang_type_specifier_dtr(&z);
-         return GL_FALSE;
-      }
-   }
-   slang_type_specifier_dtr(x);
-   *x = z;
-   return GL_TRUE;
-}
-
-
-/**
- * Test if two types are equal.
- */
-GLboolean
-slang_type_specifier_equal(const slang_type_specifier * x,
-                           const slang_type_specifier * y)
-{
-   if (x->type != y->type)
-      return GL_FALSE;
-   if (x->type == SLANG_SPEC_STRUCT)
-      return slang_struct_equal(x->_struct, y->_struct);
-   if (x->type == SLANG_SPEC_ARRAY)
-      return slang_type_specifier_equal(x->_array, y->_array);
-   return GL_TRUE;
-}
-
-
-/**
- * As above, but allow float/int casting.
- */
-GLboolean
-slang_type_specifier_compatible(const slang_type_specifier * x,
-                                const slang_type_specifier * y)
-{
-   /* special case: float == int */
-   if (x->type == SLANG_SPEC_INT && y->type == SLANG_SPEC_FLOAT) {
-      return GL_TRUE;
-   }
-   /* XXX may need to add bool/int compatibility, etc */
-
-   if (x->type != y->type)
-      return GL_FALSE;
-   if (x->type == SLANG_SPEC_STRUCT)
-      return slang_struct_equal(x->_struct, y->_struct);
-   if (x->type == SLANG_SPEC_ARRAY)
-      return slang_type_specifier_compatible(x->_array, y->_array);
-   return GL_TRUE;
-}
-
-
-GLboolean
-slang_typeinfo_construct(slang_typeinfo * ti)
-{
-   memset(ti, 0, sizeof(*ti));
-   slang_type_specifier_ctr(&ti->spec);
-   ti->array_len = 0;
-   return GL_TRUE;
-}
-
-GLvoid
-slang_typeinfo_destruct(slang_typeinfo * ti)
-{
-   slang_type_specifier_dtr(&ti->spec);
-}
-
-
-
-/**
- * Determine the return type of a function.
- * \param a_name  the function name
- * \param param  function parameters (overloading)
- * \param num_params  number of parameters to function
- * \param space  namespace to search
- * \param spec  returns the type
- * \param funFound  returns pointer to the function, or NULL if not found.
- * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
- */
-static GLboolean
-_slang_typeof_function(slang_atom a_name,
-                       slang_operation * params, GLuint num_params,
-                       const slang_name_space * space,
-                       slang_type_specifier * spec,
-                       slang_function **funFound,
-                       slang_atom_pool *atoms, slang_info_log *log)
-{
-   GLboolean error;
-
-   *funFound = _slang_function_locate(space->funcs, a_name, params,
-                                      num_params, space, atoms, log, &error);
-   if (error)
-      return GL_FALSE;
-
-   if (!*funFound)
-      return GL_TRUE;  /* yes, not false */
-
-   return slang_type_specifier_copy(spec, &(*funFound)->header.type.specifier);
-}
-
-
-/**
- * Determine the type of a math function.
- * \param name  name of the operator, one of +,-,*,/ or unary -
- * \param params  array of function parameters
- * \param num_params  number of parameters
- * \param space  namespace to use
- * \param spec  returns the function's type
- * \param atoms  atom pool
- * \return GL_TRUE for success, GL_FALSE if failure
- */
-static GLboolean
-typeof_math_call(const char *name, slang_operation *call,
-                 const slang_name_space * space,
-                 slang_type_specifier * spec,
-                 slang_atom_pool * atoms,
-                 slang_info_log *log)
-{
-   if (call->fun) {
-      /* we've previously resolved this function call */
-      slang_type_specifier_copy(spec, &call->fun->header.type.specifier);
-      return GL_TRUE;
-   }
-   else {
-      slang_atom atom;
-      slang_function *fun;
-
-      /* number of params: */
-      assert(call->num_children == 1 || call->num_children == 2);
-
-      atom = slang_atom_pool_atom(atoms, name);
-      if (!_slang_typeof_function(atom, call->children, call->num_children,
-                                  space, spec, &fun, atoms, log))
-         return GL_FALSE;
-
-      if (fun) {
-         /* Save pointer to save time in future */
-         call->fun = fun;
-         return GL_TRUE;
-      }
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Determine the return type of an operation.
- * \param op  the operation node
- * \param space  the namespace to use
- * \param ti  the returned type
- * \param atoms  atom pool
- * \return GL_TRUE for success, GL_FALSE if failure
- */
-GLboolean
-_slang_typeof_operation(slang_operation * op,
-                         const slang_name_space * space,
-                         slang_typeinfo * ti,
-                         slang_atom_pool * atoms,
-                         slang_info_log *log)
-{
-   ti->can_be_referenced = GL_FALSE;
-   ti->is_swizzled = GL_FALSE;
-
-   switch (op->type) {
-   case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
-   case SLANG_OPER_BLOCK_NEW_SCOPE:
-   case SLANG_OPER_ASM:
-   case SLANG_OPER_BREAK:
-   case SLANG_OPER_CONTINUE:
-   case SLANG_OPER_DISCARD:
-   case SLANG_OPER_RETURN:
-   case SLANG_OPER_IF:
-   case SLANG_OPER_WHILE:
-   case SLANG_OPER_DO:
-   case SLANG_OPER_FOR:
-   case SLANG_OPER_VOID:
-      ti->spec.type = SLANG_SPEC_VOID;
-      break;
-   case SLANG_OPER_EXPRESSION:
-   case SLANG_OPER_ASSIGN:
-   case SLANG_OPER_ADDASSIGN:
-   case SLANG_OPER_SUBASSIGN:
-   case SLANG_OPER_MULASSIGN:
-   case SLANG_OPER_DIVASSIGN:
-   case SLANG_OPER_PREINCREMENT:
-   case SLANG_OPER_PREDECREMENT:
-      if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
-         return GL_FALSE;
-      break;
-   case SLANG_OPER_LITERAL_BOOL:
-      if (op->literal_size == 1)
-         ti->spec.type = SLANG_SPEC_BOOL;
-      else if (op->literal_size == 2)
-         ti->spec.type = SLANG_SPEC_BVEC2;
-      else if (op->literal_size == 3)
-         ti->spec.type = SLANG_SPEC_BVEC3;
-      else if (op->literal_size == 4)
-         ti->spec.type = SLANG_SPEC_BVEC4;
-      else {
-         _mesa_problem(NULL,
-               "Unexpected bool literal_size %d in _slang_typeof_operation()",
-               op->literal_size);
-         ti->spec.type = SLANG_SPEC_BOOL;
-      }
-      break;
-   case SLANG_OPER_LOGICALOR:
-   case SLANG_OPER_LOGICALXOR:
-   case SLANG_OPER_LOGICALAND:
-   case SLANG_OPER_EQUAL:
-   case SLANG_OPER_NOTEQUAL:
-   case SLANG_OPER_LESS:
-   case SLANG_OPER_GREATER:
-   case SLANG_OPER_LESSEQUAL:
-   case SLANG_OPER_GREATEREQUAL:
-   case SLANG_OPER_NOT:
-      ti->spec.type = SLANG_SPEC_BOOL;
-      break;
-   case SLANG_OPER_LITERAL_INT:
-      if (op->literal_size == 1)
-         ti->spec.type = SLANG_SPEC_INT;
-      else if (op->literal_size == 2)
-         ti->spec.type = SLANG_SPEC_IVEC2;
-      else if (op->literal_size == 3)
-         ti->spec.type = SLANG_SPEC_IVEC3;
-      else if (op->literal_size == 4)
-         ti->spec.type = SLANG_SPEC_IVEC4;
-      else {
-         _mesa_problem(NULL,
-               "Unexpected int literal_size %d in _slang_typeof_operation()",
-               op->literal_size);
-         ti->spec.type = SLANG_SPEC_INT;
-      }
-      break;
-   case SLANG_OPER_LITERAL_FLOAT:
-      if (op->literal_size == 1)
-         ti->spec.type = SLANG_SPEC_FLOAT;
-      else if (op->literal_size == 2)
-         ti->spec.type = SLANG_SPEC_VEC2;
-      else if (op->literal_size == 3)
-         ti->spec.type = SLANG_SPEC_VEC3;
-      else if (op->literal_size == 4)
-         ti->spec.type = SLANG_SPEC_VEC4;
-      else {
-         _mesa_problem(NULL,
-               "Unexpected float literal_size %d in _slang_typeof_operation()",
-               op->literal_size);
-         ti->spec.type = SLANG_SPEC_FLOAT;
-      }
-      break;
-   case SLANG_OPER_IDENTIFIER:
-   case SLANG_OPER_VARIABLE_DECL:
-      {
-         slang_variable *var;
-         var = _slang_variable_locate(op->locals, op->a_id, GL_TRUE);
-         if (!var) {
-            slang_info_log_error(log, "undefined variable '%s'",
-                                 (char *) op->a_id);
-            return GL_FALSE;
-         }
-         if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier)) {
-            slang_info_log_memory(log);
-            return GL_FALSE;
-         }
-         ti->can_be_referenced = GL_TRUE;
-         if (var->type.specifier.type == SLANG_SPEC_ARRAY &&
-             var->type.array_len >= 1) {
-            /* the datatype is an array, ex: float[3] x; */
-            ti->array_len = var->type.array_len;
-         }
-         else {
-            /* the variable is an array, ex: float x[3]; */
-            ti->array_len = var->array_len;
-         }
-      }
-      break;
-   case SLANG_OPER_SEQUENCE:
-      /* TODO: check [0] and [1] if they match */
-      if (!_slang_typeof_operation(&op->children[1], space, ti, atoms, log)) {
-         return GL_FALSE;
-      }
-      ti->can_be_referenced = GL_FALSE;
-      ti->is_swizzled = GL_FALSE;
-      break;
-      /*case SLANG_OPER_MODASSIGN: */
-      /*case SLANG_OPER_LSHASSIGN: */
-      /*case SLANG_OPER_RSHASSIGN: */
-      /*case SLANG_OPER_ORASSIGN: */
-      /*case SLANG_OPER_XORASSIGN: */
-      /*case SLANG_OPER_ANDASSIGN: */
-   case SLANG_OPER_SELECT:
-      /* TODO: check [1] and [2] if they match */
-      if (!_slang_typeof_operation(&op->children[1], space, ti, atoms, log)) {
-         return GL_FALSE;
-      }
-      ti->can_be_referenced = GL_FALSE;
-      ti->is_swizzled = GL_FALSE;
-      break;
-      /*case SLANG_OPER_BITOR: */
-      /*case SLANG_OPER_BITXOR: */
-      /*case SLANG_OPER_BITAND: */
-      /*case SLANG_OPER_LSHIFT: */
-      /*case SLANG_OPER_RSHIFT: */
-   case SLANG_OPER_ADD:
-      assert(op->num_children == 2);
-      if (!typeof_math_call("+", op, space, &ti->spec, atoms, log))
-         return GL_FALSE;
-      break;
-   case SLANG_OPER_SUBTRACT:
-      assert(op->num_children == 2);
-      if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
-         return GL_FALSE;
-      break;
-   case SLANG_OPER_MULTIPLY:
-      assert(op->num_children == 2);
-      if (!typeof_math_call("*", op, space, &ti->spec, atoms, log))
-         return GL_FALSE;
-      break;
-   case SLANG_OPER_DIVIDE:
-      assert(op->num_children == 2);
-      if (!typeof_math_call("/", op, space, &ti->spec, atoms, log))
-         return GL_FALSE;
-      break;
-   /*case SLANG_OPER_MODULUS: */
-   case SLANG_OPER_PLUS:
-      if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
-         return GL_FALSE;
-      ti->can_be_referenced = GL_FALSE;
-      ti->is_swizzled = GL_FALSE;
-      break;
-   case SLANG_OPER_MINUS:
-      assert(op->num_children == 1);
-      if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
-         return GL_FALSE;
-      break;
-      /*case SLANG_OPER_COMPLEMENT: */
-   case SLANG_OPER_SUBSCRIPT:
-      {
-         slang_typeinfo _ti;
-
-         if (!slang_typeinfo_construct(&_ti))
-            return GL_FALSE;
-         if (!_slang_typeof_operation(op->children, space, &_ti, atoms, log)) {
-            slang_typeinfo_destruct(&_ti);
-            return GL_FALSE;
-         }
-         ti->can_be_referenced = _ti.can_be_referenced;
-         if (_ti.spec.type == SLANG_SPEC_ARRAY) {
-            if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
-               slang_typeinfo_destruct(&_ti);
-               return GL_FALSE;
-            }
-         }
-         else {
-            if (!_slang_type_is_vector(_ti.spec.type)
-                && !_slang_type_is_matrix(_ti.spec.type)) {
-               slang_typeinfo_destruct(&_ti);
-               slang_info_log_error(log, "cannot index a non-array type");
-               return GL_FALSE;
-            }
-            ti->spec.type = _slang_type_base(_ti.spec.type);
-         }
-         slang_typeinfo_destruct(&_ti);
-      }
-      break;
-   case SLANG_OPER_CALL:
-      if (op->array_constructor) {
-         /* build array typeinfo */
-         ti->spec.type = SLANG_SPEC_ARRAY;
-         ti->spec._array = (slang_type_specifier *)
-            _slang_alloc(sizeof(slang_type_specifier));
-         slang_type_specifier_ctr(ti->spec._array);
-
-         ti->spec._array->type =
-            slang_type_specifier_type_from_string((char *) op->a_id);
-         ti->array_len = op->num_children;
-      }
-      else if (op->fun) {
-         /* we've resolved this call before */
-         slang_type_specifier_copy(&ti->spec, &op->fun->header.type.specifier);
-      }
-      else {
-         slang_function *fun;
-         if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
-                                     space, &ti->spec, &fun, atoms, log))
-            return GL_FALSE;
-         if (fun) {
-            /* save result for future use */
-            op->fun = fun;
-         }
-         else {
-            slang_struct *s =
-               slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
-            if (s) {
-               /* struct initializer */
-               ti->spec.type = SLANG_SPEC_STRUCT;
-               ti->spec._struct =
-                  (slang_struct *) _slang_alloc(sizeof(slang_struct));
-               if (ti->spec._struct == NULL)
-                  return GL_FALSE;
-               if (!slang_struct_construct(ti->spec._struct)) {
-                  _slang_free(ti->spec._struct);
-                  ti->spec._struct = NULL;
-                  return GL_FALSE;
-               }
-               if (!slang_struct_copy(ti->spec._struct, s))
-                  return GL_FALSE;
-            }
-            else {
-               /* float, int, vec4, mat3, etc. constructor? */
-               const char *name;
-               slang_type_specifier_type type;
-
-               name = slang_atom_pool_id(atoms, op->a_id);
-               type = slang_type_specifier_type_from_string(name);
-               if (type == SLANG_SPEC_VOID) {
-                  slang_info_log_error(log, "undefined function '%s'", name);
-                  return GL_FALSE;
-               }
-               ti->spec.type = type;
-            }
-         }
-      }
-      break;
-   case SLANG_OPER_METHOD:
-      /* at this time, GLSL 1.20 only has one method: array.length()
-       * which returns an integer.
-       */
-      ti->spec.type = SLANG_SPEC_INT;
-      break;
-   case SLANG_OPER_FIELD:
-      {
-         slang_typeinfo _ti;
-
-         if (!slang_typeinfo_construct(&_ti))
-            return GL_FALSE;
-         if (!_slang_typeof_operation(op->children, space, &_ti, atoms, log)) {
-            slang_typeinfo_destruct(&_ti);
-            return GL_FALSE;
-         }
-         if (_ti.spec.type == SLANG_SPEC_STRUCT) {
-            slang_variable *field;
-
-            field = _slang_variable_locate(_ti.spec._struct->fields, op->a_id,
-                                           GL_FALSE);
-            if (field == NULL) {
-               slang_typeinfo_destruct(&_ti);
-               return GL_FALSE;
-            }
-            if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
-               slang_typeinfo_destruct(&_ti);
-               return GL_FALSE;
-            }
-            ti->can_be_referenced = _ti.can_be_referenced;
-            ti->array_len = field->array_len;
-         }
-         else {
-            GLuint rows;
-            const char *swizzle;
-            slang_type_specifier_type base;
-
-            /* determine the swizzle of the field expression */
-            if (!_slang_type_is_vector(_ti.spec.type)) {
-               slang_typeinfo_destruct(&_ti);
-               slang_info_log_error(log, "Can't swizzle scalar expression");
-               return GL_FALSE;
-            }
-            rows = _slang_type_dim(_ti.spec.type);
-            swizzle = slang_atom_pool_id(atoms, op->a_id);
-            if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) {
-               slang_typeinfo_destruct(&_ti);
-               slang_info_log_error(log, "bad swizzle '%s'", swizzle);
-               return GL_FALSE;
-            }
-            ti->is_swizzled = GL_TRUE;
-            ti->can_be_referenced = _ti.can_be_referenced
-               && _slang_is_swizzle_mask(&ti->swz, rows);
-            if (_ti.is_swizzled) {
-               slang_swizzle swz;
-
-               /* swizzle the swizzle */
-               _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz);
-               ti->swz = swz;
-            }
-            base = _slang_type_base(_ti.spec.type);
-            switch (ti->swz.num_components) {
-            case 1:
-               ti->spec.type = base;
-               break;
-            case 2:
-               switch (base) {
-               case SLANG_SPEC_FLOAT:
-                  ti->spec.type = SLANG_SPEC_VEC2;
-                  break;
-               case SLANG_SPEC_INT:
-                  ti->spec.type = SLANG_SPEC_IVEC2;
-                  break;
-               case SLANG_SPEC_BOOL:
-                  ti->spec.type = SLANG_SPEC_BVEC2;
-                  break;
-               default:
-                  break;
-               }
-               break;
-            case 3:
-               switch (base) {
-               case SLANG_SPEC_FLOAT:
-                  ti->spec.type = SLANG_SPEC_VEC3;
-                  break;
-               case SLANG_SPEC_INT:
-                  ti->spec.type = SLANG_SPEC_IVEC3;
-                  break;
-               case SLANG_SPEC_BOOL:
-                  ti->spec.type = SLANG_SPEC_BVEC3;
-                  break;
-               default:
-                  break;
-               }
-               break;
-            case 4:
-               switch (base) {
-               case SLANG_SPEC_FLOAT:
-                  ti->spec.type = SLANG_SPEC_VEC4;
-                  break;
-               case SLANG_SPEC_INT:
-                  ti->spec.type = SLANG_SPEC_IVEC4;
-                  break;
-               case SLANG_SPEC_BOOL:
-                  ti->spec.type = SLANG_SPEC_BVEC4;
-                  break;
-               default:
-                  break;
-               }
-               break;
-            default:
-               break;
-            }
-         }
-         slang_typeinfo_destruct(&_ti);
-      }
-      break;
-   case SLANG_OPER_POSTINCREMENT:
-   case SLANG_OPER_POSTDECREMENT:
-      if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
-         return GL_FALSE;
-      ti->can_be_referenced = GL_FALSE;
-      ti->is_swizzled = GL_FALSE;
-      break;
-   default:
-      return GL_FALSE;
-   }
-
-   return GL_TRUE;
-}
-
-
-/**
- * Determine if a type is a matrix.
- * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
- */
-GLboolean
-_slang_type_is_matrix(slang_type_specifier_type ty)
-{
-   switch (ty) {
-   case SLANG_SPEC_MAT2:
-   case SLANG_SPEC_MAT3:
-   case SLANG_SPEC_MAT4:
-   case SLANG_SPEC_MAT23:
-   case SLANG_SPEC_MAT32:
-   case SLANG_SPEC_MAT24:
-   case SLANG_SPEC_MAT42:
-   case SLANG_SPEC_MAT34:
-   case SLANG_SPEC_MAT43:
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Determine if a type is a vector.
- * \return GL_TRUE if is a vector, GL_FALSE otherwise.
- */
-GLboolean
-_slang_type_is_vector(slang_type_specifier_type ty)
-{
-   switch (ty) {
-   case SLANG_SPEC_VEC2:
-   case SLANG_SPEC_VEC3:
-   case SLANG_SPEC_VEC4:
-   case SLANG_SPEC_IVEC2:
-   case SLANG_SPEC_IVEC3:
-   case SLANG_SPEC_IVEC4:
-   case SLANG_SPEC_BVEC2:
-   case SLANG_SPEC_BVEC3:
-   case SLANG_SPEC_BVEC4:
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Determine if a type is a float, float vector or float matrix.
- * \return GL_TRUE if so, GL_FALSE otherwise
- */
-GLboolean
-_slang_type_is_float_vec_mat(slang_type_specifier_type ty)
-{
-   switch (ty) {
-   case SLANG_SPEC_FLOAT:
-   case SLANG_SPEC_VEC2:
-   case SLANG_SPEC_VEC3:
-   case SLANG_SPEC_VEC4:
-   case SLANG_SPEC_MAT2:
-   case SLANG_SPEC_MAT3:
-   case SLANG_SPEC_MAT4:
-   case SLANG_SPEC_MAT23:
-   case SLANG_SPEC_MAT32:
-   case SLANG_SPEC_MAT24:
-   case SLANG_SPEC_MAT42:
-   case SLANG_SPEC_MAT34:
-   case SLANG_SPEC_MAT43:
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Given a vector type, return the type of the vector's elements.
- * For a matrix, return the type of the columns.
- */
-slang_type_specifier_type
-_slang_type_base(slang_type_specifier_type ty)
-{
-   switch (ty) {
-   case SLANG_SPEC_FLOAT:
-   case SLANG_SPEC_VEC2:
-   case SLANG_SPEC_VEC3:
-   case SLANG_SPEC_VEC4:
-      return SLANG_SPEC_FLOAT;
-   case SLANG_SPEC_INT:
-   case SLANG_SPEC_IVEC2:
-   case SLANG_SPEC_IVEC3:
-   case SLANG_SPEC_IVEC4:
-      return SLANG_SPEC_INT;
-   case SLANG_SPEC_BOOL:
-   case SLANG_SPEC_BVEC2:
-   case SLANG_SPEC_BVEC3:
-   case SLANG_SPEC_BVEC4:
-      return SLANG_SPEC_BOOL;
-   case SLANG_SPEC_MAT2:
-      return SLANG_SPEC_VEC2;
-   case SLANG_SPEC_MAT3:
-      return SLANG_SPEC_VEC3;
-   case SLANG_SPEC_MAT4:
-      return SLANG_SPEC_VEC4;
-   case SLANG_SPEC_MAT23:
-      return SLANG_SPEC_VEC3;
-   case SLANG_SPEC_MAT32:
-      return SLANG_SPEC_VEC2;
-   case SLANG_SPEC_MAT24:
-      return SLANG_SPEC_VEC4;
-   case SLANG_SPEC_MAT42:
-      return SLANG_SPEC_VEC2;
-   case SLANG_SPEC_MAT34:
-      return SLANG_SPEC_VEC4;
-   case SLANG_SPEC_MAT43:
-      return SLANG_SPEC_VEC3;
-   default:
-      return SLANG_SPEC_VOID;
-   }
-}
-
-
-/**
- * Return the dimensionality of a vector, or for a matrix, return number
- * of columns.
- */
-GLuint
-_slang_type_dim(slang_type_specifier_type ty)
-{
-   switch (ty) {
-   case SLANG_SPEC_FLOAT:
-   case SLANG_SPEC_INT:
-   case SLANG_SPEC_BOOL:
-      return 1;
-   case SLANG_SPEC_VEC2:
-   case SLANG_SPEC_IVEC2:
-   case SLANG_SPEC_BVEC2:
-   case SLANG_SPEC_MAT2:
-      return 2;
-   case SLANG_SPEC_VEC3:
-   case SLANG_SPEC_IVEC3:
-   case SLANG_SPEC_BVEC3:
-   case SLANG_SPEC_MAT3:
-      return 3;
-   case SLANG_SPEC_VEC4:
-   case SLANG_SPEC_IVEC4:
-   case SLANG_SPEC_BVEC4:
-   case SLANG_SPEC_MAT4:
-      return 4;
-
-   case SLANG_SPEC_MAT23:
-      return 2;
-   case SLANG_SPEC_MAT32:
-      return 3;
-   case SLANG_SPEC_MAT24:
-      return 2;
-   case SLANG_SPEC_MAT42:
-      return 4;
-   case SLANG_SPEC_MAT34:
-      return 3;
-   case SLANG_SPEC_MAT43:
-      return 4;
-
-   default:
-      return 0;
-   }
-}
-
-
-/**
- * Return the GL_* type that corresponds to a SLANG_SPEC_* type.
- */
-GLenum
-_slang_gltype_from_specifier(const slang_type_specifier *type)
-{
-   switch (type->type) {
-   case SLANG_SPEC_BOOL:
-      return GL_BOOL;
-   case SLANG_SPEC_BVEC2:
-      return GL_BOOL_VEC2;
-   case SLANG_SPEC_BVEC3:
-      return GL_BOOL_VEC3;
-   case SLANG_SPEC_BVEC4:
-      return GL_BOOL_VEC4;
-   case SLANG_SPEC_INT:
-      return GL_INT;
-   case SLANG_SPEC_IVEC2:
-      return GL_INT_VEC2;
-   case SLANG_SPEC_IVEC3:
-      return GL_INT_VEC3;
-   case SLANG_SPEC_IVEC4:
-      return GL_INT_VEC4;
-   case SLANG_SPEC_FLOAT:
-      return GL_FLOAT;
-   case SLANG_SPEC_VEC2:
-      return GL_FLOAT_VEC2;
-   case SLANG_SPEC_VEC3:
-      return GL_FLOAT_VEC3;
-   case SLANG_SPEC_VEC4:
-      return GL_FLOAT_VEC4;
-   case SLANG_SPEC_MAT2:
-      return GL_FLOAT_MAT2;
-   case SLANG_SPEC_MAT3:
-      return GL_FLOAT_MAT3;
-   case SLANG_SPEC_MAT4:
-      return GL_FLOAT_MAT4;
-   case SLANG_SPEC_MAT23:
-      return GL_FLOAT_MAT2x3;
-   case SLANG_SPEC_MAT32:
-      return GL_FLOAT_MAT3x2;
-   case SLANG_SPEC_MAT24:
-      return GL_FLOAT_MAT2x4;
-   case SLANG_SPEC_MAT42:
-      return GL_FLOAT_MAT4x2;
-   case SLANG_SPEC_MAT34:
-      return GL_FLOAT_MAT3x4;
-   case SLANG_SPEC_MAT43:
-      return GL_FLOAT_MAT4x3;
-   case SLANG_SPEC_SAMPLER_1D:
-      return GL_SAMPLER_1D;
-   case SLANG_SPEC_SAMPLER_2D:
-      return GL_SAMPLER_2D;
-   case SLANG_SPEC_SAMPLER_3D:
-      return GL_SAMPLER_3D;
-   case SLANG_SPEC_SAMPLER_CUBE:
-      return GL_SAMPLER_CUBE;
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-      return GL_SAMPLER_1D_SHADOW;
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-      return GL_SAMPLER_2D_SHADOW;
-   case SLANG_SPEC_SAMPLER_RECT:
-      return GL_SAMPLER_2D_RECT_ARB;
-   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
-      return GL_SAMPLER_2D_RECT_SHADOW_ARB;
-   case SLANG_SPEC_SAMPLER_1D_ARRAY:
-      return GL_SAMPLER_1D_ARRAY_EXT;
-   case SLANG_SPEC_SAMPLER_2D_ARRAY:
-      return GL_SAMPLER_2D_ARRAY_EXT;
-   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
-      return GL_SAMPLER_1D_ARRAY_SHADOW_EXT;
-   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
-      return GL_SAMPLER_2D_ARRAY_SHADOW_EXT;
-   case SLANG_SPEC_ARRAY:
-      return _slang_gltype_from_specifier(type->_array);
-   case SLANG_SPEC_STRUCT:
-      /* fall-through */
-   default:
-      return GL_NONE;
-   }
-}
-
diff --git a/src/mesa/shader/slang/slang_typeinfo.h b/src/mesa/shader/slang/slang_typeinfo.h
deleted file mode 100644 (file)
index 9a6407a..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_TYPEINFO_H
-#define SLANG_TYPEINFO_H 1
-
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "slang_log.h"
-#include "slang_utility.h"
-#include "slang_vartable.h"
-
-
-struct slang_operation_;
-
-struct slang_name_space_;
-
-
-
-/**
- * Holds complete information about vector swizzle - the <swizzle>
- * array contains vector component source indices, where 0 is "x", 1
- * is "y", 2 is "z" and 3 is "w".
- * Example: "xwz" --> { 3, { 0, 3, 2, not used } }.
- */
-typedef struct slang_swizzle_
-{
-   GLuint num_components;
-   GLuint swizzle[4];
-} slang_swizzle;
-
-extern GLboolean
-_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle *swz);
-
-
-typedef enum slang_type_variant_
-{
-   SLANG_VARIANT,    /* the default */
-   SLANG_INVARIANT   /* indicates the "invariant" keyword */
-} slang_type_variant;
-
-
-typedef enum slang_type_centroid_
-{
-   SLANG_CENTER,    /* the default */
-   SLANG_CENTROID   /* indicates the "centroid" keyword */
-} slang_type_centroid;
-
-
-/**
- * These only apply to gl_FragCoord, but other layout qualifiers may
- * appear in the future.
- */
-typedef enum slang_layout_qualifier_
-{
-   SLANG_LAYOUT_NONE                      = 0x0,
-   SLANG_LAYOUT_UPPER_LEFT_BIT            = 0x1,
-   SLANG_LAYOUT_PIXEL_CENTER_INTEGER_BIT  = 0x2
-} slang_layout_qualifier;
-
-
-typedef enum slang_type_qualifier_
-{
-   SLANG_QUAL_NONE,
-   SLANG_QUAL_CONST,
-   SLANG_QUAL_ATTRIBUTE,
-   SLANG_QUAL_VARYING,
-   SLANG_QUAL_UNIFORM,
-   SLANG_QUAL_OUT,
-   SLANG_QUAL_INOUT,
-   SLANG_QUAL_FIXEDOUTPUT,      /* internal */
-   SLANG_QUAL_FIXEDINPUT        /* internal */
-} slang_type_qualifier;
-
-
-typedef enum slang_type_precision_
-{
-   SLANG_PREC_DEFAULT,
-   SLANG_PREC_LOW,
-   SLANG_PREC_MEDIUM,
-   SLANG_PREC_HIGH
-} slang_type_precision;
-
-
-/**
- * The basic shading language types (float, vec4, mat3, etc)
- */
-typedef enum slang_type_specifier_type_
-{
-   SLANG_SPEC_VOID,
-   SLANG_SPEC_BOOL,
-   SLANG_SPEC_BVEC2,
-   SLANG_SPEC_BVEC3,
-   SLANG_SPEC_BVEC4,
-   SLANG_SPEC_INT,
-   SLANG_SPEC_IVEC2,
-   SLANG_SPEC_IVEC3,
-   SLANG_SPEC_IVEC4,
-   SLANG_SPEC_FLOAT,
-   SLANG_SPEC_VEC2,
-   SLANG_SPEC_VEC3,
-   SLANG_SPEC_VEC4,
-   SLANG_SPEC_MAT2,
-   SLANG_SPEC_MAT3,
-   SLANG_SPEC_MAT4,
-   SLANG_SPEC_MAT23,
-   SLANG_SPEC_MAT32,
-   SLANG_SPEC_MAT24,
-   SLANG_SPEC_MAT42,
-   SLANG_SPEC_MAT34,
-   SLANG_SPEC_MAT43,
-   SLANG_SPEC_SAMPLER_1D,
-   SLANG_SPEC_SAMPLER_2D,
-   SLANG_SPEC_SAMPLER_3D,
-   SLANG_SPEC_SAMPLER_CUBE,
-   SLANG_SPEC_SAMPLER_RECT,
-   SLANG_SPEC_SAMPLER_1D_SHADOW,
-   SLANG_SPEC_SAMPLER_2D_SHADOW,
-   SLANG_SPEC_SAMPLER_RECT_SHADOW,
-   SLANG_SPEC_SAMPLER_1D_ARRAY,
-   SLANG_SPEC_SAMPLER_2D_ARRAY,
-   SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW,
-   SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW,
-   SLANG_SPEC_STRUCT,
-   SLANG_SPEC_ARRAY
-} slang_type_specifier_type;
-
-
-extern slang_type_specifier_type
-slang_type_specifier_type_from_string(const char *);
-
-extern const char *
-slang_type_specifier_type_to_string(slang_type_specifier_type);
-
-
-/**
- * Describes more sophisticated types, like structs and arrays.
- */
-typedef struct slang_type_specifier_
-{
-   slang_type_specifier_type type;
-   struct slang_struct_ *_struct;         /**< if type == SLANG_SPEC_STRUCT */
-   struct slang_type_specifier_ *_array;  /**< if type == SLANG_SPEC_ARRAY */
-} slang_type_specifier;
-
-
-extern GLvoid
-slang_type_specifier_ctr(slang_type_specifier *);
-
-extern GLvoid
-slang_type_specifier_dtr(slang_type_specifier *);
-
-extern slang_type_specifier *
-slang_type_specifier_new(slang_type_specifier_type type,
-                         struct slang_struct_ *_struct,
-                         struct slang_type_specifier_ *_array);
-
-
-extern GLboolean
-slang_type_specifier_copy(slang_type_specifier *, const slang_type_specifier *);
-
-extern GLboolean
-slang_type_specifier_equal(const slang_type_specifier *,
-                           const slang_type_specifier *);
-
-
-extern GLboolean
-slang_type_specifier_compatible(const slang_type_specifier *x,
-                                const slang_type_specifier *y);
-
-
-typedef struct slang_fully_specified_type_
-{
-   slang_type_qualifier qualifier;
-   slang_type_specifier specifier;
-   slang_type_precision precision;
-   slang_type_variant variant;
-   slang_type_centroid centroid;
-   slang_layout_qualifier layout;
-   GLint array_len;           /**< -1 if not an array type */
-} slang_fully_specified_type;
-
-extern int
-slang_fully_specified_type_construct(slang_fully_specified_type *);
-
-extern void
-slang_fully_specified_type_destruct(slang_fully_specified_type *);
-
-extern int
-slang_fully_specified_type_copy(slang_fully_specified_type *,
-                               const slang_fully_specified_type *);
-
-GLboolean
-slang_fully_specified_types_compatible(const slang_fully_specified_type * x,
-                                       const slang_fully_specified_type * y);
-
-
-typedef struct slang_typeinfo_
-{
-   GLboolean can_be_referenced;
-   GLboolean is_swizzled;
-   slang_swizzle swz;
-   slang_type_specifier spec;
-   GLuint array_len;
-} slang_typeinfo;
-
-extern GLboolean
-slang_typeinfo_construct(slang_typeinfo *);
-
-extern GLvoid
-slang_typeinfo_destruct(slang_typeinfo *);
-
-
-extern GLboolean
-_slang_typeof_operation(struct slang_operation_ *,
-                         const struct slang_name_space_ *,
-                         slang_typeinfo *, slang_atom_pool *,
-                         slang_info_log *log);
-
-extern GLboolean
-_slang_type_is_matrix(slang_type_specifier_type);
-
-extern GLboolean
-_slang_type_is_vector(slang_type_specifier_type);
-
-extern GLboolean
-_slang_type_is_float_vec_mat(slang_type_specifier_type);
-
-extern slang_type_specifier_type
-_slang_type_base(slang_type_specifier_type);
-
-extern GLuint
-_slang_type_dim(slang_type_specifier_type);
-
-extern GLenum
-_slang_gltype_from_specifier(const slang_type_specifier *type);
-
-#endif
diff --git a/src/mesa/shader/slang/slang_utility.c b/src/mesa/shader/slang/slang_utility.c
deleted file mode 100644 (file)
index c1d5740..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_utility.c
- * slang utilities
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_utility.h"
-#include "slang_mem.h"
-
-char *
-slang_string_concat (char *dst, const char *src)
-{
-   return strcpy (dst + strlen (dst), src);
-}
-
-
-/* slang_string */
-
-GLvoid
-slang_string_init (slang_string *self)
-{
-   self->data = NULL;
-   self->capacity = 0;
-   self->length = 0;
-   self->fail = GL_FALSE;
-}
-
-GLvoid
-slang_string_free (slang_string *self)
-{
-   if (self->data != NULL)
-      free(self->data);
-}
-
-GLvoid
-slang_string_reset (slang_string *self)
-{
-   self->length = 0;
-   self->fail = GL_FALSE;
-}
-
-static GLboolean
-grow (slang_string *self, GLuint size)
-{
-   if (self->fail)
-      return GL_FALSE;
-   if (size > self->capacity) {
-      /* do not overflow 32-bit range */
-      assert (size < 0x80000000);
-
-      self->data = (char *) (_mesa_realloc (self->data, self->capacity, size * 2));
-      self->capacity = size * 2;
-      if (self->data == NULL) {
-         self->capacity = 0;
-         self->fail = GL_TRUE;
-         return GL_FALSE;
-      }
-   }
-   return GL_TRUE;
-}
-
-GLvoid
-slang_string_push (slang_string *self, const slang_string *str)
-{
-   if (str->fail) {
-      self->fail = GL_TRUE;
-      return;
-   }
-   if (grow (self, self->length + str->length)) {
-      memcpy (&self->data[self->length], str->data, str->length);
-      self->length += str->length;
-   }
-}
-
-GLvoid
-slang_string_pushc (slang_string *self, const char c)
-{
-   if (grow (self, self->length + 1)) {
-      self->data[self->length] = c;
-      self->length++;
-   }
-}
-
-GLvoid
-slang_string_pushs (slang_string *self, const char *cstr, GLuint len)
-{
-   if (grow (self, self->length + len)) {
-      memcpy (&self->data[self->length], cstr, len);
-      self->length += len;
-   }
-}
-
-GLvoid
-slang_string_pushi (slang_string *self, GLint i)
-{
-   char buffer[12];
-
-   _mesa_snprintf (buffer, sizeof(buffer), "%d", i);
-   slang_string_pushs (self, buffer, strlen (buffer));
-}
-
-const char *
-slang_string_cstr (slang_string *self)
-{
-   if (grow (self, self->length + 1))
-      self->data[self->length] = '\0';
-   return self->data;
-}
-
-/* slang_atom_pool */
-
-void
-slang_atom_pool_construct(slang_atom_pool * pool)
-{
-   GLuint i;
-
-   for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++)
-      pool->entries[i] = NULL;
-}
-
-void
-slang_atom_pool_destruct (slang_atom_pool * pool)
-{
-   GLuint i;
-
-   for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++) {
-      slang_atom_entry * entry;
-               
-      entry = pool->entries[i];
-      while (entry != NULL) {
-         slang_atom_entry *next = entry->next;
-         _slang_free(entry->id);
-         _slang_free(entry);
-         entry = next;
-      }
-   }
-}
-
-/*
- * Search the atom pool for an atom with a given name.
- * If atom is not found, create and add it to the pool.
- * Returns ATOM_NULL if the atom was not found and the function failed
- * to create a new atom.
- */
-slang_atom
-slang_atom_pool_atom(slang_atom_pool * pool, const char * id)
-{
-   GLuint hash;
-   const char * p = id;
-   slang_atom_entry ** entry;
-
-   /* Hash a given string to a number in the range [0, ATOM_POOL_SIZE). */
-   hash = 0;
-   while (*p != '\0') {
-      GLuint g;
-
-      hash = (hash << 4) + (GLuint) (*p++);
-      g = hash & 0xf0000000;
-      if (g != 0)
-         hash ^= g >> 24;
-      hash &= ~g;
-   }
-   hash %= SLANG_ATOM_POOL_SIZE;
-
-   /* Now the hash points to a linked list of atoms with names that
-    * have the same hash value.  Search the linked list for a given
-    * name.
-    */
-   entry = &pool->entries[hash];
-   while (*entry != NULL) {
-      /* If the same, return the associated atom. */
-      if (slang_string_compare((**entry).id, id) == 0)
-         return (slang_atom) (**entry).id;
-      /* Grab the next atom in the linked list. */
-      entry = &(**entry).next;
-   }
-
-   /* Okay, we have not found an atom. Create a new entry for it.
-    * Note that the <entry> points to the last entry's <next> field.
-    */
-   *entry = (slang_atom_entry *) _slang_alloc(sizeof(slang_atom_entry));
-   if (*entry == NULL)
-      return SLANG_ATOM_NULL;
-
-   /* Initialize a new entry. Because we'll need the actual name of
-    * the atom, we use the pointer to this string as an actual atom's
-    * value.
-    */
-   (**entry).next = NULL;
-   (**entry).id = _slang_strdup(id);
-   if ((**entry).id == NULL)
-      return SLANG_ATOM_NULL;
-   return (slang_atom) (**entry).id;
-}
-
-/**
- * Return the name of a given atom.
- */
-const char *
-slang_atom_pool_id(slang_atom_pool * pool, slang_atom atom)
-{
-   return (const char *) (atom);
-}
diff --git a/src/mesa/shader/slang/slang_utility.h b/src/mesa/shader/slang/slang_utility.h
deleted file mode 100644 (file)
index 2c0d0bc..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_UTILITY_H
-#define SLANG_UTILITY_H
-
-
-/* Compile-time assertions.  If the expression is zero, try to declare an
- * array of size [-1] to cause compilation error.
- */
-#define static_assert(expr) do { int _array[(expr) ? 1 : -1]; (void) _array[0]; } while (0)
-
-
-#define slang_string_compare(str1, str2) strcmp (str1, str2)
-#define slang_string_copy(dst, src) strcpy (dst, src)
-#define slang_string_length(str) strlen (str)
-
-char *slang_string_concat (char *, const char *);
-
-/* slang_string */
-
-typedef struct
-{
-   char *data;
-   GLuint length;
-   GLuint capacity;
-   GLboolean fail;
-} slang_string;
-
-GLvoid
-slang_string_init (slang_string *);
-
-GLvoid
-slang_string_free (slang_string *);
-
-GLvoid
-slang_string_reset (slang_string *);
-
-GLvoid
-slang_string_push (slang_string *, const slang_string *);
-
-GLvoid
-slang_string_pushc (slang_string *, const char);
-
-GLvoid
-slang_string_pushs (slang_string *, const char *, GLuint);
-
-GLvoid
-slang_string_pushi (slang_string *, GLint);
-
-const char *
-slang_string_cstr (slang_string *);
-
-/* slang_atom */
-
-typedef GLvoid *slang_atom;
-
-#define SLANG_ATOM_NULL ((slang_atom) 0)
-
-typedef struct slang_atom_entry_
-{
-       char *id;
-       struct slang_atom_entry_ *next;
-} slang_atom_entry;
-
-#define SLANG_ATOM_POOL_SIZE 1023
-
-typedef struct slang_atom_pool_
-{
-       slang_atom_entry *entries[SLANG_ATOM_POOL_SIZE];
-} slang_atom_pool;
-
-GLvoid slang_atom_pool_construct (slang_atom_pool *);
-GLvoid slang_atom_pool_destruct (slang_atom_pool *);
-slang_atom slang_atom_pool_atom (slang_atom_pool *, const char *);
-const char *slang_atom_pool_id (slang_atom_pool *, slang_atom);
-
-
-#endif
diff --git a/src/mesa/shader/slang/slang_vartable.c b/src/mesa/shader/slang/slang_vartable.c
deleted file mode 100644 (file)
index e07e3a2..0000000
+++ /dev/null
@@ -1,362 +0,0 @@
-
-#include "main/imports.h"
-#include "shader/program.h"
-#include "shader/prog_print.h"
-#include "slang_compile.h"
-#include "slang_compile_variable.h"
-#include "slang_emit.h"
-#include "slang_mem.h"
-#include "slang_vartable.h"
-#include "slang_ir.h"
-
-
-static int dbg = 0;
-
-
-typedef enum {
-   FREE,
-   VAR,
-   TEMP
-} TempState;
-
-
-/**
- * Variable/register info for one variable scope.
- */
-struct table
-{
-   int Level;
-   int NumVars;
-   slang_variable **Vars;  /* array [NumVars] */
-
-   TempState Temps[MAX_PROGRAM_TEMPS * 4];  /* per-component state */
-   int ValSize[MAX_PROGRAM_TEMPS * 4];     /**< For debug only */
-
-   struct table *Parent;  /** Parent scope table */
-};
-
-
-/**
- * A variable table is a stack of tables, one per scope.
- */
-struct slang_var_table_
-{
-   GLint CurLevel;
-   GLuint MaxRegisters;
-   struct table *Top;  /**< Table at top of stack */
-};
-
-
-
-slang_var_table *
-_slang_new_var_table(GLuint maxRegisters)
-{
-   slang_var_table *vt
-      = (slang_var_table *) _slang_alloc(sizeof(slang_var_table));
-   if (vt) {
-      vt->MaxRegisters = maxRegisters;
-   }
-   return vt;
-}
-
-
-void
-_slang_delete_var_table(slang_var_table *vt)
-{
-   if (vt->Top) {
-      _mesa_problem(NULL, "non-empty var table in _slang_delete_var_table()");
-      return;
-   }
-   _slang_free(vt);
-}
-
-
-
-/**
- * Create new table on top of vartable stack.
- * Used when we enter a {} block.
- */
-void
-_slang_push_var_table(slang_var_table *vt)
-{
-   struct table *t = (struct table *) _slang_alloc(sizeof(struct table));
-   if (t) {
-      t->Level = vt->CurLevel++;
-      t->Parent = vt->Top;
-      if (t->Parent) {
-         /* copy the info indicating which temp regs are in use */
-         memcpy(t->Temps, t->Parent->Temps, sizeof(t->Temps));
-         memcpy(t->ValSize, t->Parent->ValSize, sizeof(t->ValSize));
-      }
-      vt->Top = t;
-      if (dbg) printf("Pushing level %d\n", t->Level);
-   }
-}
-
-
-/**
- * Pop top entry from variable table.
- * Used when we leave a {} block.
- */
-void
-_slang_pop_var_table(slang_var_table *vt)
-{
-   struct table *t = vt->Top;
-   int i;
-
-   if (dbg) printf("Popping level %d\n", t->Level);
-
-   /* free the storage allocated for each variable */
-   for (i = 0; i < t->NumVars; i++) {
-      slang_ir_storage *store = t->Vars[i]->store;
-      GLint j;
-      GLuint comp;
-      if (dbg) printf("  Free var %s, size %d at %d.%s\n",
-                      (char*) t->Vars[i]->a_name, store->Size,
-                      store->Index,
-                      _mesa_swizzle_string(store->Swizzle, 0, 0));
-
-      if (store->File == PROGRAM_SAMPLER) {
-         /* samplers have no storage */
-         continue;
-      }
-
-      if (store->Size == 1)
-         comp = GET_SWZ(store->Swizzle, 0);
-      else
-         comp = 0;
-
-      /* store->Index may be -1 if we run out of registers */
-      if (store->Index >= 0) {
-         for (j = 0; j < store->Size; j++) {
-            assert(t->Temps[store->Index * 4 + j + comp] == VAR);
-            t->Temps[store->Index * 4 + j + comp] = FREE;
-         }
-      }
-      store->Index = -1;
-   }
-   if (t->Parent) {
-      /* just verify that any remaining allocations in this scope 
-       * were for temps
-       */
-      for (i = 0; i < (int) vt->MaxRegisters * 4; i++) {
-         if (t->Temps[i] != FREE && t->Parent->Temps[i] == FREE) {
-            if (dbg) printf("  Free reg %d\n", i/4);
-            assert(t->Temps[i] == TEMP);
-         }
-      }
-   }
-
-   if (t->Vars) {
-      _slang_free(t->Vars);
-      t->Vars = NULL;
-   }
-
-   vt->Top = t->Parent;
-   _slang_free(t);
-   vt->CurLevel--;
-}
-
-
-/**
- * Add a new variable to the given var/symbol table.
- */
-void
-_slang_add_variable(slang_var_table *vt, slang_variable *v)
-{
-   struct table *t;
-   assert(vt);
-   t = vt->Top;
-   assert(t);
-   if (dbg) printf("Adding var %s, store %p\n", (char *) v->a_name, (void *) v->store);
-   t->Vars = (slang_variable **)
-      _slang_realloc(t->Vars,
-                     t->NumVars * sizeof(slang_variable *),
-                     (t->NumVars + 1) * sizeof(slang_variable *));
-   t->Vars[t->NumVars] = v;
-   t->NumVars++;
-}
-
-
-/**
- * Look for variable by name in given table.
- * If not found, Parent table will be searched.
- */
-slang_variable *
-_slang_find_variable(const slang_var_table *vt, slang_atom name)
-{
-   struct table *t = vt->Top;
-   while (1) {
-      int i;
-      for (i = 0; i < t->NumVars; i++) {
-         if (t->Vars[i]->a_name == name)
-            return t->Vars[i];
-      }
-      if (t->Parent)
-         t = t->Parent;
-      else
-         return NULL;
-   }
-}
-
-
-/**
- * Allocation helper.
- * \param size  var size in floats
- * \return  position for var, measured in floats
- */
-static GLint
-alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
-{
-   struct table *t = vt->Top;
-   /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
-   const GLuint step = (size == 1) ? 1 : 4;
-   GLuint i, j;
-   assert(size > 0); /* number of floats */
-
-   for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) {
-      GLuint found = 0;
-      for (j = 0; j < (GLuint) size; j++) {
-         assert(i + j < 4 * MAX_PROGRAM_TEMPS);
-         if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) {
-            found++;
-         }
-         else {
-            break;
-         }
-      }
-      if (found == size) {
-         /* found block of size free regs */
-         if (size > 1)
-            assert(i % 4 == 0);
-         for (j = 0; j < (GLuint) size; j++) {
-            assert(i + j < 4 * MAX_PROGRAM_TEMPS);
-            t->Temps[i + j] = isTemp ? TEMP : VAR;
-         }
-         assert(i < MAX_PROGRAM_TEMPS * 4);
-         t->ValSize[i] = size;
-         return i;
-      }
-   }
-
-   /* if we get here, we ran out of registers */
-   return -1;
-}
-
-
-/**
- * Allocate temp register(s) for storing a variable.
- * \param size  size needed, in floats
- * \param swizzle  returns swizzle mask for accessing var in register
- * \return  register allocated, or -1
- */
-GLboolean
-_slang_alloc_var(slang_var_table *vt, slang_ir_storage *store)
-{
-   struct table *t = vt->Top;
-   int i;
-
-   if (store->File == PROGRAM_SAMPLER) {
-      /* don't really allocate storage */
-      store->Index = 0;
-      return GL_TRUE;
-   }
-
-   i = alloc_reg(vt, store->Size, GL_FALSE);
-   if (i < 0)
-      return GL_FALSE;
-
-   store->Index = i / 4;
-   store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
-
-   if (dbg)
-      printf("Alloc var storage sz %d at %d.%s (level %d) store %p\n",
-             store->Size, store->Index,
-             _mesa_swizzle_string(store->Swizzle, 0, 0),
-             t->Level,
-             (void*) store);
-
-   return GL_TRUE;
-}
-
-
-
-/**
- * Allocate temp register(s) for storing an unnamed intermediate value.
- */
-GLboolean
-_slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store)
-{
-   struct table *t = vt->Top;
-   const int i = alloc_reg(vt, store->Size, GL_TRUE);
-   if (i < 0)
-      return GL_FALSE;
-
-   assert(store->Index < 0);
-
-   store->Index = i / 4;
-   store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
-
-   if (dbg) printf("Alloc temp sz %d at %d.%s (level %d) store %p\n",
-                   store->Size, store->Index,
-                   _mesa_swizzle_string(store->Swizzle, 0, 0), t->Level,
-                   (void *) store);
-
-   return GL_TRUE;
-}
-
-
-void
-_slang_free_temp(slang_var_table *vt, slang_ir_storage *store)
-{
-   struct table *t = vt->Top;
-   GLuint i;
-   GLint r = store->Index;
-   assert(store->Size > 0);
-   assert(r >= 0);
-   assert((GLuint)r + store->Size <= vt->MaxRegisters * 4);
-   if (dbg) printf("Free temp sz %d at %d.%s (level %d) store %p\n",
-                   store->Size, r,
-                   _mesa_swizzle_string(store->Swizzle, 0, 0),
-                   t->Level, (void *) store);
-   if (store->Size == 1) {
-      const GLuint comp = GET_SWZ(store->Swizzle, 0);
-      /* we can actually fail some of these assertions because of the
-       * troublesome IR_SWIZZLE handling.
-       */
-#if 0
-      assert(store->Swizzle == MAKE_SWIZZLE4(comp, comp, comp, comp));
-      assert(comp < 4);
-      assert(t->ValSize[r * 4 + comp] == 1);
-#endif
-      assert(t->Temps[r * 4 + comp] == TEMP);
-      t->Temps[r * 4 + comp] = FREE;
-   }
-   else {
-      /*assert(store->Swizzle == SWIZZLE_NOOP);*/
-      assert(t->ValSize[r*4] == store->Size);
-      for (i = 0; i < (GLuint) store->Size; i++) {
-         assert(t->Temps[r * 4 + i] == TEMP);
-         t->Temps[r * 4 + i] = FREE;
-      }
-   }
-}
-
-
-GLboolean
-_slang_is_temp(const slang_var_table *vt, const slang_ir_storage *store)
-{
-   struct table *t = vt->Top;
-   GLuint comp;
-   assert(store->Index >= 0);
-   assert(store->Index < (int) vt->MaxRegisters);
-   if (store->Swizzle == SWIZZLE_NOOP)
-      comp = 0;
-   else
-      comp = GET_SWZ(store->Swizzle, 0);
-
-   if (t->Temps[store->Index * 4 + comp] == TEMP)
-      return GL_TRUE;
-   else
-      return GL_FALSE;
-}
diff --git a/src/mesa/shader/slang/slang_vartable.h b/src/mesa/shader/slang/slang_vartable.h
deleted file mode 100644 (file)
index 94bcd63..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-
-#ifndef SLANG_VARTABLE_H
-#define SLANG_VARTABLE_H
-
-struct slang_ir_storage_;
-
-typedef struct slang_var_table_ slang_var_table;
-
-struct slang_variable_;
-
-extern slang_var_table *
-_slang_new_var_table(GLuint maxRegisters);
-
-extern void
-_slang_delete_var_table(slang_var_table *vt);
-
-extern void
-_slang_push_var_table(slang_var_table *parent);
-
-extern void
-_slang_pop_var_table(slang_var_table *t);
-
-extern void
-_slang_add_variable(slang_var_table *t, struct slang_variable_ *v);
-
-extern struct slang_variable_ *
-_slang_find_variable(const slang_var_table *t, slang_atom name);
-
-extern GLboolean
-_slang_alloc_var(slang_var_table *t, struct slang_ir_storage_ *store);
-
-extern GLboolean
-_slang_alloc_temp(slang_var_table *t, struct slang_ir_storage_ *store);
-
-extern void
-_slang_free_temp(slang_var_table *t, struct slang_ir_storage_ *store);
-
-extern GLboolean
-_slang_is_temp(const slang_var_table *t, const struct slang_ir_storage_ *store);
-
-
-#endif /* SLANG_VARTABLE_H */
diff --git a/src/mesa/slang/descrip.mms b/src/mesa/slang/descrip.mms
new file mode 100644 (file)
index 0000000..674b786
--- /dev/null
@@ -0,0 +1,67 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen  joukj@hrem.nano.tudelft.nl
+# Last revision : 3 October 2007
+
+.first
+       define gl [----.include.gl]
+       define math [--.math]
+       define swrast [--.swrast]
+       define array_cache [--.array_cache]
+       define main [--.main]
+       define glapi [--.glapi]
+       define shader [--.shader]
+
+.include [----]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [----.include],[--.main],[--.glapi],[-.slang],[-]
+LIBDIR = [----.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
+
+SOURCES = \
+       slang_compile.c
+
+OBJECTS = slang_builtin.obj,slang_codegen.obj,slang_compile.obj,\
+       slang_compile_function.obj,slang_compile_operation.obj,\
+       slang_compile_struct.obj,slang_compile_variable.obj,slang_emit.obj,\
+       slang_ir.obj,slang_label.obj,slang_library_noise.obj,slang_link.obj,\
+       slang_log.obj,slang_mem.obj,slang_preprocess.obj,slang_print.obj,\
+       slang_simplify.obj,slang_storage.obj,slang_typeinfo.obj,\
+       slang_utility.obj,slang_vartable.obj
+
+##### RULES #####
+
+VERSION=Mesa V3.4
+
+##### TARGETS #####
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS)
+  @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
+
+clean :
+       purge
+       delete *.obj;*
+
+slang_builtin.obj : slang_builtin.c
+slang_codegen.obj : slang_codegen.c
+slang_compile.obj : slang_compile.c
+slang_compile_function.obj : slang_compile_function.c
+slang_compile_operation.obj : slang_compile_operation.c
+slang_compile_struct.obj : slang_compile_struct.c
+slang_compile_variable.obj : slang_compile_variable.c
+slang_emit.obj : slang_emit.c
+slang_ir.obj : slang_ir.c
+slang_label.obj : slang_label.c
+slang_library_noise.obj : slang_library_noise.c
+slang_link.obj : slang_link.c
+slang_log.obj : slang_log.c
+slang_mem.obj : slang_mem.c
+slang_print.obj : slang_print.c
+slang_simplify.obj : slang_simplify.c
+slang_storage.obj : slang_storage.c
+slang_typeinfo.obj : slang_typeinfo.c
+slang_utility.obj : slang_utility.c
+slang_vartable.obj : slang_vartable.c
diff --git a/src/mesa/slang/library/.gitignore b/src/mesa/slang/library/.gitignore
new file mode 100644 (file)
index 0000000..02a89fc
--- /dev/null
@@ -0,0 +1 @@
+*_gc.h
diff --git a/src/mesa/slang/library/Makefile b/src/mesa/slang/library/Makefile
new file mode 100644 (file)
index 0000000..75c91e7
--- /dev/null
@@ -0,0 +1,51 @@
+# src/mesa/shader/slang/library/Makefile
+
+TOP = ../../../..
+
+include $(TOP)/configs/current
+
+GLSL_CL = $(TOP)/src/glsl/apps/compile
+
+#
+# targets
+#
+
+.PHONY: default clean
+
+default: builtin
+
+clean:
+       -rm -f *_gc.h
+
+builtin: builtin_110 builtin_120
+
+#
+# builtin library sources
+#
+
+builtin_110: slang_common_builtin_gc.h slang_core_gc.h slang_fragment_builtin_gc.h slang_vertex_builtin_gc.h
+
+builtin_120: slang_120_core_gc.h slang_builtin_120_common_gc.h slang_builtin_120_fragment_gc.h
+
+
+slang_120_core_gc.h: slang_120_core.gc
+       $(GLSL_CL) fragment slang_120_core.gc slang_120_core_gc.h
+
+slang_builtin_120_common_gc.h: slang_builtin_120_common.gc
+       $(GLSL_CL) fragment slang_builtin_120_common.gc slang_builtin_120_common_gc.h
+
+slang_builtin_120_fragment_gc.h: slang_builtin_120_fragment.gc
+       $(GLSL_CL) fragment slang_builtin_120_fragment.gc slang_builtin_120_fragment_gc.h
+
+slang_common_builtin_gc.h: slang_common_builtin.gc
+       $(GLSL_CL) fragment slang_common_builtin.gc slang_common_builtin_gc.h
+
+slang_core_gc.h: slang_core.gc
+       $(GLSL_CL) fragment slang_core.gc slang_core_gc.h
+
+slang_fragment_builtin_gc.h: slang_fragment_builtin.gc
+       $(GLSL_CL) fragment slang_fragment_builtin.gc slang_fragment_builtin_gc.h
+
+slang_vertex_builtin_gc.h: slang_vertex_builtin.gc
+       $(GLSL_CL) vertex slang_vertex_builtin.gc slang_vertex_builtin_gc.h
+
diff --git a/src/mesa/slang/library/SConscript b/src/mesa/slang/library/SConscript
new file mode 100644 (file)
index 0000000..0b25467
--- /dev/null
@@ -0,0 +1,52 @@
+#######################################################################
+# SConscript for GLSL builtin library
+
+Import('*')
+
+env = env.Clone()
+
+# See also http://www.scons.org/wiki/UsingCodeGenerators
+
+def glsl_compile_emitter(target, source, env):
+       env.Depends(target, glsl_compile)
+       return (target, source)
+bld_frag = Builder(
+       action = Action(glsl_compile[0].abspath + ' fragment $SOURCE $TARGET', '$CODEGENCODESTR'),
+       emitter = glsl_compile_emitter,
+       suffix = '.gc',
+       src_suffix = '_gc.h')
+       
+bld_vert = Builder(
+       action = Action(glsl_compile[0].abspath + ' vertex $SOURCE $TARGET', '$CODEGENCODESTR'),
+       emitter = glsl_compile_emitter,
+       suffix = '.gc',
+       src_suffix = '_gc.h')
+
+env['BUILDERS']['bld_frag'] = bld_frag
+env['BUILDERS']['bld_vert'] = bld_vert
+
+# Generate GLSL builtin library binaries
+env.bld_frag(
+       '#src/mesa/shader/slang/library/slang_core_gc.h',
+       '#src/mesa/shader/slang/library/slang_core.gc')
+env.bld_frag(
+       '#src/mesa/shader/slang/library/slang_common_builtin_gc.h',
+       '#src/mesa/shader/slang/library/slang_common_builtin.gc')
+env.bld_frag(
+       '#src/mesa/shader/slang/library/slang_fragment_builtin_gc.h',
+       '#src/mesa/shader/slang/library/slang_fragment_builtin.gc')
+env.bld_vert(
+       '#src/mesa/shader/slang/library/slang_vertex_builtin_gc.h',
+       '#src/mesa/shader/slang/library/slang_vertex_builtin.gc')
+
+# Generate GLSL 1.20 builtin library binaries
+env.bld_frag(
+       '#src/mesa/shader/slang/library/slang_120_core_gc.h',
+       '#src/mesa/shader/slang/library/slang_120_core.gc')
+env.bld_frag(
+       '#src/mesa/shader/slang/library/slang_builtin_120_common_gc.h',
+       '#src/mesa/shader/slang/library/slang_builtin_120_common.gc')
+env.bld_frag(
+       '#src/mesa/shader/slang/library/slang_builtin_120_fragment_gc.h',
+       '#src/mesa/shader/slang/library/slang_builtin_120_fragment.gc')
diff --git a/src/mesa/slang/library/slang_120_core.gc b/src/mesa/slang/library/slang_120_core.gc
new file mode 100644 (file)
index 0000000..04c5ec2
--- /dev/null
@@ -0,0 +1,1978 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+//
+// Constructors and operators introduced in GLSL 1.20 - mostly on new
+// (non-square) types of matrices.
+//
+// One important change in the language is that when a matrix is used
+// as an argument to a matrix constructor, it must be the only argument
+// for the constructor. The compiler takes care of it by itself and
+// here we only care to re-introduce constructors for old (square)
+// types of matrices.
+//
+
+//
+// From Shader Spec, ver. 1.20, rev. 6
+//
+
+//// mat2x3: 2 columns of vec3
+
+mat2x3 __constructor(const float f00, const float f10, const float f20,
+                     const float f01, const float f11, const float f21)
+{
+   __retVal[0].x = f00;
+   __retVal[0].y = f10;
+   __retVal[0].z = f20;
+   __retVal[1].x = f01;
+   __retVal[1].y = f11;
+   __retVal[1].z = f21;
+}
+
+mat2x3 __constructor(const float f)
+{
+   __retVal = mat2x3(  f, 0.0, 0.0,
+                     0.0,   f, 0.0);
+}
+
+mat2x3 __constructor(const int  i)
+{
+   const float f = float(i);
+   __retVal = mat2x3(f);
+}
+
+mat2x3 __constructor(const bool b)
+{
+   const float f = float(b);
+   __retVal = mat2x3(f);
+}
+
+mat2x3 __constructor(const vec3 c0, const vec3 c1)
+{
+   __retVal[0] = c0;
+   __retVal[1] = c1;
+}
+
+
+
+//// mat2x4: 2 columns of vec4
+
+mat2x4 __constructor(const float f00, const float f10, const float f20, const float f30,
+                     const float f01, const float f11, const float f21, const float f31)
+{
+   __retVal[0].x = f00;
+   __retVal[0].y = f10;
+   __retVal[0].z = f20;
+   __retVal[0].w = f30;
+   __retVal[1].x = f01;
+   __retVal[1].y = f11;
+   __retVal[1].z = f21;
+   __retVal[1].w = f31;
+}
+
+mat2x4 __constructor(const float f)
+{
+   __retVal = mat2x4(  f, 0.0, 0.0, 0.0,
+                     0.0,   f, 0.0, 0.0);
+}
+
+mat2x4 __constructor(const int i)
+{
+   const float f = float(i);
+   __retVal = mat2x4(f);
+}
+
+mat2x4 __constructor(const bool b)
+{
+   const float f = float(b);
+   __retVal = mat2x4(f);
+}
+
+mat2x4 __constructor(const vec4 c0, const vec4 c1)
+{
+   __retVal[0] = c0;
+   __retVal[1] = c1;
+}
+
+
+
+//// mat3x2: 3 columns of vec2
+
+mat3x2 __constructor(const float f00, const float f10,
+                     const float f01, const float f11,
+                     const float f02, const float f12)
+{
+   __retVal[0].x = f00;
+   __retVal[0].y = f10;
+   __retVal[1].x = f01;
+   __retVal[1].y = f11;
+   __retVal[2].x = f02;
+   __retVal[2].y = f12;
+}
+
+mat3x2 __constructor(const float f)
+{
+   __retVal = mat3x2(  f, 0.0,
+                     0.0,   f,
+                     0.0, 0.0);
+}
+
+mat3x2 __constructor(const int i)
+{
+   const float f = float(i);
+   __retVal = mat3x2(f);
+}
+
+mat3x2 __constructor(const bool b)
+{
+   const float f = float(b);
+   __retVal = mat3x2(f);
+}
+
+mat3x2 __constructor(const vec2 c0, const vec2 c1, const vec2 c2)
+{
+   __retVal[0] = c0;
+   __retVal[1] = c1;
+   __retVal[2] = c2;
+}
+
+
+
+//// mat3x4: 3 columns of vec4
+
+mat3x4 __constructor(const float f00, const float f10, const float f20, const float f30,
+                     const float f01, const float f11, const float f21, const float f31,
+                    const float f02, const float f12, const float f22, const float f32)
+{
+   __retVal[0].x = f00;
+   __retVal[0].y = f10;
+   __retVal[0].z = f20;
+   __retVal[0].w = f30;
+   __retVal[1].x = f01;
+   __retVal[1].y = f11;
+   __retVal[1].z = f21;
+   __retVal[1].w = f31;
+   __retVal[2].x = f02;
+   __retVal[2].y = f12;
+   __retVal[2].z = f22;
+   __retVal[2].w = f32;
+}
+
+mat3x4 __constructor(const float f)
+{
+   __retVal = mat3x4(  f, 0.0, 0.0, 0.0,
+                     0.0,   f, 0.0, 0.0,
+                     0.0, 0.0,   f, 0.0);
+}
+
+mat3x4 __constructor(const int i)
+{
+   const float f = float(i);
+   __retVal = mat3x4(f);
+}
+
+mat3x4 __constructor(const bool b)
+{
+   const float f = float(b);
+   __retVal = mat3x4(f);
+}
+
+mat3x4 __constructor(const vec4 c0, const vec4 c1, const vec4 c2)
+{
+   __retVal[0] = c0;
+   __retVal[1] = c1;
+   __retVal[2] = c2;
+}
+
+
+
+//// mat4x2: 4 columns of vec2
+
+mat4x2 __constructor(const float f00, const float f10,
+                     const float f01, const float f11,
+                    const float f02, const float f12,
+                    const float f03, const float f13)
+{
+   __retVal[0].x = f00;
+   __retVal[0].y = f10;
+   __retVal[1].x = f01;
+   __retVal[1].y = f11;
+   __retVal[2].x = f02;
+   __retVal[2].y = f12;
+   __retVal[3].x = f03;
+   __retVal[3].y = f13;
+}
+
+mat4x2 __constructor(const float f)
+{
+   __retVal = mat4x2(  f, 0.0,
+                     0.0,   4,
+                     0.0, 0.0,
+                     0.0, 0.0);
+}
+
+mat4x2 __constructor(const int i)
+{
+   const float f = float(i);
+   __retVal = mat4x2(f);
+}
+
+mat4x2 __constructor(const bool b)
+{
+   const float f = float(b);
+   __retVal = mat4x2(f);
+}
+
+mat4x2 __constructor(const vec2 c0, const vec2 c1, const vec2 c2, const vec2 c3)
+{
+   __retVal[0] = c0;
+   __retVal[1] = c1;
+   __retVal[2] = c2;
+   __retVal[3] = c3;
+}
+
+
+
+//// mat4x3: 4 columns of vec3
+
+mat4x3 __constructor(const float f00, const float f10, const float f20,
+                     const float f01, const float f11, const float f21,
+                    const float f02, const float f12, const float f22,
+                    const float f03, const float f13, const float f23)
+{
+   __retVal[0].x = f00;
+   __retVal[0].y = f10;
+   __retVal[0].z = f20;
+   __retVal[1].x = f01;
+   __retVal[1].y = f11;
+   __retVal[1].z = f21;
+   __retVal[2].x = f02;
+   __retVal[2].y = f12;
+   __retVal[2].z = f22;
+   __retVal[3].x = f03;
+   __retVal[3].y = f13;
+   __retVal[3].z = f23;
+}
+
+mat4x3 __constructor(const float f)
+{
+   __retVal = mat4x3(  f, 0.0, 0.0,
+                     0.0,   f, 0.0,
+                     0.0, 0.0,   f,
+                     0.0, 0.0, 0.0);
+}
+
+mat4x3 __constructor(const int i)
+{
+   const float f = float(i);
+   __retVal = mat4x3(f);
+}
+
+mat4x3 __constructor(const bool b)
+{
+   const float f = float(b);
+   __retVal = mat4x3(f);
+}
+
+mat4x3 __constructor(const vec3 c0, const vec3 c1, const vec3 c2, const vec3 c3)
+{
+   __retVal[0] = c0;
+   __retVal[1] = c1;
+   __retVal[2] = c2;
+   __retVal[3] = c3;
+}
+
+
+
+//// misc assorted matrix constructors
+
+mat2 __constructor(const mat2 m)
+{
+   __retVal = m;
+}
+
+mat2 __constructor(const mat3x2 m)
+{
+   __retVal = mat2(m[0], m[1]);
+}
+
+mat2 __constructor(const mat4x2 m)
+{
+   __retVal = mat2(m[0], m[1]);
+}
+
+mat2 __constructor(const mat2x3 m)
+{
+   __retVal = mat2(m[0].xy, m[1].xy);
+}
+
+mat2 __constructor(const mat2x4 m)
+{
+   __retVal = mat2(m[0].xy, m[1].xy);
+}
+
+mat2 __constructor(const mat3 m)
+{
+   __retVal = mat2(m[0].xy, m[1].xy);
+}
+
+mat2 __constructor(const mat3x4 m)
+{
+   __retVal = mat2(m[0].xy, m[1].xy);
+}
+
+mat2 __constructor(const mat4x3 m)
+{
+   __retVal = mat2(m[0].xy, m[1].xy);
+}
+
+mat2 __constructor(const mat4 m)
+{
+   __retVal = mat2(m[0].xy, m[1].xy);
+}
+
+
+
+mat2x3 __constructor(const mat2x3 m)
+{
+   __retVal = m;
+}
+
+mat2x3 __constructor(const mat3 m)
+{
+   __retVal = mat2x3(m[0], m[1]);
+}
+
+mat2x3 __constructor(const mat4x3 m)
+{
+   __retVal = mat2x3(m[0], m[1]);
+}
+
+mat2x3 __constructor(const mat2x4 m)
+{
+   __retVal = mat2x3(m[0].xyz, m[1].xyz);
+}
+
+mat2x3 __constructor(const mat3x4 m)
+{
+   __retVal = mat2x3(m[0].xyz, m[1].xyz);
+}
+
+mat2x3 __constructor(const mat4 m)
+{
+   __retVal = mat2x3(m[0].xyz, m[1].xyz);
+}
+
+mat2x3 __constructor(const mat2 m)
+{
+   __retVal = mat2x3(m[0].x, m[0].y, 0.0,
+                     m[1].x, m[1].y, 0.0);
+}
+
+mat2x3 __constructor(const mat3x2 m)
+{
+   __retVal = mat2x3(m[0].x, m[0].y, 0.0,
+                     m[1].x, m[1].y, 0.0);
+}
+
+mat2x3 __constructor(const mat4x2 m)
+{
+   __retVal = mat2x3(m[0].x, m[0].y, 0.0,
+                     m[1].x, m[1].y, 0.0);
+}
+
+
+
+mat2x4 __constructor(const mat2x4 m)
+{
+   __retVal = m;
+}
+
+mat2x4 __constructor(const mat3x4 m)
+{
+   __retVal = mat2x4(m[0], m[1]);
+}
+
+mat2x4 __constructor(const mat4 m)
+{
+   __retVal = mat2x4(m[0], m[1]);
+}
+
+mat2x4 __constructor(const mat2x3 m)
+{
+   __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
+                     m[1].x, m[1].y, m[1].z, 0.0);
+}
+
+mat2x4 __constructor(const mat3 m)
+{
+   __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
+                     m[1].x, m[1].y, m[1].z, 0.0);
+}
+
+mat2x4 __constructor(const mat4x3 m)
+{
+   __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
+                     m[1].x, m[1].y, m[1].z, 0.0);
+}
+
+mat2x4 __constructor(const mat2 m)
+{
+   __retVal = mat2x4(m[0].x, m[1].y, 0.0, 0.0,
+                     m[1].x, m[1].y, 0.0, 0.0);
+}
+
+mat2x4 __constructor(const mat3x2 m)
+{
+   __retVal = mat2x4(m[0].x, m[0].y, 0.0, 0.0,
+                     m[1].x, m[1].y, 0.0, 0.0);
+}
+
+mat2x4 __constructor(const mat4x2 m)
+{
+   __retVal = mat2x4(m[0].x, m[0].y, 0.0, 0.0,
+                     m[1].x, m[1].y, 0.0, 0.0);
+}
+
+
+
+mat3x2 __constructor(const mat3x2 m)
+{
+   __retVal = m;
+}
+
+mat3x2 __constructor(const mat4x2 m)
+{
+   __retVal = mat3x2(m[0], m[1], m[2]);
+}
+
+mat3x2 __constructor(const mat3 m)
+{
+   __retVal = mat3x2(m[0], m[1], m[2]);
+}
+
+mat3x2 __constructor(const mat3x4 m)
+{
+   __retVal = mat3x2(m[0].x, m[0].y,
+                     m[1].x, m[1].y,
+                     m[2].x, m[2].y);
+}
+
+mat3x2 __constructor(const mat4x3 m)
+{
+   __retVal = mat3x2(m[0].x, m[0].y,
+                     m[1].x, m[1].y,
+                     m[2].x, m[2].y);
+}
+
+mat3x2 __constructor(const mat4 m)
+{
+   __retVal = mat3x2(m[0].x, m[0].y,
+                     m[1].x, m[1].y,
+                        0.0,    0.0);
+}
+
+mat3x2 __constructor(const mat2 m)
+{
+   __retVal = mat3x2(m[0], m[1], vec2(0.0));
+}
+
+mat3x2 __constructor(const mat2x3 m)
+{
+   __retVal = mat3x2(m[0].x, m[0].y,
+                     m[1].x, m[1].y,
+                        0.0,    0.0);
+}
+
+mat3x2 __constructor(const mat2x4 m)
+{
+   __retVal = mat3x2(m[0].x, m[0].y,
+                     m[1].x, m[1].y,
+                        0.0,    0.0);
+}
+
+
+
+
+mat3 __constructor(const mat3 m)
+{
+   __retVal = m;
+}
+
+mat3 __constructor(const mat4x3 m)
+{
+   __retVal = mat3 (
+        m[0],
+        m[1],
+        m[2]
+    );
+}
+
+mat3 __constructor(const mat3x4 m)
+{
+   __retVal = mat3 (
+        m[0].xyz,
+        m[1].xyz,
+        m[2].xyz
+    );
+}
+
+mat3 __constructor(const mat4 m)
+{
+   __retVal = mat3 (
+        m[0].xyz,
+        m[1].xyz,
+        m[2].xyz
+    );
+}
+
+mat3 __constructor(const mat2x3 m)
+{
+   __retVal = mat3 (
+        m[0],
+        m[1],
+        0., 0., 1.
+    );
+}
+
+mat3 __constructor(const mat2x4 m)
+{
+   __retVal = mat3 (
+        m[0].xyz,
+        m[1].xyz,
+        0., 0., 1.
+    );
+}
+
+mat3 __constructor(const mat3x2 m)
+{
+   __retVal = mat3 (
+        m[0], 0.,
+        m[1], 0.,
+        m[2], 1.
+    );
+}
+
+mat3 __constructor(const mat4x2 m)
+{
+   __retVal = mat3 (
+        m[0], 0.,
+        m[1], 0.,
+        m[2], 1.
+    );
+}
+
+mat3 __constructor(const mat2 m)
+{
+   __retVal = mat3 (
+        m[0], 0.,
+        m[1], 0.,
+        0., 0., 1.
+    );
+}
+
+
+mat3x4 __constructor(const mat3x4 m)
+{
+   __retVal = m;
+}
+
+mat3x4 __constructor(const mat4 m)
+{
+   __retVal = mat3x4 (
+        m[0],
+        m[1],
+        m[2]
+    );
+}
+
+mat3x4 __constructor(const mat3 m)
+{
+   __retVal = mat3x4 (
+        m[0], 0.,
+        m[1], 0.,
+        m[2], 0.
+    );
+}
+
+mat3x4 __constructor(const mat4x3 m)
+{
+   __retVal = mat3x4 (
+        m[0], 0.,
+        m[1], 0.,
+        m[2], 0.
+    );
+}
+
+mat3x4 __constructor(const mat2x4 m)
+{
+   __retVal = mat3x4 (
+        m[0],
+        m[1],
+        0., 0., 1., 0.
+    );
+}
+
+mat3x4 __constructor(const mat2x3 m)
+{
+   __retVal = mat3x4 (
+        m[0], 0.,
+        m[1], 0.,
+        0., 0., 1., 0.
+    );
+}
+
+mat3x4 __constructor(const mat3x2 m)
+{
+   __retVal = mat3x4 (
+        m[0], 0., 0.,
+        m[1], 0., 0.,
+        m[2], 1., 0.
+    );
+}
+
+mat3x4 __constructor(const mat4x2 m)
+{
+   __retVal = mat3x4 (
+        m[0], 0., 0.,
+        m[1], 0., 0.,
+        m[2], 1., 0.
+    );
+}
+
+mat3x4 __constructor(const mat2 m)
+{
+   __retVal = mat3x4 (
+        m[0], 0., 0.,
+        m[1], 0., 0.,
+        0., 0., 1., 0.
+    );
+}
+
+
+mat4x2 __constructor(const mat4x2 m)
+{
+   __retVal = m;
+}
+
+mat4x2 __constructor(const mat4x3 m)
+{
+   __retVal = mat4x2 (
+        m[0].xy,
+        m[1].xy,
+        m[2].xy,
+        m[3].xy
+    );
+}
+
+mat4x2 __constructor(const mat4 m)
+{
+   __retVal = mat4x2 (
+        m[0].xy,
+        m[1].xy,
+        m[2].xy,
+        m[3].xy
+    );
+}
+
+mat4x2 __constructor(const mat3x2 m)
+{
+   __retVal = mat4x2 (
+        m[0],
+        m[1],
+        0., 0.
+    );
+}
+
+mat4x2 __constructor(const mat3 m)
+{
+   __retVal = mat4x2 (
+        m[0].xy,
+        m[1].xy,
+        m[2].xy,
+        0., 0.
+    );
+}
+
+mat4x2 __constructor(const mat3x4 m)
+{
+   __retVal = mat4x2 (
+        m[0].xy,
+        m[1].xy,
+        m[2].xy,
+        0., 0.
+    );
+}
+
+mat4x2 __constructor(const mat2 m)
+{
+   __retVal = mat4x2 (
+        m[0],
+        m[1],
+        0., 0.,
+        0., 0.
+    );
+}
+
+mat4x2 __constructor(const mat2x3 m)
+{
+   __retVal = mat4x2 (
+        m[0].xy,
+        m[1].xy,
+        0., 0.,
+        0., 0.
+    );
+}
+
+mat4x2 __constructor(const mat2x4 m)
+{
+   __retVal = mat4x2 (
+        m[0].xy,
+        m[1].xy,
+        0., 0.,
+        0., 0.
+    );
+}
+
+
+mat4x3 __constructor(const mat4x3 m)
+{
+   __retVal = m;
+}
+
+mat4x3 __constructor(const mat4 m)
+{
+   __retVal = mat4x3 (
+        m[0].xyz,
+        m[1].xyz,
+        m[2].xyz,
+        m[3].xyz
+    );
+}
+
+mat4x3 __constructor(const mat3 m)
+{
+   __retVal = mat4x3 (
+        m[0],
+        m[1],
+        m[2],
+        0., 0., 0.
+    );
+}
+
+mat4x3 __constructor(const mat3x4 m)
+{
+   __retVal = mat4x3 (
+        m[0].xyz,
+        m[1].xyz,
+        m[2].xyz,
+        0., 0., 0.
+    );
+}
+
+mat4x3 __constructor(const mat4x2 m)
+{
+   __retVal = mat4x3 (
+        m[0], 0.,
+        m[1], 0.,
+        m[2], 1.,
+        m[3], 0.
+    );
+}
+
+mat4x3 __constructor(const mat2x3 m)
+{
+   __retVal = mat4x3 (
+        m[0],
+        m[1],
+        0., 0., 1.,
+        0., 0., 0.
+    );
+}
+
+mat4x3 __constructor(const mat3x2 m)
+{
+   __retVal = mat4x3 (
+        m[0], 0.,
+        m[1], 0.,
+        m[2], 1.,
+        0., 0., 0.
+    );
+}
+
+mat4x3 __constructor(const mat2x4 m)
+{
+   __retVal = mat4x3 (
+        m[0].xyz,
+        m[1].xyz,
+        0., 0., 1.,
+        0., 0., 0.
+    );
+}
+
+mat4x3 __constructor(const mat2 m)
+{
+   __retVal = mat4x3 (
+        m[0], 0.,
+        m[1], 0.,
+        0., 0., 1.,
+        0., 0., 0.
+    );
+}
+
+
+mat4 __constructor(const mat4 m)
+{
+   __retVal = m;
+}
+
+mat4 __constructor(const mat3x4 m)
+{
+   __retVal = mat4 (
+        m[0],
+        m[1],
+        m[2],
+        0., 0., 0., 1.
+    );
+}
+
+mat4 __constructor(const mat4x3 m)
+{
+   __retVal = mat4 (
+        m[0], 0.,
+        m[1], 0.,
+        m[2], 0.,
+        m[3], 1.
+    );
+}
+
+mat4 __constructor(const mat2x4 m)
+{
+   __retVal = mat4 (
+        m[0],
+        m[1],
+        0., 0., 1., 0.,
+        0., 0., 0., 1.
+    );
+}
+
+mat4 __constructor(const mat4x2 m)
+{
+   __retVal = mat4 (
+        m[0], 0., 0.,
+        m[1], 0., 0.,
+        m[2], 1., 0.,
+        m[3], 0., 1.
+    );
+}
+
+mat4 __constructor(const mat3 m)
+{
+   __retVal = mat4 (
+        m[0], 0.,
+        m[1], 0.,
+        m[2], 0.,
+        0., 0., 0., 1.
+    );
+}
+
+mat4 __constructor(const mat2x3 m)
+{
+   __retVal = mat4 (
+        m[0], 0.,
+        m[1], 0.,
+        0., 0., 1., 0.,
+        0., 0., 0., 1.
+    );
+}
+
+mat4 __constructor(const mat3x2 m)
+{
+   __retVal = mat4 (
+        m[0], 0., 0.,
+        m[1], 0., 0.,
+        m[2], 1., 0.,
+        0., 0., 0., 1.
+    );
+}
+
+mat4 __constructor(const mat2 m)
+{
+   __retVal = mat4 (
+        m[0], 0., 0.,
+        m[1], 0., 0.,
+        0., 0., 1., 0.,
+        0., 0., 0., 1.
+    );
+}
+
+
+void __operator += (inout mat2x3 m, const mat2x3 n) {
+    m[0] += n[0];
+    m[1] += n[1];
+}
+
+void __operator += (inout mat2x4 m, const mat2x4 n) {
+    m[0] += n[0];
+    m[1] += n[1];
+}
+
+void __operator += (inout mat3x2 m, const mat3x2 n) {
+    m[0] += n[0];
+    m[1] += n[1];
+    m[2] += n[2];
+}
+
+void __operator += (inout mat3x4 m, const mat3x4 n) {
+    m[0] += n[0];
+    m[1] += n[1];
+    m[2] += n[2];
+}
+
+void __operator += (inout mat4x2 m, const mat4x2 n) {
+    m[0] += n[0];
+    m[1] += n[1];
+    m[2] += n[2];
+    m[3] += n[3];
+}
+
+void __operator += (inout mat4x3 m, const mat4x3 n) {
+    m[0] += n[0];
+    m[1] += n[1];
+    m[2] += n[2];
+    m[3] += n[3];
+}
+
+
+void __operator -= (inout mat2x3 m, const mat2x3 n) {
+    m[0] -= n[0];
+    m[1] -= n[1];
+}
+
+void __operator -= (inout mat2x4 m, const mat2x4 n) {
+    m[0] -= n[0];
+    m[1] -= n[1];
+}
+
+void __operator -= (inout mat3x2 m, const mat3x2 n) {
+    m[0] -= n[0];
+    m[1] -= n[1];
+    m[2] -= n[2];
+}
+
+void __operator -= (inout mat3x4 m, const mat3x4 n) {
+    m[0] -= n[0];
+    m[1] -= n[1];
+    m[2] -= n[2];
+}
+
+void __operator -= (inout mat4x2 m, const mat4x2 n) {
+    m[0] -= n[0];
+    m[1] -= n[1];
+    m[2] -= n[2];
+    m[3] -= n[3];
+}
+
+void __operator -= (inout mat4x3 m, const mat4x3 n) {
+    m[0] -= n[0];
+    m[1] -= n[1];
+    m[2] -= n[2];
+    m[3] -= n[3];
+}
+
+
+void __operator /= (inout mat2x3 m, const mat2x3 n) {
+    m[0] /= n[0];
+    m[1] /= n[1];
+}
+
+void __operator /= (inout mat2x4 m, const mat2x4 n) {
+    m[0] /= n[0];
+    m[1] /= n[1];
+}
+
+void __operator /= (inout mat3x2 m, const mat3x2 n) {
+    m[0] /= n[0];
+    m[1] /= n[1];
+    m[2] /= n[2];
+}
+
+void __operator /= (inout mat3x4 m, const mat3x4 n) {
+    m[0] /= n[0];
+    m[1] /= n[1];
+    m[2] /= n[2];
+}
+
+void __operator /= (inout mat4x2 m, const mat4x2 n) {
+    m[0] /= n[0];
+    m[1] /= n[1];
+    m[2] /= n[2];
+    m[3] /= n[3];
+}
+
+void __operator /= (inout mat4x3 m, const mat4x3 n) {
+    m[0] /= n[0];
+    m[1] /= n[1];
+    m[2] /= n[2];
+    m[3] /= n[3];
+}
+
+
+vec3 __operator * (const mat2x3 m, const vec2 v)
+{
+   __retVal.x = v.x * m[0].x + v.y * m[1].x;
+   __retVal.y = v.x * m[0].y + v.y * m[1].y;
+   __retVal.z = v.x * m[0].z + v.y * m[1].z;
+}
+
+vec4 __operator * (const mat2x4 m, const vec2 v)
+{
+   __retVal.x = v.x * m[0].x + v.y * m[1].x;
+   __retVal.y = v.x * m[0].y + v.y * m[1].y;
+   __retVal.z = v.x * m[0].z + v.y * m[1].z;
+   __retVal.w = v.x * m[0].w + v.y * m[1].w;
+}
+
+vec2 __operator * (const mat3x2 m, const vec3 v)
+{
+   __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x;
+   __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y;
+}
+
+vec4 __operator * (const mat3x4 m, const vec3 v)
+{
+   __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x;
+   __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y;
+   __retVal.z = v.x * m[0].z + v.y * m[1].z + v.z * m[2].z;
+   __retVal.w = v.x * m[0].w + v.y * m[1].w + v.z * m[2].w;
+}
+
+vec2 __operator * (const mat4x2 m, const vec4 v)
+{
+   __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x;
+   __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y;
+}
+
+vec3 __operator * (const mat4x3 m, const vec4 v)
+{
+   __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x;
+   __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y;
+   __retVal.z = v.x * m[0].z + v.y * m[1].z + v.z * m[2].z + v.w * m[3].z;
+}
+
+
+mat3x2 __operator * (const mat2 m, const mat3x2 n)
+{
+   //return mat3x2 (m * n[0], m * n[1], m * n[2]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+}
+
+mat4x2 __operator * (const mat2 m, const mat4x2 n)
+{
+   //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+   __retVal[3] = m * n[3];
+}
+
+
+mat2x3 __operator * (const mat2x3 m, const mat2 n)
+{
+   //return mat2x3 (m * n[0], m * n[1]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+}
+
+mat3 __operator * (const mat2x3 m, const mat3x2 n)
+{
+   //return mat3 (m * n[0], m * n[1], m * n[2]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+}
+
+mat4x3 __operator * (const mat2x3 m, const mat4x2 n)
+{
+   //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+   __retVal[3] = m * n[3];
+}
+
+
+mat2x4 __operator * (const mat2x4 m, const mat2 n)
+{
+   //return mat2x4 (m * n[0], m * n[1]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+}
+
+mat3x4 __operator * (const mat2x4 m, const mat3x2 n)
+{
+   //return mat3x4 (m * n[0], m * n[1], m * n[2]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+}
+
+mat4 __operator * (const mat2x4 m, const mat4x2 n)
+{
+   //return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+   __retVal[3] = m * n[3];
+}
+
+
+mat2 __operator * (const mat3x2 m, const mat2x3 n)
+{
+   //return mat2 (m * n[0], m * n[1]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+}
+
+mat3x2 __operator * (const mat3x2 m, const mat3 n)
+{
+   //return mat3x2 (m * n[0], m * n[1], m * n[2]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+}
+
+mat4x2 __operator * (const mat3x2 m, const mat4x3 n)
+{
+   //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+   __retVal[3] = m * n[3];
+}
+
+
+mat2x3 __operator * (const mat3 m, const mat2x3 n)
+{
+   //return mat2x3 (m * n[0], m * n[1]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+}
+
+mat4x3 __operator * (const mat3 m, const mat4x3 n)
+{
+   //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+   __retVal[3] = m * n[3];
+}
+
+
+mat2x4 __operator * (const mat3x4 m, const mat2x3 n)
+{
+   //return mat2x4 (m * n[0], m * n[1]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+}
+
+mat3x4 __operator * (const mat3x4 m, const mat3 n)
+{
+   //return mat3x4 (m * n[0], m * n[1], m * n[2]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+}
+
+mat4 __operator * (const mat3x4 m, const mat4x3 n)
+{
+   //return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+   __retVal[3] = m * n[3];
+}
+
+
+mat2 __operator * (const mat4x2 m, const mat2x4 n)
+{
+   //return = mat2 (m * n[0], m * n[1]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+}
+
+mat3x2 __operator * (const mat4x2 m, const mat3x4 n)
+{
+   //return mat3x2 (m * n[0], m * n[1], m * n[2]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+}
+
+mat4x2 __operator * (const mat4x2 m, const mat4 n)
+{
+   //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+   __retVal[3] = m * n[3];
+}
+
+
+mat2x3 __operator * (const mat4x3 m, const mat2x4 n)
+{
+   //return mat2x3 (m * n[0], m * n[1]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+}
+
+mat3 __operator * (const mat4x3 m, const mat3x4 n)
+{
+   //return mat3 (m * n[0], m * n[1], m * n[2]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+}
+
+mat4x3 __operator * (const mat4x3 m, const mat4 n)
+{
+   //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+   __retVal[3] = m * n[3];
+}
+
+
+mat2x4 __operator * (const mat4 m, const mat2x4 n)
+{
+   //return mat2x4 (m * n[0], m * n[1]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+}
+
+mat3x4 __operator * (const mat4 m, const mat3x4 n)
+{
+   //return mat3x4 (m * n[0], m * n[1], m * n[2]);
+   __retVal[0] = m * n[0];
+   __retVal[1] = m * n[1];
+   __retVal[2] = m * n[2];
+}
+
+
+void __operator *= (inout mat2x3 m, const mat2 n) {
+    m = m * n;
+}
+
+void __operator *= (inout mat2x4 m, const mat2 n) {
+    m = m * n;
+}
+
+void __operator *= (inout mat3x2 m, const mat3 n) {
+    m = m * n;
+}
+
+void __operator *= (inout mat3x4 m, const mat3 n) {
+    m = m * n;
+}
+
+void __operator *= (inout mat4x2 m, const mat4 n) {
+    m = m * n;
+}
+
+void __operator *= (inout mat4x3 m, const mat4 n) {
+    m = m * n;
+}
+
+
+vec3 __operator * (const vec2 v, const mat3x2 m)
+{
+   __retVal.x = dot(v, m[0]);
+   __retVal.y = dot(v, m[1]);
+   __retVal.z = dot(v, m[2]);
+}
+
+vec4 __operator * (const vec2 v, const mat4x2 m)
+{
+   __retVal.x = dot(v, m[0]);
+   __retVal.y = dot(v, m[1]);
+   __retVal.z = dot(v, m[2]);
+   __retVal.w = dot(v, m[3]);
+}
+
+vec2 __operator * (const vec3 v, const mat2x3 m)
+{
+   __retVal.x = dot(v, m[0]);
+   __retVal.y = dot(v, m[1]);
+}
+
+vec4 __operator * (const vec3 v, const mat4x3 m)
+{
+   __retVal.x = dot(v, m[0]);
+   __retVal.y = dot(v, m[1]);
+   __retVal.z = dot(v, m[2]);
+   __retVal.w = dot(v, m[3]);
+}
+
+vec2 __operator * (const vec4 v, const mat2x4 m)
+{
+   __retVal.x = dot(v, m[0]);
+   __retVal.y = dot(v, m[1]);
+}
+
+vec3 __operator * (const vec4 v, const mat3x4 m)
+{
+   __retVal.x = dot(v, m[0]);
+   __retVal.y = dot(v, m[1]);
+   __retVal.z = dot(v, m[2]);
+}
+
+
+void __operator += (inout mat2x3 m, const float a) {
+    m[0] += a;
+    m[1] += a;
+}
+
+void __operator += (inout mat2x4 m, const float a) {
+    m[0] += a;
+    m[1] += a;
+}
+
+void __operator += (inout mat3x2 m, const float a) {
+    m[0] += a;
+    m[1] += a;
+    m[2] += a;
+}
+
+void __operator += (inout mat3x4 m, const float a) {
+    m[0] += a;
+    m[1] += a;
+    m[2] += a;
+}
+
+void __operator += (inout mat4x2 m, const float a) {
+    m[0] += a;
+    m[1] += a;
+    m[2] += a;
+    m[3] += a;
+}
+
+void __operator += (inout mat4x3 m, const float a) {
+    m[0] += a;
+    m[1] += a;
+    m[2] += a;
+    m[3] += a;
+}
+
+
+void __operator -= (inout mat2x3 m, const float a) {
+    m[0] -= a;
+    m[1] -= a;
+}
+
+void __operator -= (inout mat2x4 m, const float a) {
+    m[0] -= a;
+    m[1] -= a;
+}
+
+void __operator -= (inout mat3x2 m, const float a) {
+    m[0] -= a;
+    m[1] -= a;
+    m[2] -= a;
+}
+
+void __operator -= (inout mat3x4 m, const float a) {
+    m[0] -= a;
+    m[1] -= a;
+    m[2] -= a;
+}
+
+void __operator -= (inout mat4x2 m, const float a) {
+    m[0] -= a;
+    m[1] -= a;
+    m[2] -= a;
+    m[3] -= a;
+}
+
+void __operator -= (inout mat4x3 m, const float a) {
+    m[0] -= a;
+    m[1] -= a;
+    m[2] -= a;
+    m[3] -= a;
+}
+
+
+void __operator *= (inout mat2x3 m, const float a) {
+    m[0] *= a;
+    m[1] *= a;
+}
+
+void __operator *= (inout mat2x4 m, const float a) {
+    m[0] *= a;
+    m[1] *= a;
+}
+
+void __operator *= (inout mat3x2 m, const float a) {
+    m[0] *= a;
+    m[1] *= a;
+    m[2] *= a;
+}
+
+void __operator *= (inout mat3x4 m, const float a) {
+    m[0] *= a;
+    m[1] *= a;
+    m[2] *= a;
+}
+
+void __operator *= (inout mat4x2 m, const float a) {
+    m[0] *= a;
+    m[1] *= a;
+    m[2] *= a;
+    m[3] *= a;
+}
+
+void __operator *= (inout mat4x3 m, const float a) {
+    m[0] *= a;
+    m[1] *= a;
+    m[2] *= a;
+    m[3] *= a;
+}
+
+
+void __operator /= (inout mat2x3 m, const float a) {
+    m[0] /= a;
+    m[1] /= a;
+}
+
+void __operator /= (inout mat2x4 m, const float a) {
+    m[0] /= a;
+    m[1] /= a;
+}
+
+void __operator /= (inout mat3x2 m, const float a) {
+    m[0] /= a;
+    m[1] /= a;
+    m[2] /= a;
+}
+
+void __operator /= (inout mat3x4 m, const float a) {
+    m[0] /= a;
+    m[1] /= a;
+    m[2] /= a;
+}
+
+void __operator /= (inout mat4x2 m, const float a) {
+    m[0] /= a;
+    m[1] /= a;
+    m[2] /= a;
+    m[3] /= a;
+}
+
+void __operator /= (inout mat4x3 m, const float a) {
+    m[0] /= a;
+    m[1] /= a;
+    m[2] /= a;
+    m[3] /= a;
+}
+
+
+mat2x3 __operator + (const mat2x3 m, const mat2x3 n) {
+    return mat2x3 (m[0] + n[0], m[1] + n[1]);
+}
+
+mat2x4 __operator + (const mat2x4 m, const mat2x4 n) {
+    return mat2x4 (m[0] + n[0], m[1] + n[1]);
+}
+
+mat3x2 __operator + (const mat3x2 m, const mat3x2 n) {
+    return mat3x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2]);
+}
+
+mat3x4 __operator + (const mat3x4 m, const mat3x4 n) {
+    return mat3x4 (m[0] + n[0], m[1] + n[1], m[2] + n[2]);
+}
+
+mat4x2 __operator + (const mat4x2 m, const mat4x2 n) {
+    return mat4x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]);
+}
+
+mat4x3 __operator + (const mat4x3 m, const mat4x3 n) {
+    return mat4x3 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]);
+}
+
+
+mat2x3 __operator - (const mat2x3 m, const mat2x3 n) {
+    return mat2x3 (m[0] - n[0], m[1] - n[1]);
+}
+
+mat2x4 __operator - (const mat2x4 m, const mat2x4 n) {
+    return mat2x4 (m[0] - n[0], m[1] - n[1]);
+}
+
+mat3x2 __operator - (const mat3x2 m, const mat3x2 n) {
+    return mat3x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2]);
+}
+
+mat3x4 __operator - (const mat3x4 m, const mat3x4 n) {
+    return mat3x4 (m[0] - n[0], m[1] - n[1], m[2] - n[2]);
+}
+
+mat4x2 __operator - (const mat4x2 m, const mat4x2 n) {
+    return mat4x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]);
+}
+
+mat4x3 __operator - (const mat4x3 m, const mat4x3 n) {
+    return mat4x3 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]);
+}
+
+
+mat2x3 __operator / (const mat2x3 m, const mat2x3 n) {
+    return mat2x3 (m[0] / n[0], m[1] / n[1]);
+}
+
+mat2x4 __operator / (const mat2x4 m, const mat2x4 n) {
+    return mat2x4 (m[0] / n[0], m[1] / n[1]);
+}
+
+mat3x2 __operator / (const mat3x2 m, const mat3x2 n) {
+    return mat3x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2]);
+}
+
+mat3x4 __operator / (const mat3x4 m, const mat3x4 n) {
+    return mat3x4 (m[0] / n[0], m[1] / n[1], m[2] / n[2]);
+}
+
+mat4x2 __operator / (const mat4x2 m, const mat4x2 n) {
+    return mat4x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]);
+}
+
+mat4x3 __operator / (const mat4x3 m, const mat4x3 n) {
+    return mat4x3 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]);
+}
+
+
+mat2x3 __operator + (const float a, const mat2x3 n) {
+    return mat2x3 (a + n[0], a + n[1]);
+}
+
+mat2x3 __operator + (const mat2x3 m, const float b) {
+    return mat2x3 (m[0] + b, m[1] + b);
+}
+
+mat2x4 __operator + (const float a, const mat2x4 n) {
+    return mat2x4 (a + n[0], a + n[1]);
+}
+
+mat2x4 __operator + (const mat2x4 m, const float b) {
+    return mat2x4 (m[0] + b, m[1] + b);
+}
+
+mat3x2 __operator + (const float a, const mat3x2 n) {
+    return mat3x2 (a + n[0], a + n[1], a + n[2]);
+}
+
+mat3x2 __operator + (const mat3x2 m, const float b) {
+    return mat3x2 (m[0] + b, m[1] + b, m[2] + b);
+}
+
+mat3x4 __operator + (const float a, const mat3x4 n) {
+    return mat3x4 (a + n[0], a + n[1], a + n[2]);
+}
+
+mat3x4 __operator + (const mat3x4 m, const float b) {
+    return mat3x4 (m[0] + b, m[1] + b, m[2] + b);
+}
+
+mat4x2 __operator + (const mat4x2 m, const float b) {
+    return mat4x2 (m[0] + b, m[1] + b, m[2] + b, m[3] + b);
+}
+
+mat4x2 __operator + (const float a, const mat4x2 n) {
+    return mat4x2 (a + n[0], a + n[1], a + n[2], a + n[3]);
+}
+
+mat4x3 __operator + (const mat4x3 m, const float b) {
+    return mat4x3 (m[0] + b, m[1] + b, m[2] + b, m[3] + b);
+}
+
+mat4x3 __operator + (const float a, const mat4x3 n) {
+    return mat4x3 (a + n[0], a + n[1], a + n[2], a + n[3]);
+}
+
+
+mat2x3 __operator - (const float a, const mat2x3 n) {
+    return mat2x3 (a - n[0], a - n[1]);
+}
+
+mat2x3 __operator - (const mat2x3 m, const float b) {
+    return mat2x3 (m[0] - b, m[1] - b);
+}
+
+mat2x4 __operator - (const float a, const mat2x4 n) {
+    return mat2x4 (a - n[0], a - n[1]);
+}
+
+mat2x4 __operator - (const mat2x4 m, const float b) {
+    return mat2x4 (m[0] - b, m[1] - b);
+}
+
+mat3x2 __operator - (const float a, const mat3x2 n) {
+    return mat3x2 (a - n[0], a - n[1], a - n[2]);
+}
+
+mat3x2 __operator - (const mat3x2 m, const float b) {
+    return mat3x2 (m[0] - b, m[1] - b, m[2] - b);
+}
+
+mat3x4 __operator - (const float a, const mat3x4 n) {
+    return mat3x4 (a - n[0], a - n[1], a - n[2]);
+}
+
+mat3x4 __operator - (const mat3x4 m, const float b) {
+    return mat3x4 (m[0] - b, m[1] - b, m[2] - b);
+}
+
+mat4x2 __operator - (const mat4x2 m, const float b) {
+    return mat4x2 (m[0] - b, m[1] - b, m[2] - b, m[3] - b);
+}
+
+mat4x2 __operator - (const float a, const mat4x2 n) {
+    return mat4x2 (a - n[0], a - n[1], a - n[2], a - n[3]);
+}
+
+mat4x3 __operator - (const mat4x3 m, const float b) {
+    return mat4x3 (m[0] - b, m[1] - b, m[2] - b, m[3] - b);
+}
+
+mat4x3 __operator - (const float a, const mat4x3 n) {
+    return mat4x3 (a - n[0], a - n[1], a - n[2], a - n[3]);
+}
+
+
+mat2x3 __operator * (const float a, const mat2x3 n)
+{
+   //return mat2x3 (a * n[0], a * n[1]);
+   __retVal[0] = a * n[0];
+   __retVal[1] = a * n[1];
+}
+
+mat2x3 __operator * (const mat2x3 m, const float b)
+{
+   //return mat2x3 (m[0] * b, m[1] * b);
+   __retVal[0] = m[0] * b;
+   __retVal[1] = m[1] * b;
+}
+
+mat2x4 __operator * (const float a, const mat2x4 n)
+{
+   //return mat2x4 (a * n[0], a * n[1]);
+   __retVal[0] = a * n[0];
+   __retVal[1] = a * n[1];
+}
+
+mat2x4 __operator * (const mat2x4 m, const float b)
+{
+   //return mat2x4 (m[0] * b, m[1] * b);
+   __retVal[0] = m[0] * b;
+   __retVal[1] = m[1] * b;
+}
+
+mat3x2 __operator * (const float a, const mat3x2 n)
+{
+   //return mat3x2 (a * n[0], a * n[1], a * n[2]);
+   __retVal[0] = a * n[0];
+   __retVal[1] = a * n[1];
+   __retVal[2] = a * n[2];
+}
+
+mat3x2 __operator * (const mat3x2 m, const float b)
+{
+   //return mat3x2 (m[0] * b, m[1] * b, m[2] * b);
+   __retVal[0] = m[0] * b;
+   __retVal[1] = m[1] * b;
+   __retVal[2] = m[2] * b;
+}
+
+mat3x4 __operator * (const float a, const mat3x4 n)
+{
+   //return mat3x4 (a * n[0], a * n[1], a * n[2]);
+   __retVal[0] = a * n[0];
+   __retVal[1] = a * n[1];
+   __retVal[2] = a * n[2];
+}
+
+mat3x4 __operator * (const mat3x4 m, const float b)
+{
+   //return mat3x4 (m[0] * b, m[1] * b, m[2] * b);
+   __retVal[0] = m[0] * b;
+   __retVal[1] = m[1] * b;
+   __retVal[2] = m[2] * b;
+}
+
+mat4x2 __operator * (const mat4x2 m, const float b)
+{
+   //return mat4x2 (m[0] * b, m[1] * b, m[2] * b, m[3] * b);
+   __retVal[0] = m[0] * b;
+   __retVal[1] = m[1] * b;
+   __retVal[2] = m[2] * b;
+   __retVal[3] = m[3] * b;
+}
+
+mat4x2 __operator * (const float a, const mat4x2 n)
+{
+   //return mat4x2 (a * n[0], a * n[1], a * n[2], a * n[3]);
+   __retVal[0] = a * n[0];
+   __retVal[1] = a * n[1];
+   __retVal[2] = a * n[2];
+   __retVal[3] = a * n[3];
+}
+
+mat4x3 __operator * (const mat4x3 m, const float b)
+{
+   //return mat4x3 (m[0] * b, m[1] * b, m[2] * b, m[3] * b);
+   __retVal[0] = m[0] * b;
+   __retVal[1] = m[1] * b;
+   __retVal[2] = m[2] * b;
+   __retVal[3] = m[3] * b;
+}
+
+mat4x3 __operator * (const float a, const mat4x3 n)
+{
+   //return mat4x3 (a * n[0], a * n[1], a * n[2], a * n[3]);
+   __retVal[0] = a * n[0];
+   __retVal[1] = a * n[1];
+   __retVal[2] = a * n[2];
+   __retVal[3] = a * n[3];
+}
+
+
+mat2x3 __operator / (const float a, const mat2x3 n)
+{
+   //return mat2x3 (a / n[0], a / n[1]);
+   const float inv = 1.0 / a;
+   __retVal[0] = inv * n[0];
+   __retVal[1] = inv * n[1];
+}
+
+mat2x3 __operator / (const mat2x3 m, const float b)
+{
+   //return mat2x3 (m[0] / b, m[1] / b);
+   const float inv = 1.0 / b;
+   __retVal[0] = m[0] * inv;
+   __retVal[1] = m[1] * inv;
+}
+
+mat2x4 __operator / (const float a, const mat2x4 n)
+{
+   //return mat2x4 (a / n[0], a / n[1]);
+   const float inv = 1.0 / a;
+   __retVal[0] = inv * n[0];
+   __retVal[1] = inv * n[1];
+}
+
+mat2x4 __operator / (const mat2x4 m, const float b)
+{
+   //return mat2x4 (m[0] / b, m[1] / b);
+   const float inv = 1.0 / b;
+   __retVal[0] = m[0] * inv;
+   __retVal[1] = m[1] * inv;
+}
+
+mat3x2 __operator / (const float a, const mat3x2 n)
+{
+   //return mat3x2 (a / n[0], a / n[1], a / n[2]);
+   const float inv = 1.0 / a;
+   __retVal[0] = inv * n[0];
+   __retVal[1] = inv * n[1];
+   __retVal[2] = inv * n[2];
+}
+
+mat3x2 __operator / (const mat3x2 m, const float b)
+{
+   //return mat3x2 (m[0] / b, m[1] / b, m[2] / b);
+   const float inv = 1.0 / b;
+   __retVal[0] = m[0] * inv;
+   __retVal[1] = m[1] * inv;
+   __retVal[2] = m[2] * inv;
+}
+
+mat3x4 __operator / (const float a, const mat3x4 n)
+{
+   //return mat3x4 (a / n[0], a / n[1], a / n[2]);
+   const float inv = 1.0 / a;
+   __retVal[0] = inv * n[0];
+   __retVal[1] = inv * n[1];
+   __retVal[2] = inv * n[2];
+}
+
+mat3x4 __operator / (const mat3x4 m, const float b)
+{
+   //return mat3x4 (m[0] / b, m[1] / b, m[2] / b);
+   const float inv = 1.0 / b;
+   __retVal[0] = m[0] * inv;
+   __retVal[1] = m[1] * inv;
+   __retVal[2] = m[2] * inv;
+}
+
+mat4x2 __operator / (const mat4x2 m, const float b)
+{
+   //return mat4x2 (m[0] / b, m[1] / b, m[2] / b, m[3] / b);
+   const float inv = 1.0 / b;
+   __retVal[0] = m[0] * inv;
+   __retVal[1] = m[1] * inv;
+   __retVal[2] = m[2] * inv;
+   __retVal[3] = m[3] * inv;
+}
+
+mat4x2 __operator / (const float a, const mat4x2 n)
+{
+   //return mat4x2 (a / n[0], a / n[1], a / n[2], a / n[3]);
+   const float inv = 1.0 / a;
+   __retVal[0] = inv * n[0];
+   __retVal[1] = inv * n[1];
+   __retVal[2] = inv * n[2];
+   __retVal[3] = inv * n[3];
+}
+
+mat4x3 __operator / (const mat4x3 m, const float b)
+{
+   //return mat4x3 (m[0] / b, m[1] / b, m[2] / b, m[3] / b);
+   const float inv = 1.0 / b;
+   __retVal[0] = m[0] * inv;
+   __retVal[1] = m[1] * inv;
+   __retVal[2] = m[2] * inv;
+   __retVal[3] = m[3] * inv;
+}
+
+mat4x3 __operator / (const float a, const mat4x3 n)
+{
+   //return mat4x3 (a / n[0], a / n[1], a / n[2], a / n[3]);
+   const float inv = 1.0 / a;
+   __retVal[0] = inv * n[0];
+   __retVal[1] = inv * n[1];
+   __retVal[2] = inv * n[2];
+   __retVal[3] = inv * n[3];
+}
+
+
+mat2x3 __operator - (const mat2x3 m) {
+    return mat2x3 (-m[0], -m[1]);
+}
+
+mat2x4 __operator - (const mat2x4 m) {
+    return mat2x4 (-m[0], -m[1]);
+}
+
+mat3x2 __operator - (const mat3x2 m) {
+    return mat3x2 (-m[0], -m[1], -m[2]);
+}
+
+mat3x4 __operator - (const mat3x4 m) {
+    return mat3x4 (-m[0], -m[1], -m[2]);
+}
+
+mat4x2 __operator - (const mat4x2 m) {
+    return mat4x2 (-m[0], -m[1], -m[2], -m[3]);
+}
+
+mat4x3 __operator - (const mat4x3 m) {
+    return mat4x3 (-m[0], -m[1], -m[2], -m[3]);
+}
+
+
+void __operator -- (inout mat2x3 m) {
+    --m[0];
+    --m[1];
+}
+
+void __operator -- (inout mat2x4 m) {
+    --m[0];
+    --m[1];
+}
+
+void __operator -- (inout mat3x2 m) {
+    --m[0];
+    --m[1];
+    --m[2];
+}
+
+void __operator -- (inout mat3x4 m) {
+    --m[0];
+    --m[1];
+    --m[2];
+}
+
+void __operator -- (inout mat4x2 m) {
+    --m[0];
+    --m[1];
+    --m[2];
+    --m[3];
+}
+
+void __operator -- (inout mat4x3 m) {
+    --m[0];
+    --m[1];
+    --m[2];
+    --m[3];
+}
+
+
+void __operator ++ (inout mat2x3 m) {
+    ++m[0];
+    ++m[1];
+}
+
+void __operator ++ (inout mat2x4 m) {
+    ++m[0];
+    ++m[1];
+}
+
+void __operator ++ (inout mat3x2 m) {
+    ++m[0];
+    ++m[1];
+    ++m[2];
+}
+
+void __operator ++ (inout mat3x4 m) {
+    ++m[0];
+    ++m[1];
+    ++m[2];
+}
+
+void __operator ++ (inout mat4x2 m) {
+    ++m[0];
+    ++m[1];
+    ++m[2];
+    ++m[3];
+}
+
+void __operator ++ (inout mat4x3 m) {
+    ++m[0];
+    ++m[1];
+    ++m[2];
+    ++m[3];
+}
+
diff --git a/src/mesa/slang/library/slang_builtin_120_common.gc b/src/mesa/slang/library/slang_builtin_120_common.gc
new file mode 100644 (file)
index 0000000..c6264c3
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.6
+ *
+ * Copyright (C) 2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+//
+// From Shader Spec, ver. 1.20, rev. 6
+//
+
+//
+// 8.5 Matrix Functions
+//
+
+mat2x3 matrixCompMult (mat2x3 m, mat2x3 n) {
+    return mat2x3 (m[0] * n[0], m[1] * n[1]);
+}
+
+mat2x4 matrixCompMult (mat2x4 m, mat2x4 n) {
+    return mat2x4 (m[0] * n[0], m[1] * n[1]);
+}
+
+mat3x2 matrixCompMult (mat3x2 m, mat3x2 n) {
+    return mat3x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
+}
+
+mat3x4 matrixCompMult (mat3x4 m, mat3x4 n) {
+    return mat3x4 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
+}
+
+mat4x2 matrixCompMult (mat4x2 m, mat4x2 n) {
+    return mat4x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
+}
+
+mat4x3 matrixCompMult (mat4x3 m, mat4x3 n) {
+    return mat4x3 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
+}
+
+mat2 outerProduct (vec2 c, vec2 r) {
+    return mat2 (
+        c.x * r.x, c.y * r.x,
+        c.x * r.y, c.y * r.y
+    );
+}
+
+mat3 outerProduct (vec3 c, vec3 r) {
+    return mat3 (
+        c.x * r.x, c.y * r.x, c.z * r.x,
+        c.x * r.y, c.y * r.y, c.z * r.y,
+        c.x * r.z, c.y * r.z, c.z * r.z
+    );
+}
+
+mat4 outerProduct (vec4 c, vec4 r) {
+    return mat4 (
+        c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
+        c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y,
+        c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z,
+        c.x * r.w, c.y * r.w, c.z * r.w, c.w * r.w
+    );
+}
+
+mat2x3 outerProduct (vec3 c, vec2 r) {
+    return mat2x3 (
+        c.x * r.x, c.y * r.x, c.z * r.x,
+        c.x * r.y, c.y * r.y, c.z * r.y
+    );
+}
+
+mat3x2 outerProduct (vec2 c, vec3 r) {
+    return mat3x2 (
+        c.x * r.x, c.y * r.x,
+        c.x * r.y, c.y * r.y,
+        c.x * r.z, c.y * r.z
+    );
+}
+
+mat2x4 outerProduct (vec4 c, vec2 r) {
+    return mat2x4 (
+        c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
+        c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y
+    );
+}
+
+mat4x2 outerProduct (vec2 c, vec4 r) {
+    return mat4x2 (
+        c.x * r.x, c.y * r.x,
+        c.x * r.y, c.y * r.y,
+        c.x * r.z, c.y * r.z,
+        c.x * r.w, c.y * r.w
+    );
+}
+
+mat3x4 outerProduct (vec4 c, vec3 r) {
+    return mat3x4 (
+        c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
+        c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y,
+        c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z
+    );
+}
+
+mat4x3 outerProduct (vec3 c, vec4 r) {
+    return mat4x3 (
+        c.x * r.x, c.y * r.x, c.z * r.x,
+        c.x * r.y, c.y * r.y, c.z * r.y,
+        c.x * r.z, c.y * r.z, c.z * r.z,
+        c.x * r.w, c.y * r.w, c.z * r.w
+    );
+}
+
+mat2 transpose (mat2 m) {
+    return mat2 (
+        m[0].x, m[1].x,
+        m[0].y, m[1].y
+    );
+}
+
+mat3 transpose (mat3 m) {
+    return mat3 (
+        m[0].x, m[1].x, m[2].x,
+        m[0].y, m[1].y, m[2].y,
+        m[0].z, m[1].z, m[2].z
+    );
+}
+
+mat4 transpose (mat4 m) {
+    return mat4 (
+        m[0].x, m[1].x, m[2].x, m[3].x,
+        m[0].y, m[1].y, m[2].y, m[3].y,
+        m[0].z, m[1].z, m[2].z, m[3].z,
+        m[0].w, m[1].w, m[2].w, m[3].w
+    );
+}
+
+mat2x3 transpose (mat3x2 m) {
+    return mat2x3 (
+        m[0].x, m[1].x, m[2].x,
+        m[0].y, m[1].y, m[2].y
+    );
+}
+
+mat3x2 transpose (mat2x3 m) {
+    return mat3x2 (
+        m[0].x, m[1].x,
+        m[0].y, m[1].y,
+        m[0].z, m[1].z
+    );
+}
+
+mat2x4 transpose (mat4x2 m) {
+    return mat2x4 (
+        m[0].x, m[1].x, m[2].x, m[3].x,
+        m[0].y, m[1].y, m[2].y, m[3].y
+    );
+}
+
+mat4x2 transpose (mat2x4 m) {
+    return mat4x2 (
+        m[0].x, m[1].x,
+        m[0].y, m[1].y,
+        m[0].z, m[1].z,
+        m[0].w, m[1].w
+    );
+}
+
+mat3x4 transpose (mat4x3 m) {
+    return mat3x4 (
+        m[0].x, m[1].x, m[2].x, m[3].x,
+        m[0].y, m[1].y, m[2].y, m[3].y,
+        m[0].z, m[1].z, m[2].z, m[3].z
+    );
+}
+
+mat4x3 transpose (mat3x4 m) {
+    return mat4x3 (
+        m[0].x, m[1].x, m[2].x,
+        m[0].y, m[1].y, m[2].y,
+        m[0].z, m[1].z, m[2].z,
+        m[0].w, m[1].w, m[2].w
+    );
+}
+
diff --git a/src/mesa/slang/library/slang_builtin_120_fragment.gc b/src/mesa/slang/library/slang_builtin_120_fragment.gc
new file mode 100644 (file)
index 0000000..7d51604
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+//
+// From Shader Spec, ver. 1.20, rev. 6
+//
+
+varying vec2 gl_PointCoord;
+
diff --git a/src/mesa/slang/library/slang_common_builtin.gc b/src/mesa/slang/library/slang_common_builtin.gc
new file mode 100644 (file)
index 0000000..d75354d
--- /dev/null
@@ -0,0 +1,1887 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.3
+ *
+ * Copyright (C) 2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2008  VMware, Inc.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+//
+// From Shader Spec, ver. 1.10, rev. 59
+//
+
+// Note: the values assigned to these constants here aren't actually used.
+// They're set by the compiler according to the GL context limits.
+// See slang_simplify.c
+const int gl_MaxLights = 8;
+const int gl_MaxClipPlanes = 6;
+const int gl_MaxTextureUnits = 8;
+const int gl_MaxTextureCoords = 8;
+const int gl_MaxVertexAttribs = 16;
+const int gl_MaxVertexUniformComponents = 512;
+const int gl_MaxVaryingFloats = 32;
+const int gl_MaxVertexTextureImageUnits = 0;
+const int gl_MaxCombinedTextureImageUnits = 2;
+const int gl_MaxTextureImageUnits = 2;
+const int gl_MaxFragmentUniformComponents = 64;
+const int gl_MaxDrawBuffers = 1;
+
+uniform mat4 gl_ModelViewMatrix;
+uniform mat4 gl_ProjectionMatrix;
+uniform mat4 gl_ModelViewProjectionMatrix;
+uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];
+
+uniform mat3 gl_NormalMatrix;
+
+uniform mat4 gl_ModelViewMatrixInverse;
+uniform mat4 gl_ProjectionMatrixInverse;
+uniform mat4 gl_ModelViewProjectionMatrixInverse;
+uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];
+
+uniform mat4 gl_ModelViewMatrixTranspose;
+uniform mat4 gl_ProjectionMatrixTranspose;
+uniform mat4 gl_ModelViewProjectionMatrixTranspose;
+uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];
+
+uniform mat4 gl_ModelViewMatrixInverseTranspose;
+uniform mat4 gl_ProjectionMatrixInverseTranspose;
+uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;
+uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];
+
+uniform float gl_NormalScale;
+
+struct gl_DepthRangeParameters {
+    float near;
+    float far;
+    float diff;
+};
+
+uniform gl_DepthRangeParameters gl_DepthRange;
+
+uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];
+
+struct gl_PointParameters {
+    float size;
+    float sizeMin;
+    float sizeMax;
+    float fadeThresholdSize;
+    float distanceConstantAttenuation;
+    float distanceLinearAttenuation;
+    float distanceQuadraticAttenuation;
+};
+
+uniform gl_PointParameters gl_Point;
+
+struct gl_MaterialParameters {
+    vec4 emission;
+    vec4 ambient;
+    vec4 diffuse;
+    vec4 specular;
+    float shininess;
+};
+
+uniform gl_MaterialParameters gl_FrontMaterial;
+uniform gl_MaterialParameters gl_BackMaterial;
+
+/* NOTE: the order of these fields is significant!
+ * See the definition of the lighting state vars such as STATE_SPOT_DIRECTION.
+ */
+struct gl_LightSourceParameters {
+    vec4 ambient;
+    vec4 diffuse;
+    vec4 specular;
+    vec4 position;
+    vec4 halfVector;
+    vec3 spotDirection;
+    float spotCosCutoff;
+
+    float constantAttenuation;
+    float linearAttenuation;
+    float quadraticAttenuation;
+    float spotExponent;
+
+    float spotCutoff;
+};
+
+uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];
+
+struct gl_LightModelParameters {
+    vec4 ambient;
+};
+
+uniform gl_LightModelParameters gl_LightModel;
+
+struct gl_LightModelProducts {
+    vec4 sceneColor;
+};
+
+uniform gl_LightModelProducts gl_FrontLightModelProduct;
+uniform gl_LightModelProducts gl_BackLightModelProduct;
+
+struct gl_LightProducts {
+    vec4 ambient;
+    vec4 diffuse;
+    vec4 specular;
+};
+
+uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];
+uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];
+
+uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];
+uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];
+uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];
+uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];
+uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];
+uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];
+uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];
+uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];
+uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];
+
+struct gl_FogParameters {
+    vec4 color;
+    float density;
+    float start;
+    float end;
+    float scale;
+};
+
+uniform gl_FogParameters gl_Fog;
+
+
+
+
+
+//
+// 8.1 Angle and Trigonometry Functions
+//
+
+//// radians
+
+float radians(const float deg)
+{
+   const float c = 3.1415926 / 180.0;
+   __asm vec4_multiply __retVal, deg, c;
+}
+
+vec2 radians(const vec2 deg)
+{
+   const float c = 3.1415926 / 180.0;
+   __asm vec4_multiply __retVal.xy, deg.xy, c.xx;
+}
+
+vec3 radians(const vec3 deg)
+{
+   const float c = 3.1415926 / 180.0;
+   __asm vec4_multiply __retVal.xyz, deg.xyz, c.xxx;
+}
+
+vec4 radians(const vec4 deg)
+{
+   const float c = 3.1415926 / 180.0;
+   __asm vec4_multiply __retVal, deg, c.xxxx;
+}
+
+
+//// degrees
+
+float degrees(const float rad)
+{
+   const float c = 180.0 / 3.1415926;
+   __asm vec4_multiply __retVal, rad, c;
+}
+
+vec2 degrees(const vec2 rad)
+{
+   const float c = 180.0 / 3.1415926;
+   __asm vec4_multiply __retVal.xy, rad.xy, c.xx;
+}
+
+vec3 degrees(const vec3 rad)
+{
+   const float c = 180.0 / 3.1415926;
+   __asm vec4_multiply __retVal.xyz, rad.xyz, c.xxx;
+}
+
+vec4 degrees(const vec4 rad)
+{
+   const float c = 180.0 / 3.1415926;
+   __asm vec4_multiply __retVal, rad, c.xxxx;
+}
+
+
+//// sin
+
+float sin(const float radians)
+{
+   __asm float_sine __retVal, radians;
+}
+
+vec2 sin(const vec2 radians)
+{
+   __asm float_sine __retVal.x, radians.x;
+   __asm float_sine __retVal.y, radians.y;
+}
+
+vec3 sin(const vec3 radians)
+{
+   __asm float_sine __retVal.x, radians.x;
+   __asm float_sine __retVal.y, radians.y;
+   __asm float_sine __retVal.z, radians.z;
+}
+
+vec4 sin(const vec4 radians)
+{
+   __asm float_sine __retVal.x, radians.x;
+   __asm float_sine __retVal.y, radians.y;
+   __asm float_sine __retVal.z, radians.z;
+   __asm float_sine __retVal.w, radians.w;
+}
+
+
+//// cos
+
+float cos(const float radians)
+{
+   __asm float_cosine __retVal, radians;
+}
+
+vec2 cos(const vec2 radians)
+{
+   __asm float_cosine __retVal.x, radians.x;
+   __asm float_cosine __retVal.y, radians.y;
+}
+
+vec3 cos(const vec3 radians)
+{
+   __asm float_cosine __retVal.x, radians.x;
+   __asm float_cosine __retVal.y, radians.y;
+   __asm float_cosine __retVal.z, radians.z;
+}
+
+vec4 cos(const vec4 radians)
+{
+   __asm float_cosine __retVal.x, radians.x;
+   __asm float_cosine __retVal.y, radians.y;
+   __asm float_cosine __retVal.z, radians.z;
+   __asm float_cosine __retVal.w, radians.w;
+}
+
+
+
+//// tan
+
+float tan(const float angle)
+{
+   const float s = sin(angle);
+   const float c = cos(angle);
+   return s / c;
+}
+
+vec2 tan(const vec2 angle)
+{
+   const vec2 s = sin(angle);
+   const vec2 c = cos(angle);
+   return s / c;
+}
+
+vec3 tan(const vec3 angle)
+{
+   const vec3 s = sin(angle);
+   const vec3 c = cos(angle);
+   return s / c;
+}
+
+vec4 tan(const vec4 angle)
+{
+   const vec4 s = sin(angle);
+   const vec4 c = cos(angle);
+   return s / c;
+}
+
+
+
+float asin(const float x)
+{
+   const float a0 = 1.5707288;  // PI/2?
+   const float a1 = -0.2121144;
+   const float a2 = 0.0742610;
+   //const float a3 = -0.0187293;
+   const float halfPi = 3.1415926 * 0.5;
+   const float y = abs(x);
+   // three terms seem to be enough:
+   __retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + a2 * y))) * sign(x);
+   // otherwise, try four:
+   //__retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + y * (a2 + y * a3)))) * sign(x);
+}
+
+vec2 asin(const vec2 v)
+{
+   __retVal.x = asin(v.x);
+   __retVal.y = asin(v.y);
+}
+
+vec3 asin(const vec3 v)
+{
+   __retVal.x = asin(v.x);
+   __retVal.y = asin(v.y);
+   __retVal.z = asin(v.z);
+}
+
+vec4 asin(const vec4 v)
+{
+   __retVal.x = asin(v.x);
+   __retVal.y = asin(v.y);
+   __retVal.z = asin(v.z);
+   __retVal.w = asin(v.w);
+}
+
+float acos(const float x)
+{
+   const float halfPi = 3.1415926 * 0.5;
+   __retVal = halfPi - asin(x);
+}
+
+vec2 acos(const vec2 v)
+{
+   __retVal.x = acos(v.x);
+   __retVal.y = acos(v.y);
+}
+
+vec3 acos(const vec3 v)
+{
+   __retVal.x = acos(v.x);
+   __retVal.y = acos(v.y);
+   __retVal.z = acos(v.z);
+}
+
+vec4 acos(const vec4 v)
+{
+   __retVal.x = acos(v.x);
+   __retVal.y = acos(v.y);
+   __retVal.z = acos(v.z);
+   __retVal.w = acos(v.w);
+}
+
+float atan(const float x)
+{
+   __retVal = asin(x * inversesqrt(x * x + 1.0));
+}
+
+vec2 atan(const vec2 y_over_x)
+{
+   __retVal.x = atan(y_over_x.x);
+   __retVal.y = atan(y_over_x.y);
+}
+
+vec3 atan(const vec3 y_over_x)
+{
+   __retVal.x = atan(y_over_x.x);
+   __retVal.y = atan(y_over_x.y);
+   __retVal.z = atan(y_over_x.z);
+}
+
+vec4 atan(const vec4 y_over_x)
+{
+   __retVal.x = atan(y_over_x.x);
+   __retVal.y = atan(y_over_x.y);
+   __retVal.z = atan(y_over_x.z);
+   __retVal.w = atan(y_over_x.w);
+}
+
+float atan(const float y, const float x)
+{
+   float r;
+   if (abs(x) > 1.0e-4) {
+      r = atan(y / x);
+      if (x < 0.0) {
+         r = r + sign(y) * 3.141593;
+      }
+   }
+   else {
+      r = sign(y) * 1.5707965;  // pi/2
+   }
+   return r;
+}
+
+vec2 atan(const vec2 u, const vec2 v)
+{
+   __retVal.x = atan(u.x, v.x);
+   __retVal.y = atan(u.y, v.y);
+}
+
+vec3 atan(const vec3 u, const vec3 v)
+{
+   __retVal.x = atan(u.x, v.x);
+   __retVal.y = atan(u.y, v.y);
+   __retVal.z = atan(u.z, v.z);
+}
+
+vec4 atan(const vec4 u, const vec4 v)
+{
+   __retVal.x = atan(u.x, v.x);
+   __retVal.y = atan(u.y, v.y);
+   __retVal.z = atan(u.z, v.z);
+   __retVal.w = atan(u.w, v.w);
+}
+
+
+//
+// 8.2 Exponential Functions
+//
+
+//// pow
+
+float pow(const float a, const float b)
+{
+   __asm float_power __retVal, a, b;
+}
+
+vec2 pow(const vec2 a, const vec2 b)
+{
+   __asm float_power __retVal.x, a.x, b.x;
+   __asm float_power __retVal.y, a.y, b.y;
+}
+
+vec3 pow(const vec3 a, const vec3 b)
+{
+   __asm float_power __retVal.x, a.x, b.x;
+   __asm float_power __retVal.y, a.y, b.y;
+   __asm float_power __retVal.z, a.z, b.z;
+}
+
+vec4 pow(const vec4 a, const vec4 b)
+{
+   __asm float_power __retVal.x, a.x, b.x;
+   __asm float_power __retVal.y, a.y, b.y;
+   __asm float_power __retVal.z, a.z, b.z;
+   __asm float_power __retVal.w, a.w, b.w;
+}
+
+
+//// exp
+
+float exp(const float a)
+{
+   // NOTE: log2(e) = 1.44269502
+   float t = a * 1.44269502;
+   __asm float_exp2 __retVal, t;
+}
+
+vec2 exp(const vec2 a)
+{
+   vec2 t = a * 1.44269502;
+   __asm float_exp2 __retVal.x, t.x;
+   __asm float_exp2 __retVal.y, t.y;
+}
+
+vec3 exp(const vec3 a)
+{
+   vec3 t = a * 1.44269502;
+   __asm float_exp2 __retVal.x, t.x;
+   __asm float_exp2 __retVal.y, t.y;
+   __asm float_exp2 __retVal.z, t.z;
+}
+
+vec4 exp(const vec4 a)
+{
+   vec4 t = a * 1.44269502;
+   __asm float_exp2 __retVal.x, t.x;
+   __asm float_exp2 __retVal.y, t.y;
+   __asm float_exp2 __retVal.z, t.z;
+   __asm float_exp2 __retVal.w, t.w;
+}
+
+
+
+//// log2
+
+float log2(const float x)
+{
+   __asm float_log2 __retVal, x;
+}
+
+vec2 log2(const vec2 v)
+{
+   __asm float_log2 __retVal.x, v.x;
+   __asm float_log2 __retVal.y, v.y;
+}
+
+vec3 log2(const vec3 v)
+{
+   __asm float_log2 __retVal.x, v.x;
+   __asm float_log2 __retVal.y, v.y;
+   __asm float_log2 __retVal.z, v.z;
+}
+
+vec4 log2(const vec4 v)
+{
+   __asm float_log2 __retVal.x, v.x;
+   __asm float_log2 __retVal.y, v.y;
+   __asm float_log2 __retVal.z, v.z;
+   __asm float_log2 __retVal.w, v.w;
+}
+
+
+//// log  (natural log)
+
+float log(const float x)
+{
+   // note:  logBaseB(x) = logBaseN(x) / logBaseN(B)
+   // compute log(x) = log2(x) / log2(e)
+   // c = 1.0 / log2(e) = 0.693147181
+   const float c = 0.693147181;
+   return log2(x) * c;
+}
+
+vec2 log(const vec2 v)
+{
+   const float c = 0.693147181;
+   return log2(v) * c;
+}
+
+vec3 log(const vec3 v)
+{
+   const float c = 0.693147181;
+   return log2(v) * c;
+}
+
+vec4 log(const vec4 v)
+{
+   const float c = 0.693147181;
+   return log2(v) * c;
+}
+
+
+//// exp2
+
+float exp2(const float a)
+{
+   __asm float_exp2 __retVal, a;
+}
+
+vec2 exp2(const vec2 a)
+{
+   __asm float_exp2 __retVal.x, a.x;
+   __asm float_exp2 __retVal.y, a.y;
+}
+
+vec3 exp2(const vec3 a)
+{
+   __asm float_exp2 __retVal.x, a.x;
+   __asm float_exp2 __retVal.y, a.y;
+   __asm float_exp2 __retVal.z, a.z;
+}
+
+vec4 exp2(const vec4 a)
+{
+   __asm float_exp2 __retVal.x, a.x;
+   __asm float_exp2 __retVal.y, a.y;
+   __asm float_exp2 __retVal.z, a.z;
+   __asm float_exp2 __retVal.w, a.w;
+}
+
+
+//// sqrt
+
+float sqrt(const float x)
+{
+   const float nx = -x;
+   float r;
+   __asm float_rsq r, x;
+   r = r * x;
+   __asm vec4_cmp __retVal, nx, r, 0.0;
+}
+
+vec2 sqrt(const vec2 x)
+{
+   const vec2 nx = -x, zero = vec2(0.0);
+   vec2 r;
+   __asm float_rsq r.x, x.x;
+   __asm float_rsq r.y, x.y;
+   r = r * x;
+   __asm vec4_cmp __retVal, nx, r, zero;
+}
+
+vec3 sqrt(const vec3 x)
+{
+   const vec3 nx = -x, zero = vec3(0.0);
+   vec3 r;
+   __asm float_rsq r.x, x.x;
+   __asm float_rsq r.y, x.y;
+   __asm float_rsq r.z, x.z;
+   r = r * x;
+   __asm vec4_cmp __retVal, nx, r, zero;
+}
+
+vec4 sqrt(const vec4 x)
+{
+   const vec4 nx = -x, zero = vec4(0.0);
+   vec4 r;
+   __asm float_rsq r.x, x.x;
+   __asm float_rsq r.y, x.y;
+   __asm float_rsq r.z, x.z;
+   __asm float_rsq r.w, x.w;
+   r = r * x;
+   __asm vec4_cmp __retVal, nx, r, zero;
+}
+
+
+//// inversesqrt
+
+float inversesqrt(const float x)
+{
+   __asm float_rsq __retVal.x, x;
+}
+
+vec2 inversesqrt(const vec2 v)
+{
+   __asm float_rsq __retVal.x, v.x;
+   __asm float_rsq __retVal.y, v.y;
+}
+
+vec3 inversesqrt(const vec3 v)
+{
+   __asm float_rsq __retVal.x, v.x;
+   __asm float_rsq __retVal.y, v.y;
+   __asm float_rsq __retVal.z, v.z;
+}
+
+vec4 inversesqrt(const vec4 v)
+{
+   __asm float_rsq __retVal.x, v.x;
+   __asm float_rsq __retVal.y, v.y;
+   __asm float_rsq __retVal.z, v.z;
+   __asm float_rsq __retVal.w, v.w;
+}
+
+
+//// normalize
+
+float normalize(const float x)
+{
+   __retVal = 1.0;
+}
+
+vec2 normalize(const vec2 v)
+{
+   const float s = inversesqrt(dot(v, v));
+   __asm vec4_multiply __retVal.xy, v, s;
+}
+
+vec3 normalize(const vec3 v)
+{
+//   const float s = inversesqrt(dot(v, v));
+//   __retVal = v * s;
+// XXX note, we _could_ use __retVal.w instead of tmp and save a
+// register, but that's actually a compilation error because v is a vec3
+// and the .w suffix is illegal.  Oh well.
+   float tmp;
+   __asm vec3_dot tmp, v, v;
+   __asm float_rsq tmp, tmp;
+   __asm vec4_multiply __retVal.xyz, v, tmp;
+}
+
+vec4 normalize(const vec4 v)
+{
+   float tmp;
+   __asm vec4_dot tmp, v, v;
+   __asm float_rsq tmp, tmp;
+   __asm vec4_multiply __retVal.xyz, v, tmp;
+}
+
+
+
+//
+// 8.3 Common Functions
+//
+
+
+//// abs
+
+float abs(const float a)
+{
+   __asm vec4_abs __retVal, a;
+}
+
+vec2 abs(const vec2 a)
+{
+   __asm vec4_abs __retVal.xy, a;
+}
+
+vec3 abs(const vec3 a)
+{
+   __asm vec4_abs __retVal.xyz, a;
+}
+
+vec4 abs(const vec4 a)
+{
+   __asm vec4_abs __retVal, a;
+}
+
+
+//// sign
+
+float sign(const float x)
+{
+   float p, n;
+   __asm vec4_sgt p, x, 0.0;            // p = (x > 0)
+   __asm vec4_sgt n, 0.0, x;            // n = (x < 0)
+   __asm vec4_subtract __retVal, p, n;  // sign = p - n
+}
+
+vec2 sign(const vec2 v)
+{
+   vec2 p, n;
+   __asm vec4_sgt p.xy, v, 0.0;
+   __asm vec4_sgt n.xy, 0.0, v;
+   __asm vec4_subtract __retVal.xy, p, n;
+}
+
+vec3 sign(const vec3 v)
+{
+   vec3 p, n;
+   __asm vec4_sgt p.xyz, v, 0.0;
+   __asm vec4_sgt n.xyz, 0.0, v;
+   __asm vec4_subtract __retVal.xyz, p, n;
+}
+
+vec4 sign(const vec4 v)
+{
+   vec4 p, n;
+   __asm vec4_sgt p, v, 0.0;
+   __asm vec4_sgt n, 0.0, v;
+   __asm vec4_subtract __retVal, p, n;
+}
+
+
+//// floor
+
+float floor(const float a)
+{
+   __asm vec4_floor __retVal, a;
+}
+
+vec2 floor(const vec2 a)
+{
+   __asm vec4_floor __retVal.xy, a;
+}
+
+vec3 floor(const vec3 a)
+{
+   __asm vec4_floor __retVal.xyz, a;
+}
+
+vec4 floor(const vec4 a)
+{
+   __asm vec4_floor __retVal, a;
+}
+
+
+//// ceil
+
+float ceil(const float a)
+{
+   // XXX this could be improved
+   float b = -a;
+   __asm vec4_floor b, b;
+   __retVal = -b;
+}
+
+vec2 ceil(const vec2 a)
+{
+   vec2 b = -a;
+   __asm vec4_floor b, b;
+   __retVal.xy = -b;
+}
+
+vec3 ceil(const vec3 a)
+{
+   vec3 b = -a;
+   __asm vec4_floor b, b;
+   __retVal.xyz = -b;
+}
+
+vec4 ceil(const vec4 a)
+{
+   vec4 b = -a;
+   __asm vec4_floor b, b;
+   __retVal = -b;
+}
+
+
+//// fract
+
+float fract(const float a)
+{
+   __asm vec4_frac __retVal, a;
+}
+
+vec2 fract(const vec2 a)
+{
+   __asm vec4_frac __retVal.xy, a;
+}
+
+vec3 fract(const vec3 a)
+{
+   __asm vec4_frac __retVal.xyz, a;
+}
+
+vec4 fract(const vec4 a)
+{
+   __asm vec4_frac __retVal, a;
+}
+
+
+//// mod  (very untested!)
+
+float mod(const float a, const float b)
+{
+    float oneOverB;
+    __asm float_rcp oneOverB, b;
+    __retVal = a - b * floor(a * oneOverB);
+}
+
+vec2 mod(const vec2 a, const float b)
+{
+    float oneOverB;
+    __asm float_rcp oneOverB, b;
+    __retVal.xy = a - b * floor(a * oneOverB);
+}
+
+vec3 mod(const vec3 a, const float b)
+{
+    float oneOverB;
+    __asm float_rcp oneOverB, b;
+    __retVal.xyz = a - b * floor(a * oneOverB);
+}
+
+vec4 mod(const vec4 a, const float b)
+{
+    float oneOverB;
+    __asm float_rcp oneOverB, b;
+    __retVal = a - b * floor(a * oneOverB);
+}
+
+vec2 mod(const vec2 a, const vec2 b)
+{
+    vec2 oneOverB;
+    __asm float_rcp oneOverB.x, b.x;
+    __asm float_rcp oneOverB.y, b.y;
+    __retVal = a - b * floor(a * oneOverB);
+}
+
+vec3 mod(const vec3 a, const vec3 b)
+{
+    vec3 oneOverB;
+    __asm float_rcp oneOverB.x, b.x;
+    __asm float_rcp oneOverB.y, b.y;
+    __asm float_rcp oneOverB.z, b.z;
+    __retVal = a - b * floor(a * oneOverB);
+}
+
+vec4 mod(const vec4 a, const vec4 b)
+{
+    vec4 oneOverB;
+    __asm float_rcp oneOverB.x, b.x;
+    __asm float_rcp oneOverB.y, b.y;
+    __asm float_rcp oneOverB.z, b.z;
+    __asm float_rcp oneOverB.w, b.w;
+    __retVal = a - b * floor(a * oneOverB);
+}
+
+
+//// min
+
+float min(const float a, const float b)
+{
+   __asm vec4_min __retVal, a, b;
+}
+
+vec2 min(const vec2 a, const vec2 b)
+{
+   __asm vec4_min __retVal.xy, a.xy, b.xy;
+}
+
+vec3 min(const vec3 a, const vec3 b)
+{
+   __asm vec4_min __retVal.xyz, a.xyz, b.xyz;
+}
+
+vec4 min(const vec4 a, const vec4 b)
+{
+   __asm vec4_min __retVal, a, b;
+}
+
+vec2 min(const vec2 a, const float b)
+{
+   __asm vec4_min __retVal, a.xy, b;
+}
+
+vec3 min(const vec3 a, const float b)
+{
+   __asm vec4_min __retVal, a.xyz, b;
+}
+
+vec4 min(const vec4 a, const float b)
+{
+   __asm vec4_min __retVal, a, b;
+}
+
+
+//// max
+
+float max(const float a, const float b)
+{
+   __asm vec4_max __retVal, a, b;
+}
+
+vec2 max(const vec2 a, const vec2 b)
+{
+   __asm vec4_max __retVal.xy, a.xy, b.xy;
+}
+
+vec3 max(const vec3 a, const vec3 b)
+{
+   __asm vec4_max __retVal.xyz, a.xyz, b.xyz;
+}
+
+vec4 max(const vec4 a, const vec4 b)
+{
+   __asm vec4_max __retVal, a, b;
+}
+
+vec2 max(const vec2 a, const float b)
+{
+   __asm vec4_max __retVal, a.xy, b;
+}
+
+vec3 max(const vec3 a, const float b)
+{
+   __asm vec4_max __retVal, a.xyz, b;
+}
+
+vec4 max(const vec4 a, const float b)
+{
+   __asm vec4_max __retVal, a, b;
+}
+
+
+//// clamp
+
+float clamp(const float val, const float minVal, const float maxVal)
+{
+   __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+vec2 clamp(const vec2 val, const float minVal, const float maxVal)
+{
+   __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+vec3 clamp(const vec3 val, const float minVal, const float maxVal)
+{
+   __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+vec4 clamp(const vec4 val, const float minVal, const float maxVal)
+{
+   __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+vec2 clamp(const vec2 val, const vec2 minVal, const vec2 maxVal)
+{
+   __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+vec3 clamp(const vec3 val, const vec3 minVal, const vec3 maxVal)
+{
+   __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+vec4 clamp(const vec4 val, const vec4 minVal, const vec4 maxVal)
+{
+   __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+
+//// mix
+
+float mix(const float x, const float y, const float a)
+{
+   __asm vec4_lrp __retVal, a, y, x;
+}
+
+vec2 mix(const vec2 x, const vec2 y, const float a)
+{
+   __asm vec4_lrp __retVal, a, y, x;
+}
+
+vec3 mix(const vec3 x, const vec3 y, const float a)
+{
+   __asm vec4_lrp __retVal, a, y, x;
+}
+
+vec4 mix(const vec4 x, const vec4 y, const float a)
+{
+   __asm vec4_lrp __retVal, a, y, x;
+}
+
+vec2 mix(const vec2 x, const vec2 y, const vec2 a)
+{
+   __asm vec4_lrp __retVal, a, y, x;
+}
+
+vec3 mix(const vec3 x, const vec3 y, const vec3 a)
+{
+   __asm vec4_lrp __retVal, a, y, x;
+}
+
+vec4 mix(const vec4 x, const vec4 y, const vec4 a)
+{
+   __asm vec4_lrp __retVal, a, y, x;
+}
+
+
+//// step
+
+float step(const float edge, const float x)
+{
+   __asm vec4_sge __retVal, x, edge;
+}
+
+vec2 step(const vec2 edge, const vec2 x)
+{
+   __asm vec4_sge __retVal.xy, x, edge;
+}
+
+vec3 step(const vec3 edge, const vec3 x)
+{
+   __asm vec4_sge __retVal.xyz, x, edge;
+}
+
+vec4 step(const vec4 edge, const vec4 x)
+{
+   __asm vec4_sge __retVal, x, edge;
+}
+
+vec2 step(const float edge, const vec2 v)
+{
+   __asm vec4_sge __retVal.xy, v, edge;
+}
+
+vec3 step(const float edge, const vec3 v)
+{
+   __asm vec4_sge __retVal.xyz, v, edge;
+}
+
+vec4 step(const float edge, const vec4 v)
+{
+   __asm vec4_sge __retVal, v, edge;
+}
+
+
+//// smoothstep
+
+float smoothstep(const float edge0, const float edge1, const float x)
+{
+    float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
+    return t * t * (3.0 - 2.0 * t);
+}
+
+vec2 smoothstep(const vec2 edge0, const vec2 edge1, const vec2 v)
+{
+   vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
+   return t * t * (3.0 - 2.0 * t);
+}
+
+vec3 smoothstep(const vec3 edge0, const vec3 edge1, const vec3 v)
+{
+   vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
+   return t * t * (3.0 - 2.0 * t);
+}
+
+vec4 smoothstep(const vec4 edge0, const vec4 edge1, const vec4 v)
+{
+   vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
+   return t * t * (3.0 - 2.0 * t);
+}
+
+vec2 smoothstep(const float edge0, const float edge1, const vec2 v)
+{
+   vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
+   return t * t * (3.0 - 2.0 * t);
+}
+
+vec3 smoothstep(const float edge0, const float edge1, const vec3 v)
+{
+   vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
+   return t * t * (3.0 - 2.0 * t);
+}
+
+vec4 smoothstep(const float edge0, const float edge1, const vec4 v)
+{
+   vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
+   return t * t * (3.0 - 2.0 * t);
+}
+
+
+
+//
+// 8.4 Geometric Functions
+//
+
+
+//// length
+
+float length(const float x)
+{
+   return abs(x);
+}
+
+float length(const vec2 v)
+{
+   float r;
+   const float p = dot(v, v);      // p = v.x * v.x + v.y * v.y
+   __asm float_rsq r, p;           // r = 1 / sqrt(p)
+   __retVal = p * r;               // p * r = sqrt(p);
+}
+
+float length(const vec3 v)
+{
+   float r;
+   const float p = dot(v, v);      // p = v.x * v.x + v.y * v.y + v.z * v.z
+   __asm float_rsq r, p;           // r = 1 / sqrt(p)
+   __retVal = p * r;               // p * r = sqrt(p);
+}
+
+float length(const vec4 v)
+{
+   float r;
+   const float p = dot(v, v);      // p = v.x * v.x + v.y * v.y + ...
+   __asm float_rsq r, p;           // r = 1 / sqrt(p)
+   __retVal = p * r;               // p * r = sqrt(p);
+}
+
+
+//// distance
+
+float distance(const float x, const float y)
+{
+   const float d = x - y;
+   __retVal = length(d);
+}
+
+float distance(const vec2 v, const vec2 u)
+{
+   const vec2 d2 = v - u;
+   __retVal = length(d2);
+}
+
+float distance(const vec3 v, const vec3 u)
+{
+   const vec3 d3 = v - u;
+   __retVal = length(d3);
+}
+
+float distance(const vec4 v, const vec4 u)
+{
+   const vec4 d4 = v - u;
+   __retVal = length(d4);
+}
+
+
+//// cross
+
+vec3 cross(const vec3 v, const vec3 u)
+{
+   __asm vec3_cross __retVal.xyz, v, u;
+}
+
+
+//// faceforward
+
+float faceforward(const float N, const float I, const float Nref)
+{
+    // this could probably be done better
+    const float d = dot(Nref, I);
+    float s;
+    __asm vec4_sgt s, 0.0, d;  // s = (0.0 > d) ? 1 : 0
+    return mix(-N, N, s);
+}
+
+vec2 faceforward(const vec2 N, const vec2 I, const vec2 Nref)
+{
+    // this could probably be done better
+    const float d = dot(Nref, I);
+    float s;
+    __asm vec4_sgt s, 0.0, d;  // s = (0.0 > d) ? 1 : 0
+    return mix(-N, N, s);
+}
+
+vec3 faceforward(const vec3 N, const vec3 I, const vec3 Nref)
+{
+    // this could probably be done better
+    const float d = dot(Nref, I);
+    float s;
+    __asm vec4_sgt s, 0.0, d;  // s = (0.0 > d) ? 1 : 0
+    return mix(-N, N, s);
+}
+
+vec4 faceforward(const vec4 N, const vec4 I, const vec4 Nref)
+{
+    // this could probably be done better
+    const float d = dot(Nref, I);
+    float s;
+    __asm vec4_sgt s, 0.0, d;  // s = (0.0 > d) ? 1 : 0
+    return mix(-N, N, s);
+}
+
+
+//// reflect
+
+float reflect(const float I, const float N)
+{
+   return I - 2.0 * dot(N, I) * N;
+}
+
+vec2 reflect(const vec2 I, const vec2 N)
+{
+   return I - 2.0 * dot(N, I) * N;
+}
+
+vec3 reflect(const vec3 I, const vec3 N)
+{
+   return I - 2.0 * dot(N, I) * N;
+}
+
+vec4 reflect(const vec4 I, const vec4 N)
+{
+   return I - 2.0 * dot(N, I) * N;
+}
+
+//// refract
+
+float refract(const float I, const float N, const float eta)
+{
+   float n_dot_i = dot(N, I);
+   float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
+   float retval;
+   if (k < 0.0)
+      retval = 0.0;
+   else
+      retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
+   return retval;
+}
+
+vec2 refract(const vec2 I, const vec2 N, const float eta)
+{
+   float n_dot_i = dot(N, I);
+   float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
+   vec2 retval;
+   if (k < 0.0)
+      retval = vec2(0.0);
+   else
+      retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
+   return retval;
+}
+
+vec3 refract(const vec3 I, const vec3 N, const float eta)
+{
+   float n_dot_i = dot(N, I);
+   float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
+   vec3 retval;
+   if (k < 0.0)
+      retval = vec3(0.0);
+   else
+      retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
+   return retval;
+}
+
+vec4 refract(const vec4 I, const vec4 N, const float eta)
+{
+   float n_dot_i = dot(N, I);
+   float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
+   vec4 retval;
+   if (k < 0.0)
+      retval = vec4(0.0);
+   else
+      retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
+   return retval;
+}
+
+
+
+
+//
+// 8.5 Matrix Functions
+//
+
+mat2 matrixCompMult (mat2 m, mat2 n) {
+    return mat2 (m[0] * n[0], m[1] * n[1]);
+}
+
+mat3 matrixCompMult (mat3 m, mat3 n) {
+    return mat3 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
+}
+
+mat4 matrixCompMult (mat4 m, mat4 n) {
+    return mat4 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
+}
+
+
+
+
+//
+// 8.6 Vector Relational Functions
+//
+
+//// lessThan
+
+bvec2 lessThan(const vec2 u, const vec2 v)
+{
+   __asm vec4_slt __retVal.xy, u, v;
+}
+
+bvec3 lessThan(const vec3 u, const vec3 v)
+{
+   __asm vec4_slt __retVal.xyz, u, v;
+}
+
+bvec4 lessThan(const vec4 u, const vec4 v)
+{
+   __asm vec4_slt __retVal, u, v;
+}
+
+bvec2 lessThan(const ivec2 u, const ivec2 v)
+{
+   __asm vec4_slt __retVal.xy, u, v;
+}
+
+bvec3 lessThan(const ivec3 u, const ivec3 v)
+{
+   __asm vec4_slt __retVal.xyz, u, v;
+}
+
+bvec4 lessThan(const ivec4 u, const ivec4 v)
+{
+   __asm vec4_slt __retVal, u, v;
+}
+
+
+//// lessThanEqual
+
+bvec2 lessThanEqual(const vec2 u, const vec2 v)
+{
+   __asm vec4_sle __retVal.xy, u, v;
+}
+
+bvec3 lessThanEqual(const vec3 u, const vec3 v)
+{
+   __asm vec4_sle __retVal.xyz, u, v;
+}
+
+bvec4 lessThanEqual(const vec4 u, const vec4 v)
+{
+   __asm vec4_sle __retVal, u, v;
+}
+
+bvec2 lessThanEqual(const ivec2 u, const ivec2 v)
+{
+   __asm vec4_sle __retVal.xy, u, v;
+}
+
+bvec3 lessThanEqual(const ivec3 u, const ivec3 v)
+{
+   __asm vec4_sle __retVal.xyz, u, v;
+}
+
+bvec4 lessThanEqual(const ivec4 u, const ivec4 v)
+{
+   __asm vec4_sle __retVal, u, v;
+}
+
+
+//// greaterThan
+
+bvec2 greaterThan(const vec2 u, const vec2 v)
+{
+   __asm vec4_sgt __retVal.xy, u, v;
+}
+
+bvec3 greaterThan(const vec3 u, const vec3 v)
+{
+   __asm vec4_sgt __retVal.xyz, u, v;
+}
+
+bvec4 greaterThan(const vec4 u, const vec4 v)
+{
+   __asm vec4_sgt __retVal, u, v;
+}
+
+bvec2 greaterThan(const ivec2 u, const ivec2 v)
+{
+   __asm vec4_sgt __retVal.xy, u.xy, v.xy;
+}
+
+bvec3 greaterThan(const ivec3 u, const ivec3 v)
+{
+   __asm vec4_sgt __retVal.xyz, u, v;
+}
+
+bvec4 greaterThan(const ivec4 u, const ivec4 v)
+{
+   __asm vec4_sgt __retVal, u, v;
+}
+
+
+//// greaterThanEqual
+
+bvec2 greaterThanEqual(const vec2 u, const vec2 v)
+{
+   __asm vec4_sge __retVal.xy, u, v;
+}
+
+bvec3 greaterThanEqual(const vec3 u, const vec3 v)
+{
+   __asm vec4_sge __retVal.xyz, u, v;
+}
+
+bvec4 greaterThanEqual(const vec4 u, const vec4 v)
+{
+   __asm vec4_sge __retVal, u, v;
+}
+
+bvec2 greaterThanEqual(const ivec2 u, const ivec2 v)
+{
+   __asm vec4_sge __retVal.xy, u, v;
+}
+
+bvec3 greaterThanEqual(const ivec3 u, const ivec3 v)
+{
+   __asm vec4_sge __retVal.xyz, u, v;
+}
+
+bvec4 greaterThanEqual(const ivec4 u, const ivec4 v)
+{
+   __asm vec4_sge __retVal, u, v;
+}
+
+
+//// equal
+
+bvec2 equal(const vec2 u, const vec2 v)
+{
+   __asm vec4_seq __retVal.xy, u, v;
+}
+
+bvec3 equal(const vec3 u, const vec3 v)
+{
+   __asm vec4_seq __retVal.xyz, u, v;
+}
+
+bvec4 equal(const vec4 u, const vec4 v)
+{
+   __asm vec4_seq __retVal, u, v;
+}
+
+bvec2 equal(const ivec2 u, const ivec2 v)
+{
+   __asm vec4_seq __retVal.xy, u, v;
+}
+
+bvec3 equal(const ivec3 u, const ivec3 v)
+{
+   __asm vec4_seq __retVal.xyz, u, v;
+}
+
+bvec4 equal(const ivec4 u, const ivec4 v)
+{
+   __asm vec4_seq __retVal, u, v;
+}
+
+bvec2 equal(const bvec2 u, const bvec2 v)
+{
+   __asm vec4_seq __retVal.xy, u, v;
+}
+
+bvec3 equal(const bvec3 u, const bvec3 v)
+{
+   __asm vec4_seq __retVal.xyz, u, v;
+}
+
+bvec4 equal(const bvec4 u, const bvec4 v)
+{
+   __asm vec4_seq __retVal, u, v;
+}
+
+
+
+
+//// notEqual
+
+bvec2 notEqual(const vec2 u, const vec2 v)
+{
+   __asm vec4_sne __retVal.xy, u, v;
+}
+
+bvec3 notEqual(const vec3 u, const vec3 v)
+{
+   __asm vec4_sne __retVal.xyz, u, v;
+}
+
+bvec4 notEqual(const vec4 u, const vec4 v)
+{
+   __asm vec4_sne __retVal, u, v;
+}
+
+bvec2 notEqual(const ivec2 u, const ivec2 v)
+{
+   __asm vec4_sne __retVal.xy, u, v;
+}
+
+bvec3 notEqual(const ivec3 u, const ivec3 v)
+{
+   __asm vec4_sne __retVal.xyz, u, v;
+}
+
+bvec4 notEqual(const ivec4 u, const ivec4 v)
+{
+   __asm vec4_sne __retVal, u, v;
+}
+
+bvec2 notEqual(const bvec2 u, const bvec2 v)
+{
+   __asm vec4_sne __retVal.xy, u, v;
+}
+
+bvec3 notEqual(const bvec3 u, const bvec3 v)
+{
+   __asm vec4_sne __retVal.xyz, u, v;
+}
+
+bvec4 notEqual(const bvec4 u, const bvec4 v)
+{
+   __asm vec4_sne __retVal, u, v;
+}
+
+
+
+//// any
+
+bool any(const bvec2 v)
+{
+   float sum;
+   __asm vec4_add sum.x, v.x, v.y;
+   __asm vec4_sne __retVal.x, sum.x, 0.0;
+}
+
+bool any(const bvec3 v)
+{
+   float sum;
+   __asm vec4_add sum.x, v.x, v.y;
+   __asm vec4_add sum.x, sum.x, v.z;
+   __asm vec4_sne __retVal.x, sum.x, 0.0;
+}
+
+bool any(const bvec4 v)
+{
+   float sum;
+   __asm vec4_add sum.x, v.x, v.y;
+   __asm vec4_add sum.x, sum.x, v.z;
+   __asm vec4_add sum.x, sum.x, v.w;
+   __asm vec4_sne __retVal.x, sum.x, 0.0;
+}
+
+
+//// all
+
+bool all (const bvec2 v)
+{
+   float prod;
+   __asm vec4_multiply prod, v.x, v.y;
+   __asm vec4_sne __retVal, prod, 0.0;
+}
+
+bool all (const bvec3 v)
+{
+   float prod;
+   __asm vec4_multiply prod, v.x, v.y;
+   __asm vec4_multiply prod, prod, v.z;
+   __asm vec4_sne __retVal, prod, 0.0;
+}
+
+bool all (const bvec4 v)
+{
+   float prod;
+   __asm vec4_multiply prod, v.x, v.y;
+   __asm vec4_multiply prod, prod, v.z;
+   __asm vec4_multiply prod, prod, v.w;
+   __asm vec4_sne __retVal, prod, 0.0;
+}
+
+
+
+//// not
+
+bvec2 not (const bvec2 v)
+{
+   __asm vec4_seq __retVal.xy, v, 0.0;
+}
+
+bvec3 not (const bvec3 v)
+{
+   __asm vec4_seq __retVal.xyz, v, 0.0;
+}
+
+bvec4 not (const bvec4 v)
+{
+   __asm vec4_seq __retVal, v, 0.0;
+}
+
+
+
+//// Texture Lookup Functions  (for both fragment and vertex shaders)
+
+vec4 texture1D(const sampler1D sampler, const float coord)
+{
+   __asm vec4_tex_1d __retVal, sampler, coord;
+}
+
+vec4 texture1DProj(const sampler1D sampler, const vec2 coord)
+{
+   // need to swizzle .y into .w
+   __asm vec4_tex_1d_proj __retVal, sampler, coord.xyyy;
+}
+
+vec4 texture1DProj(const sampler1D sampler, const vec4 coord)
+{
+   __asm vec4_tex_1d_proj __retVal, sampler, coord;
+}
+
+
+vec4 texture2D(const sampler2D sampler, const vec2 coord)
+{
+   __asm vec4_tex_2d __retVal, sampler, coord;
+}
+
+vec4 texture2DProj(const sampler2D sampler, const vec3 coord)
+{
+   // need to swizzle 'z' into 'w'.
+   __asm vec4_tex_2d_proj __retVal, sampler, coord.xyzz;
+}
+
+vec4 texture2DProj(const sampler2D sampler, const vec4 coord)
+{
+   __asm vec4_tex_2d_proj __retVal, sampler, coord;
+}
+
+
+vec4 texture3D(const sampler3D sampler, const vec3 coord)
+{
+   __asm vec4_tex_3d __retVal, sampler, coord;
+}
+
+vec4 texture3DProj(const sampler3D sampler, const vec4 coord)
+{
+   __asm vec4_tex_3d_proj __retVal, sampler, coord;
+}
+
+
+vec4 textureCube(const samplerCube sampler, const vec3 coord)
+{
+   __asm vec4_tex_cube __retVal, sampler, coord;
+}
+
+
+
+vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord)
+{
+   __asm vec4_tex_1d_shadow __retVal, sampler, coord;
+}
+
+vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord)
+{
+   // .s and .p will be divided by .q
+   __asm vec4_tex_1d_proj_shadow __retVal, sampler, coord;
+}
+
+vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord)
+{
+   __asm vec4_tex_2d_shadow __retVal, sampler, coord;
+}
+
+vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord)
+{
+   // .s, .t and .p will be divided by .q
+   __asm vec4_tex_2d_proj_shadow __retVal, sampler, coord;
+}
+
+
+//// GL_ARB_texture_rectangle:
+vec4 texture2DRect(const sampler2DRect sampler, const vec2 coord)
+{
+   __asm vec4_tex_rect __retVal, sampler, coord;
+}
+
+vec4 texture2DRectProj(const sampler2DRect sampler, const vec3 coord)
+{
+   // need to swizzle .y into .w
+   __asm vec4_tex_rect_proj __retVal, sampler, coord.xyzz;
+}
+
+vec4 texture2DRectProj(const sampler2DRect sampler, const vec4 coord)
+{
+   __asm vec4_tex_rect_proj __retVal, sampler, ccoord;
+}
+
+vec4 shadow2DRect(const sampler2DRectShadow sampler, const vec3 coord)
+{
+   __asm vec4_tex_rect_shadow __retVal, sampler, coord;
+}
+
+vec4 shadow2DRectProj(const sampler2DRectShadow sampler, const vec4 coord)
+{
+   __asm vec4_tex_rect_proj_shadow __retVal, sampler, coord;
+}
+
+
+
+//// GL_EXT_texture_array
+vec4 texture1DArray(const sampler1DArray sampler, const vec2 coord)
+{
+   __asm vec4_tex_1d_array __retVal, sampler, coord;
+}
+
+vec4 texture2DArray(const sampler2DArray sampler, const vec3 coord)
+{
+   __asm vec4_tex_2d_array __retVal, sampler, coord;
+}
+
+
+//
+// 8.9 Noise Functions
+//
+// AUTHOR: Stefan Gustavson (stegu@itn.liu.se), Nov 26, 2005
+//
+
+float noise1(const float x)
+{
+   __asm float_noise1 __retVal, x;
+}
+
+
+float noise1(const vec2 x)
+{
+    __asm float_noise2 __retVal, x;
+}
+
+float noise1(const vec3 x)
+{
+    __asm float_noise3 __retVal, x;
+}
+
+float noise1(const vec4 x)
+{
+    __asm float_noise4 __retVal, x;
+}
+
+vec2 noise2(const float x)
+{
+   __retVal.x = noise1(x);
+   __retVal.y = noise1(x + 19.34);
+}
+
+vec2 noise2(const vec2 x)
+{
+   __retVal.x = noise1(x);
+   __retVal.y = noise1(x + vec2(19.34, 7.66));
+}
+
+vec2 noise2(const vec3 x)
+{
+   __retVal.x = noise1(x);
+   __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
+}
+
+vec2 noise2(const vec4 x)
+{
+   __retVal.x = noise1(x);
+   __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
+}
+
+vec3 noise3(const float x)
+{
+   __retVal.x = noise1(x);
+   __retVal.y = noise1(x + 19.34);
+   __retVal.z = noise1(x + 5.47);
+}
+
+vec3 noise3(const vec2 x)
+{
+   __retVal.x = noise1(x);
+   __retVal.y = noise1(x + vec2(19.34, 7.66));
+   __retVal.z = noise1(x + vec2(5.47, 17.85));
+}
+
+vec3 noise3(const vec3 x)
+{
+   __retVal.x = noise1(x);
+   __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
+   __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04));
+}
+
+vec3 noise3(const vec4 x)
+{
+   __retVal.x = noise1(x);
+   __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
+   __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19));
+}
+
+vec4 noise4(const float x)
+{
+   __retVal.x = noise1(x);
+   __retVal.y = noise1(x + 19.34);
+   __retVal.z = noise1(x + 5.47);
+   __retVal.w = noise1(x + 23.54);
+}
+
+vec4 noise4(const vec2 x)
+{
+   __retVal.x = noise1(x);
+   __retVal.y = noise1(x + vec2 (19.34, 7.66));
+   __retVal.z = noise1(x + vec2 (5.47, 17.85));
+   __retVal.w = noise1(x + vec2 (23.54, 29.11));
+}
+
+vec4 noise4(const vec3 x)
+{
+   __retVal.x = noise1(x);
+   __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
+   __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04));
+   __retVal.w = noise1(x + vec3(23.54, 29.11, 31.91));
+}
+
+vec4 noise4(const vec4 x)
+{
+   __retVal.x = noise1(x);
+   __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
+   __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19));
+   __retVal.w = noise1(x + vec4(23.54, 29.11, 31.91, 37.48));
+}
diff --git a/src/mesa/slang/library/slang_core.gc b/src/mesa/slang/library/slang_core.gc
new file mode 100644 (file)
index 0000000..0a0d159
--- /dev/null
@@ -0,0 +1,2619 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+//
+// This file defines nearly all constructors and operators for built-in data
+// types, using extended language syntax. In general, compiler treats
+// constructors and operators as ordinary functions with some exceptions.
+// For example, the language does not allow functions to be called in
+// constant expressions - here the exception is made to allow it.
+//
+// Each implementation provides its own version of this file. Each
+// implementation can define the required set of operators and constructors
+// in its own fashion.
+//
+// The extended language syntax is only present when compiling this file.
+// It is implicitly included at the very beginning of the compiled shader,
+// so no built-in functions can be used.
+//
+// To communicate with the implementation, a special extended "__asm" keyword
+// is used, followed by an instruction name (any valid identifier), a
+// destination variable identifier and a list of zero or more source
+// variable identifiers.
+//
+// A variable identifier is a variable name declared earlier in the code
+// (as a function parameter, local or global variable).
+//
+// An instruction name designates an instruction that must be exported
+// by the implementation.  Each instruction receives data from source
+// variable identifiers and returns data in the destination variable
+// identifier.
+//
+// It is up to the implementation how to define a particular operator
+// or constructor. If it is expected to being used rarely, it can be
+// defined in terms of other operators and constructors,
+// for example:
+//
+// ivec2 __operator + (const ivec2 x, const ivec2 y) {
+//    return ivec2 (x[0] + y[0], x[1] + y[1]);
+// }
+//
+// If a particular operator or constructor is expected to be used very
+// often or is an atomic operation (that is, an operation that cannot be
+// expressed in terms of other operations or would create a dependency
+// cycle) it must be defined using one or more __asm constructs.
+//
+// Each implementation must define constructors for all scalar types
+// (bool, float, int).  There are 9 scalar-to-scalar constructors
+// (including identity constructors). However, since the language
+// introduces special constructors (like matrix constructor with a single
+// scalar value), implementations must also implement these cases.
+// The compiler provides the following algorithm when resolving a constructor:
+// - try to find a constructor with a prototype matching ours,
+// - if no constructor is found and this is a scalar-to-scalar constructor,
+//   raise an error,
+// - if a constructor is found, execute it and return,
+// - count the size of the constructor parameter list - if it is less than
+//   the size of our constructor's type, raise an error,
+// - for each parameter in the list do a recursive constructor matching for
+//   appropriate scalar fields in the constructed variable,
+//
+// Each implementation must also define a set of operators that deal with
+// built-in data types.
+// There are four kinds of operators:
+// 1) Operators that are implemented only by the compiler: "()" (function
+//    call), "," (sequence) and "?:" (selection).
+// 2) Operators that are implemented by the compiler by expressing it in
+//    terms of other operators:
+//    - "." (field selection) - translated to subscript access,
+//    - "&&" (logical and) - translated to "<left_expr> ? <right_expr> :
+//      false",
+//    - "||" (logical or) - translated to "<left_expr> ? true : <right_expr>",
+// 3) Operators that can be defined by the implementation and if the required
+//    prototype is not found, standard behaviour is used:
+//    - "==", "!=", "=" (equality, assignment) - compare or assign
+//      matching fields one-by-one;
+//      note that at least operators for scalar data types must be defined
+//      by the implementation to get it work,
+// 4) All other operators not mentioned above. If no required prototype is
+//    found, an error is raised. An implementation must follow the language
+//    specification to provide all valid operator prototypes.
+//
+
+
+
+//// Basic, scalar constructors/casts
+
+int __constructor(const float f)
+{
+   __asm vec4_to_ivec4 __retVal, f;
+}
+
+int __constructor(const bool b)
+{
+   __retVal = b;
+}
+
+int __constructor(const int i)
+{
+   __retVal = i;
+}
+
+bool __constructor(const int i)
+{
+   __asm vec4_sne __retVal, i, 0.0;
+}
+
+bool __constructor(const float f)
+{
+   __asm vec4_sne __retVal, f, 0.0;
+}
+
+bool __constructor(const bool b)
+{
+   __retVal = b;
+}
+
+float __constructor(const int i)
+{
+    __asm ivec4_to_vec4 __retVal, i;
+}
+
+float __constructor(const bool b)
+{
+    __asm ivec4_to_vec4 __retVal, b;
+}
+
+float __constructor(const float f)
+{
+   __retVal = f;
+}
+
+
+//// vec2 constructors
+
+vec2 __constructor(const float x, const float y)
+{
+   __retVal.x = x;
+   __retVal.y = y;
+}
+
+vec2 __constructor(const float f)
+{
+   __asm vec4_move __retVal.xy, f;
+}
+
+vec2 __constructor(const int i)
+{
+   __asm ivec4_to_vec4 __retVal.xy, i;
+}
+
+vec2 __constructor(const bool b)
+{
+   __asm ivec4_to_vec4 __retVal.xy, b;
+}
+
+vec2 __constructor(const bvec2 b)
+{
+//   __retVal = b;
+   __asm ivec4_to_vec4 __retVal.xy, b;
+}
+
+vec2 __constructor(const vec3 v)
+{
+   __asm vec4_move __retVal.xy, v.xy;
+}
+
+vec2 __constructor(const vec4 v)
+{
+   __asm vec4_move __retVal.xy, v.xy;
+}
+
+
+//// vec3 constructors
+
+vec3 __constructor(const float x, const float y, const float z)
+{
+   __retVal.x = x;
+   __retVal.y = y;
+   __retVal.z = z;
+}
+
+vec3 __constructor(const float f)
+{
+   // Note: this could be "__retVal.xyz = f" but that's an illegal assignment
+   __asm vec4_move __retVal.xyz, f;
+}
+
+vec3 __constructor(const int i)
+{
+   __asm ivec4_to_vec4 __retVal.xyz, i;
+}
+
+vec3 __constructor(const bool b)
+{
+   __asm ivec4_to_vec4 __retVal.xyz, b;
+}
+
+vec3 __constructor(const bvec3 b)
+{
+   __asm ivec4_to_vec4 __retVal.xyz, b;
+}
+
+vec3 __constructor(const vec4 v)
+{
+   __asm vec4_move __retVal.xyz, v;
+}
+
+
+//// vec4 constructors
+
+vec4 __constructor(const float x, const float y, const float z, const float w)
+{
+   __retVal.x = x;
+   __retVal.y = y;
+   __retVal.z = z;
+   __retVal.w = w;
+}
+
+vec4 __constructor(const float f)
+{
+   // Note: this could be "__retVal = f" but that's an illegal assignment
+   __asm vec4_move __retVal, f;
+}
+
+vec4 __constructor(const int i)
+{
+   __asm ivec4_to_vec4 __retVal, i;
+}
+
+vec4 __constructor(const bool b)
+{
+   __asm ivec4_to_vec4 __retVal, b;
+}
+
+vec4 __constructor(const bvec4 b)
+{
+   __asm ivec4_to_vec4 __retVal, b;
+}
+
+vec4 __constructor(const ivec4 i)
+{
+   __asm ivec4_to_vec4 __retVal, i;
+}
+
+vec4 __constructor(const vec3 v3, const float f)
+{
+   // XXX this constructor shouldn't be needed anymore
+   __retVal.xyz = v3;
+   __retVal.w = f;
+}
+
+vec4 __constructor(const vec2 v2, const float f1, const float f2)
+{
+   // XXX this constructor shouldn't be needed anymore
+   __retVal.xy = v2;
+   __retVal.z = f1;
+   __retVal.w = f2;
+}
+
+
+//// ivec2 constructors
+
+ivec2 __constructor(const int i, const int j)
+{
+   __retVal.x = i;
+   __retVal.y = j;
+}
+
+ivec2 __constructor(const int i)
+{
+   __asm vec4_move __retVal.xy, i;
+}
+
+ivec2 __constructor(const float f)
+{
+   __asm vec4_to_ivec4 __retVal.xy, f;
+}
+
+ivec2 __constructor(const bool b)
+{
+   __asm vec4_to_ivec4 __retVal.xy, b;
+}
+
+
+//// ivec3 constructors
+
+ivec3 __constructor(const int i, const int j, const int k)
+{
+   __retVal.x = i;
+   __retVal.y = j;
+   __retVal.z = k;
+}
+
+ivec3 __constructor(const int i)
+{
+   __asm vec4_move __retVal.xyz, i;
+}
+
+ivec3 __constructor(const float f)
+{
+   __asm vec4_to_ivec4 __retVal.xyz, f;
+}
+
+ivec3 __constructor(const bool b)
+{
+   __asm vec4_move __retVal.xyz, b;
+}
+
+
+//// ivec4 constructors
+
+ivec4 __constructor(const int x, const int y, const int z, const int w)
+{
+   __retVal.x = x;
+   __retVal.y = y;
+   __retVal.z = z;
+   __retVal.w = w;
+}
+
+ivec4 __constructor(const int i)
+{
+   __asm vec4_move __retVal, i;
+}
+
+ivec4 __constructor(const float f)
+{
+   __asm vec4_to_ivec4 __retVal, f;
+}
+
+ivec4 __constructor(const bool b)
+{
+   __asm vec4_to_ivec4 __retVal, b;
+}
+
+
+//// bvec2 constructors
+
+bvec2 __constructor(const bool b1, const bool b2)
+{
+   __retVal.x = b1;
+   __retVal.y = b2;
+}
+
+bvec2 __constructor(const int i1, const int i2)
+{
+   __asm vec4_sne __retVal.x, i1, 0.0;
+   __asm vec4_sne __retVal.y, i2, 0.0;
+}
+
+
+bvec2 __constructor(const bool b)
+{
+   __asm vec4_move __retVal.xy, b;
+}
+
+bvec2 __constructor(const float f)
+{
+   __asm vec4_sne __retVal.xy, f, 0.0;
+}
+
+bvec2 __constructor(const int i)
+{
+   __asm vec4_sne __retVal.xy, i, 0.0;
+}
+
+bvec2 __constructor(const vec2 v)
+{
+   __asm vec4_sne __retVal.xy, v, 0.0;
+}
+
+bvec2 __constructor(const ivec2 v)
+{
+   __asm vec4_sne __retVal.xy, v, 0.0;
+}
+
+
+
+//// bvec3 constructors
+
+bvec3 __constructor(const bool b1, const bool b2, const bool b3)
+{
+   __retVal.x = b1;
+   __retVal.y = b2;
+   __retVal.z = b3;
+}
+
+bvec3 __constructor(const float f1, const float f2, const float f3)
+{
+   __asm vec4_sne __retVal.x, f1, 0.0;
+   __asm vec4_sne __retVal.y, f2, 0.0;
+   __asm vec4_sne __retVal.z, f3, 0.0;
+}
+
+bvec3 __constructor(const bool b)
+{
+   __asm vec4_move __retVal.xyz, b;
+}
+
+bvec3 __constructor(const float f)
+{
+   __asm vec4_sne __retVal.xyz, f, 0.0;
+}
+
+bvec3 __constructor(const int i)
+{
+   __asm vec4_sne __retVal.xyz, i, 0.0;
+}
+
+bvec3 __constructor(const vec3 v)
+{
+   __asm vec4_sne __retVal.xyz, v, 0.0;
+}
+
+bvec3 __constructor(const ivec3 v)
+{
+   __asm vec4_sne __retVal.xyz, v, 0.0;
+}
+
+
+
+//// bvec4 constructors
+
+bvec4 __constructor(const bool b1, const bool b2, const bool b3, const bool b4)
+{
+   __retVal.x = b1;
+   __retVal.y = b2;
+   __retVal.z = b3;
+   __retVal.w = b4;
+}
+
+bvec4 __constructor(const float f1, const float f2, const float f3, const float f4)
+{
+   const float zero = 0.0;
+   __asm vec4_sne __retVal.x, f1, zero;   
+   __asm vec4_sne __retVal.y, f2, zero;   
+   __asm vec4_sne __retVal.z, f3, zero;   
+   __asm vec4_sne __retVal.w, f4, zero;   
+}
+
+bvec4 __constructor(const bool b)
+{
+   __asm vec4_move __retVal.xyzw, b;
+}
+
+bvec4 __constructor(const float f)
+{
+   __asm vec4_sne __retVal.xyzw, f, 0.0;
+}
+
+bvec4 __constructor(const int i)
+{
+   __asm vec4_sne __retVal.xyzw, i, 0.0;
+}
+
+bvec4 __constructor(const vec4 v)
+{
+   __asm vec4_sne __retVal.xyzw, v, 0.0;
+}
+
+bvec4 __constructor(const ivec4 v)
+{
+   __asm vec4_sne __retVal.xyzw, v, 0.0;
+}
+
+
+
+//// mat2 constructors
+
+mat2 __constructor(const float m00, const float m10,
+                   const float m01, const float m11)
+{
+   __retVal[0].x = m00;
+   __retVal[0].y = m10;
+   __retVal[1].x = m01;
+   __retVal[1].y = m11;
+}
+
+mat2 __constructor(const float f)
+{
+   __retVal[0].x = f;
+   __retVal[0].y = 0.0;
+   __retVal[1].x = 0.0;
+   __retVal[1].y = f;
+}
+
+mat2 __constructor(const int i)
+{
+   return mat2(float(i));
+}
+
+mat2 __constructor(const bool b)
+{
+   return mat2(float(b));
+}
+
+mat2 __constructor(const vec2 c0, const vec2 c1)
+{
+   __retVal[0] = c0;
+   __retVal[1] = c1;
+}
+
+
+//// mat3 constructors
+
+mat3 __constructor(const float m00, const float m10, const float m20,
+                   const float m01, const float m11, const float m21,
+                   const float m02, const float m12, const float m22)
+{
+   __retVal[0].x = m00;
+   __retVal[0].y = m10;
+   __retVal[0].z = m20;
+   __retVal[1].x = m01;
+   __retVal[1].y = m11;
+   __retVal[1].z = m21;
+   __retVal[2].x = m02;
+   __retVal[2].y = m12;
+   __retVal[2].z = m22;
+}
+
+mat3 __constructor(const float f)
+{
+   vec2 v = vec2(f, 0.0);
+   __retVal[0] = v.xyy;
+   __retVal[1] = v.yxy;
+   __retVal[2] = v.yyx;
+}
+
+mat3 __constructor(const int i)
+{
+   return mat3(float(i));
+}
+
+mat3 __constructor(const bool b)
+{
+   return mat3(float(b));
+}
+
+mat3 __constructor(const vec3 c0, const vec3 c1, const vec3 c2)
+{
+   __retVal[0] = c0;
+   __retVal[1] = c1;
+   __retVal[2] = c2;
+}
+
+
+//// mat4 constructors
+
+mat4 __constructor(const float m00, const float m10, const float m20, const float m30,
+                   const float m01, const float m11, const float m21, const float m31,
+                   const float m02, const float m12, const float m22, const float m32,
+                   const float m03, const float m13, const float m23, const float m33)
+{
+   __retVal[0].x = m00;
+   __retVal[0].y = m10;
+   __retVal[0].z = m20;
+   __retVal[0].w = m30;
+   __retVal[1].x = m01;
+   __retVal[1].y = m11;
+   __retVal[1].z = m21;
+   __retVal[1].w = m31;
+   __retVal[2].x = m02;
+   __retVal[2].y = m12;
+   __retVal[2].z = m22;
+   __retVal[2].w = m32;
+   __retVal[3].x = m03;
+   __retVal[3].y = m13;
+   __retVal[3].z = m23;
+   __retVal[3].w = m33;
+}
+
+
+mat4 __constructor(const float f)
+{
+   vec2 v = vec2(f, 0.0);
+   __retVal[0] = v.xyyy;
+   __retVal[1] = v.yxyy;
+   __retVal[2] = v.yyxy;
+   __retVal[3] = v.yyyx;
+}
+
+mat4 __constructor(const int i)
+{
+   return mat4(float(i));
+}
+
+mat4 __constructor(const bool b)
+{
+   return mat4(float(b));
+}
+
+mat4 __constructor(const vec4 c0, const vec4 c1, const vec4 c2, const vec4 c3)
+{
+   __retVal[0] = c0;
+   __retVal[1] = c1;
+   __retVal[2] = c2;
+   __retVal[3] = c3;
+}
+
+
+
+//// Basic int operators
+
+int __operator + (const int a, const int b)
+{
+   __asm vec4_add __retVal, a, b;
+}
+
+int __operator - (const int a, const int b)
+{
+   __asm vec4_subtract __retVal, a, b;
+}
+
+int __operator * (const int a, const int b)
+{
+   __asm vec4_multiply __retVal, a, b;
+}
+
+int __operator / (const int a, const int b)
+{
+   float bInv, x;
+   __asm float_rcp bInv, b;
+   __asm vec4_multiply x, a, bInv;
+   __asm vec4_to_ivec4 __retVal, x;
+}
+
+
+//// Basic ivec2 operators
+
+ivec2 __operator + (const ivec2 a, const ivec2 b)
+{
+   __asm vec4_add __retVal, a, b;
+}
+
+ivec2 __operator - (const ivec2 a, const ivec2 b)
+{
+   __asm vec4_subtract __retVal, a, b;
+}
+
+ivec2 __operator * (const ivec2 a, const ivec2 b)
+{
+   __asm vec4_multiply __retVal, a, b;
+}
+
+ivec2 __operator / (const ivec2 a, const ivec2 b)
+{
+   vec2 bInv, x;
+   __asm float_rcp bInv.x, b.x;
+   __asm float_rcp bInv.y, b.y;
+   __asm vec4_multiply x, a, bInv;
+   __asm vec4_to_ivec4 __retVal, x;
+}
+
+
+//// Basic ivec3 operators
+
+ivec3 __operator + (const ivec3 a, const ivec3 b)
+{
+   __asm vec4_add __retVal, a, b;
+}
+
+ivec3 __operator - (const ivec3 a, const ivec3 b)
+{
+   __asm vec4_subtract __retVal, a, b;
+}
+
+ivec3 __operator * (const ivec3 a, const ivec3 b)
+{
+   __asm vec4_multiply __retVal, a, b;
+}
+
+ivec3 __operator / (const ivec3 a, const ivec3 b)
+{
+   vec3 bInv, x;
+   __asm float_rcp bInv.x, b.x;
+   __asm float_rcp bInv.y, b.y;
+   __asm float_rcp bInv.z, b.z;
+   __asm vec4_multiply x, a, bInv;
+   __asm vec4_to_ivec4 __retVal, x;
+}
+
+
+//// Basic ivec4 operators
+
+ivec4 __operator + (const ivec4 a, const ivec4 b)
+{
+   __asm vec4_add __retVal, a, b;
+}
+
+ivec4 __operator - (const ivec4 a, const ivec4 b)
+{
+   __asm vec4_subtract __retVal, a, b;
+}
+
+ivec4 __operator * (const ivec4 a, const ivec4 b)
+{
+   __asm vec4_multiply __retVal, a, b;
+}
+
+ivec4 __operator / (const ivec4 a, const ivec4 b)
+{
+   vec4 bInv, x;
+   __asm float_rcp bInv.x, b.x;
+   __asm float_rcp bInv.y, b.y;
+   __asm float_rcp bInv.z, b.z;
+   __asm float_rcp bInv.w, b.w;
+   __asm vec4_multiply x, a, bInv;
+   __asm vec4_to_ivec4 __retVal, x;
+}
+
+
+//// Basic float operators
+
+float __operator + (const float a, const float b)
+{
+   __asm vec4_add __retVal, a, b;
+}
+
+float __operator - (const float a, const float b)
+{
+   __asm vec4_subtract __retVal, a, b;
+}
+
+float __operator * (const float a, const float b)
+{
+    __asm vec4_multiply __retVal, a, b;
+}
+
+float __operator / (const float a, const float b)
+{
+   float bInv;
+   __asm float_rcp bInv.x, b;
+   __asm vec4_multiply __retVal, a, bInv;
+}
+
+
+//// Basic vec2 operators
+
+vec2 __operator + (const vec2 v, const vec2 u)
+{
+   __asm vec4_add __retVal.xy, v, u;
+}
+
+vec2 __operator - (const vec2 v, const vec2 u)
+{
+    __asm vec4_subtract __retVal.xy, v, u;
+}
+
+vec2 __operator * (const vec2 v, const vec2 u)
+{
+    __asm vec4_multiply __retVal.xy, v, u;
+}
+
+vec2 __operator / (const vec2 v, const vec2 u)
+{
+   vec2 w; // = 1 / u
+   __asm float_rcp w.x, u.x;
+   __asm float_rcp w.y, u.y;
+   __asm vec4_multiply __retVal.xy, v, w;
+}
+
+
+//// Basic vec3 operators
+
+vec3 __operator + (const vec3 v, const vec3 u)
+{
+   __asm vec4_add __retVal.xyz, v, u;
+}
+
+vec3 __operator - (const vec3 v, const vec3 u)
+{
+    __asm vec4_subtract __retVal.xyz, v, u;
+}
+
+vec3 __operator * (const vec3 v, const vec3 u)
+{
+    __asm vec4_multiply __retVal.xyz, v, u;
+}
+
+vec3 __operator / (const vec3 v, const vec3 u)
+{
+   vec3 w; // = 1 / u
+   __asm float_rcp w.x, u.x;
+   __asm float_rcp w.y, u.y;
+   __asm float_rcp w.z, u.z;
+   __asm vec4_multiply __retVal.xyz, v, w;
+}
+
+
+//// Basic vec4 operators
+
+vec4 __operator + (const vec4 v, const vec4 u)
+{
+   __asm vec4_add __retVal, v, u;
+}
+
+vec4 __operator - (const vec4 v, const vec4 u)
+{
+    __asm vec4_subtract __retVal, v, u;
+}
+
+vec4 __operator * (const vec4 v, const vec4 u)
+{
+    __asm vec4_multiply __retVal, v, u;
+}
+
+vec4 __operator / (const vec4 v, const vec4 u)
+{
+   vec4 w; // = 1 / u
+   __asm float_rcp w.x, u.x;
+   __asm float_rcp w.y, u.y;
+   __asm float_rcp w.z, u.z;
+   __asm float_rcp w.w, u.w;
+   __asm vec4_multiply __retVal, v, w;
+}
+
+
+
+
+//// Basic vec2/float operators
+
+vec2 __operator + (const float a, const vec2 u)
+{
+   __asm vec4_add __retVal.xy, a, u.xy;
+}
+
+vec2 __operator + (const vec2 v, const float b)
+{
+   __asm vec4_add __retVal.xy, v.xy, b;
+}
+
+vec2 __operator - (const float a, const vec2 u)
+{
+   __asm vec4_subtract __retVal.xy, a, u.xy;
+}
+
+vec2 __operator - (const vec2 v, const float b)
+{
+   __asm vec4_subtract __retVal.xy, v.xy, b;
+}
+
+vec2 __operator * (const float a, const vec2 u)
+{
+   __asm vec4_multiply __retVal.xy, a, u.xy;
+}
+
+vec2 __operator * (const vec2 v, const float b)
+{
+   __asm vec4_multiply __retVal.xy, v.xy, b;
+}
+
+vec2 __operator / (const float a, const vec2 u)
+{
+   vec2 invU;
+   __asm float_rcp invU.x, u.x;
+   __asm float_rcp invU.y, u.y;
+   __asm vec4_multiply __retVal.xy, a, invU.xy;
+}
+
+vec2 __operator / (const vec2 v, const float b)
+{
+   float invB;
+   __asm float_rcp invB, b;
+   __asm vec4_multiply __retVal.xy, v.xy, invB;
+}
+
+
+//// Basic vec3/float operators
+
+vec3 __operator + (const float a, const vec3 u)
+{
+   __asm vec4_add __retVal.xyz, a, u.xyz;
+}
+
+vec3 __operator + (const vec3 v, const float b)
+{
+   __asm vec4_add __retVal.xyz, v.xyz, b;
+}
+
+vec3 __operator - (const float a, const vec3 u)
+{
+   __asm vec4_subtract __retVal.xyz, a, u.xyz;
+}
+
+vec3 __operator - (const vec3 v, const float b)
+{
+   __asm vec4_subtract __retVal.xyz, v.xyz, b;
+}
+
+vec3 __operator * (const float a, const vec3 u)
+{
+   __asm vec4_multiply __retVal.xyz, a, u.xyz;
+}
+
+vec3 __operator * (const vec3 v, const float b)
+{
+   __asm vec4_multiply __retVal.xyz, v.xyz, b;
+}
+
+vec3 __operator / (const float a, const vec3 u)
+{
+   vec3 invU;
+   __asm float_rcp invU.x, u.x;
+   __asm float_rcp invU.y, u.y;
+   __asm float_rcp invU.z, u.z;
+   __asm vec4_multiply __retVal.xyz, a, invU.xyz;
+}
+
+vec3 __operator / (const vec3 v, const float b)
+{
+   float invB;
+   __asm float_rcp invB, b;
+   __asm vec4_multiply __retVal.xyz, v.xyz, invB;
+}
+
+
+//// Basic vec4/float operators
+
+vec4 __operator + (const float a, const vec4 u)
+{
+   __asm vec4_add __retVal, a, u;
+}
+
+vec4 __operator + (const vec4 v, const float b)
+{
+   __asm vec4_add __retVal, v, b;
+}
+
+vec4 __operator - (const float a, const vec4 u)
+{
+   __asm vec4_subtract __retVal, a, u;
+}
+
+vec4 __operator - (const vec4 v, const float b)
+{
+   __asm vec4_subtract __retVal, v, b;
+}
+
+vec4 __operator * (const float a, const vec4 u)
+{
+   __asm vec4_multiply __retVal, a, u;
+}
+
+vec4 __operator * (const vec4 v, const float b)
+{
+   __asm vec4_multiply __retVal, v, b;
+}
+
+vec4 __operator / (const float a, const vec4 u)
+{
+   vec4 invU;
+   __asm float_rcp invU.x, u.x;
+   __asm float_rcp invU.y, u.y;
+   __asm float_rcp invU.z, u.z;
+   __asm float_rcp invU.w, u.w;
+   __asm vec4_multiply __retVal, a, invU;
+}
+
+vec4 __operator / (const vec4 v, const float b)
+{
+   float invB;
+   __asm float_rcp invB, b;
+   __asm vec4_multiply __retVal, v, invB;
+}
+
+
+
+//// Basic ivec2/int operators
+
+ivec2 __operator + (const int a, const ivec2 u)
+{
+   __retVal = ivec2(a) + u;
+}
+
+ivec2 __operator + (const ivec2 v, const int b)
+{
+   __retVal = v + ivec2(b);
+}
+
+ivec2 __operator - (const int a, const ivec2 u)
+{
+   __retVal = ivec2(a) - u;
+}
+
+ivec2 __operator - (const ivec2 v, const int b)
+{
+   __retVal = v - ivec2(b);
+}
+
+ivec2 __operator * (const int a, const ivec2 u)
+{
+   __retVal = ivec2(a) * u;
+}
+
+ivec2 __operator * (const ivec2 v, const int b)
+{
+   __retVal = v * ivec2(b);
+}
+
+ivec2 __operator / (const int a, const ivec2 u)
+{
+   __retVal = ivec2(a) / u;
+}
+
+ivec2 __operator / (const ivec2 v, const int b)
+{
+   __retVal = v / ivec2(b);
+}
+
+
+//// Basic ivec3/int operators
+
+ivec3 __operator + (const int a, const ivec3 u)
+{
+   __retVal = ivec3(a) + u;
+}
+
+ivec3 __operator + (const ivec3 v, const int b)
+{
+   __retVal = v + ivec3(b);
+}
+
+ivec3 __operator - (const int a, const ivec3 u)
+{
+   __retVal = ivec3(a) - u;
+}
+
+ivec3 __operator - (const ivec3 v, const int b)
+{
+   __retVal = v - ivec3(b);
+}
+
+ivec3 __operator * (const int a, const ivec3 u)
+{
+   __retVal = ivec3(a) * u;
+}
+
+ivec3 __operator * (const ivec3 v, const int b)
+{
+   __retVal = v * ivec3(b);
+}
+
+ivec3 __operator / (const int a, const ivec3 u)
+{
+   __retVal = ivec3(a) / u;
+}
+
+ivec3 __operator / (const ivec3 v, const int b)
+{
+   __retVal = v / ivec3(b);
+}
+
+
+//// Basic ivec4/int operators
+
+ivec4 __operator + (const int a, const ivec4 u)
+{
+   __retVal = ivec4(a) + u;
+}
+
+ivec4 __operator + (const ivec4 v, const int b)
+{
+   __retVal = v + ivec4(b);
+}
+
+ivec4 __operator - (const int a, const ivec4 u)
+{
+   __retVal = ivec4(a) - u;
+}
+
+ivec4 __operator - (const ivec4 v, const int b)
+{
+   __retVal = v - ivec4(b);
+}
+
+ivec4 __operator * (const int a, const ivec4 u)
+{
+   __retVal = ivec4(a) * u;
+}
+
+ivec4 __operator * (const ivec4 v, const int b)
+{
+   __retVal = v * ivec4(b);
+}
+
+ivec4 __operator / (const int a, const ivec4 u)
+{
+   __retVal = ivec4(a) / u;
+}
+
+ivec4 __operator / (const ivec4 v, const int b)
+{
+   __retVal = v / ivec4(b);
+}
+
+
+
+
+//// Unary negation operator
+
+int __operator - (const int a)
+{
+   __asm vec4_negate __retVal.x, a;
+}
+
+ivec2 __operator - (const ivec2 v)
+{
+   __asm vec4_negate __retVal, v;
+}
+
+ivec3 __operator - (const ivec3 v)
+{
+   __asm vec4_negate __retVal, v;
+}
+
+ivec4 __operator - (const ivec4 v)
+{
+   __asm vec4_negate __retVal, v;
+}
+
+float __operator - (const float a)
+{
+   __asm vec4_negate __retVal.x, a;
+}
+
+vec2 __operator - (const vec2 v)
+{
+   __asm vec4_negate __retVal.xy, v.xy;
+}
+
+vec3 __operator - (const vec3 v)
+{
+   __asm vec4_negate __retVal.xyz, v.xyz;
+}
+
+vec4 __operator - (const vec4 v)
+{
+   __asm vec4_negate __retVal, v;
+}
+
+mat2 __operator - (const mat2 m)
+{
+   __retVal[0] = -m[0];
+   __retVal[1] = -m[1];
+}
+
+mat3 __operator - (const mat3 m)
+{
+   __retVal[0] = -m[0];
+   __retVal[1] = -m[1];
+   __retVal[2] = -m[2];
+}
+
+mat4 __operator - (const mat4 m)
+{
+   __retVal[0] = -m[0];
+   __retVal[1] = -m[1];
+   __retVal[2] = -m[2];
+   __retVal[3] = -m[3];
+}
+
+
+
+//// dot product
+
+float dot(const float a, const float b)
+{
+   __retVal = a * b;
+}
+
+float dot(const vec2 a, const vec2 b)
+{
+   __retVal = a.x * b.x + a.y * b.y;
+}
+
+float dot(const vec3 a, const vec3 b)
+{
+    __asm vec3_dot __retVal, a, b;
+}
+
+float dot(const vec4 a, const vec4 b)
+{
+    __asm vec4_dot __retVal, a, b;
+}
+
+
+
+//// int assignment operators
+
+int __operator += (inout int a, const int b)
+{
+   a = a + b;
+   return a;
+}
+
+int __operator -= (inout int a, const int b)
+{
+   a = a - b;
+   return a;
+}
+
+int __operator *= (inout int a, const int b)
+{
+   a = a * b;
+   return a;
+}
+
+int __operator /= (inout int a, const int b)
+{
+   a = a / b;
+   return a;
+}
+
+
+//// ivec2 assignment operators
+
+ivec2 __operator += (inout ivec2 v, const ivec2 u)
+{
+   v = v + u;
+   return v;
+}
+
+ivec2 __operator -= (inout ivec2 v, const ivec2 u)
+{
+   v = v - u;
+   return v;
+}
+
+ivec2 __operator *= (inout ivec2 v, const ivec2 u)
+{
+   v = v * u;
+   return v;
+}
+
+ivec2 __operator /= (inout ivec2 v, const ivec2 u)
+{
+   v = v / u;
+   return v;
+}
+
+
+//// ivec3 assignment operators
+
+ivec3 __operator += (inout ivec3 v, const ivec3 u)
+{
+   v = v + u;
+   return v;
+}
+
+ivec3 __operator -= (inout ivec3 v, const ivec3 u)
+{
+   v = v - u;
+   return v;
+}
+
+ivec3 __operator *= (inout ivec3 v, const ivec3 u)
+{
+   v = v * u;
+   return v;
+}
+
+ivec3 __operator /= (inout ivec3 v, const ivec3 u)
+{
+   v = v / u;
+   return v;
+}
+
+
+//// ivec4 assignment operators
+
+ivec4 __operator += (inout ivec4 v, const ivec4 u)
+{
+   v = v + u;
+   return v;
+}
+
+ivec4 __operator -= (inout ivec4 v, const ivec4 u)
+{
+   v = v - u;
+   return v;
+}
+
+ivec4 __operator *= (inout ivec4 v, const ivec4 u)
+{
+   v = v * u;
+   return v;
+}
+
+ivec4 __operator /= (inout ivec4 v, const ivec4 u)
+{
+   v = v / u;
+   return v;
+}
+
+
+//// float assignment operators
+
+float __operator += (inout float a, const float b)
+{
+   a = a + b;
+   return a;
+}
+
+float __operator -= (inout float a, const float b)
+{
+   a = a - b;
+   return a;
+}
+
+float __operator *= (inout float a, const float b)
+{
+   a = a * b;
+   return a;
+}
+
+float __operator /= (inout float a, const float b)
+{
+   a = a / b;
+   return a;
+}
+
+
+//// vec2 assignment operators
+
+vec2 __operator += (inout vec2 v, const vec2 u)
+{
+   v = v + u;
+   return v;
+}
+
+vec2 __operator -= (inout vec2 v, const vec2 u)
+{
+   v = v - u;
+   return v;
+}
+
+vec2 __operator *= (inout vec2 v, const vec2 u)
+{
+   v = v * u;
+   return v;
+}
+
+vec2 __operator /= (inout vec2 v, const vec2 u)
+{
+   v = v / u;
+   return v;
+}
+
+
+//// vec3 assignment operators
+
+vec3 __operator += (inout vec3 v, const vec3 u)
+{
+   v = v + u;
+   return v;
+}
+
+vec3 __operator -= (inout vec3 v, const vec3 u)
+{
+   v = v - u;
+   return v;
+}
+
+vec3 __operator *= (inout vec3 v, const vec3 u)
+{
+   v = v * u;
+   return v;
+}
+
+vec3 __operator /= (inout vec3 v, const vec3 u)
+{
+   v = v / u;
+   return v;
+}
+
+
+//// vec4 assignment operators
+
+vec4 __operator += (inout vec4 v, const vec4 u)
+{
+   v = v + u;
+   return v;
+}
+
+vec4 __operator -= (inout vec4 v, const vec4 u)
+{
+   v = v - u;
+   return v;
+}
+
+vec4 __operator *= (inout vec4 v, const vec4 u)
+{
+   v = v * u;
+   return v;
+}
+
+vec4 __operator /= (inout vec4 v, const vec4 u)
+{
+   v = v / u;
+   return v;
+}
+
+
+
+//// ivec2/int assignment operators
+
+ivec2 __operator += (inout ivec2 v, const int a)
+{
+   v = v + ivec2(a);
+   return v;
+}
+
+ivec2 __operator -= (inout ivec2 v, const int a)
+{
+   v = v - ivec2(a);
+   return v;
+}
+
+ivec2 __operator *= (inout ivec2 v, const int a)
+{
+   v = v * ivec2(a);
+   return v;
+}
+
+ivec2 __operator /= (inout ivec2 v, const int a)
+{
+   v = v / ivec2(a);
+   return v;
+}
+
+
+//// ivec3/int assignment operators
+
+ivec3 __operator += (inout ivec3 v, const int a)
+{
+   v = v + ivec3(a);
+   return v;
+}
+
+ivec3 __operator -= (inout ivec3 v, const int a)
+{
+   v = v - ivec3(a);
+   return v;
+}
+
+ivec3 __operator *= (inout ivec3 v, const int a)
+{
+   v = v * ivec3(a);
+   return v;
+}
+
+ivec4 __operator /= (inout ivec3 v, const int a)
+{
+   v = v / ivec3(a);
+   return v;
+}
+
+
+//// ivec4/int assignment operators
+
+ivec4 __operator += (inout ivec4 v, const int a)
+{
+   v = v + ivec4(a);
+   return v;
+}
+
+ivec4 __operator -= (inout ivec4 v, const int a)
+{
+   v = v - ivec4(a);
+   return v;
+}
+
+ivec4 __operator *= (inout ivec4 v, const int a)
+{
+   v = v * ivec4(a);
+   return v;
+}
+
+ivec4 __operator /= (inout ivec4 v, const int a)
+{
+   v = v / ivec4(a);
+   return v;
+}
+
+
+
+//// vec2/float assignment operators
+
+vec2 __operator += (inout vec2 v, const float a)
+{
+   v = v + vec2(a);
+   return v;
+}
+
+vec2 __operator -= (inout vec2 v, const float a)
+{
+   v = v - vec2(a);
+   return v;
+}
+
+vec2 __operator *= (inout vec2 v, const float a)
+{
+   v = v * vec2(a);
+   return v;
+}
+
+vec2 __operator /= (inout vec2 v, const float a)
+{
+   v = v / vec2(a);
+   return v;
+}
+
+
+//// vec3/float assignment operators
+
+vec3 __operator += (inout vec3 v, const float a)
+{
+   v = v + vec3(a);
+   return v;
+}
+
+vec3 __operator -= (inout vec3 v, const float a)
+{
+   v = v - vec3(a);
+   return v;
+}
+
+vec3 __operator *= (inout vec3 v, const float a)
+{
+   v = v * vec3(a);
+   return v;
+}
+
+vec3 __operator /= (inout vec3 v, const float a)
+{
+   v = v / vec3(a);
+   return v;
+}
+
+
+//// vec4/float assignment operators
+
+vec4 __operator += (inout vec4 v, const float a)
+{
+   v = v + vec4(a);
+   return v;
+}
+
+vec4 __operator -= (inout vec4 v, const float a)
+{
+   v = v - vec4(a);
+   return v;
+}
+
+vec4 __operator *= (inout vec4 v, const float a)
+{
+   v = v * vec4(a);
+   return v;
+}
+
+vec4 __operator /= (inout vec4 v, const float a)
+{
+   v = v / vec4(a);
+   return v;
+}
+
+
+
+
+
+//// Basic mat2 operations
+
+mat2 __operator + (const mat2 m, const mat2 n)
+{
+   __retVal[0] = m[0] + n[0];
+   __retVal[1] = m[1] + n[1];
+}
+
+mat2 __operator - (const mat2 m, const mat2 n)
+{
+   __retVal[0] = m[0] - n[0];
+   __retVal[1] = m[1] - n[1];
+}
+
+mat2 __operator * (const mat2 m, const mat2 n)
+{
+   __retVal[0] = m[0] * n[0].xx + m[1] * n[0].yy;
+   __retVal[1] = m[0] * n[1].xx + m[1] * n[1].yy;
+}
+
+mat2 __operator / (const mat2 m, const mat2 n)
+{
+   __retVal[0] = m[0] / n[0];
+   __retVal[1] = m[1] / n[1];
+}
+
+
+//// Basic mat3 operations
+
+mat3 __operator + (const mat3 m, const mat3 n)
+{
+   __retVal[0] = m[0] + n[0];
+   __retVal[1] = m[1] + n[1];
+   __retVal[2] = m[2] + n[2];
+}
+
+mat3 __operator - (const mat3 m, const mat3 n)
+{
+   __retVal[0] = m[0] - n[0];
+   __retVal[1] = m[1] - n[1];
+   __retVal[2] = m[2] - n[2];
+}
+
+mat3 __operator * (const mat3 m, const mat3 n)
+{
+   __retVal[0] = m[0] * n[0].xxx + m[1] * n[0].yyy + m[2] * n[0].zzz;
+   __retVal[1] = m[0] * n[1].xxx + m[1] * n[1].yyy + m[2] * n[1].zzz;
+   __retVal[2] = m[0] * n[2].xxx + m[1] * n[2].yyy + m[2] * n[2].zzz;
+}
+
+mat3 __operator / (const mat3 m, const mat3 n)
+{
+    __retVal[0] = m[0] / n[0];
+    __retVal[1] = m[1] / n[1];
+    __retVal[2] = m[2] / n[2];
+}
+
+
+//// Basic mat4 operations
+
+mat4 __operator + (const mat4 m, const mat4 n)
+{
+   __retVal[0] = m[0] + n[0];
+   __retVal[1] = m[1] + n[1];
+   __retVal[2] = m[2] + n[2];
+   __retVal[3] = m[3] + n[3];
+}
+
+mat4 __operator - (const mat4 m, const mat4 n)
+{
+   __retVal[0] = m[0] - n[0];
+   __retVal[1] = m[1] - n[1];
+   __retVal[2] = m[2] - n[2];
+   __retVal[3] = m[3] - n[3];
+}
+
+mat4 __operator * (const mat4 m, const mat4 n)
+{
+   __retVal[0] = m[0] * n[0].xxxx + m[1] * n[0].yyyy + m[2] * n[0].zzzz + m[3] * n[0].wwww;
+   __retVal[1] = m[0] * n[1].xxxx + m[1] * n[1].yyyy + m[2] * n[1].zzzz + m[3] * n[1].wwww;
+   __retVal[2] = m[0] * n[2].xxxx + m[1] * n[2].yyyy + m[2] * n[2].zzzz + m[3] * n[2].wwww;
+   __retVal[3] = m[0] * n[3].xxxx + m[1] * n[3].yyyy + m[2] * n[3].zzzz + m[3] * n[3].wwww;
+}
+
+mat4 __operator / (const mat4 m, const mat4 n)
+{
+    __retVal[0] = m[0] / n[0];
+    __retVal[1] = m[1] / n[1];
+    __retVal[2] = m[2] / n[2];
+    __retVal[3] = m[3] / n[3];
+}
+
+
+//// mat2/float operations
+
+mat2 __operator + (const float a, const mat2 n)
+{
+   __retVal[0] = a + n[0];
+   __retVal[1] = a + n[1];
+}
+
+mat2 __operator + (const mat2 m, const float b)
+{
+   __retVal[0] = m[0] + b;
+   __retVal[1] = m[1] + b;
+}
+
+mat2 __operator - (const float a, const mat2 n)
+{
+   __retVal[0] = a - n[0];
+   __retVal[1] = a - n[1];
+}
+
+mat2 __operator - (const mat2 m, const float b)
+{
+   __retVal[0] = m[0] - b;
+   __retVal[1] = m[1] - b;
+}
+
+mat2 __operator * (const float a, const mat2 n)
+{
+   __retVal[0] = a * n[0];
+   __retVal[1] = a * n[1];
+}
+
+mat2 __operator * (const mat2 m, const float b)
+{
+   __retVal[0] = m[0] * b;
+   __retVal[1] = m[1] * b;
+}
+
+mat2 __operator / (const float a, const mat2 n)
+{
+   __retVal[0] = a / n[0];
+   __retVal[1] = a / n[1];
+}
+
+mat2 __operator / (const mat2 m, const float b)
+{
+   __retVal[0] = m[0] / b;
+   __retVal[1] = m[1] / b;
+}
+
+
+//// mat3/float operations
+
+mat3 __operator + (const float a, const mat3 n)
+{
+   __retVal[0] = a + n[0];
+   __retVal[1] = a + n[1];
+   __retVal[2] = a + n[2];
+}
+
+mat3 __operator + (const mat3 m, const float b)
+{
+   __retVal[0] = m[0] + b;
+   __retVal[1] = m[1] + b;
+   __retVal[2] = m[2] + b;
+}
+
+mat3 __operator - (const float a, const mat3 n)
+{
+   __retVal[0] = a - n[0];
+   __retVal[1] = a - n[1];
+   __retVal[2] = a - n[2];
+}
+
+mat3 __operator - (const mat3 m, const float b)
+{
+   __retVal[0] = m[0] - b;
+   __retVal[1] = m[1] - b;
+   __retVal[2] = m[2] - b;
+}
+
+mat3 __operator * (const float a, const mat3 n)
+{
+   __retVal[0] = a * n[0];
+   __retVal[1] = a * n[1];
+   __retVal[2] = a * n[2];
+}
+
+mat3 __operator * (const mat3 m, const float b)
+{
+   __retVal[0] = m[0] * b;
+   __retVal[1] = m[1] * b;
+   __retVal[2] = m[2] * b;
+}
+
+mat3 __operator / (const float a, const mat3 n)
+{
+   __retVal[0] = a / n[0];
+   __retVal[1] = a / n[1];
+   __retVal[2] = a / n[2];
+}
+
+mat3 __operator / (const mat3 m, const float b)
+{
+   __retVal[0] = m[0] / b;
+   __retVal[1] = m[1] / b;
+   __retVal[2] = m[2] / b;
+}
+
+
+//// mat4/float operations
+
+mat4 __operator + (const float a, const mat4 n)
+{
+   __retVal[0] = a + n[0];
+   __retVal[1] = a + n[1];
+   __retVal[2] = a + n[2];
+   __retVal[3] = a + n[3];
+}
+
+mat4 __operator + (const mat4 m, const float b)
+{
+   __retVal[0] = m[0] + b;
+   __retVal[1] = m[1] + b;
+   __retVal[2] = m[2] + b;
+   __retVal[3] = m[3] + b;
+}
+
+mat4 __operator - (const float a, const mat4 n)
+{
+   __retVal[0] = a - n[0];
+   __retVal[1] = a - n[1];
+   __retVal[2] = a - n[2];
+   __retVal[3] = a - n[3];
+}
+
+mat4 __operator - (const mat4 m, const float b)
+{
+   __retVal[0] = m[0] - b;
+   __retVal[1] = m[1] - b;
+   __retVal[2] = m[2] - b;
+   __retVal[3] = m[3] - b;
+}
+
+mat4 __operator * (const float a, const mat4 n)
+{
+   __retVal[0] = a * n[0];
+   __retVal[1] = a * n[1];
+   __retVal[2] = a * n[2];
+   __retVal[3] = a * n[3];
+}
+
+mat4 __operator * (const mat4 m, const float b)
+{
+   __retVal[0] = m[0] * b;
+   __retVal[1] = m[1] * b;
+   __retVal[2] = m[2] * b;
+   __retVal[3] = m[3] * b;
+}
+
+mat4 __operator / (const float a, const mat4 n)
+{
+   __retVal[0] = a / n[0];
+   __retVal[1] = a / n[1];
+   __retVal[2] = a / n[2];
+   __retVal[3] = a / n[3];
+}
+
+mat4 __operator / (const mat4 m, const float b)
+{
+   __retVal[0] = m[0] / b;
+   __retVal[1] = m[1] / b;
+   __retVal[2] = m[2] / b;
+   __retVal[3] = m[3] / b;
+}
+
+
+
+//// matrix / vector products
+
+vec2 __operator * (const mat2 m, const vec2 v)
+{
+   __retVal = m[0] * v.xx
+            + m[1] * v.yy;
+}
+
+vec2 __operator * (const vec2 v, const mat2 m)
+{
+   __retVal.x = dot(v, m[0]);
+   __retVal.y = dot(v, m[1]);
+}
+
+vec3 __operator * (const mat3 m, const vec3 v)
+{
+   __retVal = m[0] * v.xxx
+            + m[1] * v.yyy
+            + m[2] * v.zzz;
+}
+
+vec3 __operator * (const vec3 v, const mat3 m)
+{
+   __retVal.x = dot(v, m[0]);
+   __retVal.y = dot(v, m[1]);
+   __retVal.z = dot(v, m[2]);
+}
+
+vec4 __operator * (const mat4 m, const vec4 v)
+{
+   __retVal = m[0] * v.xxxx
+            + m[1] * v.yyyy
+            + m[2] * v.zzzz
+            + m[3] * v.wwww;
+}
+
+vec4 __operator * (const vec4 v, const mat4 m)
+{
+   __retVal.x = dot(v, m[0]);
+   __retVal.y = dot(v, m[1]);
+   __retVal.z = dot(v, m[2]);
+   __retVal.w = dot(v, m[3]);
+}
+
+
+
+//// mat2 assignment operators
+
+mat2 __operator += (inout mat2 m, const mat2 n)
+{
+   m[0] = m[0] + n[0];
+   m[1] = m[1] + n[1];
+   return m;
+}
+
+mat2 __operator -= (inout mat2 m, const mat2 n)
+{
+   m[0] = m[0] - n[0];
+   m[1] = m[1] - n[1];
+   return m;
+}
+
+mat2 __operator *= (inout mat2 m, const mat2 n)
+{
+   m = m * n;
+   return m;
+}
+
+mat2 __operator /= (inout mat2 m, const mat2 n)
+{
+   m[0] = m[0] / n[0];
+   m[1] = m[1] / n[1];
+   return m;
+}
+
+
+//// mat3 assignment operators
+
+mat3 __operator += (inout mat3 m, const mat3 n)
+{
+   m[0] = m[0] + n[0];
+   m[1] = m[1] + n[1];
+   m[2] = m[2] + n[2];
+   return m;
+}
+
+mat3 __operator -= (inout mat3 m, const mat3 n)
+{
+   m[0] = m[0] - n[0];
+   m[1] = m[1] - n[1];
+   m[2] = m[2] - n[2];
+   return m;
+}
+
+mat3 __operator *= (inout mat3 m, const mat3 n)
+{
+   m = m * n;
+   return m;
+}
+
+mat3 __operator /= (inout mat3 m, const mat3 n)
+{
+   m[0] = m[0] / n[0];
+   m[1] = m[1] / n[1];
+   m[2] = m[2] / n[2];
+   return m;
+}
+
+
+// mat4 assignment operators
+
+mat4 __operator += (inout mat4 m, const mat4 n)
+{
+   m[0] = m[0] + n[0];
+   m[1] = m[1] + n[1];
+   m[2] = m[2] + n[2];
+   m[3] = m[3] + n[3];
+   return m;
+}
+
+mat4 __operator -= (inout mat4 m, const mat4 n)
+{
+   m[0] = m[0] - n[0];
+   m[1] = m[1] - n[1];
+   m[2] = m[2] - n[2];
+   m[3] = m[3] - n[3];
+   return m;
+}
+
+mat4 __operator *= (inout mat4 m, const mat4 n)
+{
+   m = m * n;
+   return m;
+}
+
+mat4 __operator /= (inout mat4 m, const mat4 n)
+{
+   m[0] = m[0] / n[0];
+   m[1] = m[1] / n[1];
+   m[2] = m[2] / n[2];
+   m[3] = m[3] / n[3];
+   return m;
+}
+
+
+//// mat2/float assignment operators
+
+mat2 __operator += (inout mat2 m, const float a)
+{
+   vec2 v = vec2(a);
+   m[0] = m[0] + v;
+   m[1] = m[1] + v;
+   return m;
+}
+
+mat2 __operator -= (inout mat2 m, const float a)
+{
+   vec2 v = vec2(a);
+   m[0] = m[0] - v;
+   m[1] = m[1] - v;
+   return m;
+}
+
+mat2 __operator *= (inout mat2 m, const float a)
+{
+   vec2 v = vec2(a);
+   m[0] = m[0] * v;
+   m[1] = m[1] * v;
+   return m;
+}
+
+mat2 __operator /= (inout mat2 m, const float a)
+{
+   vec2 v = vec2(1.0 / a);
+   m[0] = m[0] * v;
+   m[1] = m[1] * v;
+   return m;
+}
+
+
+//// mat3/float assignment operators
+
+mat3 __operator += (inout mat3 m, const float a)
+{
+   vec3 v = vec3(a);
+   m[0] = m[0] + v;
+   m[1] = m[1] + v;
+   m[2] = m[2] + v;
+   return m;
+}
+
+mat3 __operator -= (inout mat3 m, const float a)
+{
+   vec3 v = vec3(a);
+   m[0] = m[0] - v;
+   m[1] = m[1] - v;
+   m[2] = m[2] - v;
+   return m;
+}
+
+mat3 __operator *= (inout mat3 m, const float a)
+{
+   vec3 v = vec3(a);
+   m[0] = m[0] * v;
+   m[1] = m[1] * v;
+   m[2] = m[2] * v;
+   return m;
+}
+
+mat3 __operator /= (inout mat3 m, const float a)
+{
+   vec3 v = vec3(1.0 / a);
+   m[0] = m[0] * v;
+   m[1] = m[1] * v;
+   m[2] = m[2] * v;
+   return m;
+}
+
+
+//// mat4/float assignment operators
+
+mat4 __operator += (inout mat4 m, const float a)
+{
+   vec4 v = vec4(a);
+   m[0] = m[0] + v;
+   m[1] = m[1] + v;
+   m[2] = m[2] + v;
+   m[3] = m[3] + v;
+   return m;
+}
+
+mat4 __operator -= (inout mat4 m, const float a)
+{
+   vec4 v = vec4(a);
+   m[0] = m[0] - v;
+   m[1] = m[1] - v;
+   m[2] = m[2] - v;
+   m[3] = m[3] - v;
+   return m;
+}
+
+mat4 __operator *= (inout mat4 m, const float a)
+{
+   vec4 v = vec4(a);
+   m[0] = m[0] * v;
+   m[1] = m[1] * v;
+   m[2] = m[2] * v;
+   m[3] = m[3] * v;
+   return m;
+}
+
+mat4 __operator /= (inout mat4 m, const float a)
+{
+   vec4 v = vec4(1.0 / a);
+   m[0] = m[0] * v;
+   m[1] = m[1] * v;
+   m[2] = m[2] * v;
+   m[3] = m[3] * v;
+   return m;
+}
+
+
+
+//// vec/mat assignment operators
+
+vec2 __operator *= (inout vec2 v, const mat2 m)
+{
+   v = v * m;
+   return v;
+}
+
+vec3 __operator *= (inout vec3 v, const mat3 m)
+{
+   v = v * m;
+   return v;
+}
+
+vec4 __operator *= (inout vec4 v, const mat4 m)
+{
+   v = v * m;
+   return v;
+}
+
+
+
+//// pre-decrement operators
+
+int __operator --(inout int a)
+{
+    a = a - 1;
+   __retVal = a;
+}
+
+ivec2 __operator --(inout ivec2 v)
+{
+   v = v - ivec2(1);
+   __retVal = v;
+}
+
+ivec3 __operator --(inout ivec3 v)
+{
+   v = v - ivec3(1);
+   __retVal = v;
+}
+
+ivec4 __operator --(inout ivec4 v)
+{
+   v = v - ivec4(1);
+   __retVal = v;
+}
+
+
+float __operator --(inout float a)
+{
+   a = a - 1.0;
+   __retVal = a;
+}
+
+vec2 __operator --(inout vec2 v)
+{
+   v = v - vec2(1.0);
+   __retVal = v;
+}
+
+vec3 __operator --(inout vec3 v)
+{
+   v = v - vec3(1.0);
+   __retVal = v;
+}
+
+vec4 __operator --(inout vec4 v)
+{
+   v = v - vec4(1.0);
+   __retVal = v;
+}
+
+
+mat2 __operator --(inout mat2 m)
+{
+   m[0] = m[0] - vec2(1.0);
+   m[1] = m[1] - vec2(1.0);
+   __retVal = m;
+}
+
+mat3 __operator --(inout mat3 m)
+{
+   m[0] = m[0] - vec3(1.0);
+   m[1] = m[1] - vec3(1.0);
+   m[2] = m[2] - vec3(1.0);
+   __retVal = m;
+}
+
+mat4 __operator --(inout mat4 m)
+{
+   m[0] = m[0] - vec4(1.0);
+   m[1] = m[1] - vec4(1.0);
+   m[2] = m[2] - vec4(1.0);
+   m[3] = m[3] - vec4(1.0);
+   __retVal = m;
+}
+
+
+//// pre-increment operators
+
+int __operator ++(inout int a)
+{
+    a = a + 1;
+    __retVal = a;
+}
+
+ivec2 __operator ++(inout ivec2 v)
+{
+   v = v + ivec2(1);
+   __retVal = v;
+}
+
+ivec3 __operator ++(inout ivec3 v)
+{
+   v = v + ivec3(1);
+   __retVal = v;
+}
+
+ivec4 __operator ++(inout ivec4 v)
+{
+   v = v + ivec4(1);
+   __retVal = v;
+}
+
+
+float __operator ++(inout float a)
+{
+    a = a + 1.0;
+    __retVal = a;
+}
+
+vec2 __operator ++(inout vec2 v)
+{
+   v = v + vec2(1.0);
+   __retVal = v;
+}
+
+vec3 __operator ++(inout vec3 v)
+{
+   v = v + vec3(1.0);
+   __retVal = v;
+}
+
+vec4 __operator ++(inout vec4 v)
+{
+   v = v + vec4(1.0);
+   __retVal = v;
+}
+
+
+mat2 __operator ++(inout mat2 m)
+{
+   m[0] = m[0] + vec2(1.0);
+   m[1] = m[1] + vec2(1.0);
+   __retVal = m;
+}
+
+mat3 __operator ++(inout mat3 m)
+{
+   m[0] = m[0] + vec3(1.0);
+   m[1] = m[1] + vec3(1.0);
+   m[2] = m[2] + vec3(1.0);
+   __retVal = m;
+}
+
+mat4 __operator ++(inout mat4 m)
+{
+   m[0] = m[0] + vec4(1.0);
+   m[1] = m[1] + vec4(1.0);
+   m[2] = m[2] + vec4(1.0);
+   m[3] = m[3] + vec4(1.0);
+   __retVal = m;
+}
+
+
+
+//// post-decrement
+
+int __postDecr(inout int a)
+{
+   __retVal = a;
+   a = a - 1;
+}
+
+ivec2 __postDecr(inout ivec2 v)
+{
+   __retVal = v;
+   v = v - ivec2(1);
+}
+
+ivec3 __postDecr(inout ivec3 v)
+{
+   __retVal = v;
+   v = v - ivec3(1);
+}
+
+ivec4 __postDecr(inout ivec4 v)
+{
+   __retVal = v;
+   v = v - ivec4(1);
+}
+
+
+float __postDecr(inout float a)
+{
+   __retVal = a;
+   a = a - 1.0;
+}
+
+vec2 __postDecr(inout vec2 v)
+{
+   __retVal = v;
+   v = v - vec2(1.0);
+}
+
+vec3 __postDecr(inout vec3 v)
+{
+   __retVal = v;
+   v = v - vec3(1.0);
+}
+
+vec4 __postDecr(inout vec4 v)
+{
+   __retVal = v;
+   v = v - vec4(1.0);
+}
+
+
+mat2 __postDecr(inout mat2 m)
+{
+   __retVal = m;
+   m[0] = m[0] - vec2(1.0);
+   m[1] = m[1] - vec2(1.0);
+}
+
+mat3 __postDecr(inout mat3 m)
+{
+   __retVal = m;
+   m[0] = m[0] - vec3(1.0);
+   m[1] = m[1] - vec3(1.0);
+   m[2] = m[2] - vec3(1.0);
+}
+
+mat4 __postDecr(inout mat4 m)
+{
+   __retVal = m;
+   m[0] = m[0] - vec4(1.0);
+   m[1] = m[1] - vec4(1.0);
+   m[2] = m[2] - vec4(1.0);
+   m[3] = m[3] - vec4(1.0);
+}
+
+
+//// post-increment
+
+float __postIncr(inout float a)
+{
+   __retVal = a;
+   a = a + 1;
+}
+
+vec2 __postIncr(inout vec2 v)
+{
+   __retVal = v;
+   v = v + vec2(1.0);
+}
+
+vec3 __postIncr(inout vec3 v)
+{
+   __retVal = v;
+   v = v + vec3(1.0);
+}
+
+vec4 __postIncr(inout vec4 v)
+{
+   __retVal = v;
+   v = v + vec4(1.0);
+}
+
+
+int __postIncr(inout int a)
+{
+   __retVal = a;
+   a = a + 1;
+}
+
+ivec2 __postIncr(inout ivec2 v)
+{
+   __retVal = v;
+   v = v + ivec2(1);
+}
+
+ivec3 __postIncr(inout ivec3 v)
+{
+   __retVal = v;
+   v = v + ivec3(1);
+}
+
+ivec4 __postIncr(inout ivec4 v)
+{
+   __retVal = v;
+   v = v + ivec3(1);
+}
+
+
+mat2 __postIncr(inout mat2 m)
+{
+   mat2 n = m;
+   m[0] = m[0] + vec2(1.0);
+   m[1] = m[1] + vec2(1.0);
+   return n;
+}
+
+mat3 __postIncr(inout mat3 m)
+{
+   mat3 n = m;
+   m[0] = m[0] + vec3(1.0);
+   m[1] = m[1] + vec3(1.0);
+   m[2] = m[2] + vec3(1.0);
+   return n;
+}
+
+mat4 __postIncr(inout mat4 m)
+{
+   mat4 n = m;
+   m[0] = m[0] + vec4(1.0);
+   m[1] = m[1] + vec4(1.0);
+   m[2] = m[2] + vec4(1.0);
+   m[3] = m[3] + vec4(1.0);
+   return n;
+}
+
+
+
+//// inequality operators
+
+
+// XXX are the inequality operators for floats/ints really needed????
+bool __operator < (const float a, const float b)
+{
+   __asm vec4_sgt __retVal.x, b, a;
+}
+
+
+bool __operator < (const int a, const int b) {
+    return float (a) < float (b);
+}
+
+bool __operator > (const float a, const float b) {
+    bool c;
+    __asm float_less c, b, a;
+    return c;
+}
+
+bool __operator > (const int a, const int b) {
+    return float (a) > float (b);
+}
+
+bool __operator >= (const float a, const float b) {
+    bool g, e;
+    __asm float_less  g, b, a;
+    __asm float_equal e, a, b;
+    return g || e;
+}
+
+bool __operator >= (const int a, const int b) {
+    return float (a) >= float (b);
+}
+
+bool __operator <= (const float a, const float b) {
+    bool g, e;
+    __asm float_less  g, a, b;
+    __asm float_equal e, a, b;
+    return g || e;
+}
+
+bool __operator <= (const int a, const int b) {
+    return float (a) <= float (b);
+}
+
+
+
+//
+// MESA-specific extension functions.
+//
+
+void printMESA (const float f) {
+    __asm float_print f;
+}
+
+void printMESA (const int i) {
+    __asm int_print i;
+}
+
+void printMESA (const bool b) {
+    __asm bool_print b;
+}
+
+void printMESA (const vec2 v) {
+    printMESA (v.x);
+    printMESA (v.y);
+}
+
+void printMESA (const vec3 v) {
+    printMESA (v.x);
+    printMESA (v.y);
+    printMESA (v.z);
+}
+
+void printMESA (const vec4 v) {
+    printMESA (v.x);
+    printMESA (v.y);
+    printMESA (v.z);
+    printMESA (v.w);
+}
+
+void printMESA (const ivec2 v) {
+    printMESA (v.x);
+    printMESA (v.y);
+}
+
+void printMESA (const ivec3 v) {
+    printMESA (v.x);
+    printMESA (v.y);
+    printMESA (v.z);
+}
+
+void printMESA (const ivec4 v) {
+    printMESA (v.x);
+    printMESA (v.y);
+    printMESA (v.z);
+    printMESA (v.w);
+}
+
+void printMESA (const bvec2 v) {
+    printMESA (v.x);
+    printMESA (v.y);
+}
+
+void printMESA (const bvec3 v) {
+    printMESA (v.x);
+    printMESA (v.y);
+    printMESA (v.z);
+}
+
+void printMESA (const bvec4 v) {
+    printMESA (v.x);
+    printMESA (v.y);
+    printMESA (v.z);
+    printMESA (v.w);
+}
+
+void printMESA (const mat2 m) {
+    printMESA (m[0]);
+    printMESA (m[1]);
+}
+
+void printMESA (const mat3 m) {
+    printMESA (m[0]);
+    printMESA (m[1]);
+    printMESA (m[2]);
+}
+
+void printMESA (const mat4 m) {
+    printMESA (m[0]);
+    printMESA (m[1]);
+    printMESA (m[2]);
+    printMESA (m[3]);
+}
+
+void printMESA (const sampler1D e) {
+    __asm int_print e;
+}
+
+void printMESA (const sampler2D e) {
+    __asm int_print e;
+}
+
+void printMESA (const sampler3D e) {
+    __asm int_print e;
+}
+
+void printMESA (const samplerCube e) {
+    __asm int_print e;
+}
+
+void printMESA (const sampler1DShadow e) {
+    __asm int_print e;
+}
+
+void printMESA (const sampler2DShadow e) {
+    __asm int_print e;
+}
+
diff --git a/src/mesa/slang/library/slang_fragment_builtin.gc b/src/mesa/slang/library/slang_fragment_builtin.gc
new file mode 100644 (file)
index 0000000..54a80ea
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+//
+// From Shader Spec, ver. 1.10, rev. 59
+//
+
+__fixed_input vec4 gl_FragCoord;
+__fixed_input bool gl_FrontFacing;
+__fixed_output vec4 gl_FragColor;
+__fixed_output vec4 gl_FragData[gl_MaxDrawBuffers];
+__fixed_output float gl_FragDepth;
+
+varying vec4 gl_Color;
+varying vec4 gl_SecondaryColor;
+varying vec4 gl_TexCoord[gl_MaxTextureCoords];
+varying float gl_FogFragCoord;
+
+
+
+//// 8.7 Texture Lookup Functions (with bias)
+
+vec4 texture1D(const sampler1D sampler, const float coord, const float bias)
+{
+   vec4 coord4;
+   coord4.x = coord;
+   coord4.w = bias;
+   __asm vec4_tex_1d_bias __retVal, sampler, coord4;
+}
+
+vec4 texture1DProj(const sampler1D sampler, const vec2 coord, const float bias)
+{
+   // do projection here (there's no vec4_texbp1d instruction)
+   vec4 pcoord;
+   pcoord.x = coord.x / coord.y;
+   pcoord.w = bias;
+   __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
+}
+
+vec4 texture1DProj(const sampler1D sampler, const vec4 coord, const float bias)
+{
+   // do projection here (there's no vec4_texbp1d instruction)
+   vec4 pcoord;
+   pcoord.x = coord.x / coord.z;
+   pcoord.w = bias;
+   __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
+}
+
+
+
+
+vec4 texture2D(const sampler2D sampler, const vec2 coord, const float bias)
+{
+   vec4 coord4;
+   coord4.xy = coord.xy;
+   coord4.w = bias;
+   __asm vec4_tex_2d_bias __retVal, sampler, coord4;
+}
+
+vec4 texture2DProj(const sampler2D sampler, const vec3 coord, const float bias)
+{
+   // do projection here (there's no vec4_texbp2d instruction)
+   vec4 pcoord;
+   pcoord.xy = coord.xy / coord.z;
+   pcoord.w = bias;
+   __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
+}
+
+vec4 texture2DProj(const sampler2D sampler, const vec4 coord, const float bias)
+{
+   // do projection here (there's no vec4_texbp2d instruction)
+   vec4 pcoord;
+   pcoord.xy = coord.xy / coord.w;
+   pcoord.w = bias;
+   __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
+}
+
+
+
+
+vec4 texture3D(const sampler3D sampler, const vec3 coord, const float bias)
+{
+   vec4 coord4;
+   coord4.xyz = coord.xyz;
+   coord4.w = bias;
+   __asm vec4_tex_3d_bias __retVal, sampler, coord4;
+}
+
+vec4 texture3DProj(const sampler3D sampler, const vec4 coord, const float bias)
+{
+   // do projection here (there's no vec4_texbp3d instruction)
+   vec4 pcoord;
+   pcoord.xyz = coord.xyz / coord.w;
+   pcoord.w = bias;
+   __asm vec4_tex_3d_bias __retVal, sampler, pcoord;
+}
+
+
+
+
+vec4 textureCube(const samplerCube sampler, const vec3 coord, const float bias)
+{
+   vec4 coord4;
+   coord4.xyz = coord;
+   coord4.w = bias;
+   __asm vec4_tex_cube __retVal, sampler, coord4;
+}
+
+
+
+vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord, const float bias)
+{
+   vec4 coord4;
+   coord4.xyz = coord;
+   coord4.w = bias;
+   __asm vec4_tex_1d_bias_shadow __retVal, sampler, coord4;
+}
+
+vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord, const float bias)
+{
+   vec4 pcoord;
+   pcoord.x = coord.x / coord.w;
+   pcoord.z = coord.z;
+   pcoord.w = bias;
+   __asm vec4_tex_1d_bias_shadow __retVal, sampler, pcoord;
+}
+
+vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord, const float bias)
+{
+   vec4 coord4;
+   coord4.xyz = coord;
+   coord4.w = bias;
+   __asm vec4_tex_2d_bias_shadow __retVal, sampler, coord4;
+}
+
+vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord, const float bias)
+{
+   vec4 pcoord;
+   pcoord.xy = coord.xy / coord.w;
+   pcoord.z = coord.z;
+   pcoord.w = bias;
+   __asm vec4_tex_2d_bias_shadow __retVal, sampler, pcoord;
+}
+
+
+
+//// GL_EXT_texture_array
+
+vec4 texture1DArray(const sampler1DArray sampler, const vec2 coord)
+{
+   vec4 coord4;
+   coord4.xy = coord;
+   __asm vec4_tex_1d_array __retVal, sampler, coord4;
+}
+
+vec4 texture1DArray(const sampler1DArray sampler, const vec2 coord, const float bias)
+{
+   vec4 coord4;
+   coord4.xy = coord;
+   coord4.w = bias;
+   __asm vec4_tex_1d_array_bias __retVal, sampler, coord4;
+}
+
+vec4 texure2DArray(const sampler2DArray sampler, const vec3 coord)
+{
+   vec4 coord4;
+   coord4.xyz = coord;
+   __asm vec4_tex_2d_array __retVal, sampler, coord4;
+}
+
+vec4 texture2DArray(const sampler2DArray sampler, const vec3 coord, const float bias)
+{
+   vec4 coord4;
+   coord4.xyz = coord;
+   coord4.w = bias;
+   __asm vec4_tex_2d_array_bias __retVal, sampler, coord4;
+}
+
+vec4 shadow1DArray(const sampler1DArrayShadow sampler, const vec2 coord)
+{
+   vec4 coord4;
+   coord4.xy = coord;
+   __asm vec4_tex_1d_array_shadow __retVal, sampler, coord4;
+}
+
+vec4 shadow1DArray(const sampler1DArrayShadow sampler, const vec2 coord, const float bias)
+{
+   vec4 coord4;
+   coord4.xy = coord;
+   coord4.w = bias;
+   __asm vec4_tex_1d_array_bias_shadow __retVal, sampler, coord4;
+}
+
+vec4 shadow2DArray(const sampler2DArrayShadow sampler, const vec3 coord)
+{
+   vec4 coord4;
+   coord4.xyz = coord;
+   __asm vec4_tex_2d_array_shadow __retVal, sampler, coord4;
+}
+
+vec4 shadow2DArray(const sampler2DArrayShadow sampler, const vec3 coord, const float bias)
+{
+   vec4 coord4;
+   coord4.xyz = coord;
+   coord4.w = bias;
+   __asm vec4_tex_2d_array_bias_shadow __retVal, sampler, coord4;
+}
+
+
+
+//
+// 8.8 Fragment Processing Functions
+//
+
+float dFdx(const float p)
+{
+   __asm vec4_ddx __retVal.x, p.xxxx;
+}
+
+vec2 dFdx(const vec2 p)
+{
+   __asm vec4_ddx __retVal.xy, p.xyyy;
+}
+
+vec3 dFdx(const vec3 p)
+{
+   __asm vec4_ddx __retVal.xyz, p.xyzz;
+}
+
+vec4 dFdx(const vec4 p)
+{
+   __asm vec4_ddx __retVal, p;
+}
+
+float dFdy(const float p)
+{
+   __asm vec4_ddy __retVal.x, p.xxxx;
+}
+
+vec2 dFdy(const vec2 p)
+{
+   __asm vec4_ddy __retVal.xy, p.xyyy;
+}
+
+vec3 dFdy(const vec3 p)
+{
+   __asm vec4_ddy __retVal.xyz, p.xyzz;
+}
+
+vec4 dFdy(const vec4 p)
+{
+   __asm vec4_ddy __retVal, p;
+}
+
+float fwidth (const float p)
+{
+   // XXX hand-write with __asm
+   return abs(dFdx(p)) + abs(dFdy(p));
+}
+
+vec2 fwidth(const vec2 p)
+{
+   // XXX hand-write with __asm
+   return abs(dFdx(p)) + abs(dFdy(p));
+}
+
+vec3 fwidth(const vec3 p)
+{
+   // XXX hand-write with __asm
+   return abs(dFdx(p)) + abs(dFdy(p));
+}
+
+vec4 fwidth(const vec4 p)
+{
+   // XXX hand-write with __asm
+   return abs(dFdx(p)) + abs(dFdy(p));
+}
+
diff --git a/src/mesa/slang/library/slang_vertex_builtin.gc b/src/mesa/slang/library/slang_vertex_builtin.gc
new file mode 100644 (file)
index 0000000..0c67c2e
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+//
+// From Shader Spec, ver. 1.10, rev. 59
+//
+
+__fixed_output vec4 gl_Position;
+__fixed_output float gl_PointSize;
+__fixed_output vec4 gl_ClipVertex;
+
+attribute vec4 gl_Color;
+attribute vec4 gl_SecondaryColor;
+attribute vec3 gl_Normal;
+attribute vec4 gl_Vertex;
+attribute vec4 gl_MultiTexCoord0;
+attribute vec4 gl_MultiTexCoord1;
+attribute vec4 gl_MultiTexCoord2;
+attribute vec4 gl_MultiTexCoord3;
+attribute vec4 gl_MultiTexCoord4;
+attribute vec4 gl_MultiTexCoord5;
+attribute vec4 gl_MultiTexCoord6;
+attribute vec4 gl_MultiTexCoord7;
+attribute float gl_FogCoord;
+
+varying vec4 gl_FrontColor;
+varying vec4 gl_BackColor;
+varying vec4 gl_FrontSecondaryColor;
+varying vec4 gl_BackSecondaryColor;
+varying vec4 gl_TexCoord[gl_MaxTextureCoords];
+varying float gl_FogFragCoord;
+
+//
+// Geometric Functions
+//
+
+vec4 ftransform()
+{
+   __retVal = gl_ModelViewProjectionMatrix[0] * gl_Vertex.xxxx
+            + gl_ModelViewProjectionMatrix[1] * gl_Vertex.yyyy
+            + gl_ModelViewProjectionMatrix[2] * gl_Vertex.zzzz
+            + gl_ModelViewProjectionMatrix[3] * gl_Vertex.wwww;
+}
+
+
+
+//
+// 8.7 Texture Lookup Functions
+// These are pretty much identical to the ones in slang_fragment_builtin.gc
+// When used in a vertex program, the texture sample instructions should not
+// be using a LOD term so it's effectively zero.  Adding 'lod' to that does
+// what we want.
+//
+
+vec4 texture1DLod(const sampler1D sampler, const float coord, const float lod)
+{
+   vec4 coord4;
+   coord4.x = coord;
+   coord4.w = lod;
+   __asm vec4_tex_1d_bias __retVal, sampler, coord4;
+}
+
+vec4 texture1DProjLod(const sampler1D sampler, const vec2 coord, const float lod)
+{
+   vec4 pcoord;
+   pcoord.x = coord.x / coord.y;
+   pcoord.w = lod;
+   __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
+}
+
+vec4 texture1DProjLod(const sampler1D sampler, const vec4 coord, const float lod)
+{
+   vec4 pcoord;
+   pcoord.x = coord.x / coord.z;
+   pcoord.w = lod;
+   __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
+}
+
+
+
+vec4 texture2DLod(const sampler2D sampler, const vec2 coord, const float lod)
+{
+   vec4 coord4;
+   coord4.xy = coord.xy;
+   coord4.w = lod;
+   __asm vec4_tex_2d_bias __retVal, sampler, coord4;
+}
+
+vec4 texture2DProjLod(const sampler2D sampler, const vec3 coord, const float lod)
+{
+   vec4 pcoord;
+   pcoord.xy = coord.xy / coord.z;
+   pcoord.w = lod;
+   __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
+}
+
+vec4 texture2DProjLod(const sampler2D sampler, const vec4 coord, const float lod)
+{
+   vec4 pcoord;
+   pcoord.xy = coord.xy / coord.z;
+   pcoord.w = lod;
+   __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
+}
+
+
+vec4 texture3DLod(const sampler3D sampler, const vec3 coord, const float lod)
+{
+   vec4 coord4;
+   coord4.xyz = coord.xyz;
+   coord4.w = lod;
+   __asm vec4_tex_3d_bias __retVal, sampler, coord4;
+}
+
+vec4 texture3DProjLod(const sampler3D sampler, const vec4 coord, const float lod)
+{
+   // do projection here (there's no vec4_tex_3d_bias_proj instruction)
+   vec4 pcoord;
+   pcoord.xyz = coord.xyz / coord.w;
+   pcoord.w = lod;
+   __asm vec4_tex_3d_bias __retVal, sampler, pcoord;
+}
+
+
+vec4 textureCubeLod(const samplerCube sampler, const vec3 coord, const float lod)
+{
+   vec4 coord4;
+   coord4.xyz = coord;
+   coord4.w = lod;
+   __asm vec4_tex_cube __retVal, sampler, coord4;
+}
+
+
+vec4 shadow1DLod(const sampler1DShadow sampler, const vec3 coord, const float lod)
+{
+   vec4 coord4;
+   coord4.xyz = coord;
+   coord4.w = lod;
+   __asm vec4_tex_1d_bias_shadow __retVal, sampler, coord4;
+}
+
+vec4 shadow1DProjLod(const sampler1DShadow sampler, const vec4 coord,
+                     const float lod)
+{
+   vec4 pcoord;
+   pcoord.x = coord.x / coord.w;
+   pcoord.z = coord.z;
+   pcoord.w = lod;
+   __asm vec4_tex_1d_bias_shadow __retVal, sampler, pcoord;
+}
+
+
+vec4 shadow2DLod(const sampler2DShadow sampler, const vec3 coord, const float lod)
+{
+   vec4 coord4;
+   coord4.xyz = coord;
+   coord4.w = lod;
+   __asm vec4_tex_2d_bias_shadow __retVal, sampler, coord4;
+}
+
+vec4 shadow2DProjLod(const sampler2DShadow sampler, const vec4 coord,
+                     const float lod)
+{
+   vec4 pcoord;
+   pcoord.xy = coord.xy / coord.w;
+   pcoord.z = coord.z;
+   pcoord.w = lod;
+   __asm vec4_tex_2d_bias_shadow __retVal, sampler, pcoord;
+}
+
+
+//// GL_EXT_texture_array
+
+vec4 texture1DArrayLod(const sampler1DArray sampler, const vec2 coord, const float lod)
+{
+   vec4 coord4;
+   coord4.xy = coord;
+   coord4.w = lod;
+   __asm vec4_tex_1d_array_bias __retVal, sampler, coord4;
+}
+
+
+vec4 texture2DArrayLod(const sampler2DArray sampler, const vec3 coord, const float lod)
+{
+   vec4 coord4;
+   coord4.xyz = coord;
+   coord4.w = lod;
+   __asm vec4_tex_2d_array_bias __retVal, sampler, coord4;
+}
+
diff --git a/src/mesa/slang/slang_builtin.c b/src/mesa/slang/slang_builtin.c
new file mode 100644 (file)
index 0000000..edb6052
--- /dev/null
@@ -0,0 +1,937 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2008  VMware, Inc.   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_builtin.c
+ * Resolve built-in uniform vars.
+ * \author Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_statevars.h"
+#include "slang/slang_ir.h"
+#include "slang/slang_builtin.h"
+
+
+/** special state token (see below) */
+#define STATE_ARRAY ((gl_state_index) 0xfffff)
+
+
+/**
+ * Lookup GL state given a variable name, 0, 1 or 2 indexes and a field.
+ * Allocate room for the state in the given param list and return position
+ * in the list.
+ * Yes, this is kind of ugly, but it works.
+ */
+static GLint
+lookup_statevar(const char *var, GLint index1, GLint index2, const char *field,
+                GLuint *swizzleOut,
+                struct gl_program_parameter_list *paramList)
+{
+   /*
+    * NOTE: The ARB_vertex_program extension specified that matrices get
+    * loaded in registers in row-major order.  With GLSL, we want column-
+    * major order.  So, we need to transpose all matrices here...
+    */
+   static const struct {
+      const char *name;
+      gl_state_index matrix;
+      gl_state_index modifier;
+   } matrices[] = {
+      { "gl_ModelViewMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE },
+      { "gl_ModelViewMatrixInverse", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS },
+      { "gl_ModelViewMatrixTranspose", STATE_MODELVIEW_MATRIX, 0 },
+      { "gl_ModelViewMatrixInverseTranspose", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
+
+      { "gl_ProjectionMatrix", STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE },
+      { "gl_ProjectionMatrixInverse", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS },
+      { "gl_ProjectionMatrixTranspose", STATE_PROJECTION_MATRIX, 0 },
+      { "gl_ProjectionMatrixInverseTranspose", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE },
+
+      { "gl_ModelViewProjectionMatrix", STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE },
+      { "gl_ModelViewProjectionMatrixInverse", STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS },
+      { "gl_ModelViewProjectionMatrixTranspose", STATE_MVP_MATRIX, 0 },
+      { "gl_ModelViewProjectionMatrixInverseTranspose", STATE_MVP_MATRIX, STATE_MATRIX_INVERSE },
+
+      { "gl_TextureMatrix", STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE },
+      { "gl_TextureMatrixInverse", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS },
+      { "gl_TextureMatrixTranspose", STATE_TEXTURE_MATRIX, 0 },
+      { "gl_TextureMatrixInverseTranspose", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE },
+
+      { "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
+
+      { NULL, 0, 0 }
+   };
+   gl_state_index tokens[STATE_LENGTH];
+   GLuint i;
+   GLboolean isMatrix = GL_FALSE;
+
+   for (i = 0; i < STATE_LENGTH; i++) {
+      tokens[i] = 0;
+   }
+   *swizzleOut = SWIZZLE_NOOP;
+
+   /* first, look if var is a pre-defined matrix */
+   for (i = 0; matrices[i].name; i++) {
+      if (strcmp(var, matrices[i].name) == 0) {
+         tokens[0] = matrices[i].matrix;
+         /* tokens[1], [2] and [3] filled below */
+         tokens[4] = matrices[i].modifier;
+         isMatrix = GL_TRUE;
+         break;
+      }
+   }
+
+   if (isMatrix) {
+      if (tokens[0] == STATE_TEXTURE_MATRIX) {
+         /* texture_matrix[index1][index2] */
+         tokens[1] = index1 >= 0 ? index1 : 0; /* which texture matrix */
+         index1 = index2; /* move matrix row value to index1 */
+      }
+      if (index1 < 0) {
+         /* index1 is unused: prevent extra addition at end of function */
+         index1 = 0;
+      }
+   }
+   else if (strcmp(var, "gl_DepthRange") == 0) {
+      tokens[0] = STATE_DEPTH_RANGE;
+      assert(field);
+      if (strcmp(field, "near") == 0) {
+         *swizzleOut = SWIZZLE_XXXX;
+      }
+      else if (strcmp(field, "far") == 0) {
+         *swizzleOut = SWIZZLE_YYYY;
+      }
+      else if (strcmp(field, "diff") == 0) {
+         *swizzleOut = SWIZZLE_ZZZZ;
+      }
+      else {
+         return -1;
+      }
+   }
+   else if (strcmp(var, "gl_ClipPlane") == 0) {
+      if (index1 < 0)
+         return -1;
+      tokens[0] = STATE_CLIPPLANE;
+      tokens[1] = index1;
+   }
+   else if (strcmp(var, "gl_Point") == 0) {
+      assert(field);
+      if (strcmp(field, "size") == 0) {
+         tokens[0] = STATE_POINT_SIZE;
+         *swizzleOut = SWIZZLE_XXXX;
+      }
+      else if (strcmp(field, "sizeMin") == 0) {
+         tokens[0] = STATE_POINT_SIZE;
+         *swizzleOut = SWIZZLE_YYYY;
+      }
+      else if (strcmp(field, "sizeMax") == 0) {
+         tokens[0] = STATE_POINT_SIZE;
+         *swizzleOut = SWIZZLE_ZZZZ;
+      }
+      else if (strcmp(field, "fadeThresholdSize") == 0) {
+         tokens[0] = STATE_POINT_SIZE;
+         *swizzleOut = SWIZZLE_WWWW;
+      }
+      else if (strcmp(field, "distanceConstantAttenuation") == 0) {
+         tokens[0] = STATE_POINT_ATTENUATION;
+         *swizzleOut = SWIZZLE_XXXX;
+      }
+      else if (strcmp(field, "distanceLinearAttenuation") == 0) {
+         tokens[0] = STATE_POINT_ATTENUATION;
+         *swizzleOut = SWIZZLE_YYYY;
+      }
+      else if (strcmp(field, "distanceQuadraticAttenuation") == 0) {
+         tokens[0] = STATE_POINT_ATTENUATION;
+         *swizzleOut = SWIZZLE_ZZZZ;
+      }
+      else {
+         return -1;
+      }
+   }
+   else if (strcmp(var, "gl_FrontMaterial") == 0 ||
+            strcmp(var, "gl_BackMaterial") == 0) {
+      tokens[0] = STATE_MATERIAL;
+      if (strcmp(var, "gl_FrontMaterial") == 0)
+         tokens[1] = 0;
+      else
+         tokens[1] = 1;
+      assert(field);
+      if (strcmp(field, "emission") == 0) {
+         tokens[2] = STATE_EMISSION;
+      }
+      else if (strcmp(field, "ambient") == 0) {
+         tokens[2] = STATE_AMBIENT;
+      }
+      else if (strcmp(field, "diffuse") == 0) {
+         tokens[2] = STATE_DIFFUSE;
+      }
+      else if (strcmp(field, "specular") == 0) {
+         tokens[2] = STATE_SPECULAR;
+      }
+      else if (strcmp(field, "shininess") == 0) {
+         tokens[2] = STATE_SHININESS;
+         *swizzleOut = SWIZZLE_XXXX;
+      }
+      else {
+         return -1;
+      }
+   }
+   else if (strcmp(var, "gl_LightSource") == 0) {
+      if (!field || index1 < 0)
+         return -1;
+
+      tokens[0] = STATE_LIGHT;
+      tokens[1] = index1;
+
+      if (strcmp(field, "ambient") == 0) {
+         tokens[2] = STATE_AMBIENT;
+      }
+      else if (strcmp(field, "diffuse") == 0) {
+         tokens[2] = STATE_DIFFUSE;
+      }
+      else if (strcmp(field, "specular") == 0) {
+         tokens[2] = STATE_SPECULAR;
+      }
+      else if (strcmp(field, "position") == 0) {
+         tokens[2] = STATE_POSITION;
+      }
+      else if (strcmp(field, "halfVector") == 0) {
+         tokens[2] = STATE_HALF_VECTOR;
+      }
+      else if (strcmp(field, "spotDirection") == 0) {
+         tokens[2] = STATE_SPOT_DIRECTION;
+      }
+      else if (strcmp(field, "spotCosCutoff") == 0) {
+         tokens[2] = STATE_SPOT_DIRECTION;
+         *swizzleOut = SWIZZLE_WWWW;
+      }
+      else if (strcmp(field, "spotCutoff") == 0) {
+         tokens[2] = STATE_SPOT_CUTOFF;
+         *swizzleOut = SWIZZLE_XXXX;
+      }
+      else if (strcmp(field, "spotExponent") == 0) {
+         tokens[2] = STATE_ATTENUATION;
+         *swizzleOut = SWIZZLE_WWWW;
+      }
+      else if (strcmp(field, "constantAttenuation") == 0) {
+         tokens[2] = STATE_ATTENUATION;
+         *swizzleOut = SWIZZLE_XXXX;
+      }
+      else if (strcmp(field, "linearAttenuation") == 0) {
+         tokens[2] = STATE_ATTENUATION;
+         *swizzleOut = SWIZZLE_YYYY;
+      }
+      else if (strcmp(field, "quadraticAttenuation") == 0) {
+         tokens[2] = STATE_ATTENUATION;
+         *swizzleOut = SWIZZLE_ZZZZ;
+      }
+      else {
+         return -1;
+      }
+   }
+   else if (strcmp(var, "gl_LightModel") == 0) {
+      if (strcmp(field, "ambient") == 0) {
+         tokens[0] = STATE_LIGHTMODEL_AMBIENT;
+      }
+      else {
+         return -1;
+      }
+   }
+   else if (strcmp(var, "gl_FrontLightModelProduct") == 0) {
+      if (strcmp(field, "sceneColor") == 0) {
+         tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
+         tokens[1] = 0;
+      }
+      else {
+         return -1;
+      }
+   }
+   else if (strcmp(var, "gl_BackLightModelProduct") == 0) {
+      if (strcmp(field, "sceneColor") == 0) {
+         tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
+         tokens[1] = 1;
+      }
+      else {
+         return -1;
+      }
+   }
+   else if (strcmp(var, "gl_FrontLightProduct") == 0 ||
+            strcmp(var, "gl_BackLightProduct") == 0) {
+      if (index1 < 0 || !field)
+         return -1;
+
+      tokens[0] = STATE_LIGHTPROD;
+      tokens[1] = index1; /* light number */
+      if (strcmp(var, "gl_FrontLightProduct") == 0) {
+         tokens[2] = 0; /* front */
+      }
+      else {
+         tokens[2] = 1; /* back */
+      }
+      if (strcmp(field, "ambient") == 0) {
+         tokens[3] = STATE_AMBIENT;
+      }
+      else if (strcmp(field, "diffuse") == 0) {
+         tokens[3] = STATE_DIFFUSE;
+      }
+      else if (strcmp(field, "specular") == 0) {
+         tokens[3] = STATE_SPECULAR;
+      }
+      else {
+         return -1;
+      }
+   }
+   else if (strcmp(var, "gl_TextureEnvColor") == 0) {
+      if (index1 < 0)
+         return -1;
+      tokens[0] = STATE_TEXENV_COLOR;
+      tokens[1] = index1;
+   }
+   else if (strcmp(var, "gl_EyePlaneS") == 0) {
+      if (index1 < 0)
+         return -1;
+      tokens[0] = STATE_TEXGEN;
+      tokens[1] = index1; /* tex unit */
+      tokens[2] = STATE_TEXGEN_EYE_S;
+   }
+   else if (strcmp(var, "gl_EyePlaneT") == 0) {
+      if (index1 < 0)
+         return -1;
+      tokens[0] = STATE_TEXGEN;
+      tokens[1] = index1; /* tex unit */
+      tokens[2] = STATE_TEXGEN_EYE_T;
+   }
+   else if (strcmp(var, "gl_EyePlaneR") == 0) {
+      if (index1 < 0)
+         return -1;
+      tokens[0] = STATE_TEXGEN;
+      tokens[1] = index1; /* tex unit */
+      tokens[2] = STATE_TEXGEN_EYE_R;
+   }
+   else if (strcmp(var, "gl_EyePlaneQ") == 0) {
+      if (index1 < 0)
+         return -1;
+      tokens[0] = STATE_TEXGEN;
+      tokens[1] = index1; /* tex unit */
+      tokens[2] = STATE_TEXGEN_EYE_Q;
+   }
+   else if (strcmp(var, "gl_ObjectPlaneS") == 0) {
+      if (index1 < 0)
+         return -1;
+      tokens[0] = STATE_TEXGEN;
+      tokens[1] = index1; /* tex unit */
+      tokens[2] = STATE_TEXGEN_OBJECT_S;
+   }
+   else if (strcmp(var, "gl_ObjectPlaneT") == 0) {
+      if (index1 < 0)
+         return -1;
+      tokens[0] = STATE_TEXGEN;
+      tokens[1] = index1; /* tex unit */
+      tokens[2] = STATE_TEXGEN_OBJECT_T;
+   }
+   else if (strcmp(var, "gl_ObjectPlaneR") == 0) {
+      if (index1 < 0)
+         return -1;
+      tokens[0] = STATE_TEXGEN;
+      tokens[1] = index1; /* tex unit */
+      tokens[2] = STATE_TEXGEN_OBJECT_R;
+   }
+   else if (strcmp(var, "gl_ObjectPlaneQ") == 0) {
+      if (index1 < 0)
+         return -1;
+      tokens[0] = STATE_TEXGEN;
+      tokens[1] = index1; /* tex unit */
+      tokens[2] = STATE_TEXGEN_OBJECT_Q;
+   }
+   else if (strcmp(var, "gl_Fog") == 0) {
+      if (strcmp(field, "color") == 0) {
+         tokens[0] = STATE_FOG_COLOR;
+      }
+      else if (strcmp(field, "density") == 0) {
+         tokens[0] = STATE_FOG_PARAMS;
+         *swizzleOut = SWIZZLE_XXXX;
+      }
+      else if (strcmp(field, "start") == 0) {
+         tokens[0] = STATE_FOG_PARAMS;
+         *swizzleOut = SWIZZLE_YYYY;
+      }
+      else if (strcmp(field, "end") == 0) {
+         tokens[0] = STATE_FOG_PARAMS;
+         *swizzleOut = SWIZZLE_ZZZZ;
+      }
+      else if (strcmp(field, "scale") == 0) {
+         tokens[0] = STATE_FOG_PARAMS;
+         *swizzleOut = SWIZZLE_WWWW;
+      }
+      else {
+         return -1;
+      }
+   }
+   else {
+      return -1;
+   }
+
+   if (isMatrix) {
+      /* load all four columns of matrix */
+      GLint pos[4];
+      GLuint j;
+      for (j = 0; j < 4; j++) {
+         tokens[2] = tokens[3] = j; /* jth row of matrix */
+         pos[j] = _mesa_add_state_reference(paramList, tokens);
+         assert(pos[j] >= 0);
+         ASSERT(pos[j] >= 0);
+      }
+      return pos[0] + index1;
+   }
+   else {
+      /* allocate a single register */
+      GLint pos = _mesa_add_state_reference(paramList, tokens);
+      ASSERT(pos >= 0);
+      return pos;
+   }
+}
+
+
+
+/**
+ * Given a variable name and datatype, emit uniform/constant buffer
+ * entries which will store that state variable.
+ * For example, if name="gl_LightSource" we'll emit 64 state variable
+ * vectors/references and return position where that data starts.  This will
+ * allow run-time array indexing into the light source array.
+ *
+ * Note that this is a recursive function.
+ *
+ * \return -1 if error, else index of start of data in the program parameter list
+ */
+static GLint
+emit_statevars(const char *name, int array_len,
+               const slang_type_specifier *type,
+               gl_state_index tokens[STATE_LENGTH],
+               struct gl_program_parameter_list *paramList)
+{
+   if (type->type == SLANG_SPEC_ARRAY) {
+      GLint i, pos = -1;
+      assert(array_len > 0);
+      if (strcmp(name, "gl_ClipPlane") == 0) {
+         tokens[0] = STATE_CLIPPLANE;
+      }
+      else if (strcmp(name, "gl_LightSource") == 0) {
+         tokens[0] = STATE_LIGHT;
+      }
+      else if (strcmp(name, "gl_FrontLightProduct") == 0) {
+         tokens[0] = STATE_LIGHTPROD;
+         tokens[2] = 0; /* front */
+      }
+      else if (strcmp(name, "gl_BackLightProduct") == 0) {
+         tokens[0] = STATE_LIGHTPROD;
+         tokens[2] = 1; /* back */
+      }
+      else if (strcmp(name, "gl_TextureEnvColor") == 0) {
+         tokens[0] = STATE_TEXENV_COLOR;
+      }
+      else if (strcmp(name, "gl_EyePlaneS") == 0) {
+         tokens[0] = STATE_TEXGEN;
+         tokens[2] = STATE_TEXGEN_EYE_S;
+      }
+      else if (strcmp(name, "gl_EyePlaneT") == 0) {
+         tokens[0] = STATE_TEXGEN;
+         tokens[2] = STATE_TEXGEN_EYE_T;
+      }
+      else if (strcmp(name, "gl_EyePlaneR") == 0) {
+         tokens[0] = STATE_TEXGEN;
+         tokens[2] = STATE_TEXGEN_EYE_R;
+      }
+      else if (strcmp(name, "gl_EyePlaneQ") == 0) {
+         tokens[0] = STATE_TEXGEN;
+         tokens[2] = STATE_TEXGEN_EYE_Q;
+      }
+      else if (strcmp(name, "gl_ObjectPlaneS") == 0) {
+         tokens[0] = STATE_TEXGEN;
+         tokens[2] = STATE_TEXGEN_OBJECT_S;
+      }
+      else if (strcmp(name, "gl_ObjectPlaneT") == 0) {
+         tokens[0] = STATE_TEXGEN;
+         tokens[2] = STATE_TEXGEN_OBJECT_T;
+      }
+      else if (strcmp(name, "gl_ObjectPlaneR") == 0) {
+         tokens[0] = STATE_TEXGEN;
+         tokens[2] = STATE_TEXGEN_OBJECT_R;
+      }
+      else if (strcmp(name, "gl_ObjectPlaneQ") == 0) {
+         tokens[0] = STATE_TEXGEN;
+         tokens[2] = STATE_TEXGEN_OBJECT_Q;
+      }
+      else {
+         return -1; /* invalid array name */
+      }
+      for (i = 0; i < array_len; i++) {
+         GLint p;
+         tokens[1] = i;
+         p = emit_statevars(NULL, 0, type->_array, tokens, paramList);
+         if (i == 0)
+            pos = p;
+      }
+      return pos;
+   }
+   else if (type->type == SLANG_SPEC_STRUCT) {
+      const slang_variable_scope *fields = type->_struct->fields;
+      GLuint i, pos = 0;
+      for (i = 0; i < fields->num_variables; i++) {
+         const slang_variable *var = fields->variables[i];
+         GLint p = emit_statevars(var->a_name, 0, &var->type.specifier,
+                                  tokens, paramList);
+         if (i == 0)
+            pos = p;
+      }
+      return pos;
+   }
+   else {
+      GLint pos;
+      assert(type->type == SLANG_SPEC_VEC4 ||
+             type->type == SLANG_SPEC_VEC3 ||
+             type->type == SLANG_SPEC_VEC2 ||
+             type->type == SLANG_SPEC_FLOAT ||
+             type->type == SLANG_SPEC_IVEC4 ||
+             type->type == SLANG_SPEC_IVEC3 ||
+             type->type == SLANG_SPEC_IVEC2 ||
+             type->type == SLANG_SPEC_INT);
+      if (name) {
+         GLint t;
+
+         if (tokens[0] == STATE_LIGHT)
+            t = 2;
+         else if (tokens[0] == STATE_LIGHTPROD)
+            t = 3;
+         else
+            return -1; /* invalid array name */
+
+         if (strcmp(name, "ambient") == 0) {
+            tokens[t] = STATE_AMBIENT;
+         }
+         else if (strcmp(name, "diffuse") == 0) {
+            tokens[t] = STATE_DIFFUSE;
+         }
+         else if (strcmp(name, "specular") == 0) {
+            tokens[t] = STATE_SPECULAR;
+         }
+         else if (strcmp(name, "position") == 0) {
+            tokens[t] = STATE_POSITION;
+         }
+         else if (strcmp(name, "halfVector") == 0) {
+            tokens[t] = STATE_HALF_VECTOR;
+         }
+         else if (strcmp(name, "spotDirection") == 0) {
+            tokens[t] = STATE_SPOT_DIRECTION; /* xyz components */
+         }
+         else if (strcmp(name, "spotCosCutoff") == 0) {
+            tokens[t] = STATE_SPOT_DIRECTION; /* w component */
+         }
+
+         else if (strcmp(name, "constantAttenuation") == 0) {
+            tokens[t] = STATE_ATTENUATION; /* x component */
+         }
+         else if (strcmp(name, "linearAttenuation") == 0) {
+            tokens[t] = STATE_ATTENUATION; /* y component */
+         }
+         else if (strcmp(name, "quadraticAttenuation") == 0) {
+            tokens[t] = STATE_ATTENUATION; /* z component */
+         }
+         else if (strcmp(name, "spotExponent") == 0) {
+            tokens[t] = STATE_ATTENUATION; /* w = spot exponent */
+         }
+
+         else if (strcmp(name, "spotCutoff") == 0) {
+            tokens[t] = STATE_SPOT_CUTOFF; /* x component */
+         }
+
+         else {
+            return -1; /* invalid field name */
+         }
+      }
+
+      pos = _mesa_add_state_reference(paramList, tokens);
+      return pos;
+   }
+
+   return 1;
+}
+
+
+/**
+ * Unroll the named built-in uniform variable into a sequence of state
+ * vars in the given parameter list.
+ */
+static GLint
+alloc_state_var_array(const slang_variable *var,
+                      struct gl_program_parameter_list *paramList)
+{
+   gl_state_index tokens[STATE_LENGTH];
+   GLuint i;
+   GLint pos;
+
+   /* Initialize the state tokens array.  This is very important.
+    * When we call _mesa_add_state_reference() it'll searches the parameter
+    * list to see if the given statevar token sequence is already present.
+    * This is normally a good thing since it prevents redundant values in the
+    * constant buffer.
+    *
+    * But when we're building arrays of state this can be bad.  For example,
+    * consider this fragment of GLSL code:
+    *   foo = gl_LightSource[3].diffuse;
+    *   ...
+    *   bar = gl_LightSource[i].diffuse;
+    *
+    * When we unroll the gl_LightSource array (for "bar") we want to re-emit
+    * gl_LightSource[3].diffuse and not re-use the first instance (from "foo")
+    * since that would upset the array layout.  We handle this situation by
+    * setting the last token in the state var token array to the special
+    * value STATE_ARRAY.
+    * This token will only be set for array state.  We can hijack the last
+    * element in the array for this since it's never used for light, clipplane
+    * or texture env array state.
+    */
+   for (i = 0; i < STATE_LENGTH; i++)
+      tokens[i] = 0;
+   tokens[STATE_LENGTH - 1] = STATE_ARRAY;
+
+   pos = emit_statevars(var->a_name, var->array_len, &var->type.specifier,
+                        tokens, paramList);
+
+   return pos;
+}
+
+
+
+/**
+ * Allocate storage for a pre-defined uniform (a GL state variable).
+ * As a memory-saving optimization, we try to only allocate storage for
+ * state vars that are actually used.
+ *
+ * Arrays such as gl_LightSource are handled specially.  For an expression
+ * like "gl_LightSource[2].diffuse", we can allocate a single uniform/constant
+ * slot and return the index.  In this case, we return direct=TRUE.
+ *
+ * Buf for something like "gl_LightSource[i].diffuse" we don't know the value
+ * of 'i' at compile time so we need to "unroll" the gl_LightSource array
+ * into a consecutive sequence of uniform/constant slots so it can be indexed
+ * at runtime.  In this case, we return direct=FALSE.
+ *
+ * Currently, all pre-defined uniforms are in one of these forms:
+ *   var
+ *   var[i]
+ *   var.field
+ *   var[i].field
+ *   var[i][j]
+ *
+ * \return -1 upon error, else position in paramList of the state variable/data
+ */
+GLint
+_slang_alloc_statevar(slang_ir_node *n,
+                      struct gl_program_parameter_list *paramList,
+                      GLboolean *direct)
+{
+   slang_ir_node *n0 = n;
+   const char *field = NULL;
+   GLint index1 = -1, index2 = -1;
+   GLuint swizzle;
+
+   *direct = GL_TRUE;
+
+   if (n->Opcode == IR_FIELD) {
+      field = n->Field;
+      n = n->Children[0];
+   }
+
+   if (n->Opcode == IR_ELEMENT) {
+      if (n->Children[1]->Opcode == IR_FLOAT) {
+         index1 = (GLint) n->Children[1]->Value[0];
+      }
+      else {
+         *direct = GL_FALSE;
+      }
+      n = n->Children[0];
+   }
+
+   if (n->Opcode == IR_ELEMENT) {
+      /* XXX can only handle constant indexes for now */
+      if (n->Children[1]->Opcode == IR_FLOAT) {
+         /* two-dimensional array index: mat[i][j] */
+         index2 = index1;
+         index1 = (GLint) n->Children[1]->Value[0];
+      }
+      else {
+         *direct = GL_FALSE;
+      }
+      n = n->Children[0];
+   }
+
+   assert(n->Opcode == IR_VAR);
+
+   if (*direct) {
+      const char *var = (const char *) n->Var->a_name;
+      GLint pos =
+         lookup_statevar(var, index1, index2, field, &swizzle, paramList);
+      if (pos >= 0) {
+         /* newly resolved storage for the statevar/constant/uniform */
+         n0->Store->File = PROGRAM_STATE_VAR;
+         n0->Store->Index = pos;
+         n0->Store->Swizzle = swizzle;
+         n0->Store->Parent = NULL;
+         return pos;
+      }
+   }
+
+   *direct = GL_FALSE;
+   return alloc_state_var_array(n->Var, paramList);
+}
+
+
+
+
+#define SWIZZLE_ZWWW MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W)
+
+
+/** Predefined shader inputs */
+struct input_info
+{
+   const char *Name;
+   GLuint Attrib;
+   GLenum Type;
+   GLuint Swizzle;
+};
+
+/** Predefined vertex shader inputs/attributes */
+static const struct input_info vertInputs[] = {
+   { "gl_Vertex", VERT_ATTRIB_POS, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_Normal", VERT_ATTRIB_NORMAL, GL_FLOAT_VEC3, SWIZZLE_NOOP },
+   { "gl_Color", VERT_ATTRIB_COLOR0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_SecondaryColor", VERT_ATTRIB_COLOR1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_FogCoord", VERT_ATTRIB_FOG, GL_FLOAT, SWIZZLE_XXXX },
+   { "gl_MultiTexCoord0", VERT_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_MultiTexCoord1", VERT_ATTRIB_TEX1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_MultiTexCoord2", VERT_ATTRIB_TEX2, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_MultiTexCoord3", VERT_ATTRIB_TEX3, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_MultiTexCoord4", VERT_ATTRIB_TEX4, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_MultiTexCoord5", VERT_ATTRIB_TEX5, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_MultiTexCoord6", VERT_ATTRIB_TEX6, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_MultiTexCoord7", VERT_ATTRIB_TEX7, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { NULL, 0, GL_NONE, SWIZZLE_NOOP }
+};
+
+/** Predefined fragment shader inputs */
+static const struct input_info fragInputs[] = {
+   { "gl_FragCoord", FRAG_ATTRIB_WPOS, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_Color", FRAG_ATTRIB_COL0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_SecondaryColor", FRAG_ATTRIB_COL1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_TexCoord", FRAG_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+   { "gl_FogFragCoord", FRAG_ATTRIB_FOGC, GL_FLOAT, SWIZZLE_XXXX },
+   { "gl_FrontFacing", FRAG_ATTRIB_FACE, GL_FLOAT, SWIZZLE_XXXX },
+   { "gl_PointCoord", FRAG_ATTRIB_PNTC, GL_FLOAT_VEC2, SWIZZLE_XYZW },
+   { NULL, 0, GL_NONE, SWIZZLE_NOOP }
+};
+
+
+/**
+ * Return the VERT_ATTRIB_* or FRAG_ATTRIB_* value that corresponds to
+ * a vertex or fragment program input variable.  Return -1 if the input
+ * name is invalid.
+ * XXX return size too
+ */
+GLint
+_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut)
+{
+   const struct input_info *inputs;
+   GLuint i;
+
+   switch (target) {
+   case GL_VERTEX_PROGRAM_ARB:
+      inputs = vertInputs;
+      break;
+   case GL_FRAGMENT_PROGRAM_ARB:
+      inputs = fragInputs;
+      break;
+   /* XXX geom program */
+   default:
+      _mesa_problem(NULL, "bad target in _slang_input_index");
+      return -1;
+   }
+
+   ASSERT(MAX_TEXTURE_COORD_UNITS == 8); /* if this fails, fix vertInputs above */
+
+   for (i = 0; inputs[i].Name; i++) {
+      if (strcmp(inputs[i].Name, name) == 0) {
+         /* found */
+         *swizzleOut = inputs[i].Swizzle;
+         return inputs[i].Attrib;
+      }
+   }
+   return -1;
+}
+
+
+/**
+ * Return name of the given vertex attribute (VERT_ATTRIB_x).
+ */
+const char *
+_slang_vert_attrib_name(GLuint attrib)
+{
+   GLuint i;
+   assert(attrib < VERT_ATTRIB_GENERIC0);
+   for (i = 0; vertInputs[i].Name; i++) {
+      if (vertInputs[i].Attrib == attrib)
+         return vertInputs[i].Name;
+   }
+   return NULL;
+}
+
+
+/**
+ * Return type (GL_FLOAT, GL_FLOAT_VEC2, etc) of the given vertex
+ * attribute (VERT_ATTRIB_x).
+ */
+GLenum
+_slang_vert_attrib_type(GLuint attrib)
+{
+   GLuint i;
+   assert(attrib < VERT_ATTRIB_GENERIC0);
+   for (i = 0; vertInputs[i].Name; i++) {
+      if (vertInputs[i].Attrib == attrib)
+         return vertInputs[i].Type;
+   }
+   return GL_NONE;
+}
+
+
+
+
+
+/** Predefined shader output info */
+struct output_info
+{
+   const char *Name;
+   GLuint Attrib;
+   GLenum Type;
+};
+
+/** Predefined vertex shader outputs */
+static const struct output_info vertOutputs[] = {
+   { "gl_Position", VERT_RESULT_HPOS, GL_FLOAT_VEC4 },
+   { "gl_FrontColor", VERT_RESULT_COL0, GL_FLOAT_VEC4 },
+   { "gl_BackColor", VERT_RESULT_BFC0, GL_FLOAT_VEC4 },
+   { "gl_FrontSecondaryColor", VERT_RESULT_COL1, GL_FLOAT_VEC4 },
+   { "gl_BackSecondaryColor", VERT_RESULT_BFC1, GL_FLOAT_VEC4 },
+   { "gl_TexCoord", VERT_RESULT_TEX0, GL_FLOAT_VEC4 },
+   { "gl_FogFragCoord", VERT_RESULT_FOGC, GL_FLOAT },
+   { "gl_PointSize", VERT_RESULT_PSIZ, GL_FLOAT },
+   { NULL, 0, GL_NONE }
+};
+
+/** Predefined fragment shader outputs */
+static const struct output_info fragOutputs[] = {
+   { "gl_FragColor", FRAG_RESULT_COLOR, GL_FLOAT_VEC4 },
+   { "gl_FragDepth", FRAG_RESULT_DEPTH, GL_FLOAT },
+   { "gl_FragData", FRAG_RESULT_DATA0, GL_FLOAT_VEC4 },
+   { NULL, 0, GL_NONE }
+};
+
+
+/**
+ * Return the VERT_RESULT_* or FRAG_RESULT_* value that corresponds to
+ * a vertex or fragment program output variable.  Return -1 for an invalid
+ * output name.
+ */
+GLint
+_slang_output_index(const char *name, GLenum target)
+{
+   const struct output_info *outputs;
+   GLuint i;
+
+   switch (target) {
+   case GL_VERTEX_PROGRAM_ARB:
+      outputs = vertOutputs;
+      break;
+   case GL_FRAGMENT_PROGRAM_ARB:
+      outputs = fragOutputs;
+      break;
+   /* XXX geom program */
+   default:
+      _mesa_problem(NULL, "bad target in _slang_output_index");
+      return -1;
+   }
+
+   for (i = 0; outputs[i].Name; i++) {
+      if (strcmp(outputs[i].Name, name) == 0) {
+         /* found */
+         return outputs[i].Attrib;
+      }
+   }
+   return -1;
+}
+
+
+/**
+ * Given a VERT_RESULT_x index, return the corresponding string name.
+ */
+const char *
+_slang_vertex_output_name(gl_vert_result index)
+{
+   if (index < Elements(vertOutputs))
+      return vertOutputs[index].Name;
+   else
+      return NULL;
+}
+
+
+/**
+ * Given a FRAG_RESULT_x index, return the corresponding string name.
+ */
+const char *
+_slang_fragment_output_name(gl_frag_result index)
+{
+   if (index < Elements(fragOutputs))
+      return fragOutputs[index].Name;
+   else
+      return NULL;
+}
+
+
+/**
+ * Given a VERT_RESULT_x index, return the corresponding varying
+ * var's datatype.
+ */
+GLenum
+_slang_vertex_output_type(gl_vert_result index)
+{
+   if (index < Elements(vertOutputs))
+      return vertOutputs[index].Type;
+   else
+      return GL_NONE;
+}
diff --git a/src/mesa/slang/slang_builtin.h b/src/mesa/slang/slang_builtin.h
new file mode 100644 (file)
index 0000000..c3021ca
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef SLANG_BUILTIN_H
+#define SLANG_BUILTIN_H
+
+#include "shader/prog_parameter.h"
+#include "slang_utility.h"
+#include "slang_ir.h"
+
+
+extern GLint
+_slang_alloc_statevar(slang_ir_node *n,
+                      struct gl_program_parameter_list *paramList,
+                      GLboolean *direct);
+
+
+extern GLint
+_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut);
+
+extern GLint
+_slang_output_index(const char *name, GLenum target);
+
+
+extern const char *
+_slang_vert_attrib_name(GLuint attrib);
+
+extern GLenum
+_slang_vert_attrib_type(GLuint attrib);
+
+
+const char *
+_slang_vertex_output_name(gl_vert_result index);
+
+const char *
+_slang_fragment_output_name(gl_frag_result index);
+
+GLenum
+_slang_vertex_output_type(gl_vert_result index);
+
+
+#endif /* SLANG_BUILTIN_H */
diff --git a/src/mesa/slang/slang_codegen.c b/src/mesa/slang/slang_codegen.c
new file mode 100644 (file)
index 0000000..0504d47
--- /dev/null
@@ -0,0 +1,5357 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_codegen.c
+ * Generate IR tree from AST.
+ * \author Brian Paul
+ */
+
+
+/***
+ *** NOTES:
+ *** The new_() functions return a new instance of a simple IR node.
+ *** The gen_() functions generate larger IR trees from the simple nodes.
+ ***/
+
+
+
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "shader/prog_statevars.h"
+#include "slang_typeinfo.h"
+#include "slang_builtin.h"
+#include "slang_codegen.h"
+#include "slang_compile.h"
+#include "slang_label.h"
+#include "slang_mem.h"
+#include "slang_simplify.h"
+#include "slang_emit.h"
+#include "slang_vartable.h"
+#include "slang_ir.h"
+#include "slang_print.h"
+
+
+/** Max iterations to unroll */
+const GLuint MAX_FOR_LOOP_UNROLL_ITERATIONS = 32;
+
+/** Max for-loop body size (in slang operations) to unroll */
+const GLuint MAX_FOR_LOOP_UNROLL_BODY_SIZE = 50;
+
+/** Max for-loop body complexity to unroll.
+ * We'll compute complexity as the product of the number of iterations
+ * and the size of the body.  So long-ish loops with very simple bodies
+ * can be unrolled, as well as short loops with larger bodies.
+ */
+const GLuint MAX_FOR_LOOP_UNROLL_COMPLEXITY = 256;
+
+
+
+static slang_ir_node *
+_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper);
+
+static void
+slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
+                 GLuint substCount, slang_variable **substOld,
+                slang_operation **substNew, GLboolean isLHS);
+
+
+/**
+ * Retrieves type information about an operation.
+ * Returns GL_TRUE on success.
+ * Returns GL_FALSE otherwise.
+ */
+static GLboolean
+typeof_operation(const struct slang_assemble_ctx_ *A,
+                 slang_operation *op,
+                 slang_typeinfo *ti)
+{
+   return _slang_typeof_operation(op, &A->space, ti, A->atoms, A->log);
+}
+
+
+static GLboolean
+is_sampler_type(const slang_fully_specified_type *t)
+{
+   switch (t->specifier.type) {
+   case SLANG_SPEC_SAMPLER_1D:
+   case SLANG_SPEC_SAMPLER_2D:
+   case SLANG_SPEC_SAMPLER_3D:
+   case SLANG_SPEC_SAMPLER_CUBE:
+   case SLANG_SPEC_SAMPLER_1D_SHADOW:
+   case SLANG_SPEC_SAMPLER_2D_SHADOW:
+   case SLANG_SPEC_SAMPLER_RECT:
+   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
+   case SLANG_SPEC_SAMPLER_1D_ARRAY:
+   case SLANG_SPEC_SAMPLER_2D_ARRAY:
+   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
+   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Return the offset (in floats or ints) of the named field within
+ * the given struct.  Return -1 if field not found.
+ * If field is NULL, return the size of the struct instead.
+ */
+static GLint
+_slang_field_offset(const slang_type_specifier *spec, slang_atom field)
+{
+   GLint offset = 0;
+   GLuint i;
+   for (i = 0; i < spec->_struct->fields->num_variables; i++) {
+      const slang_variable *v = spec->_struct->fields->variables[i];
+      const GLuint sz = _slang_sizeof_type_specifier(&v->type.specifier);
+      if (sz > 1) {
+         /* types larger than 1 float are register (4-float) aligned */
+         offset = (offset + 3) & ~3;
+      }
+      if (field && v->a_name == field) {
+         return offset;
+      }
+      offset += sz;
+   }
+   if (field)
+      return -1; /* field not found */
+   else
+      return offset;  /* struct size */
+}
+
+
+/**
+ * Return the size (in floats) of the given type specifier.
+ * If the size is greater than 4, the size should be a multiple of 4
+ * so that the correct number of 4-float registers are allocated.
+ * For example, a mat3x2 is size 12 because we want to store the
+ * 3 columns in 3 float[4] registers.
+ */
+GLuint
+_slang_sizeof_type_specifier(const slang_type_specifier *spec)
+{
+   GLuint sz;
+   switch (spec->type) {
+   case SLANG_SPEC_VOID:
+      sz = 0;
+      break;
+   case SLANG_SPEC_BOOL:
+      sz = 1;
+      break;
+   case SLANG_SPEC_BVEC2:
+      sz = 2;
+      break;
+   case SLANG_SPEC_BVEC3:
+      sz = 3;
+      break;
+   case SLANG_SPEC_BVEC4:
+      sz = 4;
+      break;
+   case SLANG_SPEC_INT:
+      sz = 1;
+      break;
+   case SLANG_SPEC_IVEC2:
+      sz = 2;
+      break;
+   case SLANG_SPEC_IVEC3:
+      sz = 3;
+      break;
+   case SLANG_SPEC_IVEC4:
+      sz = 4;
+      break;
+   case SLANG_SPEC_FLOAT:
+      sz = 1;
+      break;
+   case SLANG_SPEC_VEC2:
+      sz = 2;
+      break;
+   case SLANG_SPEC_VEC3:
+      sz = 3;
+      break;
+   case SLANG_SPEC_VEC4:
+      sz = 4;
+      break;
+   case SLANG_SPEC_MAT2:
+      sz = 2 * 4; /* 2 columns (regs) */
+      break;
+   case SLANG_SPEC_MAT3:
+      sz = 3 * 4;
+      break;
+   case SLANG_SPEC_MAT4:
+      sz = 4 * 4;
+      break;
+   case SLANG_SPEC_MAT23:
+      sz = 2 * 4; /* 2 columns (regs) */
+      break;
+   case SLANG_SPEC_MAT32:
+      sz = 3 * 4; /* 3 columns (regs) */
+      break;
+   case SLANG_SPEC_MAT24:
+      sz = 2 * 4;
+      break;
+   case SLANG_SPEC_MAT42:
+      sz = 4 * 4; /* 4 columns (regs) */
+      break;
+   case SLANG_SPEC_MAT34:
+      sz = 3 * 4;
+      break;
+   case SLANG_SPEC_MAT43:
+      sz = 4 * 4; /* 4 columns (regs) */
+      break;
+   case SLANG_SPEC_SAMPLER_1D:
+   case SLANG_SPEC_SAMPLER_2D:
+   case SLANG_SPEC_SAMPLER_3D:
+   case SLANG_SPEC_SAMPLER_CUBE:
+   case SLANG_SPEC_SAMPLER_1D_SHADOW:
+   case SLANG_SPEC_SAMPLER_2D_SHADOW:
+   case SLANG_SPEC_SAMPLER_RECT:
+   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
+   case SLANG_SPEC_SAMPLER_1D_ARRAY:
+   case SLANG_SPEC_SAMPLER_2D_ARRAY:
+   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
+   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
+      sz = 1; /* a sampler is basically just an integer index */
+      break;
+   case SLANG_SPEC_STRUCT:
+      sz = _slang_field_offset(spec, 0); /* special use */
+      if (sz == 1) {
+         /* 1-float structs are actually troublesome to deal with since they
+          * might get placed at R.x, R.y, R.z or R.z.  Return size=2 to
+          * ensure the object is placed at R.x
+          */
+         sz = 2;
+      }
+      else if (sz > 4) {
+         sz = (sz + 3) & ~0x3; /* round up to multiple of four */
+      }
+      break;
+   case SLANG_SPEC_ARRAY:
+      sz = _slang_sizeof_type_specifier(spec->_array);
+      break;
+   default:
+      _mesa_problem(NULL, "Unexpected type in _slang_sizeof_type_specifier()");
+      sz = 0;
+   }
+
+   if (sz > 4) {
+      /* if size is > 4, it should be a multiple of four */
+      assert((sz & 0x3) == 0);
+   }
+   return sz;
+}
+
+
+/**
+ * Query variable/array length (number of elements).
+ * This is slightly non-trivial because there are two ways to express
+ * arrays: "float x[3]" vs. "float[3] x".
+ * \return the length of the array for the given variable, or 0 if not an array
+ */
+static GLint
+_slang_array_length(const slang_variable *var)
+{
+   if (var->type.array_len > 0) {
+      /* Ex: float[4] x; */
+      return var->type.array_len;
+   }
+   if (var->array_len > 0) {
+      /* Ex: float x[4]; */
+      return var->array_len;
+   }
+   return 0;
+}
+
+
+/**
+ * Compute total size of array give size of element, number of elements.
+ * \return size in floats
+ */
+static GLint
+_slang_array_size(GLint elemSize, GLint arrayLen)
+{
+   GLint total;
+   assert(elemSize > 0);
+   if (arrayLen > 1) {
+      /* round up base type to multiple of 4 */
+      total = ((elemSize + 3) & ~0x3) * MAX2(arrayLen, 1);
+   }
+   else {
+      total = elemSize;
+   }
+   return total;
+}
+
+
+/**
+ * Return the TEXTURE_*_INDEX value that corresponds to a sampler type,
+ * or -1 if the type is not a sampler.
+ */
+static GLint
+sampler_to_texture_index(const slang_type_specifier_type type)
+{
+   switch (type) {
+   case SLANG_SPEC_SAMPLER_1D:
+      return TEXTURE_1D_INDEX;
+   case SLANG_SPEC_SAMPLER_2D:
+      return TEXTURE_2D_INDEX;
+   case SLANG_SPEC_SAMPLER_3D:
+      return TEXTURE_3D_INDEX;
+   case SLANG_SPEC_SAMPLER_CUBE:
+      return TEXTURE_CUBE_INDEX;
+   case SLANG_SPEC_SAMPLER_1D_SHADOW:
+      return TEXTURE_1D_INDEX; /* XXX fix */
+   case SLANG_SPEC_SAMPLER_2D_SHADOW:
+      return TEXTURE_2D_INDEX; /* XXX fix */
+   case SLANG_SPEC_SAMPLER_RECT:
+      return TEXTURE_RECT_INDEX;
+   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
+      return TEXTURE_RECT_INDEX; /* XXX fix */
+   case SLANG_SPEC_SAMPLER_1D_ARRAY:
+      return TEXTURE_1D_ARRAY_INDEX;
+   case SLANG_SPEC_SAMPLER_2D_ARRAY:
+      return TEXTURE_2D_ARRAY_INDEX;
+   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
+      return TEXTURE_1D_ARRAY_INDEX;
+   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
+      return TEXTURE_2D_ARRAY_INDEX;
+   default:
+      return -1;
+   }
+}
+
+
+/** helper to build a SLANG_OPER_IDENTIFIER node */
+static void
+slang_operation_identifier(slang_operation *oper,
+                           slang_assemble_ctx *A,
+                           const char *name)
+{
+   oper->type = SLANG_OPER_IDENTIFIER;
+   oper->a_id = slang_atom_pool_atom(A->atoms, name);
+}
+
+
+/**
+ * Called when we begin code/IR generation for a new while/do/for loop.
+ */
+static void
+push_loop(slang_assemble_ctx *A, slang_operation *loopOper, slang_ir_node *loopIR)
+{
+   A->LoopOperStack[A->LoopDepth] = loopOper;
+   A->LoopIRStack[A->LoopDepth] = loopIR;
+   A->LoopDepth++;
+}
+
+
+/**
+ * Called when we end code/IR generation for a new while/do/for loop.
+ */
+static void
+pop_loop(slang_assemble_ctx *A)
+{
+   assert(A->LoopDepth > 0);
+   A->LoopDepth--;
+}
+
+
+/**
+ * Return pointer to slang_operation for the loop we're currently inside,
+ * or NULL if not in a loop.
+ */
+static const slang_operation *
+current_loop_oper(const slang_assemble_ctx *A)
+{
+   if (A->LoopDepth > 0)
+      return A->LoopOperStack[A->LoopDepth - 1];
+   else
+      return NULL;
+}
+
+
+/**
+ * Return pointer to slang_ir_node for the loop we're currently inside,
+ * or NULL if not in a loop.
+ */
+static slang_ir_node *
+current_loop_ir(const slang_assemble_ctx *A)
+{
+   if (A->LoopDepth > 0)
+      return A->LoopIRStack[A->LoopDepth - 1];
+   else
+      return NULL;
+}
+
+
+/**********************************************************************/
+
+
+/**
+ * Map "_asm foo" to IR_FOO, etc.
+ */
+typedef struct
+{
+   const char *Name;
+   slang_ir_opcode Opcode;
+   GLuint HaveRetValue, NumParams;
+} slang_asm_info;
+
+
+static slang_asm_info AsmInfo[] = {
+   /* vec4 binary op */
+   { "vec4_add", IR_ADD, 1, 2 },
+   { "vec4_subtract", IR_SUB, 1, 2 },
+   { "vec4_multiply", IR_MUL, 1, 2 },
+   { "vec4_dot", IR_DOT4, 1, 2 },
+   { "vec3_dot", IR_DOT3, 1, 2 },
+   { "vec2_dot", IR_DOT2, 1, 2 },
+   { "vec3_nrm", IR_NRM3, 1, 1 },
+   { "vec4_nrm", IR_NRM4, 1, 1 },
+   { "vec3_cross", IR_CROSS, 1, 2 },
+   { "vec4_lrp", IR_LRP, 1, 3 },
+   { "vec4_min", IR_MIN, 1, 2 },
+   { "vec4_max", IR_MAX, 1, 2 },
+   { "vec4_cmp", IR_CMP, 1, 3 },
+   { "vec4_clamp", IR_CLAMP, 1, 3 },
+   { "vec4_seq", IR_SEQUAL, 1, 2 },
+   { "vec4_sne", IR_SNEQUAL, 1, 2 },
+   { "vec4_sge", IR_SGE, 1, 2 },
+   { "vec4_sgt", IR_SGT, 1, 2 },
+   { "vec4_sle", IR_SLE, 1, 2 },
+   { "vec4_slt", IR_SLT, 1, 2 },
+   /* vec4 unary */
+   { "vec4_move", IR_MOVE, 1, 1 },
+   { "vec4_floor", IR_FLOOR, 1, 1 },
+   { "vec4_frac", IR_FRAC, 1, 1 },
+   { "vec4_abs", IR_ABS, 1, 1 },
+   { "vec4_negate", IR_NEG, 1, 1 },
+   { "vec4_ddx", IR_DDX, 1, 1 },
+   { "vec4_ddy", IR_DDY, 1, 1 },
+   /* float binary op */
+   { "float_power", IR_POW, 1, 2 },
+   /* texture / sampler */
+   { "vec4_tex_1d", IR_TEX, 1, 2 },
+   { "vec4_tex_1d_bias", IR_TEXB, 1, 2 },  /* 1d w/ bias */
+   { "vec4_tex_1d_proj", IR_TEXP, 1, 2 },  /* 1d w/ projection */
+   { "vec4_tex_2d", IR_TEX, 1, 2 },
+   { "vec4_tex_2d_bias", IR_TEXB, 1, 2 },  /* 2d w/ bias */
+   { "vec4_tex_2d_proj", IR_TEXP, 1, 2 },  /* 2d w/ projection */
+   { "vec4_tex_3d", IR_TEX, 1, 2 },
+   { "vec4_tex_3d_bias", IR_TEXB, 1, 2 },  /* 3d w/ bias */
+   { "vec4_tex_3d_proj", IR_TEXP, 1, 2 },  /* 3d w/ projection */
+   { "vec4_tex_cube", IR_TEX, 1, 2 },      /* cubemap */
+   { "vec4_tex_rect", IR_TEX, 1, 2 },      /* rectangle */
+   { "vec4_tex_rect_bias", IR_TEX, 1, 2 }, /* rectangle w/ projection */
+   { "vec4_tex_1d_array", IR_TEX, 1, 2 },
+   { "vec4_tex_1d_array_bias", IR_TEXB, 1, 2 },
+   { "vec4_tex_1d_array_shadow", IR_TEX, 1, 2 },
+   { "vec4_tex_1d_array_bias_shadow", IR_TEXB, 1, 2 },
+   { "vec4_tex_2d_array", IR_TEX, 1, 2 },
+   { "vec4_tex_2d_array_bias", IR_TEXB, 1, 2 },
+   { "vec4_tex_2d_array_shadow", IR_TEX, 1, 2 },
+   { "vec4_tex_2d_array_bias_shadow", IR_TEXB, 1, 2 },
+
+   /* texture / sampler but with shadow comparison */
+   { "vec4_tex_1d_shadow", IR_TEX_SH, 1, 2 },
+   { "vec4_tex_1d_bias_shadow", IR_TEXB_SH, 1, 2 },
+   { "vec4_tex_1d_proj_shadow", IR_TEXP_SH, 1, 2 },
+   { "vec4_tex_2d_shadow", IR_TEX_SH, 1, 2 },
+   { "vec4_tex_2d_bias_shadow", IR_TEXB_SH, 1, 2 },
+   { "vec4_tex_2d_proj_shadow", IR_TEXP_SH, 1, 2 },
+   { "vec4_tex_rect_shadow", IR_TEX_SH, 1, 2 },
+   { "vec4_tex_rect_proj_shadow", IR_TEXP_SH, 1, 2 },
+
+   /* unary op */
+   { "ivec4_to_vec4", IR_I_TO_F, 1, 1 }, /* int[4] to float[4] */
+   { "vec4_to_ivec4", IR_F_TO_I, 1, 1 },  /* float[4] to int[4] */
+   { "float_exp", IR_EXP, 1, 1 },
+   { "float_exp2", IR_EXP2, 1, 1 },
+   { "float_log2", IR_LOG2, 1, 1 },
+   { "float_rsq", IR_RSQ, 1, 1 },
+   { "float_rcp", IR_RCP, 1, 1 },
+   { "float_sine", IR_SIN, 1, 1 },
+   { "float_cosine", IR_COS, 1, 1 },
+   { "float_noise1", IR_NOISE1, 1, 1},
+   { "float_noise2", IR_NOISE2, 1, 1},
+   { "float_noise3", IR_NOISE3, 1, 1},
+   { "float_noise4", IR_NOISE4, 1, 1},
+
+   { NULL, IR_NOP, 0, 0 }
+};
+
+
+static slang_ir_node *
+new_node3(slang_ir_opcode op,
+          slang_ir_node *c0, slang_ir_node *c1, slang_ir_node *c2)
+{
+   slang_ir_node *n = (slang_ir_node *) _slang_alloc(sizeof(slang_ir_node));
+   if (n) {
+      n->Opcode = op;
+      n->Children[0] = c0;
+      n->Children[1] = c1;
+      n->Children[2] = c2;
+      n->InstLocation = -1;
+   }
+   return n;
+}
+
+static slang_ir_node *
+new_node2(slang_ir_opcode op, slang_ir_node *c0, slang_ir_node *c1)
+{
+   return new_node3(op, c0, c1, NULL);
+}
+
+static slang_ir_node *
+new_node1(slang_ir_opcode op, slang_ir_node *c0)
+{
+   return new_node3(op, c0, NULL, NULL);
+}
+
+static slang_ir_node *
+new_node0(slang_ir_opcode op)
+{
+   return new_node3(op, NULL, NULL, NULL);
+}
+
+
+/**
+ * Create sequence of two nodes.
+ */
+static slang_ir_node *
+new_seq(slang_ir_node *left, slang_ir_node *right)
+{
+   if (!left)
+      return right;
+   if (!right)
+      return left;
+   return new_node2(IR_SEQ, left, right);
+}
+
+static slang_ir_node *
+new_label(slang_label *label)
+{
+   slang_ir_node *n = new_node0(IR_LABEL);
+   assert(label);
+   if (n)
+      n->Label = label;
+   return n;
+}
+
+static slang_ir_node *
+new_float_literal(const float v[4], GLuint size)
+{
+   slang_ir_node *n = new_node0(IR_FLOAT);
+   assert(size <= 4);
+   COPY_4V(n->Value, v);
+   /* allocate a storage object, but compute actual location (Index) later */
+   n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size);
+   return n;
+}
+
+
+static slang_ir_node *
+new_not(slang_ir_node *n)
+{
+   return new_node1(IR_NOT, n);
+}
+
+
+/**
+ * Non-inlined function call.
+ */
+static slang_ir_node *
+new_function_call(slang_ir_node *code, slang_label *name)
+{
+   slang_ir_node *n = new_node1(IR_CALL, code);
+   assert(name);
+   if (n)
+      n->Label = name;
+   return n;
+}
+
+
+/**
+ * Unconditional jump.
+ */
+static slang_ir_node *
+new_return(slang_label *dest)
+{
+   slang_ir_node *n = new_node0(IR_RETURN);
+   assert(dest);
+   if (n)
+      n->Label = dest;
+   return n;
+}
+
+
+static slang_ir_node *
+new_loop(slang_ir_node *body)
+{
+   return new_node1(IR_LOOP, body);
+}
+
+
+static slang_ir_node *
+new_break(slang_ir_node *loopNode)
+{
+   slang_ir_node *n = new_node0(IR_BREAK);
+   assert(loopNode);
+   assert(loopNode->Opcode == IR_LOOP);
+   if (n) {
+      /* insert this node at head of linked list of cont/break instructions */
+      n->List = loopNode->List;
+      loopNode->List = n;
+   }
+   return n;
+}
+
+
+/**
+ * Make new IR_BREAK_IF_TRUE.
+ */
+static slang_ir_node *
+new_break_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
+{
+   slang_ir_node *loopNode = current_loop_ir(A);
+   slang_ir_node *n;
+   assert(loopNode);
+   assert(loopNode->Opcode == IR_LOOP);
+   n = new_node1(IR_BREAK_IF_TRUE, cond);
+   if (n) {
+      /* insert this node at head of linked list of cont/break instructions */
+      n->List = loopNode->List;
+      loopNode->List = n;
+   }
+   return n;
+}
+
+
+/**
+ * Make new IR_CONT_IF_TRUE node.
+ */
+static slang_ir_node *
+new_cont_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
+{
+   slang_ir_node *loopNode = current_loop_ir(A);
+   slang_ir_node *n;
+   assert(loopNode);
+   assert(loopNode->Opcode == IR_LOOP);
+   n = new_node1(IR_CONT_IF_TRUE, cond);
+   if (n) {
+      n->Parent = loopNode; /* pointer to containing loop */
+      /* insert this node at head of linked list of cont/break instructions */
+      n->List = loopNode->List;
+      loopNode->List = n;
+   }
+   return n;
+}
+
+
+static slang_ir_node *
+new_cond(slang_ir_node *n)
+{
+   slang_ir_node *c = new_node1(IR_COND, n);
+   return c;
+}
+
+
+static slang_ir_node *
+new_if(slang_ir_node *cond, slang_ir_node *ifPart, slang_ir_node *elsePart)
+{
+   return new_node3(IR_IF, cond, ifPart, elsePart);
+}
+
+
+/**
+ * New IR_VAR node - a reference to a previously declared variable.
+ */
+static slang_ir_node *
+new_var(slang_assemble_ctx *A, slang_variable *var)
+{
+   slang_ir_node *n = new_node0(IR_VAR);
+   if (n) {
+      ASSERT(var);
+      ASSERT(var->store);
+      ASSERT(!n->Store);
+      ASSERT(!n->Var);
+
+      /* Set IR node's Var and Store pointers */
+      n->Var = var;
+      n->Store = var->store;
+   }
+   return n;
+}
+
+
+/**
+ * Check if the given function is really just a wrapper for a
+ * basic assembly instruction.
+ */
+static GLboolean
+slang_is_asm_function(const slang_function *fun)
+{
+   if (fun->body->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE &&
+       fun->body->num_children == 1 &&
+       fun->body->children[0].type == SLANG_OPER_ASM) {
+      return GL_TRUE;
+   }
+   return GL_FALSE;
+}
+
+
+static GLboolean
+_slang_is_noop(const slang_operation *oper)
+{
+   if (!oper ||
+       oper->type == SLANG_OPER_VOID ||
+       (oper->num_children == 1 && oper->children[0].type == SLANG_OPER_VOID))
+      return GL_TRUE;
+   else
+      return GL_FALSE;
+}
+
+
+/**
+ * Recursively search tree for a node of the given type.
+ */
+#if 0
+static slang_operation *
+_slang_find_node_type(slang_operation *oper, slang_operation_type type)
+{
+   GLuint i;
+   if (oper->type == type)
+      return oper;
+   for (i = 0; i < oper->num_children; i++) {
+      slang_operation *p = _slang_find_node_type(&oper->children[i], type);
+      if (p)
+         return p;
+   }
+   return NULL;
+}
+#endif
+
+
+/**
+ * Count the number of operations of the given time rooted at 'oper'.
+ */
+static GLuint
+_slang_count_node_type(const slang_operation *oper, slang_operation_type type)
+{
+   GLuint i, count = 0;
+   if (oper->type == type) {
+      return 1;
+   }
+   for (i = 0; i < oper->num_children; i++) {
+      count += _slang_count_node_type(&oper->children[i], type);
+   }
+   return count;
+}
+
+
+/**
+ * Check if the 'return' statement found under 'oper' is a "tail return"
+ * that can be no-op'd.  For example:
+ *
+ * void func(void)
+ * {
+ *    .. do something ..
+ *    return;   // this is a no-op
+ * }
+ *
+ * This is used when determining if a function can be inlined.  If the
+ * 'return' is not the last statement, we can't inline the function since
+ * we still need the semantic behaviour of the 'return' but we don't want
+ * to accidentally return from the _calling_ function.  We'd need to use an
+ * unconditional branch, but we don't have such a GPU instruction (not
+ * always, at least).
+ */
+static GLboolean
+_slang_is_tail_return(const slang_operation *oper)
+{
+   GLuint k = oper->num_children;
+
+   while (k > 0) {
+      const slang_operation *last = &oper->children[k - 1];
+      if (last->type == SLANG_OPER_RETURN)
+         return GL_TRUE;
+      else if (last->type == SLANG_OPER_IDENTIFIER ||
+               last->type == SLANG_OPER_LABEL)
+         k--; /* try prev child */
+      else if (last->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE ||
+               last->type == SLANG_OPER_BLOCK_NEW_SCOPE)
+         /* try sub-children */
+         return _slang_is_tail_return(last);
+      else
+         break;
+   }
+
+   return GL_FALSE;
+}
+
+
+/**
+ * Generate a variable declaration opeartion.
+ * I.e.: generate AST code for "bool flag = false;"
+ */
+static void
+slang_generate_declaration(slang_assemble_ctx *A,
+                           slang_variable_scope *scope,
+                           slang_operation *decl,
+                           slang_type_specifier_type type,
+                           const char *name,
+                           GLint initValue)
+{
+   slang_variable *var;
+
+   assert(type == SLANG_SPEC_BOOL ||
+          type == SLANG_SPEC_INT);
+
+   decl->type = SLANG_OPER_VARIABLE_DECL;
+
+   var = slang_variable_scope_grow(scope);
+
+   slang_fully_specified_type_construct(&var->type);
+
+   var->type.specifier.type = type;
+   var->a_name = slang_atom_pool_atom(A->atoms, name);
+   decl->a_id = var->a_name;
+   var->initializer = slang_operation_new(1);
+   slang_operation_literal_bool(var->initializer, initValue);
+}
+
+
+static void
+slang_resolve_variable(slang_operation *oper)
+{
+   if (oper->type == SLANG_OPER_IDENTIFIER && !oper->var) {
+      oper->var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
+   }
+}
+
+
+/**
+ * Rewrite AST code for "return expression;".
+ *
+ * We return values from functions by assinging the returned value to
+ * the hidden __retVal variable which is an extra 'out' parameter we add
+ * to the function signature.
+ * This code basically converts "return expr;" into "__retVal = expr; return;"
+ *
+ * \return the new AST code.
+ */
+static slang_operation *
+gen_return_with_expression(slang_assemble_ctx *A, slang_operation *oper)
+{
+   slang_operation *blockOper, *assignOper;
+
+   assert(oper->type == SLANG_OPER_RETURN);
+
+   if (A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) {
+      slang_info_log_error(A->log, "illegal return expression");
+      return NULL;
+   }
+
+   blockOper = slang_operation_new(1);
+   blockOper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
+   blockOper->locals->outer_scope = oper->locals->outer_scope;
+   slang_operation_add_children(blockOper, 2);
+
+   if (A->UseReturnFlag) {
+      /* Emit:
+       *    {
+       *       if (__notRetFlag)
+       *          __retVal = expr;
+       *       __notRetFlag = 0;
+       *    }
+       */
+      {
+         slang_operation *ifOper = slang_oper_child(blockOper, 0);
+         ifOper->type = SLANG_OPER_IF;
+         slang_operation_add_children(ifOper, 3);
+         {
+            slang_operation *cond = slang_oper_child(ifOper, 0);
+            cond->type = SLANG_OPER_IDENTIFIER;
+            cond->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
+         }
+         {
+            slang_operation *elseOper = slang_oper_child(ifOper, 2);
+            elseOper->type = SLANG_OPER_VOID;
+         }
+         assignOper = slang_oper_child(ifOper, 1);
+      }
+      {
+         slang_operation *setOper = slang_oper_child(blockOper, 1);
+         setOper->type = SLANG_OPER_ASSIGN;
+         slang_operation_add_children(setOper, 2);
+         {
+            slang_operation *lhs = slang_oper_child(setOper, 0);
+            lhs->type = SLANG_OPER_IDENTIFIER;
+            lhs->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
+         }
+         {
+            slang_operation *rhs = slang_oper_child(setOper, 1);
+            slang_operation_literal_bool(rhs, GL_FALSE);
+         }
+      }
+   }
+   else {
+      /* Emit:
+       *    {
+       *       __retVal = expr;
+       *       return_inlined;
+       *    }
+       */
+      assignOper = slang_oper_child(blockOper, 0);
+      {
+         slang_operation *returnOper = slang_oper_child(blockOper, 1);
+         returnOper->type = SLANG_OPER_RETURN_INLINED;
+         assert(returnOper->num_children == 0);
+      }
+   }
+
+   /* __retVal = expression; */
+   assignOper->type = SLANG_OPER_ASSIGN;
+   slang_operation_add_children(assignOper, 2);
+   {
+      slang_operation *lhs = slang_oper_child(assignOper, 0);
+      lhs->type = SLANG_OPER_IDENTIFIER;
+      lhs->a_id = slang_atom_pool_atom(A->atoms, "__retVal");
+   }
+   {
+      slang_operation *rhs = slang_oper_child(assignOper, 1);
+      slang_operation_copy(rhs, &oper->children[0]);
+   }
+
+   /*blockOper->locals->outer_scope = oper->locals->outer_scope;*/
+
+   /*slang_print_tree(blockOper, 0);*/
+
+   return blockOper;
+}
+
+
+/**
+ * Rewrite AST code for "return;" (no expression).
+ */
+static slang_operation *
+gen_return_without_expression(slang_assemble_ctx *A, slang_operation *oper)
+{
+   slang_operation *newRet;
+
+   assert(oper->type == SLANG_OPER_RETURN);
+
+   if (A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
+      slang_info_log_error(A->log, "return statement requires an expression");
+      return NULL;
+   }
+
+   if (A->UseReturnFlag) {
+      /* Emit:
+       *    __notRetFlag = 0;
+       */
+      {
+         newRet = slang_operation_new(1);
+         newRet->locals->outer_scope = oper->locals->outer_scope;
+         newRet->type = SLANG_OPER_ASSIGN;
+         slang_operation_add_children(newRet, 2);
+         {
+            slang_operation *lhs = slang_oper_child(newRet, 0);
+            lhs->type = SLANG_OPER_IDENTIFIER;
+            lhs->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
+         }
+         {
+            slang_operation *rhs = slang_oper_child(newRet, 1);
+            slang_operation_literal_bool(rhs, GL_FALSE);
+         }
+      }
+   }
+   else {
+      /* Emit:
+       *    return_inlined;
+       */
+      newRet = slang_operation_new(1);
+      newRet->locals->outer_scope = oper->locals->outer_scope;
+      newRet->type = SLANG_OPER_RETURN_INLINED;
+   }
+
+   /*slang_print_tree(newRet, 0);*/
+
+   return newRet;
+}
+
+
+
+
+/**
+ * Replace particular variables (SLANG_OPER_IDENTIFIER) with new expressions.
+ */
+static void
+slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
+                 GLuint substCount, slang_variable **substOld,
+                slang_operation **substNew, GLboolean isLHS)
+{
+   switch (oper->type) {
+   case SLANG_OPER_VARIABLE_DECL:
+      {
+         slang_variable *v = _slang_variable_locate(oper->locals,
+                                                    oper->a_id, GL_TRUE);
+         assert(v);
+         if (v->initializer && oper->num_children == 0) {
+            /* set child of oper to copy of initializer */
+            oper->num_children = 1;
+            oper->children = slang_operation_new(1);
+            slang_operation_copy(&oper->children[0], v->initializer);
+         }
+         if (oper->num_children == 1) {
+            /* the initializer */
+            slang_substitute(A, &oper->children[0], substCount,
+                             substOld, substNew, GL_FALSE);
+         }
+      }
+      break;
+   case SLANG_OPER_IDENTIFIER:
+      assert(oper->num_children == 0);
+      if (1/**!isLHS XXX FIX */) {
+         slang_atom id = oper->a_id;
+         slang_variable *v;
+        GLuint i;
+         v = _slang_variable_locate(oper->locals, id, GL_TRUE);
+        if (!v) {
+            if (strcmp((char *) oper->a_id, "__notRetFlag"))
+               _mesa_problem(NULL, "var %s not found!\n", (char *) oper->a_id);
+            return;
+        }
+
+        /* look for a substitution */
+        for (i = 0; i < substCount; i++) {
+           if (v == substOld[i]) {
+               /* OK, replace this SLANG_OPER_IDENTIFIER with a new expr */
+#if 0 /* DEBUG only */
+              if (substNew[i]->type == SLANG_OPER_IDENTIFIER) {
+                  assert(substNew[i]->var);
+                  assert(substNew[i]->var->a_name);
+                 printf("Substitute %s with %s in id node %p\n",
+                        (char*)v->a_name, (char*) substNew[i]->var->a_name,
+                        (void*) oper);
+               }
+              else {
+                 printf("Substitute %s with %f in id node %p\n",
+                        (char*)v->a_name, substNew[i]->literal[0],
+                        (void*) oper);
+               }
+#endif
+              slang_operation_copy(oper, substNew[i]);
+              break;
+           }
+        }
+      }
+      break;
+
+   case SLANG_OPER_RETURN:
+      {
+         slang_operation *newReturn;
+         /* generate new 'return' code' */
+         if (slang_oper_child(oper, 0)->type == SLANG_OPER_VOID)
+            newReturn = gen_return_without_expression(A, oper);
+         else
+            newReturn = gen_return_with_expression(A, oper);
+
+         if (!newReturn)
+            return;
+
+         /* do substitutions on the new 'return' code */
+         slang_substitute(A, newReturn,
+                          substCount, substOld, substNew, GL_FALSE);
+
+         /* install new 'return' code */
+         slang_operation_copy(oper, newReturn);
+         slang_operation_destruct(newReturn);
+      }
+      break;
+
+   case SLANG_OPER_ASSIGN:
+   case SLANG_OPER_SUBSCRIPT:
+      /* special case:
+       * child[0] can't have substitutions but child[1] can.
+       */
+      slang_substitute(A, &oper->children[0],
+                       substCount, substOld, substNew, GL_TRUE);
+      slang_substitute(A, &oper->children[1],
+                       substCount, substOld, substNew, GL_FALSE);
+      break;
+   case SLANG_OPER_FIELD:
+      /* XXX NEW - test */
+      slang_substitute(A, &oper->children[0],
+                       substCount, substOld, substNew, GL_TRUE);
+      break;
+   default:
+      {
+         GLuint i;
+         for (i = 0; i < oper->num_children; i++) 
+            slang_substitute(A, &oper->children[i],
+                             substCount, substOld, substNew, GL_FALSE);
+      }
+   }
+}
+
+
+/**
+ * Produce inline code for a call to an assembly instruction.
+ * This is typically used to compile a call to a built-in function like this:
+ *
+ * vec4 mix(const vec4 x, const vec4 y, const vec4 a)
+ * {
+ *    __asm vec4_lrp __retVal, a, y, x;
+ * }
+ *
+ *
+ * A call to
+ *     r = mix(p1, p2, p3);
+ *
+ * Becomes:
+ *
+ *              mov
+ *             /   \
+ *            r   vec4_lrp
+ *                 /  |  \
+ *                p3  p2  p1
+ *
+ * We basically translate a SLANG_OPER_CALL into a SLANG_OPER_ASM.
+ */
+static slang_operation *
+slang_inline_asm_function(slang_assemble_ctx *A,
+                          slang_function *fun, slang_operation *oper)
+{
+   const GLuint numArgs = oper->num_children;
+   GLuint i;
+   slang_operation *inlined;
+   const GLboolean haveRetValue = _slang_function_has_return_value(fun);
+   slang_variable **substOld;
+   slang_operation **substNew;
+
+   ASSERT(slang_is_asm_function(fun));
+   ASSERT(fun->param_count == numArgs + haveRetValue);
+
+   /*
+   printf("Inline %s as %s\n",
+          (char*) fun->header.a_name,
+          (char*) fun->body->children[0].a_id);
+   */
+
+   /*
+    * We'll substitute formal params with actual args in the asm call.
+    */
+   substOld = (slang_variable **)
+      _slang_alloc(numArgs * sizeof(slang_variable *));
+   substNew = (slang_operation **)
+      _slang_alloc(numArgs * sizeof(slang_operation *));
+   for (i = 0; i < numArgs; i++) {
+      substOld[i] = fun->parameters->variables[i];
+      substNew[i] = oper->children + i;
+   }
+
+   /* make a copy of the code to inline */
+   inlined = slang_operation_new(1);
+   slang_operation_copy(inlined, &fun->body->children[0]);
+   if (haveRetValue) {
+      /* get rid of the __retVal child */
+      inlined->num_children--;
+      for (i = 0; i < inlined->num_children; i++) {
+         inlined->children[i] = inlined->children[i + 1];
+      }
+   }
+
+   /* now do formal->actual substitutions */
+   slang_substitute(A, inlined, numArgs, substOld, substNew, GL_FALSE);
+
+   _slang_free(substOld);
+   _slang_free(substNew);
+
+#if 0
+   printf("+++++++++++++ inlined asm function %s +++++++++++++\n",
+          (char *) fun->header.a_name);
+   slang_print_tree(inlined, 3);
+   printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n");
+#endif
+
+   return inlined;
+}
+
+
+/**
+ * Inline the given function call operation.
+ * Return a new slang_operation that corresponds to the inlined code.
+ */
+static slang_operation *
+slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
+                          slang_operation *oper, slang_operation *returnOper)
+{
+   typedef enum {
+      SUBST = 1,
+      COPY_IN,
+      COPY_OUT
+   } ParamMode;
+   ParamMode *paramMode;
+   const GLboolean haveRetValue = _slang_function_has_return_value(fun);
+   const GLuint numArgs = oper->num_children;
+   const GLuint totalArgs = numArgs + haveRetValue;
+   slang_operation *args = oper->children;
+   slang_operation *inlined, *top;
+   slang_variable **substOld;
+   slang_operation **substNew;
+   GLuint substCount, numCopyIn, i;
+   slang_function *prevFunction;
+   slang_variable_scope *newScope = NULL;
+
+   /* save / push */
+   prevFunction = A->CurFunction;
+   A->CurFunction = fun;
+
+   /*assert(oper->type == SLANG_OPER_CALL); (or (matrix) multiply, etc) */
+   assert(fun->param_count == totalArgs);
+
+   /* allocate temporary arrays */
+   paramMode = (ParamMode *)
+      _slang_alloc(totalArgs * sizeof(ParamMode));
+   substOld = (slang_variable **)
+      _slang_alloc(totalArgs * sizeof(slang_variable *));
+   substNew = (slang_operation **)
+      _slang_alloc(totalArgs * sizeof(slang_operation *));
+
+#if 0
+   printf("\nInline call to %s  (total vars=%d  nparams=%d)\n",
+         (char *) fun->header.a_name,
+         fun->parameters->num_variables, numArgs);
+#endif
+
+   if (haveRetValue && !returnOper) {
+      /* Create 3-child comma sequence for inlined code:
+       * child[0]:  declare __resultTmp
+       * child[1]:  inlined function body
+       * child[2]:  __resultTmp
+       */
+      slang_operation *commaSeq;
+      slang_operation *declOper = NULL;
+      slang_variable *resultVar;
+
+      commaSeq = slang_operation_new(1);
+      commaSeq->type = SLANG_OPER_SEQUENCE;
+      assert(commaSeq->locals);
+      commaSeq->locals->outer_scope = oper->locals->outer_scope;
+      commaSeq->num_children = 3;
+      commaSeq->children = slang_operation_new(3);
+      /* allocate the return var */
+      resultVar = slang_variable_scope_grow(commaSeq->locals);
+      /*
+      printf("Alloc __resultTmp in scope %p for retval of calling %s\n",
+             (void*)commaSeq->locals, (char *) fun->header.a_name);
+      */
+
+      resultVar->a_name = slang_atom_pool_atom(A->atoms, "__resultTmp");
+      resultVar->type = fun->header.type; /* XXX copy? */
+      resultVar->isTemp = GL_TRUE;
+
+      /* child[0] = __resultTmp declaration */
+      declOper = &commaSeq->children[0];
+      declOper->type = SLANG_OPER_VARIABLE_DECL;
+      declOper->a_id = resultVar->a_name;
+      declOper->locals->outer_scope = commaSeq->locals;
+
+      /* child[1] = function body */
+      inlined = &commaSeq->children[1];
+      inlined->locals->outer_scope = commaSeq->locals;
+
+      /* child[2] = __resultTmp reference */
+      returnOper = &commaSeq->children[2];
+      returnOper->type = SLANG_OPER_IDENTIFIER;
+      returnOper->a_id = resultVar->a_name;
+      returnOper->locals->outer_scope = commaSeq->locals;
+
+      top = commaSeq;
+   }
+   else {
+      top = inlined = slang_operation_new(1);
+      /* XXXX this may be inappropriate!!!! */
+      inlined->locals->outer_scope = oper->locals->outer_scope;
+   }
+
+
+   assert(inlined->locals);
+
+   /* Examine the parameters, look for inout/out params, look for possible
+    * substitutions, etc:
+    *    param type      behaviour
+    *     in             copy actual to local
+    *     const in       substitute param with actual
+    *     out            copy out
+    */
+   substCount = 0;
+   for (i = 0; i < totalArgs; i++) {
+      slang_variable *p = fun->parameters->variables[i];
+      /*
+      printf("Param %d: %s %s \n", i,
+             slang_type_qual_string(p->type.qualifier),
+            (char *) p->a_name);
+      */
+      if (p->type.qualifier == SLANG_QUAL_INOUT ||
+         p->type.qualifier == SLANG_QUAL_OUT) {
+        /* an output param */
+         slang_operation *arg;
+         if (i < numArgs)
+            arg = &args[i];
+         else
+            arg = returnOper;
+        paramMode[i] = SUBST;
+
+        if (arg->type == SLANG_OPER_IDENTIFIER)
+            slang_resolve_variable(arg);
+
+         /* replace parameter 'p' with argument 'arg' */
+        substOld[substCount] = p;
+        substNew[substCount] = arg; /* will get copied */
+        substCount++;
+      }
+      else if (p->type.qualifier == SLANG_QUAL_CONST) {
+        /* a constant input param */
+         if (args[i].type == SLANG_OPER_IDENTIFIER ||
+             args[i].type == SLANG_OPER_LITERAL_FLOAT ||
+             args[i].type == SLANG_OPER_SUBSCRIPT) {
+           /* replace all occurances of this parameter variable with the
+            * actual argument variable or a literal.
+            */
+           paramMode[i] = SUBST;
+            slang_resolve_variable(&args[i]);
+           substOld[substCount] = p;
+           substNew[substCount] = &args[i]; /* will get copied */
+           substCount++;
+        }
+        else {
+           paramMode[i] = COPY_IN;
+        }
+      }
+      else {
+        paramMode[i] = COPY_IN;
+      }
+      assert(paramMode[i]);
+   }
+
+   /* actual code inlining: */
+   slang_operation_copy(inlined, fun->body);
+
+   /*** XXX review this */
+   assert(inlined->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE ||
+          inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE);
+   inlined->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+
+#if 0
+   printf("======================= orig body code ======================\n");
+   printf("=== params scope = %p\n", (void*) fun->parameters);
+   slang_print_tree(fun->body, 8);
+   printf("======================= copied code =========================\n");
+   slang_print_tree(inlined, 8);
+#endif
+
+   /* do parameter substitution in inlined code: */
+   slang_substitute(A, inlined, substCount, substOld, substNew, GL_FALSE);
+
+#if 0
+   printf("======================= subst code ==========================\n");
+   slang_print_tree(inlined, 8);
+   printf("=============================================================\n");
+#endif
+
+   /* New prolog statements: (inserted before the inlined code)
+    * Copy the 'in' arguments.
+    */
+   numCopyIn = 0;
+   for (i = 0; i < numArgs; i++) {
+      if (paramMode[i] == COPY_IN) {
+        slang_variable *p = fun->parameters->variables[i];
+        /* declare parameter 'p' */
+        slang_operation *decl = slang_operation_insert(&inlined->num_children,
+                                                       &inlined->children,
+                                                       numCopyIn);
+
+        decl->type = SLANG_OPER_VARIABLE_DECL;
+         assert(decl->locals);
+         decl->locals->outer_scope = inlined->locals;
+        decl->a_id = p->a_name;
+        decl->num_children = 1;
+        decl->children = slang_operation_new(1);
+
+         /* child[0] is the var's initializer */
+         slang_operation_copy(&decl->children[0], args + i);
+
+         /* add parameter 'p' to the local variable scope here */
+         {
+            slang_variable *pCopy = slang_variable_scope_grow(inlined->locals);
+            pCopy->type = p->type;
+            pCopy->a_name = p->a_name;
+            pCopy->array_len = p->array_len;
+         }
+
+         newScope = inlined->locals;
+        numCopyIn++;
+      }
+   }
+
+   /* Now add copies of the function's local vars to the new variable scope */
+   for (i = totalArgs; i < fun->parameters->num_variables; i++) {
+      slang_variable *p = fun->parameters->variables[i];
+      slang_variable *pCopy = slang_variable_scope_grow(inlined->locals);
+      pCopy->type = p->type;
+      pCopy->a_name = p->a_name;
+      pCopy->array_len = p->array_len;
+   }
+
+
+   /* New epilog statements:
+    * 1. Create end of function label to jump to from return statements.
+    * 2. Copy the 'out' parameter vars
+    */
+   {
+      slang_operation *lab = slang_operation_insert(&inlined->num_children,
+                                                    &inlined->children,
+                                                    inlined->num_children);
+      lab->type = SLANG_OPER_LABEL;
+      lab->label = A->curFuncEndLabel;
+   }
+
+   for (i = 0; i < totalArgs; i++) {
+      if (paramMode[i] == COPY_OUT) {
+        const slang_variable *p = fun->parameters->variables[i];
+        /* actualCallVar = outParam */
+        /*if (i > 0 || !haveRetValue)*/
+        slang_operation *ass = slang_operation_insert(&inlined->num_children,
+                                                      &inlined->children,
+                                                      inlined->num_children);
+        ass->type = SLANG_OPER_ASSIGN;
+        ass->num_children = 2;
+         ass->locals->outer_scope = inlined->locals;
+        ass->children = slang_operation_new(2);
+        ass->children[0] = args[i]; /*XXX copy */
+        ass->children[1].type = SLANG_OPER_IDENTIFIER;
+        ass->children[1].a_id = p->a_name;
+         ass->children[1].locals->outer_scope = ass->locals;
+      }
+   }
+
+   _slang_free(paramMode);
+   _slang_free(substOld);
+   _slang_free(substNew);
+
+   /* Update scoping to use the new local vars instead of the
+    * original function's vars.  This is especially important
+    * for nested inlining.
+    */
+   if (newScope)
+      slang_replace_scope(inlined, fun->parameters, newScope);
+
+#if 0
+   printf("Done Inline call to %s  (total vars=%d  nparams=%d)\n\n",
+         (char *) fun->header.a_name,
+         fun->parameters->num_variables, numArgs);
+   slang_print_tree(top, 0);
+#endif
+
+   /* pop */
+   A->CurFunction = prevFunction;
+
+   return top;
+}
+
+
+/**
+ * Insert declaration for "bool __notRetFlag" in given block operation.
+ * This is used when we can't emit "early" return statements in subroutines.
+ */
+static void
+declare_return_flag(slang_assemble_ctx *A, slang_operation *oper)
+{
+   slang_operation *decl;
+
+   assert(oper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+          oper->type == SLANG_OPER_SEQUENCE);
+
+   decl = slang_operation_insert_child(oper, 1);
+
+   slang_generate_declaration(A, oper->locals, decl,
+                              SLANG_SPEC_BOOL, "__notRetFlag", GL_TRUE);
+
+   /*slang_print_tree(oper, 0);*/
+}
+
+
+/**
+ * Recursively replace instances of the old node type with the new type.
+ */
+static void
+replace_node_type(slang_operation *oper, slang_operation_type oldType,
+                  slang_operation_type newType)
+{
+   GLuint i;
+
+   if (oper->type == oldType)
+      oper->type = newType;
+
+   for (i = 0; i < slang_oper_num_children(oper); i++) {
+      replace_node_type(slang_oper_child(oper, i), oldType, newType);
+   }
+}
+
+
+
+/**
+ * Test if the given function body has an "early return".  That is, there's
+ * a 'return' statement that's not the very last instruction in the body.
+ */
+static GLboolean
+has_early_return(const slang_operation *funcBody)
+{
+   GLuint retCount = _slang_count_node_type(funcBody, SLANG_OPER_RETURN);
+   if (retCount == 0)
+      return GL_FALSE;
+   else if (retCount == 1 && _slang_is_tail_return(funcBody))
+      return GL_FALSE;
+   else
+      return GL_TRUE;
+}
+
+
+/**
+ * Emit IR code for a function call.  This does one of two things:
+ * 1. Inline the function's code
+ * 2. Create an IR for the function's body and create a real call to it.
+ */
+static slang_ir_node *
+_slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
+                         slang_operation *oper, slang_operation *dest)
+{
+   slang_ir_node *n;
+   slang_operation *instance;
+   slang_label *prevFuncEndLabel;
+   char name[200];
+
+   prevFuncEndLabel = A->curFuncEndLabel;
+   _mesa_snprintf(name, sizeof(name), "__endOfFunc_%s_", (char *) fun->header.a_name);
+   A->curFuncEndLabel = _slang_label_new(name);
+   assert(A->curFuncEndLabel);
+
+   /*
+    * 'instance' is basically a copy of the function's body with various
+    * transformations.
+    */
+
+   if (slang_is_asm_function(fun) && !dest) {
+      /* assemble assembly function - tree style */
+      instance = slang_inline_asm_function(A, fun, oper);
+   }
+   else {
+      /* non-assembly function */
+      /* We always generate an "inline-able" block of code here.
+       * We may either:
+       *  1. insert the inline code
+       *  2. Generate a call to the "inline" code as a subroutine
+       */
+      const GLboolean earlyReturn = has_early_return(fun->body);
+
+      if (earlyReturn && !A->EmitContReturn) {
+         A->UseReturnFlag = GL_TRUE;
+      }
+
+      instance = slang_inline_function_call(A, fun, oper, dest);
+      if (!instance)
+         return NULL;
+
+      if (earlyReturn) {
+         /* The function we're calling has one or more 'return' statements
+          * that prevent us from inlining the function's code.
+          *
+          * In this case, change the function's body type from
+          * SLANG_OPER_BLOCK_NEW_SCOPE to SLANG_OPER_NON_INLINED_CALL.
+          * During code emit this will result in a true subroutine call.
+          *
+          * Also, convert SLANG_OPER_RETURN_INLINED nodes to SLANG_OPER_RETURN.
+          */
+         slang_operation *callOper;
+
+         assert(instance->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+                instance->type == SLANG_OPER_SEQUENCE);
+
+         if (_slang_function_has_return_value(fun) && !dest) {
+            assert(instance->children[0].type == SLANG_OPER_VARIABLE_DECL);
+            assert(instance->children[2].type == SLANG_OPER_IDENTIFIER);
+            callOper = &instance->children[1];
+         }
+         else {
+            callOper = instance;
+         }
+
+         if (A->UseReturnFlag) {
+            /* Early returns not supported.  Create a _returnFlag variable
+             * that's set upon 'return' and tested elsewhere to no-op any
+             * remaining instructions in the subroutine.
+             */
+            assert(callOper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+                   callOper->type == SLANG_OPER_SEQUENCE);
+            declare_return_flag(A, callOper);
+         }
+         else {
+            /* We can emit real 'return' statements.  If we generated any
+             * 'inline return' statements during function instantiation,
+             * change them back to regular 'return' statements.
+             */
+            replace_node_type(instance, SLANG_OPER_RETURN_INLINED,
+                              SLANG_OPER_RETURN);
+         }
+
+         callOper->type = SLANG_OPER_NON_INLINED_CALL;
+         callOper->fun = fun;
+         callOper->label = _slang_label_new_unique((char*) fun->header.a_name);
+      }
+      else {
+         /* If there are any 'return' statements remaining, they're at the
+          * very end of the function and can effectively become no-ops.
+          */
+         replace_node_type(instance, SLANG_OPER_RETURN_INLINED,
+                           SLANG_OPER_VOID);
+      }
+   }
+
+   if (!instance)
+      return NULL;
+
+   /* Replace the function call with the instance block (or new CALL stmt) */
+   slang_operation_destruct(oper);
+   *oper = *instance;
+   _slang_free(instance);
+
+#if 0
+   assert(instance->locals);
+   printf("*** Inlined code for call to %s:\n", (char*) fun->header.a_name);
+   slang_print_tree(oper, 10);
+   printf("\n");
+#endif
+
+   n = _slang_gen_operation(A, oper);
+
+   /*_slang_label_delete(A->curFuncEndLabel);*/
+   A->curFuncEndLabel = prevFuncEndLabel;
+
+   if (A->pragmas->Debug) {
+      char s[1000];
+      _mesa_snprintf(s, sizeof(s), "Call/inline %s()", (char *) fun->header.a_name);
+      n->Comment = _slang_strdup(s);
+   }
+
+   A->UseReturnFlag = GL_FALSE;
+
+   return n;
+}
+
+
+static slang_asm_info *
+slang_find_asm_info(const char *name)
+{
+   GLuint i;
+   for (i = 0; AsmInfo[i].Name; i++) {
+      if (strcmp(AsmInfo[i].Name, name) == 0) {
+         return AsmInfo + i;
+      }
+   }
+   return NULL;
+}
+
+
+/**
+ * Some write-masked assignments are simple, but others are hard.
+ * Simple example:
+ *    vec3 v;
+ *    v.xy = vec2(a, b);
+ * Hard example:
+ *    vec3 v;
+ *    v.zy = vec2(a, b);
+ * this gets transformed/swizzled into:
+ *    v.zy = vec2(a, b).*yx*         (* = don't care)
+ * This function helps to determine simple vs. non-simple.
+ */
+static GLboolean
+_slang_simple_writemask(GLuint writemask, GLuint swizzle)
+{
+   switch (writemask) {
+   case WRITEMASK_X:
+      return GET_SWZ(swizzle, 0) == SWIZZLE_X;
+   case WRITEMASK_Y:
+      return GET_SWZ(swizzle, 1) == SWIZZLE_Y;
+   case WRITEMASK_Z:
+      return GET_SWZ(swizzle, 2) == SWIZZLE_Z;
+   case WRITEMASK_W:
+      return GET_SWZ(swizzle, 3) == SWIZZLE_W;
+   case WRITEMASK_XY:
+      return (GET_SWZ(swizzle, 0) == SWIZZLE_X)
+         && (GET_SWZ(swizzle, 1) == SWIZZLE_Y);
+   case WRITEMASK_XYZ:
+      return (GET_SWZ(swizzle, 0) == SWIZZLE_X)
+         && (GET_SWZ(swizzle, 1) == SWIZZLE_Y)
+         && (GET_SWZ(swizzle, 2) == SWIZZLE_Z);
+   case WRITEMASK_XYZW:
+      return swizzle == SWIZZLE_NOOP;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Convert the given swizzle into a writemask.  In some cases this
+ * is trivial, in other cases, we'll need to also swizzle the right
+ * hand side to put components in the right places.
+ * See comment above for more info.
+ * XXX this function could be simplified and should probably be renamed.
+ * \param swizzle  the incoming swizzle
+ * \param writemaskOut  returns the writemask
+ * \param swizzleOut  swizzle to apply to the right-hand-side
+ * \return GL_FALSE for simple writemasks, GL_TRUE for non-simple
+ */
+static GLboolean
+swizzle_to_writemask(slang_assemble_ctx *A, GLuint swizzle,
+                     GLuint *writemaskOut, GLuint *swizzleOut)
+{
+   GLuint mask = 0x0, newSwizzle[4];
+   GLint i, size;
+
+   /* make new dst writemask, compute size */
+   for (i = 0; i < 4; i++) {
+      const GLuint swz = GET_SWZ(swizzle, i);
+      if (swz == SWIZZLE_NIL) {
+         /* end */
+         break;
+      }
+      assert(swz <= 3);
+
+      if (swizzle != SWIZZLE_XXXX &&
+          swizzle != SWIZZLE_YYYY &&
+          swizzle != SWIZZLE_ZZZZ &&
+          swizzle != SWIZZLE_WWWW &&
+          (mask & (1 << swz))) {
+         /* a channel can't be specified twice (ex: ".xyyz") */
+         slang_info_log_error(A->log, "Invalid writemask '%s'",
+                              _mesa_swizzle_string(swizzle, 0, 0));
+         return GL_FALSE;
+      }
+
+      mask |= (1 << swz);
+   }
+   assert(mask <= 0xf);
+   size = i;  /* number of components in mask/swizzle */
+
+   *writemaskOut = mask;
+
+   /* make new src swizzle, by inversion */
+   for (i = 0; i < 4; i++) {
+      newSwizzle[i] = i; /*identity*/
+   }
+   for (i = 0; i < size; i++) {
+      const GLuint swz = GET_SWZ(swizzle, i);
+      newSwizzle[swz] = i;
+   }
+   *swizzleOut = MAKE_SWIZZLE4(newSwizzle[0],
+                               newSwizzle[1],
+                               newSwizzle[2],
+                               newSwizzle[3]);
+
+   if (_slang_simple_writemask(mask, *swizzleOut)) {
+      if (size >= 1)
+         assert(GET_SWZ(*swizzleOut, 0) == SWIZZLE_X);
+      if (size >= 2)
+         assert(GET_SWZ(*swizzleOut, 1) == SWIZZLE_Y);
+      if (size >= 3)
+         assert(GET_SWZ(*swizzleOut, 2) == SWIZZLE_Z);
+      if (size >= 4)
+         assert(GET_SWZ(*swizzleOut, 3) == SWIZZLE_W);
+      return GL_TRUE;
+   }
+   else
+      return GL_FALSE;
+}
+
+
+#if 0 /* not used, but don't remove just yet */
+/**
+ * Recursively traverse 'oper' to produce a swizzle mask in the event
+ * of any vector subscripts and swizzle suffixes.
+ * Ex:  for "vec4 v",  "v[2].x" resolves to v.z
+ */
+static GLuint
+resolve_swizzle(const slang_operation *oper)
+{
+   if (oper->type == SLANG_OPER_FIELD) {
+      /* writemask from .xyzw suffix */
+      slang_swizzle swz;
+      if (_slang_is_swizzle((char*) oper->a_id, 4, &swz)) {
+         GLuint swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
+                                        swz.swizzle[1],
+                                        swz.swizzle[2],
+                                        swz.swizzle[3]);
+         GLuint child_swizzle = resolve_swizzle(&oper->children[0]);
+         GLuint s = _slang_swizzle_swizzle(child_swizzle, swizzle);
+         return s;
+      }
+      else
+         return SWIZZLE_XYZW;
+   }
+   else if (oper->type == SLANG_OPER_SUBSCRIPT &&
+            oper->children[1].type == SLANG_OPER_LITERAL_INT) {
+      /* writemask from [index] */
+      GLuint child_swizzle = resolve_swizzle(&oper->children[0]);
+      GLuint i = (GLuint) oper->children[1].literal[0];
+      GLuint swizzle;
+      GLuint s;
+      switch (i) {
+      case 0:
+         swizzle = SWIZZLE_XXXX;
+         break;
+      case 1:
+         swizzle = SWIZZLE_YYYY;
+         break;
+      case 2:
+         swizzle = SWIZZLE_ZZZZ;
+         break;
+      case 3:
+         swizzle = SWIZZLE_WWWW;
+         break;
+      default:
+         swizzle = SWIZZLE_XYZW;
+      }
+      s = _slang_swizzle_swizzle(child_swizzle, swizzle);
+      return s;
+   }
+   else {
+      return SWIZZLE_XYZW;
+   }
+}
+#endif
+
+
+#if 0
+/**
+ * Recursively descend through swizzle nodes to find the node's storage info.
+ */
+static slang_ir_storage *
+get_store(const slang_ir_node *n)
+{
+   if (n->Opcode == IR_SWIZZLE) {
+      return get_store(n->Children[0]);
+   }
+   return n->Store;
+}
+#endif
+
+
+/**
+ * Generate IR tree for an asm instruction/operation such as:
+ *    __asm vec4_dot __retVal.x, v1, v2;
+ */
+static slang_ir_node *
+_slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper,
+               slang_operation *dest)
+{
+   const slang_asm_info *info;
+   slang_ir_node *kids[3], *n;
+   GLuint j, firstOperand;
+
+   assert(oper->type == SLANG_OPER_ASM);
+
+   info = slang_find_asm_info((char *) oper->a_id);
+   if (!info) {
+      _mesa_problem(NULL, "undefined __asm function %s\n",
+                    (char *) oper->a_id);
+      assert(info);
+      return NULL;
+   }
+   assert(info->NumParams <= 3);
+
+   if (info->NumParams == oper->num_children) {
+      /* Storage for result is not specified.
+       * Children[0], [1], [2] are the operands.
+       */
+      firstOperand = 0;
+   }
+   else {
+      /* Storage for result (child[0]) is specified.
+       * Children[1], [2], [3] are the operands.
+       */
+      firstOperand = 1;
+   }
+
+   /* assemble child(ren) */
+   kids[0] = kids[1] = kids[2] = NULL;
+   for (j = 0; j < info->NumParams; j++) {
+      kids[j] = _slang_gen_operation(A, &oper->children[firstOperand + j]);
+      if (!kids[j])
+         return NULL;
+   }
+
+   n = new_node3(info->Opcode, kids[0], kids[1], kids[2]);
+
+   if (firstOperand) {
+      /* Setup n->Store to be a particular location.  Otherwise, storage
+       * for the result (a temporary) will be allocated later.
+       */
+      slang_operation *dest_oper;
+      slang_ir_node *n0;
+
+      dest_oper = &oper->children[0];
+
+      n0 = _slang_gen_operation(A, dest_oper);
+      if (!n0)
+         return NULL;
+
+      assert(!n->Store);
+      n->Store = n0->Store;
+
+      assert(n->Store->File != PROGRAM_UNDEFINED || n->Store->Parent);
+
+      _slang_free(n0);
+   }
+
+   return n;
+}
+
+
+#if 0
+static void
+print_funcs(struct slang_function_scope_ *scope, const char *name)
+{
+   GLuint i;
+   for (i = 0; i < scope->num_functions; i++) {
+      slang_function *f = &scope->functions[i];
+      if (!name || strcmp(name, (char*) f->header.a_name) == 0)
+          printf("  %s (%d args)\n", name, f->param_count);
+
+   }
+   if (scope->outer_scope)
+      print_funcs(scope->outer_scope, name);
+}
+#endif
+
+
+/**
+ * Find a function of the given name, taking 'numArgs' arguments.
+ * This is the function we'll try to call when there is no exact match
+ * between function parameters and call arguments.
+ *
+ * XXX we should really create a list of candidate functions and try
+ * all of them...
+ */
+static slang_function *
+_slang_find_function_by_argc(slang_function_scope *scope,
+                             const char *name, int numArgs)
+{
+   while (scope) {
+      GLuint i;
+      for (i = 0; i < scope->num_functions; i++) {
+         slang_function *f = &scope->functions[i];
+         if (strcmp(name, (char*) f->header.a_name) == 0) {
+            int haveRetValue = _slang_function_has_return_value(f);
+            if (numArgs == f->param_count - haveRetValue)
+               return f;
+         }
+      }
+      scope = scope->outer_scope;
+   }
+
+   return NULL;
+}
+
+
+static slang_function *
+_slang_find_function_by_max_argc(slang_function_scope *scope,
+                                 const char *name)
+{
+   slang_function *maxFunc = NULL;
+   GLuint maxArgs = 0;
+
+   while (scope) {
+      GLuint i;
+      for (i = 0; i < scope->num_functions; i++) {
+         slang_function *f = &scope->functions[i];
+         if (strcmp(name, (char*) f->header.a_name) == 0) {
+            if (f->param_count > maxArgs) {
+               maxArgs = f->param_count;
+               maxFunc = f;
+            }
+         }
+      }
+      scope = scope->outer_scope;
+   }
+
+   return maxFunc;
+}
+
+
+/**
+ * Generate a new slang_function which is a constructor for a user-defined
+ * struct type.
+ */
+static slang_function *
+_slang_make_struct_constructor(slang_assemble_ctx *A, slang_struct *str)
+{
+   const GLint numFields = str->fields->num_variables;
+   slang_function *fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
+
+   /* function header (name, return type) */
+   fun->header.a_name = str->a_name;
+   fun->header.type.qualifier = SLANG_QUAL_NONE;
+   fun->header.type.specifier.type = SLANG_SPEC_STRUCT;
+   fun->header.type.specifier._struct = str;
+
+   /* function parameters (= struct's fields) */
+   {
+      GLint i;
+      for (i = 0; i < numFields; i++) {
+         /*
+         printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name);
+         */
+         slang_variable *p = slang_variable_scope_grow(fun->parameters);
+         *p = *str->fields->variables[i]; /* copy the variable and type */
+         p->type.qualifier = SLANG_QUAL_CONST;
+      }
+      fun->param_count = fun->parameters->num_variables;
+   }
+
+   /* Add __retVal to params */
+   {
+      slang_variable *p = slang_variable_scope_grow(fun->parameters);
+      slang_atom a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
+      assert(a_retVal);
+      p->a_name = a_retVal;
+      p->type = fun->header.type;
+      p->type.qualifier = SLANG_QUAL_OUT;
+      fun->param_count++;
+   }
+
+   /* function body is:
+    *    block:
+    *       declare T;
+    *       T.f1 = p1;
+    *       T.f2 = p2;
+    *       ...
+    *       T.fn = pn;
+    *       return T;
+    */
+   {
+      slang_variable_scope *scope;
+      slang_variable *var;
+      GLint i;
+
+      fun->body = slang_operation_new(1);
+      fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+      fun->body->num_children = numFields + 2;
+      fun->body->children = slang_operation_new(numFields + 2);
+
+      scope = fun->body->locals;
+      scope->outer_scope = fun->parameters;
+
+      /* create local var 't' */
+      var = slang_variable_scope_grow(scope);
+      var->a_name = slang_atom_pool_atom(A->atoms, "t");
+      var->type = fun->header.type;
+
+      /* declare t */
+      {
+         slang_operation *decl;
+
+         decl = &fun->body->children[0];
+         decl->type = SLANG_OPER_VARIABLE_DECL;
+         decl->locals = _slang_variable_scope_new(scope);
+         decl->a_id = var->a_name;
+      }
+
+      /* assign params to fields of t */
+      for (i = 0; i < numFields; i++) {
+         slang_operation *assign = &fun->body->children[1 + i];
+
+         assign->type = SLANG_OPER_ASSIGN;
+         assign->locals = _slang_variable_scope_new(scope);
+         assign->num_children = 2;
+         assign->children = slang_operation_new(2);
+         
+         {
+            slang_operation *lhs = &assign->children[0];
+
+            lhs->type = SLANG_OPER_FIELD;
+            lhs->locals = _slang_variable_scope_new(scope);
+            lhs->num_children = 1;
+            lhs->children = slang_operation_new(1);
+            lhs->a_id = str->fields->variables[i]->a_name;
+
+            lhs->children[0].type = SLANG_OPER_IDENTIFIER;
+            lhs->children[0].a_id = var->a_name;
+            lhs->children[0].locals = _slang_variable_scope_new(scope);
+
+#if 0
+            lhs->children[1].num_children = 1;
+            lhs->children[1].children = slang_operation_new(1);
+            lhs->children[1].children[0].type = SLANG_OPER_IDENTIFIER;
+            lhs->children[1].children[0].a_id = str->fields->variables[i]->a_name;
+            lhs->children[1].children->locals = _slang_variable_scope_new(scope);
+#endif
+         }
+
+         {
+            slang_operation *rhs = &assign->children[1];
+
+            rhs->type = SLANG_OPER_IDENTIFIER;
+            rhs->locals = _slang_variable_scope_new(scope);
+            rhs->a_id = str->fields->variables[i]->a_name;
+         }         
+      }
+
+      /* return t; */
+      {
+         slang_operation *ret = &fun->body->children[numFields + 1];
+
+         ret->type = SLANG_OPER_RETURN;
+         ret->locals = _slang_variable_scope_new(scope);
+         ret->num_children = 1;
+         ret->children = slang_operation_new(1);
+         ret->children[0].type = SLANG_OPER_IDENTIFIER;
+         ret->children[0].a_id = var->a_name;
+         ret->children[0].locals = _slang_variable_scope_new(scope);
+      }
+   }
+   /*
+   slang_print_function(fun, 1);
+   */
+   return fun;
+}
+
+
+/**
+ * Find/create a function (constructor) for the given structure name.
+ */
+static slang_function *
+_slang_locate_struct_constructor(slang_assemble_ctx *A, const char *name)
+{
+   unsigned int i;
+   for (i = 0; i < A->space.structs->num_structs; i++) {
+      slang_struct *str = &A->space.structs->structs[i];
+      if (strcmp(name, (const char *) str->a_name) == 0) {
+         /* found a structure type that matches the function name */
+         if (!str->constructor) {
+            /* create the constructor function now */
+            str->constructor = _slang_make_struct_constructor(A, str);
+         }
+         return str->constructor;
+      }
+   }
+   return NULL;
+}
+
+
+/**
+ * Generate a new slang_function to satisfy a call to an array constructor.
+ * Ex:  float[3](1., 2., 3.)
+ */
+static slang_function *
+_slang_make_array_constructor(slang_assemble_ctx *A, slang_operation *oper)
+{
+   slang_type_specifier_type baseType;
+   slang_function *fun;
+   int num_elements;
+
+   fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
+   if (!fun)
+      return NULL;
+
+   baseType = slang_type_specifier_type_from_string((char *) oper->a_id);
+
+   num_elements = oper->num_children;
+
+   /* function header, return type */
+   {
+      fun->header.a_name = oper->a_id;
+      fun->header.type.qualifier = SLANG_QUAL_NONE;
+      fun->header.type.specifier.type = SLANG_SPEC_ARRAY;
+      fun->header.type.specifier._array =
+         slang_type_specifier_new(baseType, NULL, NULL);
+      fun->header.type.array_len = num_elements;
+   }
+
+   /* function parameters (= number of elements) */
+   {
+      GLint i;
+      for (i = 0; i < num_elements; i++) {
+         /*
+         printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name);
+         */
+         slang_variable *p = slang_variable_scope_grow(fun->parameters);
+         char name[10];
+         _mesa_snprintf(name, sizeof(name), "p%d", i);
+         p->a_name = slang_atom_pool_atom(A->atoms, name);
+         p->type.qualifier = SLANG_QUAL_CONST;
+         p->type.specifier.type = baseType;
+      }
+      fun->param_count = fun->parameters->num_variables;
+   }
+
+   /* Add __retVal to params */
+   {
+      slang_variable *p = slang_variable_scope_grow(fun->parameters);
+      slang_atom a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
+      assert(a_retVal);
+      p->a_name = a_retVal;
+      p->type = fun->header.type;
+      p->type.qualifier = SLANG_QUAL_OUT;
+      p->type.specifier.type = baseType;
+      fun->param_count++;
+   }
+
+   /* function body is:
+    *    block:
+    *       declare T;
+    *       T[0] = p0;
+    *       T[1] = p1;
+    *       ...
+    *       T[n] = pn;
+    *       return T;
+    */
+   {
+      slang_variable_scope *scope;
+      slang_variable *var;
+      GLint i;
+
+      fun->body = slang_operation_new(1);
+      fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+      fun->body->num_children = num_elements + 2;
+      fun->body->children = slang_operation_new(num_elements + 2);
+
+      scope = fun->body->locals;
+      scope->outer_scope = fun->parameters;
+
+      /* create local var 't' */
+      var = slang_variable_scope_grow(scope);
+      var->a_name = slang_atom_pool_atom(A->atoms, "ttt");
+      var->type = fun->header.type;/*XXX copy*/
+
+      /* declare t */
+      {
+         slang_operation *decl;
+
+         decl = &fun->body->children[0];
+         decl->type = SLANG_OPER_VARIABLE_DECL;
+         decl->locals = _slang_variable_scope_new(scope);
+         decl->a_id = var->a_name;
+      }
+
+      /* assign params to elements of t */
+      for (i = 0; i < num_elements; i++) {
+         slang_operation *assign = &fun->body->children[1 + i];
+
+         assign->type = SLANG_OPER_ASSIGN;
+         assign->locals = _slang_variable_scope_new(scope);
+         assign->num_children = 2;
+         assign->children = slang_operation_new(2);
+         
+         {
+            slang_operation *lhs = &assign->children[0];
+
+            lhs->type = SLANG_OPER_SUBSCRIPT;
+            lhs->locals = _slang_variable_scope_new(scope);
+            lhs->num_children = 2;
+            lhs->children = slang_operation_new(2);
+            lhs->children[0].type = SLANG_OPER_IDENTIFIER;
+            lhs->children[0].a_id = var->a_name;
+            lhs->children[0].locals = _slang_variable_scope_new(scope);
+
+            lhs->children[1].type = SLANG_OPER_LITERAL_INT;
+            lhs->children[1].literal[0] = (GLfloat) i;
+         }
+
+         {
+            slang_operation *rhs = &assign->children[1];
+
+            rhs->type = SLANG_OPER_IDENTIFIER;
+            rhs->locals = _slang_variable_scope_new(scope);
+            rhs->a_id = fun->parameters->variables[i]->a_name;
+         }         
+      }
+
+      /* return t; */
+      {
+         slang_operation *ret = &fun->body->children[num_elements + 1];
+
+         ret->type = SLANG_OPER_RETURN;
+         ret->locals = _slang_variable_scope_new(scope);
+         ret->num_children = 1;
+         ret->children = slang_operation_new(1);
+         ret->children[0].type = SLANG_OPER_IDENTIFIER;
+         ret->children[0].a_id = var->a_name;
+         ret->children[0].locals = _slang_variable_scope_new(scope);
+      }
+   }
+
+   /*
+   slang_print_function(fun, 1);
+   */
+
+   return fun;
+}
+
+
+static GLboolean
+_slang_is_vec_mat_type(const char *name)
+{
+   static const char *vecmat_types[] = {
+      "float", "int", "bool",
+      "vec2", "vec3", "vec4",
+      "ivec2", "ivec3", "ivec4",
+      "bvec2", "bvec3", "bvec4",
+      "mat2", "mat3", "mat4",
+      "mat2x3", "mat2x4", "mat3x2", "mat3x4", "mat4x2", "mat4x3",
+      NULL
+   };
+   int i;
+   for (i = 0; vecmat_types[i]; i++)
+      if (strcmp(name, vecmat_types[i]) == 0)
+         return GL_TRUE;
+   return GL_FALSE;
+}
+
+
+/**
+ * Assemble a function call, given a particular function name.
+ * \param name  the function's name (operators like '*' are possible).
+ */
+static slang_ir_node *
+_slang_gen_function_call_name(slang_assemble_ctx *A, const char *name,
+                              slang_operation *oper, slang_operation *dest)
+{
+   slang_operation *params = oper->children;
+   const GLuint param_count = oper->num_children;
+   slang_atom atom;
+   slang_function *fun;
+   slang_ir_node *n;
+
+   atom = slang_atom_pool_atom(A->atoms, name);
+   if (atom == SLANG_ATOM_NULL)
+      return NULL;
+
+   if (oper->array_constructor) {
+      /* this needs special handling */
+      fun = _slang_make_array_constructor(A, oper);
+   }
+   else {
+      /* Try to find function by name and exact argument type matching */
+      GLboolean error = GL_FALSE;
+      fun = _slang_function_locate(A->space.funcs, atom, params, param_count,
+                                   &A->space, A->atoms, A->log, &error);
+      if (error) {
+         slang_info_log_error(A->log,
+                              "Function '%s' not found (check argument types)",
+                              name);
+         return NULL;
+      }
+   }
+
+   if (!fun) {
+      /* Next, try locating a constructor function for a user-defined type */
+      fun = _slang_locate_struct_constructor(A, name);
+   }
+
+   /*
+    * At this point, some heuristics are used to try to find a function
+    * that matches the calling signature by means of casting or "unrolling"
+    * of constructors.
+    */
+
+   if (!fun && _slang_is_vec_mat_type(name)) {
+      /* Next, if this call looks like a vec() or mat() constructor call,
+       * try "unwinding" the args to satisfy a constructor.
+       */
+      fun = _slang_find_function_by_max_argc(A->space.funcs, name);
+      if (fun) {
+         if (!_slang_adapt_call(oper, fun, &A->space, A->atoms, A->log)) {
+            slang_info_log_error(A->log,
+                                 "Function '%s' not found (check argument types)",
+                                 name);
+            return NULL;
+         }
+      }
+   }
+
+   if (!fun && _slang_is_vec_mat_type(name)) {
+      /* Next, try casting args to the types of the formal parameters */
+      int numArgs = oper->num_children;
+      fun = _slang_find_function_by_argc(A->space.funcs, name, numArgs);
+      if (!fun || !_slang_cast_func_params(oper, fun, &A->space, A->atoms, A->log)) {
+         slang_info_log_error(A->log,
+                              "Function '%s' not found (check argument types)",
+                              name);
+         return NULL;
+      }
+      assert(fun);
+   }
+
+   if (!fun) {
+      slang_info_log_error(A->log,
+                           "Function '%s' not found (check argument types)",
+                           name);
+      return NULL;
+   }
+
+   if (!fun->body) {
+      /* The function body may be in another compilation unit.
+       * We'll try concatenating the shaders and recompile at link time.
+       */
+      A->UnresolvedRefs = GL_TRUE;
+      return new_node1(IR_NOP, NULL);
+   }
+
+   /* type checking to be sure function's return type matches 'dest' type */
+   if (dest) {
+      slang_typeinfo t0;
+
+      slang_typeinfo_construct(&t0);
+      typeof_operation(A, dest, &t0);
+
+      if (!slang_type_specifier_equal(&t0.spec, &fun->header.type.specifier)) {
+         slang_info_log_error(A->log,
+                              "Incompatible type returned by call to '%s'",
+                              name);
+         return NULL;
+      }
+   }
+
+   n = _slang_gen_function_call(A, fun, oper, dest);
+
+   if (n && !n->Store && !dest
+       && fun->header.type.specifier.type != SLANG_SPEC_VOID) {
+      /* setup n->Store for the result of the function call */
+      GLint size = _slang_sizeof_type_specifier(&fun->header.type.specifier);
+      n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, size);
+      /*printf("Alloc storage for function result, size %d \n", size);*/
+   }
+
+   if (oper->array_constructor) {
+      /* free the temporary array constructor function now */
+      slang_function_destruct(fun);
+   }
+
+   return n;
+}
+
+
+static slang_ir_node *
+_slang_gen_method_call(slang_assemble_ctx *A, slang_operation *oper)
+{
+   slang_atom *a_length = slang_atom_pool_atom(A->atoms, "length");
+   slang_ir_node *n;
+   slang_variable *var;
+
+   /* NOTE: In GLSL 1.20, there's only one kind of method
+    * call: array.length().  Anything else is an error.
+    */
+   if (oper->a_id != a_length) {
+      slang_info_log_error(A->log,
+                           "Undefined method call '%s'", (char *) oper->a_id);
+      return NULL;
+   }
+
+   /* length() takes no arguments */
+   if (oper->num_children > 0) {
+      slang_info_log_error(A->log, "Invalid arguments to length() method");
+      return NULL;
+   }
+
+   /* lookup the object/variable */
+   var = _slang_variable_locate(oper->locals, oper->a_obj, GL_TRUE);
+   if (!var || var->type.specifier.type != SLANG_SPEC_ARRAY) {
+      slang_info_log_error(A->log,
+                           "Undefined object '%s'", (char *) oper->a_obj);
+      return NULL;
+   }
+
+   /* Create a float/literal IR node encoding the array length */
+   n = new_node0(IR_FLOAT);
+   if (n) {
+      n->Value[0] = (float) _slang_array_length(var);
+      n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, 1);
+   }
+   return n;
+}
+
+
+static GLboolean
+_slang_is_constant_cond(const slang_operation *oper, GLboolean *value)
+{
+   if (oper->type == SLANG_OPER_LITERAL_FLOAT ||
+       oper->type == SLANG_OPER_LITERAL_INT ||
+       oper->type == SLANG_OPER_LITERAL_BOOL) {
+      if (oper->literal[0])
+         *value = GL_TRUE;
+      else
+         *value = GL_FALSE;
+      return GL_TRUE;
+   }
+   else if (oper->type == SLANG_OPER_EXPRESSION &&
+            oper->num_children == 1) {
+      return _slang_is_constant_cond(&oper->children[0], value);
+   }
+   return GL_FALSE;
+}
+
+
+/**
+ * Test if an operation is a scalar or boolean.
+ */
+static GLboolean
+_slang_is_scalar_or_boolean(slang_assemble_ctx *A, slang_operation *oper)
+{
+   slang_typeinfo type;
+   GLint size;
+
+   slang_typeinfo_construct(&type);
+   typeof_operation(A, oper, &type);
+   size = _slang_sizeof_type_specifier(&type.spec);
+   slang_typeinfo_destruct(&type);
+   return size == 1;
+}
+
+
+/**
+ * Test if an operation is boolean.
+ */
+static GLboolean
+_slang_is_boolean(slang_assemble_ctx *A, slang_operation *oper)
+{
+   slang_typeinfo type;
+   GLboolean isBool;
+
+   slang_typeinfo_construct(&type);
+   typeof_operation(A, oper, &type);
+   isBool = (type.spec.type == SLANG_SPEC_BOOL);
+   slang_typeinfo_destruct(&type);
+   return isBool;
+}
+
+
+/**
+ * Check if a loop contains a 'continue' statement.
+ * Stop looking if we find a nested loop.
+ */
+static GLboolean
+_slang_loop_contains_continue(const slang_operation *oper)
+{
+   switch (oper->type) {
+   case SLANG_OPER_CONTINUE:
+      return GL_TRUE;
+   case SLANG_OPER_FOR:
+   case SLANG_OPER_DO:
+   case SLANG_OPER_WHILE:
+      /* stop upon finding a nested loop */
+      return GL_FALSE;
+   default:
+       /* recurse */
+      {
+         GLuint i;
+         for (i = 0; i < oper->num_children; i++) {
+            const slang_operation *child = slang_oper_child_const(oper, i);
+            if (_slang_loop_contains_continue(child))
+               return GL_TRUE;
+         }
+      }
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Check if a loop contains a 'continue' or 'break' statement.
+ * Stop looking if we find a nested loop.
+ */
+static GLboolean
+_slang_loop_contains_continue_or_break(const slang_operation *oper)
+{
+   switch (oper->type) {
+   case SLANG_OPER_CONTINUE:
+   case SLANG_OPER_BREAK:
+      return GL_TRUE;
+   case SLANG_OPER_FOR:
+   case SLANG_OPER_DO:
+   case SLANG_OPER_WHILE:
+      /* stop upon finding a nested loop */
+      return GL_FALSE;
+   default:
+       /* recurse */
+      {
+         GLuint i;
+         for (i = 0; i < oper->num_children; i++) {
+            const slang_operation *child = slang_oper_child_const(oper, i);
+            if (_slang_loop_contains_continue_or_break(child))
+               return GL_TRUE;
+         }
+      }
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Replace 'break' and 'continue' statements inside a do and while loops.
+ * This is a recursive helper function used by
+ * _slang_gen_do/while_without_continue().
+ */
+static void
+replace_break_and_cont(slang_assemble_ctx *A, slang_operation *oper)
+{
+   switch (oper->type) {
+   case SLANG_OPER_BREAK:
+      /* replace 'break' with "_notBreakFlag = false; break" */
+      {
+         slang_operation *block = oper;
+         block->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+         slang_operation_add_children(block, 2);
+         {
+            slang_operation *assign = slang_oper_child(block, 0);
+            assign->type = SLANG_OPER_ASSIGN;
+            slang_operation_add_children(assign, 2);
+            {
+               slang_operation *lhs = slang_oper_child(assign, 0);
+               slang_operation_identifier(lhs, A, "_notBreakFlag");
+            }
+            {
+               slang_operation *rhs = slang_oper_child(assign, 1);
+               slang_operation_literal_bool(rhs, GL_FALSE);
+            }
+         }
+         {
+            slang_operation *brk = slang_oper_child(block, 1);
+            brk->type = SLANG_OPER_BREAK;
+            assert(!brk->children);
+         }
+      }
+      break;
+   case SLANG_OPER_CONTINUE:
+      /* convert continue into a break */
+      oper->type = SLANG_OPER_BREAK;
+      break;
+   case SLANG_OPER_FOR:
+   case SLANG_OPER_DO:
+   case SLANG_OPER_WHILE:
+      /* stop upon finding a nested loop */
+      break;
+   default:
+      /* recurse */
+      {
+         GLuint i;
+         for (i = 0; i < oper->num_children; i++) {
+            replace_break_and_cont(A, slang_oper_child(oper, i));
+         }
+      }
+   }
+}
+
+
+/**
+ * Transform a while-loop so that continue statements are converted to breaks.
+ * Then do normal IR code generation.
+ *
+ * Before:
+ * 
+ * while (LOOPCOND) {
+ *    A;
+ *    if (IFCOND)
+ *       continue;
+ *    B;
+ *    break;
+ *    C;
+ * }
+ * 
+ * After:
+ * 
+ * {
+ *    bool _notBreakFlag = 1;
+ *    while (_notBreakFlag && LOOPCOND) {
+ *       do {
+ *          A;
+ *          if (IFCOND) {
+ *             break;  // was continue
+ *          }
+ *          B;
+ *          _notBreakFlag = 0; // was
+ *          break;             // break
+ *          C;
+ *       } while (0)
+ *    }
+ * }
+ */
+static slang_ir_node *
+_slang_gen_while_without_continue(slang_assemble_ctx *A, slang_operation *oper)
+{
+   slang_operation *top;
+   slang_operation *innerBody;
+
+   assert(oper->type == SLANG_OPER_WHILE);
+
+   top = slang_operation_new(1);
+   top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+   top->locals->outer_scope = oper->locals->outer_scope;
+   slang_operation_add_children(top, 2);
+
+   /* declare: bool _notBreakFlag = true */
+   {
+      slang_operation *condDecl = slang_oper_child(top, 0);
+      slang_generate_declaration(A, top->locals, condDecl,
+                                 SLANG_SPEC_BOOL, "_notBreakFlag", GL_TRUE);
+   }
+
+   /* build outer while-loop:  while (_notBreakFlag && LOOPCOND) { ... } */
+   {
+      slang_operation *outerWhile = slang_oper_child(top, 1);
+      outerWhile->type = SLANG_OPER_WHILE;
+      slang_operation_add_children(outerWhile, 2);
+
+      /* _notBreakFlag && LOOPCOND */
+      {
+         slang_operation *cond = slang_oper_child(outerWhile, 0);
+         cond->type = SLANG_OPER_LOGICALAND;
+         slang_operation_add_children(cond, 2);
+         {
+            slang_operation *notBreak = slang_oper_child(cond, 0);
+            slang_operation_identifier(notBreak, A, "_notBreakFlag");
+         }
+         {
+            slang_operation *origCond = slang_oper_child(cond, 1);
+            slang_operation_copy(origCond, slang_oper_child(oper, 0));
+         }
+      }
+
+      /* inner loop */
+      {
+         slang_operation *innerDo = slang_oper_child(outerWhile, 1);
+         innerDo->type = SLANG_OPER_DO;
+         slang_operation_add_children(innerDo, 2);
+
+         /* copy original do-loop body into inner do-loop's body */
+         innerBody = slang_oper_child(innerDo, 0);
+         slang_operation_copy(innerBody, slang_oper_child(oper, 1));
+         innerBody->locals->outer_scope = innerDo->locals;
+
+         /* inner do-loop's condition is constant/false */
+         {
+            slang_operation *constFalse = slang_oper_child(innerDo, 1);
+            slang_operation_literal_bool(constFalse, GL_FALSE);
+         }
+      }
+   }
+
+   /* Finally, in innerBody,
+    *   replace "break" with "_notBreakFlag = 0; break"
+    *   replace "continue" with "break"
+    */
+   replace_break_and_cont(A, innerBody);
+
+   /*slang_print_tree(top, 0);*/
+
+   return _slang_gen_operation(A, top);
+
+   return NULL;
+}
+
+
+/**
+ * Generate loop code using high-level IR_LOOP instruction
+ */
+static slang_ir_node *
+_slang_gen_while(slang_assemble_ctx * A, slang_operation *oper)
+{
+   /*
+    * LOOP:
+    *    BREAK if !expr (child[0])
+    *    body code (child[1])
+    */
+   slang_ir_node *loop, *breakIf, *body;
+   GLboolean isConst, constTrue = GL_FALSE;
+
+   if (!A->EmitContReturn) {
+      /* We don't want to emit CONT instructions.  If this while-loop has
+       * a continue, translate it away.
+       */
+      if (_slang_loop_contains_continue(slang_oper_child(oper, 1))) {
+         return _slang_gen_while_without_continue(A, oper);
+      }
+   }
+
+   /* type-check expression */
+   if (!_slang_is_boolean(A, &oper->children[0])) {
+      slang_info_log_error(A->log, "scalar/boolean expression expected for 'while'");
+      return NULL;
+   }
+
+   /* Check if loop condition is a constant */
+   isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
+
+   if (isConst && !constTrue) {
+      /* loop is never executed! */
+      return new_node0(IR_NOP);
+   }
+
+   /* Begin new loop */
+   loop = new_loop(NULL);
+
+   /* save loop state */
+   push_loop(A, oper, loop);
+
+   if (isConst && constTrue) {
+      /* while(nonzero constant), no conditional break */
+      breakIf = NULL;
+   }
+   else {
+      slang_ir_node *cond
+         = new_cond(new_not(_slang_gen_operation(A, &oper->children[0])));
+      breakIf = new_break_if_true(A, cond);
+   }
+   body = _slang_gen_operation(A, &oper->children[1]);
+   loop->Children[0] = new_seq(breakIf, body);
+
+   /* Do infinite loop detection */
+   /* loop->List is head of linked list of break/continue nodes */
+   if (!loop->List && isConst && constTrue) {
+      /* infinite loop detected */
+      pop_loop(A);
+      slang_info_log_error(A->log, "Infinite loop detected!");
+      return NULL;
+   }
+
+   /* restore loop state */
+   pop_loop(A);
+
+   return loop;
+}
+
+
+/**
+ * Transform a do-while-loop so that continue statements are converted to breaks.
+ * Then do normal IR code generation.
+ *
+ * Before:
+ * 
+ * do {
+ *    A;
+ *    if (IFCOND)
+ *       continue;
+ *    B;
+ *    break;
+ *    C;
+ * } while (LOOPCOND);
+ * 
+ * After:
+ * 
+ * {
+ *    bool _notBreakFlag = 1;
+ *    do {
+ *       do {
+ *          A;
+ *          if (IFCOND) {
+ *             break;  // was continue
+ *          }
+ *          B;
+ *          _notBreakFlag = 0; // was
+ *          break;             // break
+ *          C;
+ *       } while (0)
+ *    } while (_notBreakFlag && LOOPCOND);
+ * }
+ */
+static slang_ir_node *
+_slang_gen_do_without_continue(slang_assemble_ctx *A, slang_operation *oper)
+{
+   slang_operation *top;
+   slang_operation *innerBody;
+
+   assert(oper->type == SLANG_OPER_DO);
+
+   top = slang_operation_new(1);
+   top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+   top->locals->outer_scope = oper->locals->outer_scope;
+   slang_operation_add_children(top, 2);
+
+   /* declare: bool _notBreakFlag = true */
+   {
+      slang_operation *condDecl = slang_oper_child(top, 0);
+      slang_generate_declaration(A, top->locals, condDecl,
+                                 SLANG_SPEC_BOOL, "_notBreakFlag", GL_TRUE);
+   }
+
+   /* build outer do-loop:  do { ... } while (_notBreakFlag && LOOPCOND) */
+   {
+      slang_operation *outerDo = slang_oper_child(top, 1);
+      outerDo->type = SLANG_OPER_DO;
+      slang_operation_add_children(outerDo, 2);
+
+      /* inner do-loop */
+      {
+         slang_operation *innerDo = slang_oper_child(outerDo, 0);
+         innerDo->type = SLANG_OPER_DO;
+         slang_operation_add_children(innerDo, 2);
+
+         /* copy original do-loop body into inner do-loop's body */
+         innerBody = slang_oper_child(innerDo, 0);
+         slang_operation_copy(innerBody, slang_oper_child(oper, 0));
+         innerBody->locals->outer_scope = innerDo->locals;
+
+         /* inner do-loop's condition is constant/false */
+         {
+            slang_operation *constFalse = slang_oper_child(innerDo, 1);
+            slang_operation_literal_bool(constFalse, GL_FALSE);
+         }
+      }
+
+      /* _notBreakFlag && LOOPCOND */
+      {
+         slang_operation *cond = slang_oper_child(outerDo, 1);
+         cond->type = SLANG_OPER_LOGICALAND;
+         slang_operation_add_children(cond, 2);
+         {
+            slang_operation *notBreak = slang_oper_child(cond, 0);
+            slang_operation_identifier(notBreak, A, "_notBreakFlag");
+         }
+         {
+            slang_operation *origCond = slang_oper_child(cond, 1);
+            slang_operation_copy(origCond, slang_oper_child(oper, 1));
+         }
+      }
+   }
+
+   /* Finally, in innerBody,
+    *   replace "break" with "_notBreakFlag = 0; break"
+    *   replace "continue" with "break"
+    */
+   replace_break_and_cont(A, innerBody);
+
+   /*slang_print_tree(top, 0);*/
+
+   return _slang_gen_operation(A, top);
+}
+
+
+/**
+ * Generate IR tree for a do-while loop using high-level LOOP, IF instructions.
+ */
+static slang_ir_node *
+_slang_gen_do(slang_assemble_ctx * A, slang_operation *oper)
+{
+   /*
+    * LOOP:
+    *    body code (child[0])
+    *    tail code:
+    *       BREAK if !expr (child[1])
+    */
+   slang_ir_node *loop;
+   GLboolean isConst, constTrue;
+
+   if (!A->EmitContReturn) {
+      /* We don't want to emit CONT instructions.  If this do-loop has
+       * a continue, translate it away.
+       */
+      if (_slang_loop_contains_continue(slang_oper_child(oper, 0))) {
+         return _slang_gen_do_without_continue(A, oper);
+      }
+   }
+
+   /* type-check expression */
+   if (!_slang_is_boolean(A, &oper->children[1])) {
+      slang_info_log_error(A->log, "scalar/boolean expression expected for 'do/while'");
+      return NULL;
+   }
+
+   loop = new_loop(NULL);
+
+   /* save loop state */
+   push_loop(A, oper, loop);
+
+   /* loop body: */
+   loop->Children[0] = _slang_gen_operation(A, &oper->children[0]);
+
+   /* Check if loop condition is a constant */
+   isConst = _slang_is_constant_cond(&oper->children[1], &constTrue);
+   if (isConst && constTrue) {
+      /* do { } while(1)   ==> no conditional break */
+      loop->Children[1] = NULL; /* no tail code */
+   }
+   else {
+      slang_ir_node *cond
+         = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
+      loop->Children[1] = new_break_if_true(A, cond);
+   }
+
+   /* XXX we should do infinite loop detection, as above */
+
+   /* restore loop state */
+   pop_loop(A);
+
+   return loop;
+}
+
+
+/**
+ * Recursively count the number of operations rooted at 'oper'.
+ * This gives some kind of indication of the size/complexity of an operation.
+ */
+static GLuint
+sizeof_operation(const slang_operation *oper)
+{
+   if (oper) {
+      GLuint count = 1; /* me */
+      GLuint i;
+      for (i = 0; i < oper->num_children; i++) {
+         count += sizeof_operation(&oper->children[i]);
+      }
+      return count;
+   }
+   else {
+      return 0;
+   }
+}
+
+
+/**
+ * Determine if a for-loop can be unrolled.
+ * At this time, only a rather narrow class of for loops can be unrolled.
+ * See code for details.
+ * When a loop can't be unrolled because it's too large we'll emit a
+ * message to the log.
+ */
+static GLboolean
+_slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
+{
+   GLuint bodySize;
+   GLint start, end;
+   const char *varName;
+   slang_atom varId;
+
+   if (oper->type != SLANG_OPER_FOR)
+      return GL_FALSE;
+
+   assert(oper->num_children == 4);
+
+   if (_slang_loop_contains_continue_or_break(slang_oper_child_const(oper, 3)))
+      return GL_FALSE;
+
+   /* children[0] must be either "int i=constant" or "i=constant" */
+   if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
+      slang_variable *var;
+
+      if (oper->children[0].children[0].type != SLANG_OPER_VARIABLE_DECL)
+         return GL_FALSE;
+
+      varId = oper->children[0].children[0].a_id;
+
+      var = _slang_variable_locate(oper->children[0].children[0].locals,
+                                   varId, GL_TRUE);
+      if (!var)
+         return GL_FALSE;
+      if (!var->initializer)
+         return GL_FALSE;
+      if (var->initializer->type != SLANG_OPER_LITERAL_INT)
+         return GL_FALSE;
+      start = (GLint) var->initializer->literal[0];
+   }
+   else if (oper->children[0].type == SLANG_OPER_EXPRESSION) {
+      if (oper->children[0].children[0].type != SLANG_OPER_ASSIGN)
+         return GL_FALSE;
+      if (oper->children[0].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
+         return GL_FALSE;
+      if (oper->children[0].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
+         return GL_FALSE;
+
+      varId = oper->children[0].children[0].children[0].a_id;
+
+      start = (GLint) oper->children[0].children[0].children[1].literal[0];
+   }
+   else {
+      return GL_FALSE;
+   }
+
+   /* children[1] must be "i<constant" */
+   if (oper->children[1].type != SLANG_OPER_EXPRESSION)
+      return GL_FALSE;
+   if (oper->children[1].children[0].type != SLANG_OPER_LESS)
+      return GL_FALSE;
+   if (oper->children[1].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
+      return GL_FALSE;
+   if (oper->children[1].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
+      return GL_FALSE;
+
+   end = (GLint) oper->children[1].children[0].children[1].literal[0];
+
+   /* children[2] must be "i++" or "++i" */
+   if (oper->children[2].type != SLANG_OPER_POSTINCREMENT &&
+       oper->children[2].type != SLANG_OPER_PREINCREMENT)
+      return GL_FALSE;
+   if (oper->children[2].children[0].type != SLANG_OPER_IDENTIFIER)
+      return GL_FALSE;
+
+   /* make sure the same variable name is used in all places */
+   if ((oper->children[1].children[0].children[0].a_id != varId) ||
+       (oper->children[2].children[0].a_id != varId))
+      return GL_FALSE;
+
+   varName = (const char *) varId;
+
+   /* children[3], the loop body, can't be too large */
+   bodySize = sizeof_operation(&oper->children[3]);
+   if (bodySize > MAX_FOR_LOOP_UNROLL_BODY_SIZE) {
+      slang_info_log_print(A->log,
+                           "Note: 'for (%s ... )' body is too large/complex"
+                           " to unroll",
+                           varName);
+      return GL_FALSE;
+   }
+
+   if (start >= end)
+      return GL_FALSE; /* degenerate case */
+
+   if ((GLuint)(end - start) > MAX_FOR_LOOP_UNROLL_ITERATIONS) {
+      slang_info_log_print(A->log,
+                           "Note: 'for (%s=%d; %s<%d; ++%s)' is too"
+                           " many iterations to unroll",
+                           varName, start, varName, end, varName);
+      return GL_FALSE;
+   }
+
+   if ((end - start) * bodySize > MAX_FOR_LOOP_UNROLL_COMPLEXITY) {
+      slang_info_log_print(A->log,
+                           "Note: 'for (%s=%d; %s<%d; ++%s)' will generate"
+                           " too much code to unroll",
+                           varName, start, varName, end, varName);
+      return GL_FALSE;
+   }
+
+   return GL_TRUE; /* we can unroll the loop */
+}
+
+
+/**
+ * Unroll a for-loop.
+ * First we determine the number of iterations to unroll.
+ * Then for each iteration:
+ *   make a copy of the loop body
+ *   replace instances of the loop variable with the current iteration value
+ *   generate IR code for the body
+ * \return pointer to generated IR code or NULL if error, out of memory, etc.
+ */
+static slang_ir_node *
+_slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
+{
+   GLint start, end, iter;
+   slang_ir_node *n, *root = NULL;
+   slang_atom varId;
+
+   if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
+      /* for (int i=0; ... */
+      slang_variable *var;
+
+      varId = oper->children[0].children[0].a_id;
+      var = _slang_variable_locate(oper->children[0].children[0].locals,
+                                   varId, GL_TRUE);
+      assert(var);
+      start = (GLint) var->initializer->literal[0];
+   }
+   else {
+      /* for (i=0; ... */
+      varId = oper->children[0].children[0].children[0].a_id;
+      start = (GLint) oper->children[0].children[0].children[1].literal[0];
+   }
+
+   end = (GLint) oper->children[1].children[0].children[1].literal[0];
+
+   for (iter = start; iter < end; iter++) {
+      slang_operation *body;
+
+      /* make a copy of the loop body */
+      body = slang_operation_new(1);
+      if (!body)
+         return NULL;
+
+      if (!slang_operation_copy(body, &oper->children[3]))
+         return NULL;
+
+      /* in body, replace instances of 'varId' with literal 'iter' */
+      {
+         slang_variable *oldVar;
+         slang_operation *newOper;
+
+         oldVar = _slang_variable_locate(oper->locals, varId, GL_TRUE);
+         if (!oldVar) {
+            /* undeclared loop variable */
+            slang_operation_delete(body);
+            return NULL;
+         }
+
+         newOper = slang_operation_new(1);
+         newOper->type = SLANG_OPER_LITERAL_INT;
+         newOper->literal_size = 1;
+         newOper->literal[0] = (GLfloat) iter;
+
+         /* replace instances of the loop variable with newOper */
+         slang_substitute(A, body, 1, &oldVar, &newOper, GL_FALSE);
+      }
+
+      /* do IR codegen for body */
+      n = _slang_gen_operation(A, body);
+      if (!n)
+         return NULL;
+
+      root = new_seq(root, n);
+
+      slang_operation_delete(body);
+   }
+
+   return root;
+}
+
+
+/**
+ * Replace 'continue' statement with 'break' inside a for-loop.
+ * This is a recursive helper function used by _slang_gen_for_without_continue().
+ */
+static void
+replace_continue_with_break(slang_assemble_ctx *A, slang_operation *oper)
+{
+   switch (oper->type) {
+   case SLANG_OPER_CONTINUE:
+      oper->type = SLANG_OPER_BREAK;
+      break;
+   case SLANG_OPER_FOR:
+   case SLANG_OPER_DO:
+   case SLANG_OPER_WHILE:
+      /* stop upon finding a nested loop */
+      break;
+   default:
+      /* recurse */
+      {
+         GLuint i;
+         for (i = 0; i < oper->num_children; i++) {
+            replace_continue_with_break(A, slang_oper_child(oper, i));
+         }
+      }
+   }
+}
+
+
+/**
+ * Transform a for-loop so that continue statements are converted to breaks.
+ * Then do normal IR code generation.
+ *
+ * Before:
+ * 
+ * for (INIT; LOOPCOND; INCR) {
+ *    A;
+ *    if (IFCOND) {
+ *       continue;
+ *    }
+ *    B;
+ * }
+ * 
+ * After:
+ * 
+ * {
+ *    bool _condFlag = 1;
+ *    for (INIT; _condFlag; ) {
+ *       for ( ; _condFlag = LOOPCOND; INCR) {
+ *          A;
+ *          if (IFCOND) {
+ *             break;
+ *          }
+ *          B;
+ *       }
+ *       if (_condFlag)
+ *          INCR;
+ *    }
+ * }
+ */
+static slang_ir_node *
+_slang_gen_for_without_continue(slang_assemble_ctx *A, slang_operation *oper)
+{
+   slang_operation *top;
+   slang_operation *outerFor, *innerFor, *init, *cond, *incr;
+   slang_operation *lhs, *rhs;
+
+   assert(oper->type == SLANG_OPER_FOR);
+
+   top = slang_operation_new(1);
+   top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+   top->locals->outer_scope = oper->locals->outer_scope;
+   slang_operation_add_children(top, 2);
+
+   /* declare: bool _condFlag = true */
+   {
+      slang_operation *condDecl = slang_oper_child(top, 0);
+      slang_generate_declaration(A, top->locals, condDecl,
+                                 SLANG_SPEC_BOOL, "_condFlag", GL_TRUE);
+   }
+
+   /* build outer loop:  for (INIT; _condFlag; ) { */
+   outerFor = slang_oper_child(top, 1);
+   outerFor->type = SLANG_OPER_FOR;
+   slang_operation_add_children(outerFor, 4);
+
+   init = slang_oper_child(outerFor, 0);
+   slang_operation_copy(init, slang_oper_child(oper, 0));
+
+   cond = slang_oper_child(outerFor, 1);
+   cond->type = SLANG_OPER_IDENTIFIER;
+   cond->a_id = slang_atom_pool_atom(A->atoms, "_condFlag");
+
+   incr = slang_oper_child(outerFor, 2);
+   incr->type = SLANG_OPER_VOID;
+
+   /* body of the outer loop */
+   {
+      slang_operation *block = slang_oper_child(outerFor, 3);
+
+      slang_operation_add_children(block, 2);
+      block->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
+
+      /* build inner loop:  for ( ; _condFlag = LOOPCOND; INCR) { */
+      {
+         innerFor = slang_oper_child(block, 0);
+
+         /* make copy of orig loop */
+         slang_operation_copy(innerFor, oper);
+         assert(innerFor->type == SLANG_OPER_FOR);
+         innerFor->locals->outer_scope = block->locals;
+
+         init = slang_oper_child(innerFor, 0);
+         init->type = SLANG_OPER_VOID; /* leak? */
+
+         cond = slang_oper_child(innerFor, 1);
+         slang_operation_destruct(cond);
+         cond->type = SLANG_OPER_ASSIGN;
+         cond->locals = _slang_variable_scope_new(innerFor->locals);
+         slang_operation_add_children(cond, 2);
+
+         lhs = slang_oper_child(cond, 0);
+         lhs->type = SLANG_OPER_IDENTIFIER;
+         lhs->a_id = slang_atom_pool_atom(A->atoms, "_condFlag");
+
+         rhs = slang_oper_child(cond, 1);
+         slang_operation_copy(rhs, slang_oper_child(oper, 1));
+      }
+
+      /* if (_condFlag) INCR; */
+      {
+         slang_operation *ifop = slang_oper_child(block, 1);
+         ifop->type = SLANG_OPER_IF;
+         slang_operation_add_children(ifop, 2);
+
+         /* re-use cond node build above */
+         slang_operation_copy(slang_oper_child(ifop, 0), cond);
+
+         /* incr node from original for-loop operation */
+         slang_operation_copy(slang_oper_child(ifop, 1),
+                              slang_oper_child(oper, 2));
+      }
+
+      /* finally, replace "continue" with "break" in the inner for-loop */
+      replace_continue_with_break(A, slang_oper_child(innerFor, 3));
+   }
+
+   return _slang_gen_operation(A, top);
+}
+
+
+
+/**
+ * Generate IR for a for-loop.  Unrolling will be done when possible.
+ */
+static slang_ir_node *
+_slang_gen_for(slang_assemble_ctx * A, slang_operation *oper)
+{
+   GLboolean unroll;
+
+   if (!A->EmitContReturn) {
+      /* We don't want to emit CONT instructions.  If this for-loop has
+       * a continue, translate it away.
+       */
+      if (_slang_loop_contains_continue(slang_oper_child(oper, 3))) {
+         return _slang_gen_for_without_continue(A, oper);
+      }
+   }
+
+   unroll = _slang_can_unroll_for_loop(A, oper);
+   if (unroll) {
+      slang_ir_node *code = _slang_unroll_for_loop(A, oper);
+      if (code)
+         return code;
+   }
+
+   assert(oper->type == SLANG_OPER_FOR);
+
+   /* conventional for-loop code generation */
+   {
+      /*
+       * init code (child[0])
+       * LOOP:
+       *    BREAK if !expr (child[1])
+       *    body code (child[3])
+       *    tail code:
+       *       incr code (child[2])   // XXX continue here
+       */
+      slang_ir_node *loop, *cond, *breakIf, *body, *init, *incr;
+      init = _slang_gen_operation(A, &oper->children[0]);
+      loop = new_loop(NULL);
+
+      /* save loop state */
+      push_loop(A, oper, loop);
+
+      cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
+      breakIf = new_break_if_true(A, cond);
+      body = _slang_gen_operation(A, &oper->children[3]);
+      incr = _slang_gen_operation(A, &oper->children[2]);
+
+      loop->Children[0] = new_seq(breakIf, body);
+      loop->Children[1] = incr;  /* tail code */
+
+      /* restore loop state */
+      pop_loop(A);
+
+      return new_seq(init, loop);
+   }
+}
+
+
+static slang_ir_node *
+_slang_gen_continue(slang_assemble_ctx * A, const slang_operation *oper)
+{
+   slang_ir_node *n, *cont, *incr = NULL, *loopNode;
+
+   assert(oper->type == SLANG_OPER_CONTINUE);
+   loopNode = current_loop_ir(A);
+   assert(loopNode);
+   assert(loopNode->Opcode == IR_LOOP);
+
+   cont = new_node0(IR_CONT);
+   if (cont) {
+      cont->Parent = loopNode;
+      /* insert this node at head of linked list of cont/break instructions */
+      cont->List = loopNode->List;
+      loopNode->List = cont;
+   }
+
+   n = new_seq(incr, cont);
+   return n;
+}
+
+
+/**
+ * Determine if the given operation is of a specific type.
+ */
+static GLboolean
+is_operation_type(const slang_operation *oper, slang_operation_type type)
+{
+   if (oper->type == type)
+      return GL_TRUE;
+   else if ((oper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+             oper->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) &&
+            oper->num_children == 1)
+      return is_operation_type(&oper->children[0], type);
+   else
+      return GL_FALSE;
+}
+
+
+/**
+ * Generate IR tree for an if/then/else conditional using high-level
+ * IR_IF instruction.
+ */
+static slang_ir_node *
+_slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
+{
+   /*
+    * eval expr (child[0])
+    * IF expr THEN
+    *    if-body code
+    * ELSE
+    *    else-body code
+    * ENDIF
+    */
+   const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]);
+   slang_ir_node *ifNode, *cond, *ifBody, *elseBody;
+   GLboolean isConst, constTrue;
+
+   /* type-check expression */
+   if (!_slang_is_boolean(A, &oper->children[0])) {
+      slang_info_log_error(A->log, "boolean expression expected for 'if'");
+      return NULL;
+   }
+
+   if (!_slang_is_scalar_or_boolean(A, &oper->children[0])) {
+      slang_info_log_error(A->log, "scalar/boolean expression expected for 'if'");
+      return NULL;
+   }
+
+   isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
+   if (isConst) {
+      if (constTrue) {
+         /* if (true) ... */
+         return _slang_gen_operation(A, &oper->children[1]);
+      }
+      else {
+         /* if (false) ... */
+         return _slang_gen_operation(A, &oper->children[2]);
+      }
+   }
+
+   cond = _slang_gen_operation(A, &oper->children[0]);
+   cond = new_cond(cond);
+
+   if (is_operation_type(&oper->children[1], SLANG_OPER_BREAK)
+       && !haveElseClause) {
+      /* Special case: generate a conditional break */
+      ifBody = new_break_if_true(A, cond);
+      return ifBody;
+   }
+   else if (is_operation_type(&oper->children[1], SLANG_OPER_CONTINUE)
+            && !haveElseClause
+            && current_loop_oper(A)
+            && current_loop_oper(A)->type != SLANG_OPER_FOR) {
+      /* Special case: generate a conditional continue */
+      ifBody = new_cont_if_true(A, cond);
+      return ifBody;
+   }
+   else {
+      /* general case */
+      ifBody = _slang_gen_operation(A, &oper->children[1]);
+      if (haveElseClause)
+         elseBody = _slang_gen_operation(A, &oper->children[2]);
+      else
+         elseBody = NULL;
+      ifNode = new_if(cond, ifBody, elseBody);
+      return ifNode;
+   }
+}
+
+
+
+static slang_ir_node *
+_slang_gen_not(slang_assemble_ctx * A, const slang_operation *oper)
+{
+   slang_ir_node *n;
+
+   assert(oper->type == SLANG_OPER_NOT);
+
+   /* type-check expression */
+   if (!_slang_is_scalar_or_boolean(A, &oper->children[0])) {
+      slang_info_log_error(A->log,
+                           "scalar/boolean expression expected for '!'");
+      return NULL;
+   }
+
+   n = _slang_gen_operation(A, &oper->children[0]);
+   if (n)
+      return new_not(n);
+   else
+      return NULL;
+}
+
+
+static slang_ir_node *
+_slang_gen_xor(slang_assemble_ctx * A, const slang_operation *oper)
+{
+   slang_ir_node *n1, *n2;
+
+   assert(oper->type == SLANG_OPER_LOGICALXOR);
+
+   if (!_slang_is_scalar_or_boolean(A, &oper->children[0]) ||
+       !_slang_is_scalar_or_boolean(A, &oper->children[0])) {
+      slang_info_log_error(A->log,
+                           "scalar/boolean expressions expected for '^^'");
+      return NULL;
+   }
+
+   n1 = _slang_gen_operation(A, &oper->children[0]);
+   if (!n1)
+      return NULL;
+   n2 = _slang_gen_operation(A, &oper->children[1]);
+   if (!n2)
+      return NULL;
+   return new_node2(IR_NOTEQUAL, n1, n2);
+}
+
+
+/**
+ * Generate IR node for storage of a temporary of given size.
+ */
+static slang_ir_node *
+_slang_gen_temporary(GLint size)
+{
+   slang_ir_storage *store;
+   slang_ir_node *n = NULL;
+
+   store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -2, size);
+   if (store) {
+      n = new_node0(IR_VAR_DECL);
+      if (n) {
+         n->Store = store;
+      }
+      else {
+         _slang_free(store);
+      }
+   }
+   return n;
+}
+
+
+/**
+ * Generate program constants for an array.
+ * Ex: const vec2[3] v = vec2[3](vec2(1,1), vec2(2,2), vec2(3,3));
+ * This will allocate and initialize three vector constants, storing
+ * the array in constant memory, not temporaries like a non-const array.
+ * This can also be used for uniform array initializers.
+ * \return GL_TRUE for success, GL_FALSE if failure (semantic error, etc).
+ */
+static GLboolean
+make_constant_array(slang_assemble_ctx *A,
+                    slang_variable *var,
+                    slang_operation *initializer)
+{
+   struct gl_program *prog = A->program;
+   const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
+   const char *varName = (char *) var->a_name;
+   const GLuint numElements = initializer->num_children;
+   GLint size;
+   GLuint i, j;
+   GLfloat *values;
+
+   if (!var->store) {
+      var->store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -6, -6);
+   }
+   size = var->store->Size;
+
+   assert(var->type.qualifier == SLANG_QUAL_CONST ||
+          var->type.qualifier == SLANG_QUAL_UNIFORM);
+   assert(initializer->type == SLANG_OPER_CALL);
+   assert(initializer->array_constructor);
+
+   values = (GLfloat *) malloc(numElements * 4 * sizeof(GLfloat));
+
+   /* convert constructor params into ordinary floats */
+   for (i = 0; i < numElements; i++) {
+      const slang_operation *op = &initializer->children[i];
+      if (op->type != SLANG_OPER_LITERAL_FLOAT) {
+         /* unsupported type for this optimization */
+         free(values);
+         return GL_FALSE;
+      }
+      for (j = 0; j < op->literal_size; j++) {
+         values[i * 4 + j] = op->literal[j];
+      }
+      for ( ; j < 4; j++) {
+         values[i * 4 + j] = 0.0f;
+      }
+   }
+
+   /* slightly different paths for constants vs. uniforms */
+   if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
+      var->store->File = PROGRAM_UNIFORM;
+      var->store->Index = _mesa_add_uniform(prog->Parameters, varName,
+                                            size, datatype, values);
+   }
+   else {
+      var->store->File = PROGRAM_CONSTANT;
+      var->store->Index = _mesa_add_named_constant(prog->Parameters, varName,
+                                                   values, size);
+   }
+   assert(var->store->Size == size);
+
+   free(values);
+
+   return GL_TRUE;
+}
+
+
+
+/**
+ * Generate IR node for allocating/declaring a variable (either a local or
+ * a global).
+ * Generally, this involves allocating an slang_ir_storage instance for the
+ * variable, choosing a register file (temporary, constant, etc).
+ * For ordinary variables we do not yet allocate storage though.  We do that
+ * when we find the first actual use of the variable to avoid allocating temp
+ * regs that will never get used.
+ * At this time, uniforms are always allocated space in this function.
+ *
+ * \param initializer  Optional initializer expression for the variable.
+ */
+static slang_ir_node *
+_slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
+                    slang_operation *initializer)
+{
+   const char *varName = (const char *) var->a_name;
+   const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
+   slang_ir_node *varDecl, *n;
+   slang_ir_storage *store;
+   GLint arrayLen, size, totalSize;  /* if array then totalSize > size */
+   gl_register_file file;
+
+   /*assert(!var->declared);*/
+   var->declared = GL_TRUE;
+
+   /* determine GPU register file for simple cases */
+   if (is_sampler_type(&var->type)) {
+      file = PROGRAM_SAMPLER;
+   }
+   else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
+      file = PROGRAM_UNIFORM;
+   }
+   else {
+      file = PROGRAM_TEMPORARY;
+   }
+
+   size = _slang_sizeof_type_specifier(&var->type.specifier);
+   if (size <= 0) {
+      slang_info_log_error(A->log, "invalid declaration for '%s'", varName);
+      return NULL;
+   }
+
+   arrayLen = _slang_array_length(var);
+   totalSize = _slang_array_size(size, arrayLen);
+
+   /* Allocate IR node for the declaration */
+   varDecl = new_node0(IR_VAR_DECL);
+   if (!varDecl)
+      return NULL;
+
+   /* Allocate slang_ir_storage for this variable if needed.
+    * Note that we may not actually allocate a constant or temporary register
+    * until later.
+    */
+   if (!var->store) {
+      GLint index = -7;  /* TBD / unknown */
+      var->store = _slang_new_ir_storage(file, index, totalSize);
+      if (!var->store)
+         return NULL; /* out of memory */
+   }
+
+   /* set the IR node's Var and Store pointers */
+   varDecl->Var = var;
+   varDecl->Store = var->store;
+
+
+   store = var->store;
+
+   /* if there's an initializer, generate IR for the expression */
+   if (initializer) {
+      slang_ir_node *varRef, *init;
+
+      if (var->type.qualifier == SLANG_QUAL_CONST) {
+         /* if the variable is const, the initializer must be a const
+          * expression as well.
+          */
+#if 0
+         if (!_slang_is_constant_expr(initializer)) {
+            slang_info_log_error(A->log,
+                                 "initializer for %s not constant", varName);
+            return NULL;
+         }
+#endif
+      }
+
+      if (var->type.qualifier == SLANG_QUAL_UNIFORM &&
+          !A->allow_uniform_initializers) {
+         slang_info_log_error(A->log,
+                              "initializer for uniform %s not allowed",
+                              varName);
+         return NULL;
+      }
+
+      /* IR for the variable we're initializing */
+      varRef = new_var(A, var);
+      if (!varRef) {
+         slang_info_log_error(A->log, "out of memory");
+         return NULL;
+      }
+
+      /* constant-folding, etc here */
+      _slang_simplify(initializer, &A->space, A->atoms); 
+
+      /* look for simple constant-valued variables and uniforms */
+      if (var->type.qualifier == SLANG_QUAL_CONST ||
+          var->type.qualifier == SLANG_QUAL_UNIFORM) {
+
+         if (initializer->type == SLANG_OPER_CALL &&
+             initializer->array_constructor) {
+            /* array initializer */
+            if (make_constant_array(A, var, initializer))
+               return varRef;
+         }
+         else if (initializer->type == SLANG_OPER_LITERAL_FLOAT ||
+                  initializer->type == SLANG_OPER_LITERAL_INT) {
+            /* simple float/vector initializer */
+            if (store->File == PROGRAM_UNIFORM) {
+               store->Index = _mesa_add_uniform(A->program->Parameters,
+                                                varName,
+                                                totalSize, datatype,
+                                                initializer->literal);
+               store->Swizzle = _slang_var_swizzle(size, 0);
+               return varRef;
+            }
+#if 0
+            else {
+               store->File = PROGRAM_CONSTANT;
+               store->Index = _mesa_add_named_constant(A->program->Parameters,
+                                                       varName,
+                                                       initializer->literal,
+                                                       totalSize);
+               store->Swizzle = _slang_var_swizzle(size, 0);
+               return varRef;
+            }
+#endif
+         }
+      }
+
+      /* IR for initializer */
+      init = _slang_gen_operation(A, initializer);
+      if (!init)
+         return NULL;
+
+      /* XXX remove this when type checking is added above */
+      if (init->Store && init->Store->Size != totalSize) {
+         slang_info_log_error(A->log, "invalid assignment (wrong types)");
+         return NULL;
+      }
+
+      /* assign RHS to LHS */
+      n = new_node2(IR_COPY, varRef, init);
+      n = new_seq(varDecl, n);
+   }
+   else {
+      /* no initializer */
+      n = varDecl;
+   }
+
+   if (store->File == PROGRAM_UNIFORM && store->Index < 0) {
+      /* always need to allocate storage for uniforms at this point */
+      store->Index = _mesa_add_uniform(A->program->Parameters, varName,
+                                       totalSize, datatype, NULL);
+      store->Swizzle = _slang_var_swizzle(size, 0);
+   }
+
+#if 0
+   printf("%s var %p %s  store=%p index=%d size=%d\n",
+          __FUNCTION__, (void *) var, (char *) varName,
+          (void *) store, store->Index, store->Size);
+#endif
+
+   return n;
+}
+
+
+/**
+ * Generate code for a selection expression:   b ? x : y
+ * XXX In some cases we could implement a selection expression
+ * with an LRP instruction (use the boolean as the interpolant).
+ * Otherwise, we use an IF/ELSE/ENDIF construct.
+ */
+static slang_ir_node *
+_slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
+{
+   slang_ir_node *cond, *ifNode, *trueExpr, *falseExpr, *trueNode, *falseNode;
+   slang_ir_node *tmpDecl, *tmpVar, *tree;
+   slang_typeinfo type0, type1, type2;
+   int size, isBool, isEqual;
+
+   assert(oper->type == SLANG_OPER_SELECT);
+   assert(oper->num_children == 3);
+
+   /* type of children[0] must be boolean */
+   slang_typeinfo_construct(&type0);
+   typeof_operation(A, &oper->children[0], &type0);
+   isBool = (type0.spec.type == SLANG_SPEC_BOOL);
+   slang_typeinfo_destruct(&type0);
+   if (!isBool) {
+      slang_info_log_error(A->log, "selector type is not boolean");
+      return NULL;
+   }
+
+   slang_typeinfo_construct(&type1);
+   slang_typeinfo_construct(&type2);
+   typeof_operation(A, &oper->children[1], &type1);
+   typeof_operation(A, &oper->children[2], &type2);
+   isEqual = slang_type_specifier_equal(&type1.spec, &type2.spec);
+   slang_typeinfo_destruct(&type1);
+   slang_typeinfo_destruct(&type2);
+   if (!isEqual) {
+      slang_info_log_error(A->log, "incompatible types for ?: operator");
+      return NULL;
+   }
+
+   /* size of x or y's type */
+   size = _slang_sizeof_type_specifier(&type1.spec);
+   assert(size > 0);
+
+   /* temporary var */
+   tmpDecl = _slang_gen_temporary(size);
+
+   /* the condition (child 0) */
+   cond = _slang_gen_operation(A, &oper->children[0]);
+   cond = new_cond(cond);
+
+   /* if-true body (child 1) */
+   tmpVar = new_node0(IR_VAR);
+   tmpVar->Store = tmpDecl->Store;
+   trueExpr = _slang_gen_operation(A, &oper->children[1]);
+   trueNode = new_node2(IR_COPY, tmpVar, trueExpr);
+
+   /* if-false body (child 2) */
+   tmpVar = new_node0(IR_VAR);
+   tmpVar->Store = tmpDecl->Store;
+   falseExpr = _slang_gen_operation(A, &oper->children[2]);
+   falseNode = new_node2(IR_COPY, tmpVar, falseExpr);
+
+   ifNode = new_if(cond, trueNode, falseNode);
+
+   /* tmp var value */
+   tmpVar = new_node0(IR_VAR);
+   tmpVar->Store = tmpDecl->Store;
+
+   tree = new_seq(ifNode, tmpVar);
+   tree = new_seq(tmpDecl, tree);
+
+   /*_slang_print_ir_tree(tree, 10);*/
+   return tree;
+}
+
+
+/**
+ * Generate code for &&.
+ */
+static slang_ir_node *
+_slang_gen_logical_and(slang_assemble_ctx *A, slang_operation *oper)
+{
+   /* rewrite "a && b" as  "a ? b : false" */
+   slang_operation *select;
+   slang_ir_node *n;
+
+   select = slang_operation_new(1);
+   select->type = SLANG_OPER_SELECT;
+   slang_operation_add_children(select, 3);
+
+   slang_operation_copy(slang_oper_child(select, 0), &oper->children[0]);
+   slang_operation_copy(slang_oper_child(select, 1), &oper->children[1]);
+   slang_operation_literal_bool(slang_oper_child(select, 2), GL_FALSE);
+
+   n = _slang_gen_select(A, select);
+   return n;
+}
+
+
+/**
+ * Generate code for ||.
+ */
+static slang_ir_node *
+_slang_gen_logical_or(slang_assemble_ctx *A, slang_operation *oper)
+{
+   /* rewrite "a || b" as  "a ? true : b" */
+   slang_operation *select;
+   slang_ir_node *n;
+
+   select = slang_operation_new(1);
+   select->type = SLANG_OPER_SELECT;
+   slang_operation_add_children(select, 3);
+
+   slang_operation_copy(slang_oper_child(select, 0), &oper->children[0]);
+   slang_operation_literal_bool(slang_oper_child(select, 1), GL_TRUE);
+   slang_operation_copy(slang_oper_child(select, 2), &oper->children[1]);
+
+   n = _slang_gen_select(A, select);
+   return n;
+}
+
+
+/**
+ * Generate IR tree for a return statement.
+ */
+static slang_ir_node *
+_slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
+{
+   assert(oper->type == SLANG_OPER_RETURN);
+   return new_return(A->curFuncEndLabel);
+}
+
+
+#if 0
+/**
+ * Determine if the given operation/expression is const-valued.
+ */
+static GLboolean
+_slang_is_constant_expr(const slang_operation *oper)
+{
+   slang_variable *var;
+   GLuint i;
+
+   switch (oper->type) {
+   case SLANG_OPER_IDENTIFIER:
+      var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
+      if (var && var->type.qualifier == SLANG_QUAL_CONST)
+         return GL_TRUE;
+      return GL_FALSE;
+   default:
+      for (i = 0; i < oper->num_children; i++) {
+         if (!_slang_is_constant_expr(&oper->children[i]))
+            return GL_FALSE;
+      }
+      return GL_TRUE;
+   }
+}
+#endif
+
+
+/**
+ * Check if an assignment of type t1 to t0 is legal.
+ * XXX more cases needed.
+ */
+static GLboolean
+_slang_assignment_compatible(slang_assemble_ctx *A,
+                             slang_operation *op0,
+                             slang_operation *op1)
+{
+   slang_typeinfo t0, t1;
+   GLuint sz0, sz1;
+
+   if (op0->type == SLANG_OPER_POSTINCREMENT ||
+       op0->type == SLANG_OPER_POSTDECREMENT) {
+      return GL_FALSE;
+   }
+
+   slang_typeinfo_construct(&t0);
+   typeof_operation(A, op0, &t0);
+
+   slang_typeinfo_construct(&t1);
+   typeof_operation(A, op1, &t1);
+
+   sz0 = _slang_sizeof_type_specifier(&t0.spec);
+   sz1 = _slang_sizeof_type_specifier(&t1.spec);
+
+#if 1
+   if (sz0 != sz1) {
+      /*printf("assignment size mismatch %u vs %u\n", sz0, sz1);*/
+      return GL_FALSE;
+   }
+#endif
+
+   if (t0.spec.type == SLANG_SPEC_STRUCT &&
+       t1.spec.type == SLANG_SPEC_STRUCT &&
+       t0.spec._struct->a_name != t1.spec._struct->a_name)
+      return GL_FALSE;
+
+   if (t0.spec.type == SLANG_SPEC_FLOAT &&
+       t1.spec.type == SLANG_SPEC_BOOL)
+      return GL_FALSE;
+
+#if 0 /* not used just yet - causes problems elsewhere */
+   if (t0.spec.type == SLANG_SPEC_INT &&
+       t1.spec.type == SLANG_SPEC_FLOAT)
+      return GL_FALSE;
+#endif
+
+   if (t0.spec.type == SLANG_SPEC_BOOL &&
+       t1.spec.type == SLANG_SPEC_FLOAT)
+      return GL_FALSE;
+
+   if (t0.spec.type == SLANG_SPEC_BOOL &&
+       t1.spec.type == SLANG_SPEC_INT)
+      return GL_FALSE;
+
+   return GL_TRUE;
+}
+
+
+/**
+ * Generate IR tree for a local variable declaration.
+ * Basically do some error checking and call _slang_gen_var_decl().
+ */
+static slang_ir_node *
+_slang_gen_declaration(slang_assemble_ctx *A, slang_operation *oper)
+{
+   const char *varName = (char *) oper->a_id;
+   slang_variable *var;
+   slang_ir_node *varDecl;
+   slang_operation *initializer;
+
+   assert(oper->type == SLANG_OPER_VARIABLE_DECL);
+   assert(oper->num_children <= 1);
+
+
+   /* lookup the variable by name */
+   var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
+   if (!var)
+      return NULL;  /* "shouldn't happen" */
+
+   if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
+       var->type.qualifier == SLANG_QUAL_VARYING ||
+       var->type.qualifier == SLANG_QUAL_UNIFORM) {
+      /* can't declare attribute/uniform vars inside functions */
+      slang_info_log_error(A->log,
+                "local variable '%s' cannot be an attribute/uniform/varying",
+                varName);
+      return NULL;
+   }
+
+#if 0
+   if (v->declared) {
+      slang_info_log_error(A->log, "variable '%s' redeclared", varName);
+      return NULL;
+   }
+#endif
+
+   /* check if the var has an initializer */
+   if (oper->num_children > 0) {
+      assert(oper->num_children == 1);
+      initializer = &oper->children[0];
+   }
+   else if (var->initializer) {
+      initializer = var->initializer;
+   }
+   else {
+      initializer = NULL;
+   }
+
+   if (initializer) {
+      /* check/compare var type and initializer type */
+      if (!_slang_assignment_compatible(A, oper, initializer)) {
+         slang_info_log_error(A->log, "incompatible types in assignment");
+         return NULL;
+      }         
+   }
+   else {
+      if (var->type.qualifier == SLANG_QUAL_CONST) {
+         slang_info_log_error(A->log,
+                       "const-qualified variable '%s' requires initializer",
+                       varName);
+         return NULL;
+      }
+   }
+
+   /* Generate IR node */
+   varDecl = _slang_gen_var_decl(A, var, initializer);
+   if (!varDecl)
+      return NULL;
+
+   return varDecl;
+}
+
+
+/**
+ * Generate IR tree for a reference to a variable (such as in an expression).
+ * This is different from a variable declaration.
+ */
+static slang_ir_node *
+_slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper)
+{
+   /* If there's a variable associated with this oper (from inlining)
+    * use it.  Otherwise, use the oper's var id.
+    */
+   slang_atom name = oper->var ? oper->var->a_name : oper->a_id;
+   slang_variable *var = _slang_variable_locate(oper->locals, name, GL_TRUE);
+   slang_ir_node *n;
+   if (!var || !var->declared) {
+      slang_info_log_error(A->log, "undefined variable '%s'", (char *) name);
+      return NULL;
+   }
+   n = new_var(A, var);
+   return n;
+}
+
+
+
+/**
+ * Return the number of components actually named by the swizzle.
+ * Recall that swizzles may have undefined/don't-care values.
+ */
+static GLuint
+swizzle_size(GLuint swizzle)
+{
+   GLuint size = 0, i;
+   for (i = 0; i < 4; i++) {
+      GLuint swz = GET_SWZ(swizzle, i);
+      size += (swz <= 3);
+   }
+   return size;
+}
+
+
+static slang_ir_node *
+_slang_gen_swizzle(slang_ir_node *child, GLuint swizzle)
+{
+   slang_ir_node *n = new_node1(IR_SWIZZLE, child);
+   assert(child);
+   if (n) {
+      assert(!n->Store);
+      n->Store = _slang_new_ir_storage_relative(0,
+                                                swizzle_size(swizzle),
+                                                child->Store);
+      assert(n->Store);
+      n->Store->Swizzle = swizzle;
+   }
+   return n;
+}
+
+
+static GLboolean
+is_store_writable(const slang_assemble_ctx *A, const slang_ir_storage *store)
+{
+   while (store->Parent)
+      store = store->Parent;
+
+   if (!(store->File == PROGRAM_OUTPUT ||
+         store->File == PROGRAM_TEMPORARY ||
+         (store->File == PROGRAM_VARYING &&
+          A->program->Target == GL_VERTEX_PROGRAM_ARB))) {
+      return GL_FALSE;
+   }
+   else {
+      return GL_TRUE;
+   }
+}
+
+
+/**
+ * Walk up an IR storage path to compute the final swizzle.
+ * This is used when we find an expression such as "foo.xz.yx".
+ */
+static GLuint
+root_swizzle(const slang_ir_storage *st)
+{
+   GLuint swizzle = st->Swizzle;
+   while (st->Parent) {
+      st = st->Parent;
+      swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
+   }
+   return swizzle;
+}
+
+
+/**
+ * Generate IR tree for an assignment (=).
+ */
+static slang_ir_node *
+_slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
+{
+   slang_operation *pred = NULL;
+   slang_ir_node *n = NULL;
+
+   if (oper->children[0].type == SLANG_OPER_IDENTIFIER) {
+      /* Check that var is writeable */
+      const char *varName = (char *) oper->children[0].a_id;
+      slang_variable *var
+         = _slang_variable_locate(oper->children[0].locals,
+                                  oper->children[0].a_id, GL_TRUE);
+      if (!var) {
+         slang_info_log_error(A->log, "undefined variable '%s'", varName);
+         return NULL;
+      }
+
+      if (var->type.qualifier == SLANG_QUAL_CONST ||
+          var->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
+          var->type.qualifier == SLANG_QUAL_UNIFORM ||
+          (var->type.qualifier == SLANG_QUAL_VARYING &&
+           A->program->Target == GL_FRAGMENT_PROGRAM_ARB)) {
+         slang_info_log_error(A->log,
+                              "illegal assignment to read-only variable '%s'",
+                              varName);
+         return NULL;
+      }
+
+      /* check if we need to predicate this assignment based on __notRetFlag */
+      if ((var->is_global ||
+           var->type.qualifier == SLANG_QUAL_OUT ||
+           var->type.qualifier == SLANG_QUAL_INOUT) && A->UseReturnFlag) {
+         /* create predicate, used below */
+         pred = slang_operation_new(1);
+         pred->type = SLANG_OPER_IDENTIFIER;
+         pred->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
+         pred->locals->outer_scope = oper->locals->outer_scope;
+      }
+   }
+
+   if (oper->children[0].type == SLANG_OPER_IDENTIFIER &&
+       oper->children[1].type == SLANG_OPER_CALL) {
+      /* Special case of:  x = f(a, b)
+       * Replace with f(a, b, x)  (where x == hidden __retVal out param)
+       *
+       * XXX this could be even more effective if we could accomodate
+       * cases such as "v.x = f();"  - would help with typical vertex
+       * transformation.
+       */
+      n = _slang_gen_function_call_name(A,
+                                      (const char *) oper->children[1].a_id,
+                                      &oper->children[1], &oper->children[0]);
+   }
+   else {
+      slang_ir_node *lhs, *rhs;
+
+      /* lhs and rhs type checking */
+      if (!_slang_assignment_compatible(A,
+                                        &oper->children[0],
+                                        &oper->children[1])) {
+         slang_info_log_error(A->log, "incompatible types in assignment");
+         return NULL;
+      }
+
+      lhs = _slang_gen_operation(A, &oper->children[0]);
+      if (!lhs) {
+         return NULL;
+      }
+
+      if (!lhs->Store) {
+         slang_info_log_error(A->log,
+                              "invalid left hand side for assignment");
+         return NULL;
+      }
+
+      /* check that lhs is writable */
+      if (!is_store_writable(A, lhs->Store)) {
+         slang_info_log_error(A->log,
+                              "illegal assignment to read-only l-value");
+         return NULL;
+      }
+
+      rhs = _slang_gen_operation(A, &oper->children[1]);
+      if (lhs && rhs) {
+         /* convert lhs swizzle into writemask */
+         const GLuint swizzle = root_swizzle(lhs->Store);
+         GLuint writemask, newSwizzle = 0x0;
+         if (!swizzle_to_writemask(A, swizzle, &writemask, &newSwizzle)) {
+            /* Non-simple writemask, need to swizzle right hand side in
+             * order to put components into the right place.
+             */
+            rhs = _slang_gen_swizzle(rhs, newSwizzle);
+         }
+         n = new_node2(IR_COPY, lhs, rhs);
+      }
+      else {
+         return NULL;
+      }
+   }
+
+   if (n && pred) {
+      /* predicate the assignment code on __notRetFlag */
+      slang_ir_node *top, *cond;
+
+      cond = _slang_gen_operation(A, pred);
+      top = new_if(cond, n, NULL);
+      return top;
+   }
+   return n;
+}
+
+
+/**
+ * Generate IR tree for referencing a field in a struct (or basic vector type)
+ */
+static slang_ir_node *
+_slang_gen_struct_field(slang_assemble_ctx * A, slang_operation *oper)
+{
+   slang_typeinfo ti;
+
+   /* type of struct */
+   slang_typeinfo_construct(&ti);
+   typeof_operation(A, &oper->children[0], &ti);
+
+   if (_slang_type_is_vector(ti.spec.type)) {
+      /* the field should be a swizzle */
+      const GLuint rows = _slang_type_dim(ti.spec.type);
+      slang_swizzle swz;
+      slang_ir_node *n;
+      GLuint swizzle;
+      if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
+         slang_info_log_error(A->log, "Bad swizzle");
+         return NULL;
+      }
+      swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
+                              swz.swizzle[1],
+                              swz.swizzle[2],
+                              swz.swizzle[3]);
+
+      n = _slang_gen_operation(A, &oper->children[0]);
+      /* create new parent node with swizzle */
+      if (n)
+         n = _slang_gen_swizzle(n, swizzle);
+      return n;
+   }
+   else if (   ti.spec.type == SLANG_SPEC_FLOAT
+            || ti.spec.type == SLANG_SPEC_INT
+            || ti.spec.type == SLANG_SPEC_BOOL) {
+      const GLuint rows = 1;
+      slang_swizzle swz;
+      slang_ir_node *n;
+      GLuint swizzle;
+      if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
+         slang_info_log_error(A->log, "Bad swizzle");
+      }
+      swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
+                              swz.swizzle[1],
+                              swz.swizzle[2],
+                              swz.swizzle[3]);
+      n = _slang_gen_operation(A, &oper->children[0]);
+      /* create new parent node with swizzle */
+      n = _slang_gen_swizzle(n, swizzle);
+      return n;
+   }
+   else {
+      /* the field is a structure member (base.field) */
+      /* oper->children[0] is the base */
+      /* oper->a_id is the field name */
+      slang_ir_node *base, *n;
+      slang_typeinfo field_ti;
+      GLint fieldSize, fieldOffset = -1;
+
+      /* type of field */
+      slang_typeinfo_construct(&field_ti);
+      typeof_operation(A, oper, &field_ti);
+
+      fieldSize = _slang_sizeof_type_specifier(&field_ti.spec);
+      if (fieldSize > 0)
+         fieldOffset = _slang_field_offset(&ti.spec, oper->a_id);
+
+      if (fieldSize == 0 || fieldOffset < 0) {
+         const char *structName;
+         if (ti.spec._struct)
+            structName = (char *) ti.spec._struct->a_name;
+         else
+            structName = "unknown";
+         slang_info_log_error(A->log,
+                              "\"%s\" is not a member of struct \"%s\"",
+                              (char *) oper->a_id, structName);
+         return NULL;
+      }
+      assert(fieldSize >= 0);
+
+      base = _slang_gen_operation(A, &oper->children[0]);
+      if (!base) {
+         /* error msg should have already been logged */
+         return NULL;
+      }
+
+      n = new_node1(IR_FIELD, base);
+      if (!n)
+         return NULL;
+
+      n->Field = (char *) oper->a_id;
+
+      /* Store the field's offset in storage->Index */
+      n->Store = _slang_new_ir_storage(base->Store->File,
+                                       fieldOffset,
+                                       fieldSize);
+
+      return n;
+   }
+}
+
+
+/**
+ * Gen code for array indexing.
+ */
+static slang_ir_node *
+_slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper)
+{
+   slang_typeinfo array_ti;
+
+   /* get array's type info */
+   slang_typeinfo_construct(&array_ti);
+   typeof_operation(A, &oper->children[0], &array_ti);
+
+   if (_slang_type_is_vector(array_ti.spec.type)) {
+      /* indexing a simple vector type: "vec4 v; v[0]=p;" */
+      /* translate the index into a swizzle/writemask: "v.x=p" */
+      const GLuint max = _slang_type_dim(array_ti.spec.type);
+      GLint index;
+      slang_ir_node *n;
+
+      index = (GLint) oper->children[1].literal[0];
+      if (oper->children[1].type != SLANG_OPER_LITERAL_INT ||
+          index >= (GLint) max) {
+#if 0
+         slang_info_log_error(A->log, "Invalid array index for vector type");
+         printf("type = %d\n", oper->children[1].type);
+         printf("index = %d, max = %d\n", index, max);
+         printf("array = %s\n", (char*)oper->children[0].a_id);
+         printf("index = %s\n", (char*)oper->children[1].a_id);
+         return NULL;
+#else
+         index = 0;
+#endif
+      }
+
+      n = _slang_gen_operation(A, &oper->children[0]);
+      if (n) {
+         /* use swizzle to access the element */
+         GLuint swizzle = MAKE_SWIZZLE4(SWIZZLE_X + index,
+                                        SWIZZLE_NIL,
+                                        SWIZZLE_NIL,
+                                        SWIZZLE_NIL);
+         n = _slang_gen_swizzle(n, swizzle);
+      }
+      return n;
+   }
+   else {
+      /* conventional array */
+      slang_typeinfo elem_ti;
+      slang_ir_node *elem, *array, *index;
+      GLint elemSize, arrayLen;
+
+      /* size of array element */
+      slang_typeinfo_construct(&elem_ti);
+      typeof_operation(A, oper, &elem_ti);
+      elemSize = _slang_sizeof_type_specifier(&elem_ti.spec);
+
+      if (_slang_type_is_matrix(array_ti.spec.type))
+         arrayLen = _slang_type_dim(array_ti.spec.type);
+      else
+         arrayLen = array_ti.array_len;
+
+      slang_typeinfo_destruct(&array_ti);
+      slang_typeinfo_destruct(&elem_ti);
+
+      if (elemSize <= 0) {
+         /* unknown var or type */
+         slang_info_log_error(A->log, "Undefined variable or type");
+         return NULL;
+      }
+
+      array = _slang_gen_operation(A, &oper->children[0]);
+      index = _slang_gen_operation(A, &oper->children[1]);
+      if (array && index) {
+         /* bounds check */
+         GLint constIndex = -1;
+         if (index->Opcode == IR_FLOAT) {
+            constIndex = (int) index->Value[0];
+            if (constIndex < 0 || constIndex >= arrayLen) {
+               slang_info_log_error(A->log,
+                                "Array index out of bounds (index=%d size=%d)",
+                                 constIndex, arrayLen);
+               _slang_free_ir_tree(array);
+               _slang_free_ir_tree(index);
+               return NULL;
+            }
+         }
+
+         if (!array->Store) {
+            slang_info_log_error(A->log, "Invalid array");
+            return NULL;
+         }
+
+         elem = new_node2(IR_ELEMENT, array, index);
+
+         /* The storage info here will be updated during code emit */
+         elem->Store = _slang_new_ir_storage(array->Store->File,
+                                             array->Store->Index,
+                                             elemSize);
+         elem->Store->Swizzle = _slang_var_swizzle(elemSize, 0);
+         return elem;
+      }
+      else {
+         _slang_free_ir_tree(array);
+         _slang_free_ir_tree(index);
+         return NULL;
+      }
+   }
+}
+
+
+static slang_ir_node *
+_slang_gen_compare(slang_assemble_ctx *A, slang_operation *oper,
+                   slang_ir_opcode opcode)
+{
+   slang_typeinfo t0, t1;
+   slang_ir_node *n;
+   
+   slang_typeinfo_construct(&t0);
+   typeof_operation(A, &oper->children[0], &t0);
+
+   slang_typeinfo_construct(&t1);
+   typeof_operation(A, &oper->children[0], &t1);
+
+   if (t0.spec.type == SLANG_SPEC_ARRAY ||
+       t1.spec.type == SLANG_SPEC_ARRAY) {
+      slang_info_log_error(A->log, "Illegal array comparison");
+      return NULL;
+   }
+
+   if (oper->type != SLANG_OPER_EQUAL &&
+       oper->type != SLANG_OPER_NOTEQUAL) {
+      /* <, <=, >, >= can only be used with scalars */
+      if ((t0.spec.type != SLANG_SPEC_INT &&
+           t0.spec.type != SLANG_SPEC_FLOAT) ||
+          (t1.spec.type != SLANG_SPEC_INT &&
+           t1.spec.type != SLANG_SPEC_FLOAT)) {
+         slang_info_log_error(A->log, "Incompatible type(s) for inequality operator");
+         return NULL;
+      }
+   }
+
+   n =  new_node2(opcode,
+                  _slang_gen_operation(A, &oper->children[0]),
+                  _slang_gen_operation(A, &oper->children[1]));
+
+   /* result is a bool (size 1) */
+   n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
+
+   return n;
+}
+
+
+#if 0
+static void
+print_vars(slang_variable_scope *s)
+{
+   int i;
+   printf("vars: ");
+   for (i = 0; i < s->num_variables; i++) {
+      printf("%s %d, \n",
+             (char*) s->variables[i]->a_name,
+             s->variables[i]->declared);
+   }
+
+   printf("\n");
+}
+#endif
+
+
+#if 0
+static void
+_slang_undeclare_vars(slang_variable_scope *locals)
+{
+   if (locals->num_variables > 0) {
+      int i;
+      for (i = 0; i < locals->num_variables; i++) {
+         slang_variable *v = locals->variables[i];
+         printf("undeclare %s at %p\n", (char*) v->a_name, v);
+         v->declared = GL_FALSE;
+      }
+   }
+}
+#endif
+
+
+/**
+ * Generate IR tree for a slang_operation (AST node)
+ */
+static slang_ir_node *
+_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
+{
+   switch (oper->type) {
+   case SLANG_OPER_BLOCK_NEW_SCOPE:
+      {
+         slang_ir_node *n;
+
+         _slang_push_var_table(A->vartable);
+
+         oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE; /* temp change */
+         n = _slang_gen_operation(A, oper);
+         oper->type = SLANG_OPER_BLOCK_NEW_SCOPE; /* restore */
+
+         _slang_pop_var_table(A->vartable);
+
+         /*_slang_undeclare_vars(oper->locals);*/
+         /*print_vars(oper->locals);*/
+
+         if (n)
+            n = new_node1(IR_SCOPE, n);
+         return n;
+      }
+      break;
+
+   case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
+      /* list of operations */
+      if (oper->num_children > 0)
+      {
+         slang_ir_node *n, *tree = NULL;
+         GLuint i;
+
+         for (i = 0; i < oper->num_children; i++) {
+            n = _slang_gen_operation(A, &oper->children[i]);
+            if (!n) {
+               _slang_free_ir_tree(tree);
+               return NULL; /* error must have occured */
+            }
+            tree = new_seq(tree, n);
+         }
+
+         return tree;
+      }
+      else {
+         return new_node0(IR_NOP);
+      }
+
+   case SLANG_OPER_EXPRESSION:
+      return _slang_gen_operation(A, &oper->children[0]);
+
+   case SLANG_OPER_FOR:
+      return _slang_gen_for(A, oper);
+   case SLANG_OPER_DO:
+      return _slang_gen_do(A, oper);
+   case SLANG_OPER_WHILE:
+      return _slang_gen_while(A, oper);
+   case SLANG_OPER_BREAK:
+      if (!current_loop_oper(A)) {
+         slang_info_log_error(A->log, "'break' not in loop");
+         return NULL;
+      }
+      return new_break(current_loop_ir(A));
+   case SLANG_OPER_CONTINUE:
+      if (!current_loop_oper(A)) {
+         slang_info_log_error(A->log, "'continue' not in loop");
+         return NULL;
+      }
+      return _slang_gen_continue(A, oper);
+   case SLANG_OPER_DISCARD:
+      return new_node0(IR_KILL);
+
+   case SLANG_OPER_EQUAL:
+      return _slang_gen_compare(A, oper, IR_EQUAL);
+   case SLANG_OPER_NOTEQUAL:
+      return _slang_gen_compare(A, oper, IR_NOTEQUAL);
+   case SLANG_OPER_GREATER:
+      return _slang_gen_compare(A, oper, IR_SGT);
+   case SLANG_OPER_LESS:
+      return _slang_gen_compare(A, oper, IR_SLT);
+   case SLANG_OPER_GREATEREQUAL:
+      return _slang_gen_compare(A, oper, IR_SGE);
+   case SLANG_OPER_LESSEQUAL:
+      return _slang_gen_compare(A, oper, IR_SLE);
+   case SLANG_OPER_ADD:
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 2);
+        n = _slang_gen_function_call_name(A, "+", oper, NULL);
+        return n;
+      }
+   case SLANG_OPER_SUBTRACT:
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 2);
+        n = _slang_gen_function_call_name(A, "-", oper, NULL);
+        return n;
+      }
+   case SLANG_OPER_MULTIPLY:
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 2);
+         n = _slang_gen_function_call_name(A, "*", oper, NULL);
+        return n;
+      }
+   case SLANG_OPER_DIVIDE:
+      {
+         slang_ir_node *n;
+         assert(oper->num_children == 2);
+        n = _slang_gen_function_call_name(A, "/", oper, NULL);
+        return n;
+      }
+   case SLANG_OPER_MINUS:
+      {
+         slang_ir_node *n;
+         assert(oper->num_children == 1);
+        n = _slang_gen_function_call_name(A, "-", oper, NULL);
+        return n;
+      }
+   case SLANG_OPER_PLUS:
+      /* +expr   --> do nothing */
+      return _slang_gen_operation(A, &oper->children[0]);
+   case SLANG_OPER_VARIABLE_DECL:
+      return _slang_gen_declaration(A, oper);
+   case SLANG_OPER_ASSIGN:
+      return _slang_gen_assignment(A, oper);
+   case SLANG_OPER_ADDASSIGN:
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 2);
+        n = _slang_gen_function_call_name(A, "+=", oper, NULL);
+        return n;
+      }
+   case SLANG_OPER_SUBASSIGN:
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 2);
+        n = _slang_gen_function_call_name(A, "-=", oper, NULL);
+        return n;
+      }
+      break;
+   case SLANG_OPER_MULASSIGN:
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 2);
+        n = _slang_gen_function_call_name(A, "*=", oper, NULL);
+        return n;
+      }
+   case SLANG_OPER_DIVASSIGN:
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 2);
+        n = _slang_gen_function_call_name(A, "/=", oper, NULL);
+        return n;
+      }
+   case SLANG_OPER_LOGICALAND:
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 2);
+        n = _slang_gen_logical_and(A, oper);
+        return n;
+      }
+   case SLANG_OPER_LOGICALOR:
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 2);
+        n = _slang_gen_logical_or(A, oper);
+        return n;
+      }
+   case SLANG_OPER_LOGICALXOR:
+      return _slang_gen_xor(A, oper);
+   case SLANG_OPER_NOT:
+      return _slang_gen_not(A, oper);
+   case SLANG_OPER_SELECT:  /* b ? x : y */
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 3);
+        n = _slang_gen_select(A, oper);
+        return n;
+      }
+
+   case SLANG_OPER_ASM:
+      return _slang_gen_asm(A, oper, NULL);
+   case SLANG_OPER_CALL:
+      return _slang_gen_function_call_name(A, (const char *) oper->a_id,
+                                           oper, NULL);
+   case SLANG_OPER_METHOD:
+      return _slang_gen_method_call(A, oper);
+   case SLANG_OPER_RETURN:
+      return _slang_gen_return(A, oper);
+   case SLANG_OPER_RETURN_INLINED:
+      return _slang_gen_return(A, oper);
+   case SLANG_OPER_LABEL:
+      return new_label(oper->label);
+   case SLANG_OPER_IDENTIFIER:
+      return _slang_gen_variable(A, oper);
+   case SLANG_OPER_IF:
+      return _slang_gen_if(A, oper);
+   case SLANG_OPER_FIELD:
+      return _slang_gen_struct_field(A, oper);
+   case SLANG_OPER_SUBSCRIPT:
+      return _slang_gen_array_element(A, oper);
+   case SLANG_OPER_LITERAL_FLOAT:
+      /* fall-through */
+   case SLANG_OPER_LITERAL_INT:
+      /* fall-through */
+   case SLANG_OPER_LITERAL_BOOL:
+      return new_float_literal(oper->literal, oper->literal_size);
+
+   case SLANG_OPER_POSTINCREMENT:   /* var++ */
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 1);
+        n = _slang_gen_function_call_name(A, "__postIncr", oper, NULL);
+        return n;
+      }
+   case SLANG_OPER_POSTDECREMENT:   /* var-- */
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 1);
+        n = _slang_gen_function_call_name(A, "__postDecr", oper, NULL);
+        return n;
+      }
+   case SLANG_OPER_PREINCREMENT:   /* ++var */
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 1);
+        n = _slang_gen_function_call_name(A, "++", oper, NULL);
+        return n;
+      }
+   case SLANG_OPER_PREDECREMENT:   /* --var */
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 1);
+        n = _slang_gen_function_call_name(A, "--", oper, NULL);
+        return n;
+      }
+
+   case SLANG_OPER_NON_INLINED_CALL:
+   case SLANG_OPER_SEQUENCE:
+      {
+         slang_ir_node *tree = NULL;
+         GLuint i;
+         for (i = 0; i < oper->num_children; i++) {
+            slang_ir_node *n = _slang_gen_operation(A, &oper->children[i]);
+            tree = new_seq(tree, n);
+            if (n)
+               tree->Store = n->Store;
+         }
+         if (oper->type == SLANG_OPER_NON_INLINED_CALL) {
+            tree = new_function_call(tree, oper->label);
+         }
+         return tree;
+      }
+
+   case SLANG_OPER_NONE:
+   case SLANG_OPER_VOID:
+      /* returning NULL here would generate an error */
+      return new_node0(IR_NOP);
+
+   default:
+      _mesa_problem(NULL, "bad node type %d in _slang_gen_operation",
+                    oper->type);
+      return new_node0(IR_NOP);
+   }
+
+   return NULL;
+}
+
+
+/**
+ * Check if the given type specifier is a rectangular texture sampler.
+ */
+static GLboolean
+is_rect_sampler_spec(const slang_type_specifier *spec)
+{
+   while (spec->_array) {
+      spec = spec->_array;
+   }
+   return spec->type == SLANG_SPEC_SAMPLER_RECT ||
+          spec->type == SLANG_SPEC_SAMPLER_RECT_SHADOW;
+}
+
+
+
+/**
+ * Called by compiler when a global variable has been parsed/compiled.
+ * Here we examine the variable's type to determine what kind of register
+ * storage will be used.
+ *
+ * A uniform such as "gl_Position" will become the register specification
+ * (PROGRAM_OUTPUT, VERT_RESULT_HPOS).  Or, uniform "gl_FogFragCoord"
+ * will be (PROGRAM_INPUT, FRAG_ATTRIB_FOGC).
+ *
+ * Samplers are interesting.  For "uniform sampler2D tex;" we'll specify
+ * (PROGRAM_SAMPLER, index) where index is resolved at link-time to an
+ * actual texture unit (as specified by the user calling glUniform1i()).
+ */
+GLboolean
+_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
+                               slang_unit_type type)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_program *prog = A->program;
+   const char *varName = (char *) var->a_name;
+   GLboolean success = GL_TRUE;
+   slang_ir_storage *store = NULL;
+   int dbg = 0;
+   const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
+   const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
+   const GLint arrayLen = _slang_array_length(var);
+   const GLint totalSize = _slang_array_size(size, arrayLen);
+   GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
+
+   var->is_global = GL_TRUE;
+
+   /* check for sampler2D arrays */
+   if (texIndex == -1 && var->type.specifier._array)
+      texIndex = sampler_to_texture_index(var->type.specifier._array->type);
+
+   if (texIndex != -1) {
+      /* This is a texture sampler variable...
+       * store->File = PROGRAM_SAMPLER
+       * store->Index = sampler number (0..7, typically)
+       * store->Size = texture type index (1D, 2D, 3D, cube, etc)
+       */
+      if (var->initializer) {
+         slang_info_log_error(A->log, "illegal assignment to '%s'", varName);
+         return GL_FALSE;
+      }
+#if FEATURE_es2_glsl /* XXX should use FEATURE_texture_rect */
+      /* disallow rect samplers */
+      if (ctx->API == API_OPENGLES2 &&
+         is_rect_sampler_spec(&var->type.specifier)) {
+         slang_info_log_error(A->log, "invalid sampler type for '%s'", varName);
+         return GL_FALSE;
+      }
+#else
+      (void) is_rect_sampler_spec; /* silence warning */
+      (void) ctx;
+#endif
+      {
+         GLint sampNum = _mesa_add_sampler(prog->Parameters, varName, datatype);
+         store = _slang_new_ir_storage_sampler(sampNum, texIndex, totalSize);
+
+         /* If we have a sampler array, then we need to allocate the 
+         * additional samplers to ensure we don't allocate them elsewhere.
+         * We can't directly use _mesa_add_sampler() as that checks the
+         * varName and gets a match, so we call _mesa_add_parameter()
+         * directly and use the last sampler number from the call above.
+         */
+        if (arrayLen > 0) {
+           GLint a = arrayLen - 1;
+           GLint i;
+           for (i = 0; i < a; i++) {
+               GLfloat value = (GLfloat)(i + sampNum + 1);
+               (void) _mesa_add_parameter(prog->Parameters, PROGRAM_SAMPLER,
+                                 varName, 1, datatype, &value, NULL, 0x0);
+           }
+        }
+      }
+      if (dbg) printf("SAMPLER ");
+   }
+   else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
+      /* Uniform variable */
+      const GLuint swizzle = _slang_var_swizzle(totalSize, 0);
+
+      if (prog) {
+         /* user-defined uniform */
+         if (datatype == GL_NONE) {
+           if ((var->type.specifier.type == SLANG_SPEC_ARRAY &&
+                var->type.specifier._array->type == SLANG_SPEC_STRUCT) ||
+                (var->type.specifier.type == SLANG_SPEC_STRUCT)) {
+               /* temporary work-around */
+               GLenum datatype = GL_FLOAT;
+               GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName,
+                                                    totalSize, datatype, NULL);
+               store = _slang_new_ir_storage_swz(PROGRAM_UNIFORM, uniformLoc,
+                                                 totalSize, swizzle);
+        
+              if (arrayLen > 0) {
+                 GLint a = arrayLen - 1;
+                 GLint i;
+                 for (i = 0; i < a; i++) {
+                     GLfloat value = (GLfloat)(i + uniformLoc + 1);
+                     (void) _mesa_add_parameter(prog->Parameters, PROGRAM_UNIFORM,
+                                 varName, 1, datatype, &value, NULL, 0x0);
+                  }
+              }
+
+               /* XXX what we need to do is unroll the struct into its
+                * basic types, creating a uniform variable for each.
+                * For example:
+                * struct foo {
+                *   vec3 a;
+                *   vec4 b;
+                * };
+                * uniform foo f;
+                *
+                * Should produce uniforms:
+                * "f.a"  (GL_FLOAT_VEC3)
+                * "f.b"  (GL_FLOAT_VEC4)
+                */
+
+               if (var->initializer) {
+                  slang_info_log_error(A->log,
+                     "unsupported initializer for uniform '%s'", varName);
+                  return GL_FALSE;
+               }
+            }
+            else {
+               slang_info_log_error(A->log,
+                                    "invalid datatype for uniform variable %s",
+                                    varName);
+               return GL_FALSE;
+            }
+         }
+         else {
+            /* non-struct uniform */
+            if (!_slang_gen_var_decl(A, var, var->initializer))
+               return GL_FALSE;
+            store = var->store;
+         }
+      }
+      else {
+         /* pre-defined uniform, like gl_ModelviewMatrix */
+         /* We know it's a uniform, but don't allocate storage unless
+          * it's really used.
+          */
+         store = _slang_new_ir_storage_swz(PROGRAM_STATE_VAR, -1,
+                                           totalSize, swizzle);
+      }
+      if (dbg) printf("UNIFORM (sz %d) ", totalSize);
+   }
+   else if (var->type.qualifier == SLANG_QUAL_VARYING) {
+      /* varyings must be float, vec or mat */
+      if (!_slang_type_is_float_vec_mat(var->type.specifier.type) &&
+          var->type.specifier.type != SLANG_SPEC_ARRAY) {
+         slang_info_log_error(A->log,
+                              "varying '%s' must be float/vector/matrix",
+                              varName);
+         return GL_FALSE;
+      }
+
+      if (var->initializer) {
+         slang_info_log_error(A->log, "illegal initializer for varying '%s'",
+                              varName);
+         return GL_FALSE;
+      }
+
+      if (prog) {
+         /* user-defined varying */
+         GLbitfield flags;
+         GLint varyingLoc;
+         GLuint swizzle;
+
+         flags = 0x0;
+         if (var->type.centroid == SLANG_CENTROID)
+            flags |= PROG_PARAM_BIT_CENTROID;
+         if (var->type.variant == SLANG_INVARIANT)
+            flags |= PROG_PARAM_BIT_INVARIANT;
+
+         varyingLoc = _mesa_add_varying(prog->Varying, varName,
+                                        totalSize, GL_NONE, flags);
+         swizzle = _slang_var_swizzle(size, 0);
+         store = _slang_new_ir_storage_swz(PROGRAM_VARYING, varyingLoc,
+                                           totalSize, swizzle);
+      }
+      else {
+         /* pre-defined varying, like gl_Color or gl_TexCoord */
+         if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
+            /* fragment program input */
+            GLuint swizzle;
+            GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
+                                             &swizzle);
+            assert(index >= 0);
+            assert(index < FRAG_ATTRIB_MAX);
+            store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index,
+                                              size, swizzle);
+         }
+         else {
+            /* vertex program output */
+            GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
+            GLuint swizzle = _slang_var_swizzle(size, 0);
+            assert(index >= 0);
+            assert(index < VERT_RESULT_MAX);
+            assert(type == SLANG_UNIT_VERTEX_BUILTIN);
+            store = _slang_new_ir_storage_swz(PROGRAM_OUTPUT, index,
+                                              size, swizzle);
+         }
+         if (dbg) printf("V/F ");
+      }
+      if (dbg) printf("VARYING ");
+   }
+   else if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE) {
+      GLuint swizzle;
+      GLint index;
+      /* attributes must be float, vec or mat */
+      if (!_slang_type_is_float_vec_mat(var->type.specifier.type)) {
+         slang_info_log_error(A->log,
+                              "attribute '%s' must be float/vector/matrix",
+                              varName);
+         return GL_FALSE;
+      }
+
+      if (prog) {
+         /* user-defined vertex attribute */
+         const GLint attr = -1; /* unknown */
+         swizzle = _slang_var_swizzle(size, 0);
+         index = _mesa_add_attribute(prog->Attributes, varName,
+                                     size, datatype, attr);
+         assert(index >= 0);
+         index = VERT_ATTRIB_GENERIC0 + index;
+      }
+      else {
+         /* pre-defined vertex attrib */
+         index = _slang_input_index(varName, GL_VERTEX_PROGRAM_ARB, &swizzle);
+         assert(index >= 0);
+      }
+      store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
+      if (dbg) printf("ATTRIB ");
+   }
+   else if (var->type.qualifier == SLANG_QUAL_FIXEDINPUT) {
+      GLuint swizzle = SWIZZLE_XYZW; /* silence compiler warning */
+      GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
+                                       &swizzle);
+      store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
+      if (dbg) printf("INPUT ");
+   }
+   else if (var->type.qualifier == SLANG_QUAL_FIXEDOUTPUT) {
+      if (type == SLANG_UNIT_VERTEX_BUILTIN) {
+         GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
+         store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
+      }
+      else {
+         GLint index = _slang_output_index(varName, GL_FRAGMENT_PROGRAM_ARB);
+         GLint specialSize = 4; /* treat all fragment outputs as float[4] */
+         assert(type == SLANG_UNIT_FRAGMENT_BUILTIN);
+         store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, specialSize);
+      }
+      if (dbg) printf("OUTPUT ");
+   }
+   else if (var->type.qualifier == SLANG_QUAL_CONST && !prog) {
+      /* pre-defined global constant, like gl_MaxLights */
+      store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size);
+      if (dbg) printf("CONST ");
+   }
+   else {
+      /* ordinary variable (may be const) */
+      slang_ir_node *n;
+
+      /* IR node to declare the variable */
+      n = _slang_gen_var_decl(A, var, var->initializer);
+
+      /* emit GPU instructions */
+      success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_FALSE, A->log);
+
+      _slang_free_ir_tree(n);
+   }
+
+   if (dbg) printf("GLOBAL VAR %s  idx %d\n", (char*) var->a_name,
+                   store ? store->Index : -2);
+
+   if (store)
+      var->store = store;  /* save var's storage info */
+
+   var->declared = GL_TRUE;
+
+   return success;
+}
+
+
+/**
+ * Produce an IR tree from a function AST (fun->body).
+ * Then call the code emitter to convert the IR tree into gl_program
+ * instructions.
+ */
+GLboolean
+_slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
+{
+   slang_ir_node *n;
+   GLboolean success = GL_TRUE;
+
+   if (strcmp((char *) fun->header.a_name, "main") != 0) {
+      /* we only really generate code for main, all other functions get
+       * inlined or codegen'd upon an actual call.
+       */
+#if 0
+      /* do some basic error checking though */
+      if (fun->header.type.specifier.type != SLANG_SPEC_VOID) {
+         /* check that non-void functions actually return something */
+         slang_operation *op
+            = _slang_find_node_type(fun->body, SLANG_OPER_RETURN);
+         if (!op) {
+            slang_info_log_error(A->log,
+                                 "function \"%s\" has no return statement",
+                                 (char *) fun->header.a_name);
+            printf(
+                   "function \"%s\" has no return statement\n",
+                   (char *) fun->header.a_name);
+            return GL_FALSE;
+         }
+      }
+#endif
+      return GL_TRUE;  /* not an error */
+   }
+
+#if 0
+   printf("\n*********** codegen_function %s\n", (char *) fun->header.a_name);
+   slang_print_function(fun, 1);
+#endif
+
+   /* should have been allocated earlier: */
+   assert(A->program->Parameters );
+   assert(A->program->Varying);
+   assert(A->vartable);
+
+   A->LoopDepth = 0;
+   A->UseReturnFlag = GL_FALSE;
+   A->CurFunction = fun;
+
+   /* fold constant expressions, etc. */
+   _slang_simplify(fun->body, &A->space, A->atoms);
+
+#if 0
+   printf("\n*********** simplified %s\n", (char *) fun->header.a_name);
+   slang_print_function(fun, 1);
+#endif
+
+   /* Create an end-of-function label */
+   A->curFuncEndLabel = _slang_label_new("__endOfFunc__main");
+
+   /* push new vartable scope */
+   _slang_push_var_table(A->vartable);
+
+   /* Generate IR tree for the function body code */
+   n = _slang_gen_operation(A, fun->body);
+   if (n)
+      n = new_node1(IR_SCOPE, n);
+
+   /* pop vartable, restore previous */
+   _slang_pop_var_table(A->vartable);
+
+   if (!n) {
+      /* XXX record error */
+      return GL_FALSE;
+   }
+
+   /* append an end-of-function-label to IR tree */
+   n = new_seq(n, new_label(A->curFuncEndLabel));
+
+   /*_slang_label_delete(A->curFuncEndLabel);*/
+   A->curFuncEndLabel = NULL;
+
+#if 0
+   printf("************* New AST for %s *****\n", (char*)fun->header.a_name);
+   slang_print_function(fun, 1);
+#endif
+#if 0
+   printf("************* IR for %s *******\n", (char*)fun->header.a_name);
+   _slang_print_ir_tree(n, 0);
+#endif
+#if 0
+   printf("************* End codegen function ************\n\n");
+#endif
+
+   if (A->UnresolvedRefs) {
+      /* Can't codegen at this time.
+       * At link time we'll concatenate all the vertex shaders and/or all
+       * the fragment shaders and try recompiling.
+       */
+      return GL_TRUE;
+   }
+
+   /* Emit program instructions */
+   success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_TRUE, A->log);
+   _slang_free_ir_tree(n);
+
+   /* free codegen context */
+   /*
+   free(A->codegen);
+   */
+
+   return success;
+}
+
diff --git a/src/mesa/slang/slang_codegen.h b/src/mesa/slang/slang_codegen.h
new file mode 100644 (file)
index 0000000..461633f
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef SLANG_CODEGEN_H
+#define SLANG_CODEGEN_H
+
+
+#include "main/imports.h"
+#include "slang_compile.h"
+
+
+#define MAX_LOOP_DEPTH 30
+
+
+typedef struct slang_assemble_ctx_
+{
+   slang_atom_pool *atoms;
+   slang_name_space space;
+   struct gl_program *program;
+   struct gl_sl_pragmas *pragmas;
+   slang_var_table *vartable;
+   slang_info_log *log;
+   GLboolean allow_uniform_initializers;
+
+   /* current loop stack */
+   const slang_operation *LoopOperStack[MAX_LOOP_DEPTH];
+   struct slang_ir_node_ *LoopIRStack[MAX_LOOP_DEPTH];
+   GLuint LoopDepth;
+
+   /* current function */
+   struct slang_function_ *CurFunction;
+   struct slang_label_ *curFuncEndLabel;
+   GLboolean UseReturnFlag;
+
+   GLboolean UnresolvedRefs;
+   GLboolean EmitContReturn;
+} slang_assemble_ctx;
+
+
+extern GLuint
+_slang_sizeof_type_specifier(const slang_type_specifier *spec);
+
+extern GLboolean
+_slang_codegen_function(slang_assemble_ctx *A , struct slang_function_ *fun);
+
+extern GLboolean
+_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
+                               slang_unit_type type);
+
+
+#endif /* SLANG_CODEGEN_H */
diff --git a/src/mesa/slang/slang_compile.c b/src/mesa/slang/slang_compile.c
new file mode 100644 (file)
index 0000000..b6b1f3c
--- /dev/null
@@ -0,0 +1,3044 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_compile.c
+ * slang front-end compiler
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "shader/program.h"
+#include "shader/programopt.h"
+#include "shader/prog_optimize.h"
+#include "shader/prog_print.h"
+#include "shader/prog_parameter.h"
+#include "../../glsl/pp/sl_pp_public.h"
+#include "../../glsl/cl/sl_cl_parse.h"
+#include "slang_codegen.h"
+#include "slang_compile.h"
+#include "slang_storage.h"
+#include "slang_log.h"
+#include "slang_mem.h"
+#include "slang_vartable.h"
+#include "slang_simplify.h"
+
+/*
+ * This is a straightforward implementation of the slang front-end
+ * compiler.  Lots of error-checking functionality is missing but
+ * every well-formed shader source should compile successfully and
+ * execute as expected. However, some semantically ill-formed shaders
+ * may be accepted resulting in undefined behaviour.
+ */
+
+
+/** re-defined below, should be the same though */
+#define TYPE_SPECIFIER_COUNT 36
+
+
+/**
+ * Check if the given identifier is legal.
+ */
+static GLboolean
+legal_identifier(slang_atom name)
+{
+   /* "gl_" is a reserved prefix */
+   if (strncmp((char *) name, "gl_", 3) == 0) {
+      return GL_FALSE;
+   }
+   return GL_TRUE;
+}
+
+
+/*
+ * slang_code_unit
+ */
+
+GLvoid
+_slang_code_unit_ctr(slang_code_unit * self,
+                     struct slang_code_object_ * object)
+{
+   _slang_variable_scope_ctr(&self->vars);
+   _slang_function_scope_ctr(&self->funs);
+   _slang_struct_scope_ctr(&self->structs);
+   self->object = object;
+}
+
+GLvoid
+_slang_code_unit_dtr(slang_code_unit * self)
+{
+   slang_variable_scope_destruct(&self->vars);
+   slang_function_scope_destruct(&self->funs);
+   slang_struct_scope_destruct(&self->structs);
+}
+
+/*
+ * slang_code_object
+ */
+
+GLvoid
+_slang_code_object_ctr(slang_code_object * self)
+{
+   GLuint i;
+
+   for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
+      _slang_code_unit_ctr(&self->builtin[i], self);
+   _slang_code_unit_ctr(&self->unit, self);
+   slang_atom_pool_construct(&self->atompool);
+}
+
+GLvoid
+_slang_code_object_dtr(slang_code_object * self)
+{
+   GLuint i;
+
+   for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
+      _slang_code_unit_dtr(&self->builtin[i]);
+   _slang_code_unit_dtr(&self->unit);
+   slang_atom_pool_destruct(&self->atompool);
+}
+
+
+/* slang_parse_ctx */
+
+typedef struct slang_parse_ctx_
+{
+   const unsigned char *I;
+   slang_info_log *L;
+   int parsing_builtin;
+   GLboolean global_scope;   /**< Is object being declared a global? */
+   slang_atom_pool *atoms;
+   slang_unit_type type;     /**< Vertex vs. Fragment */
+   GLuint version;           /**< user-specified (or default) #version */
+} slang_parse_ctx;
+
+/* slang_output_ctx */
+
+typedef struct slang_output_ctx_
+{
+   slang_variable_scope *vars;
+   slang_function_scope *funs;
+   slang_struct_scope *structs;
+   struct gl_program *program;
+   struct gl_sl_pragmas *pragmas;
+   slang_var_table *vartable;
+   GLuint default_precision[TYPE_SPECIFIER_COUNT];
+   GLboolean allow_precision;
+   GLboolean allow_invariant;
+   GLboolean allow_centroid;
+   GLboolean allow_array_types;  /* float[] syntax */
+} slang_output_ctx;
+
+/* _slang_compile() */
+
+
+/* Debugging aid, print file/line where parsing error is detected */
+#define RETURN0 \
+   do { \
+      if (0) \
+         printf("slang error at %s:%d\n", __FILE__, __LINE__); \
+      return 0; \
+   } while (0)
+
+
+static void
+parse_identifier_str(slang_parse_ctx * C, char **id)
+{
+   *id = (char *) C->I;
+   C->I += strlen(*id) + 1;
+}
+
+static slang_atom
+parse_identifier(slang_parse_ctx * C)
+{
+   const char *id;
+
+   id = (const char *) C->I;
+   C->I += strlen(id) + 1;
+   return slang_atom_pool_atom(C->atoms, id);
+}
+
+static int
+is_hex_digit(char c)
+{
+   return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
+}
+
+static int
+parse_general_number(slang_parse_ctx *ctx, float *number)
+{
+   char *flt = NULL;
+
+   if (*ctx->I == '0') {
+      int value = 0;
+      const unsigned char *pi;
+
+      if (ctx->I[1] == 'x' || ctx->I[1] == 'X') {
+         ctx->I += 2;
+         if (!is_hex_digit(*ctx->I)) {
+            return 0;
+         }
+         do {
+            int digit;
+
+            if (*ctx->I >= '0' && *ctx->I <= '9') {
+               digit = (int)(*ctx->I - '0');
+            } else if (*ctx->I >= 'a' && *ctx->I <= 'f') {
+               digit = (int)(*ctx->I - 'a') + 10;
+            } else {
+               digit = (int)(*ctx->I - 'A') + 10;
+            }
+            value = value * 0x10 + digit;
+            ctx->I++;
+         } while (is_hex_digit(*ctx->I));
+         if (*ctx->I != '\0') {
+            return 0;
+         }
+         ctx->I++;
+         *number = (float)value;
+         return 1;
+      }
+
+      pi = ctx->I;
+      pi++;
+      while (*pi >= '0' && *pi <= '7') {
+         int digit;
+
+         digit = (int)(*pi - '0');
+         value = value * 010 + digit;
+         pi++;
+      }
+      if (*pi == '\0') {
+         pi++;
+         ctx->I = pi;
+         *number = (float)value;
+         return 1;
+      }
+   }
+
+   parse_identifier_str(ctx, &flt);
+   flt = _mesa_strdup(flt);
+   if (!flt) {
+      return 0;
+   }
+   if (flt[strlen(flt) - 1] == 'f' || flt[strlen(flt) - 1] == 'F') {
+      flt[strlen(flt) - 1] = '\0';
+   }
+   *number = _mesa_strtof(flt, (char **)NULL);
+   free(flt);
+
+   return 1;
+}
+
+static int
+parse_number(slang_parse_ctx * C, int *number)
+{
+   const int radix = (int) (*C->I++);
+
+   if (radix == 1) {
+      float f = 0.0f;
+
+      parse_general_number(C, &f);
+      *number = (int)f;
+   } else {
+      *number = 0;
+      while (*C->I != '\0') {
+         int digit;
+         if (*C->I >= '0' && *C->I <= '9')
+            digit = (int) (*C->I - '0');
+         else if (*C->I >= 'A' && *C->I <= 'Z')
+            digit = (int) (*C->I - 'A') + 10;
+         else
+            digit = (int) (*C->I - 'a') + 10;
+         *number = *number * radix + digit;
+         C->I++;
+      }
+      C->I++;
+   }
+   if (*number > 65535)
+      slang_info_log_warning(C->L, "%d: literal integer overflow.", *number);
+   return 1;
+}
+
+static int
+parse_float(slang_parse_ctx * C, float *number)
+{
+   if (*C->I == 1) {
+      C->I++;
+      parse_general_number(C, number);
+   } else {
+      char *integral = NULL;
+      char *fractional = NULL;
+      char *exponent = NULL;
+      char *whole = NULL;
+
+      parse_identifier_str(C, &integral);
+      parse_identifier_str(C, &fractional);
+      parse_identifier_str(C, &exponent);
+
+      whole = (char *) _slang_alloc((strlen(integral) +
+                                     strlen(fractional) +
+                                     strlen(exponent) + 3) * sizeof(char));
+      if (whole == NULL) {
+         slang_info_log_memory(C->L);
+         RETURN0;
+      }
+
+      slang_string_copy(whole, integral);
+      slang_string_concat(whole, ".");
+      slang_string_concat(whole, fractional);
+      slang_string_concat(whole, "E");
+      slang_string_concat(whole, exponent);
+
+      *number = _mesa_strtof(whole, (char **) NULL);
+
+      _slang_free(whole);
+   }
+
+   return 1;
+}
+
+/* revision number - increment after each change affecting emitted output */
+#define REVISION 5
+
+static int
+check_revision(slang_parse_ctx * C)
+{
+   if (*C->I != REVISION) {
+      slang_info_log_error(C->L, "Internal compiler error.");
+      RETURN0;
+   }
+   C->I++;
+   return 1;
+}
+
+static int parse_statement(slang_parse_ctx *, slang_output_ctx *,
+                           slang_operation *);
+static int parse_expression(slang_parse_ctx *, slang_output_ctx *,
+                            slang_operation *);
+static int parse_type_specifier(slang_parse_ctx *, slang_output_ctx *,
+                                slang_type_specifier *);
+static int
+parse_type_array_size(slang_parse_ctx *C,
+                      slang_output_ctx *O,
+                      GLint *array_len);
+
+static GLboolean
+parse_array_len(slang_parse_ctx * C, slang_output_ctx * O, GLuint * len)
+{
+   slang_operation array_size;
+   slang_name_space space;
+   GLboolean result;
+
+   if (!slang_operation_construct(&array_size))
+      return GL_FALSE;
+   if (!parse_expression(C, O, &array_size)) {
+      slang_operation_destruct(&array_size);
+      return GL_FALSE;
+   }
+
+   space.funcs = O->funs;
+   space.structs = O->structs;
+   space.vars = O->vars;
+
+   /* evaluate compile-time expression which is array size */
+   _slang_simplify(&array_size, &space, C->atoms);
+
+   if (array_size.type == SLANG_OPER_LITERAL_INT) {
+      result = GL_TRUE;
+      *len = (GLint) array_size.literal[0];
+   } else if (array_size.type == SLANG_OPER_IDENTIFIER) {
+      slang_variable *var = _slang_variable_locate(array_size.locals, array_size.a_id, GL_TRUE);
+      if (!var) {
+         slang_info_log_error(C->L, "undefined variable '%s'",
+                              (char *) array_size.a_id);
+         result = GL_FALSE;
+      } else if (var->type.qualifier == SLANG_QUAL_CONST &&
+                 var->type.specifier.type == SLANG_SPEC_INT) {
+         if (var->initializer &&
+             var->initializer->type == SLANG_OPER_LITERAL_INT) {
+            *len = (GLint) var->initializer->literal[0];
+            result = GL_TRUE;
+         } else {
+            slang_info_log_error(C->L, "unable to parse array size declaration");
+            result = GL_FALSE;
+         }
+      } else {
+         slang_info_log_error(C->L, "unable to parse array size declaration");
+         result = GL_FALSE;
+      }
+   } else {
+      result = GL_FALSE;
+   }
+
+   slang_operation_destruct(&array_size);
+   return result;
+}
+
+static GLboolean
+calculate_var_size(slang_parse_ctx * C, slang_output_ctx * O,
+                   slang_variable * var)
+{
+   slang_storage_aggregate agg;
+
+   if (!slang_storage_aggregate_construct(&agg))
+      return GL_FALSE;
+   if (!_slang_aggregate_variable(&agg, &var->type.specifier, var->array_len,
+                                  O->funs, O->structs, O->vars, C->atoms)) {
+      slang_storage_aggregate_destruct(&agg);
+      return GL_FALSE;
+   }
+   var->size = _slang_sizeof_aggregate(&agg);
+   slang_storage_aggregate_destruct(&agg);
+   return GL_TRUE;
+}
+
+static void
+promote_type_to_array(slang_parse_ctx *C,
+                      slang_fully_specified_type *type,
+                      GLint array_len)
+{
+   slang_type_specifier *baseType =
+      slang_type_specifier_new(type->specifier.type, NULL, NULL);
+
+   type->specifier.type = SLANG_SPEC_ARRAY;
+   type->specifier._array = baseType;
+   type->array_len = array_len;
+}
+
+
+static GLboolean
+convert_to_array(slang_parse_ctx * C, slang_variable * var,
+                 const slang_type_specifier * sp)
+{
+   /* sized array - mark it as array, copy the specifier to the array element
+    * and parse the expression */
+   var->type.specifier.type = SLANG_SPEC_ARRAY;
+   var->type.specifier._array = (slang_type_specifier *)
+      _slang_alloc(sizeof(slang_type_specifier));
+   if (var->type.specifier._array == NULL) {
+      slang_info_log_memory(C->L);
+      return GL_FALSE;
+   }
+   slang_type_specifier_ctr(var->type.specifier._array);
+   return slang_type_specifier_copy(var->type.specifier._array, sp);
+}
+
+/* structure field */
+#define FIELD_NONE 0
+#define FIELD_NEXT 1
+#define FIELD_ARRAY 2
+
+static GLboolean
+parse_struct_field_var(slang_parse_ctx * C, slang_output_ctx * O,
+                       slang_variable * var, slang_atom a_name,
+                       const slang_type_specifier * sp,
+                       GLuint array_len)
+{
+   var->a_name = a_name;
+   if (var->a_name == SLANG_ATOM_NULL)
+      return GL_FALSE;
+
+   switch (*C->I++) {
+   case FIELD_NONE:
+      if (array_len != -1) {
+         if (!convert_to_array(C, var, sp))
+            return GL_FALSE;
+         var->array_len = array_len;
+      }
+      else {
+         if (!slang_type_specifier_copy(&var->type.specifier, sp))
+            return GL_FALSE;
+      }
+      break;
+   case FIELD_ARRAY:
+      if (array_len != -1)
+         return GL_FALSE;
+      if (!convert_to_array(C, var, sp))
+         return GL_FALSE;
+      if (!parse_array_len(C, O, &var->array_len))
+         return GL_FALSE;
+      break;
+   default:
+      return GL_FALSE;
+   }
+
+   return calculate_var_size(C, O, var);
+}
+
+static int
+parse_struct_field(slang_parse_ctx * C, slang_output_ctx * O,
+                   slang_struct * st, slang_type_specifier * sp)
+{
+   slang_output_ctx o = *O;
+   GLint array_len;
+
+   o.structs = st->structs;
+   if (!parse_type_specifier(C, &o, sp))
+      RETURN0;
+   if (!parse_type_array_size(C, &o, &array_len))
+      RETURN0;
+
+   do {
+      slang_atom a_name;
+      slang_variable *var = slang_variable_scope_grow(st->fields);
+      if (!var) {
+         slang_info_log_memory(C->L);
+         RETURN0;
+      }
+      a_name = parse_identifier(C);
+      if (_slang_variable_locate(st->fields, a_name, GL_FALSE)) {
+         slang_info_log_error(C->L, "duplicate field '%s'", (char *) a_name);
+         RETURN0;
+      }
+
+      if (!parse_struct_field_var(C, &o, var, a_name, sp, array_len))
+         RETURN0;
+   }
+   while (*C->I++ != FIELD_NONE);
+
+   return 1;
+}
+
+static int
+parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st)
+{
+   slang_atom a_name;
+   const char *name;
+
+   /* parse struct name (if any) and make sure it is unique in current scope */
+   a_name = parse_identifier(C);
+   if (a_name == SLANG_ATOM_NULL)
+      RETURN0;
+
+   name = slang_atom_pool_id(C->atoms, a_name);
+   if (name[0] != '\0'
+       && slang_struct_scope_find(O->structs, a_name, 0) != NULL) {
+      slang_info_log_error(C->L, "%s: duplicate type name.", name);
+      RETURN0;
+   }
+
+   /* set-up a new struct */
+   *st = (slang_struct *) _slang_alloc(sizeof(slang_struct));
+   if (*st == NULL) {
+      slang_info_log_memory(C->L);
+      RETURN0;
+   }
+   if (!slang_struct_construct(*st)) {
+      _slang_free(*st);
+      *st = NULL;
+      slang_info_log_memory(C->L);
+      RETURN0;
+   }
+   (**st).a_name = a_name;
+   (**st).structs->outer_scope = O->structs;
+
+   /* parse individual struct fields */
+   do {
+      slang_type_specifier sp;
+
+      slang_type_specifier_ctr(&sp);
+      if (!parse_struct_field(C, O, *st, &sp)) {
+         slang_type_specifier_dtr(&sp);
+         RETURN0;
+      }
+      slang_type_specifier_dtr(&sp);
+   }
+   while (*C->I++ != FIELD_NONE);
+
+   /* if named struct, copy it to current scope */
+   if (name[0] != '\0') {
+      slang_struct *s;
+
+      O->structs->structs =
+         (slang_struct *) _slang_realloc(O->structs->structs,
+                                         O->structs->num_structs
+                                         * sizeof(slang_struct),
+                                         (O->structs->num_structs + 1)
+                                         * sizeof(slang_struct));
+      if (O->structs->structs == NULL) {
+         slang_info_log_memory(C->L);
+         RETURN0;
+      }
+      s = &O->structs->structs[O->structs->num_structs];
+      if (!slang_struct_construct(s))
+         RETURN0;
+      O->structs->num_structs++;
+      if (!slang_struct_copy(s, *st))
+         RETURN0;
+   }
+
+   return 1;
+}
+
+
+/* invariant qualifer */
+#define TYPE_VARIANT    90
+#define TYPE_INVARIANT  91
+
+static int
+parse_type_variant(slang_parse_ctx * C, slang_type_variant *variant)
+{
+   GLuint invariant = *C->I++;
+   switch (invariant) {
+   case TYPE_VARIANT:
+      *variant = SLANG_VARIANT;
+      return 1;
+   case TYPE_INVARIANT:
+      *variant = SLANG_INVARIANT;
+      return 1;
+   default:
+      RETURN0;
+   }
+}
+
+
+/* centroid qualifer */
+#define TYPE_CENTER    95
+#define TYPE_CENTROID  96
+
+static int
+parse_type_centroid(slang_parse_ctx * C, slang_type_centroid *centroid)
+{
+   GLuint c = *C->I++;
+   switch (c) {
+   case TYPE_CENTER:
+      *centroid = SLANG_CENTER;
+      return 1;
+   case TYPE_CENTROID:
+      *centroid = SLANG_CENTROID;
+      return 1;
+   default:
+      RETURN0;
+   }
+}
+
+
+/* Layout qualifiers */
+#define LAYOUT_QUALIFIER_NONE                      0
+#define LAYOUT_QUALIFIER_UPPER_LEFT                1
+#define LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER      2
+
+static int
+parse_layout_qualifiers(slang_parse_ctx * C, slang_layout_qualifier *layout)
+{
+   *layout = 0x0;
+
+   /* the layout qualifiers come as a list of LAYOUT_QUALIFER_x tokens,
+    * terminated by LAYOUT_QUALIFIER_NONE.
+    */
+   while (1) {
+      GLuint c = *C->I++;
+      switch (c) {
+      case LAYOUT_QUALIFIER_NONE:
+         /* end of list of qualifiers */
+         return 1;
+      case LAYOUT_QUALIFIER_UPPER_LEFT:
+         *layout |= SLANG_LAYOUT_UPPER_LEFT_BIT;
+         break;
+      case LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER:
+         *layout |= SLANG_LAYOUT_PIXEL_CENTER_INTEGER_BIT;
+         break;
+      default:
+         assert(0 && "Bad layout qualifier");
+      }
+   }
+}
+
+
+/* type qualifier */
+#define TYPE_QUALIFIER_NONE 0
+#define TYPE_QUALIFIER_CONST 1
+#define TYPE_QUALIFIER_ATTRIBUTE 2
+#define TYPE_QUALIFIER_VARYING 3
+#define TYPE_QUALIFIER_UNIFORM 4
+#define TYPE_QUALIFIER_FIXEDOUTPUT 5
+#define TYPE_QUALIFIER_FIXEDINPUT 6
+
+static int
+parse_type_qualifier(slang_parse_ctx * C, slang_type_qualifier * qual)
+{
+   GLuint qualifier = *C->I++;
+   switch (qualifier) {
+   case TYPE_QUALIFIER_NONE:
+      *qual = SLANG_QUAL_NONE;
+      break;
+   case TYPE_QUALIFIER_CONST:
+      *qual = SLANG_QUAL_CONST;
+      break;
+   case TYPE_QUALIFIER_ATTRIBUTE:
+      *qual = SLANG_QUAL_ATTRIBUTE;
+      break;
+   case TYPE_QUALIFIER_VARYING:
+      *qual = SLANG_QUAL_VARYING;
+      break;
+   case TYPE_QUALIFIER_UNIFORM:
+      *qual = SLANG_QUAL_UNIFORM;
+      break;
+   case TYPE_QUALIFIER_FIXEDOUTPUT:
+      *qual = SLANG_QUAL_FIXEDOUTPUT;
+      break;
+   case TYPE_QUALIFIER_FIXEDINPUT:
+      *qual = SLANG_QUAL_FIXEDINPUT;
+      break;
+   default:
+      RETURN0;
+   }
+   return 1;
+}
+
+/* type specifier */
+#define TYPE_SPECIFIER_VOID 0
+#define TYPE_SPECIFIER_BOOL 1
+#define TYPE_SPECIFIER_BVEC2 2
+#define TYPE_SPECIFIER_BVEC3 3
+#define TYPE_SPECIFIER_BVEC4 4
+#define TYPE_SPECIFIER_INT 5
+#define TYPE_SPECIFIER_IVEC2 6
+#define TYPE_SPECIFIER_IVEC3 7
+#define TYPE_SPECIFIER_IVEC4 8
+#define TYPE_SPECIFIER_FLOAT 9
+#define TYPE_SPECIFIER_VEC2 10
+#define TYPE_SPECIFIER_VEC3 11
+#define TYPE_SPECIFIER_VEC4 12
+#define TYPE_SPECIFIER_MAT2 13
+#define TYPE_SPECIFIER_MAT3 14
+#define TYPE_SPECIFIER_MAT4 15
+#define TYPE_SPECIFIER_SAMPLER1D 16
+#define TYPE_SPECIFIER_SAMPLER2D 17
+#define TYPE_SPECIFIER_SAMPLER3D 18
+#define TYPE_SPECIFIER_SAMPLERCUBE 19
+#define TYPE_SPECIFIER_SAMPLER1DSHADOW 20
+#define TYPE_SPECIFIER_SAMPLER2DSHADOW 21
+#define TYPE_SPECIFIER_SAMPLER2DRECT 22
+#define TYPE_SPECIFIER_SAMPLER2DRECTSHADOW 23
+#define TYPE_SPECIFIER_STRUCT 24
+#define TYPE_SPECIFIER_TYPENAME 25
+#define TYPE_SPECIFIER_MAT23 26
+#define TYPE_SPECIFIER_MAT32 27
+#define TYPE_SPECIFIER_MAT24 28
+#define TYPE_SPECIFIER_MAT42 29
+#define TYPE_SPECIFIER_MAT34 30
+#define TYPE_SPECIFIER_MAT43 31
+#define TYPE_SPECIFIER_SAMPLER_1D_ARRAY 32
+#define TYPE_SPECIFIER_SAMPLER_2D_ARRAY 33
+#define TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW 34
+#define TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW 35
+#define TYPE_SPECIFIER_COUNT 36
+
+static int
+parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O,
+                     slang_type_specifier * spec)
+{
+   int type = *C->I++;
+   switch (type) {
+   case TYPE_SPECIFIER_VOID:
+      spec->type = SLANG_SPEC_VOID;
+      break;
+   case TYPE_SPECIFIER_BOOL:
+      spec->type = SLANG_SPEC_BOOL;
+      break;
+   case TYPE_SPECIFIER_BVEC2:
+      spec->type = SLANG_SPEC_BVEC2;
+      break;
+   case TYPE_SPECIFIER_BVEC3:
+      spec->type = SLANG_SPEC_BVEC3;
+      break;
+   case TYPE_SPECIFIER_BVEC4:
+      spec->type = SLANG_SPEC_BVEC4;
+      break;
+   case TYPE_SPECIFIER_INT:
+      spec->type = SLANG_SPEC_INT;
+      break;
+   case TYPE_SPECIFIER_IVEC2:
+      spec->type = SLANG_SPEC_IVEC2;
+      break;
+   case TYPE_SPECIFIER_IVEC3:
+      spec->type = SLANG_SPEC_IVEC3;
+      break;
+   case TYPE_SPECIFIER_IVEC4:
+      spec->type = SLANG_SPEC_IVEC4;
+      break;
+   case TYPE_SPECIFIER_FLOAT:
+      spec->type = SLANG_SPEC_FLOAT;
+      break;
+   case TYPE_SPECIFIER_VEC2:
+      spec->type = SLANG_SPEC_VEC2;
+      break;
+   case TYPE_SPECIFIER_VEC3:
+      spec->type = SLANG_SPEC_VEC3;
+      break;
+   case TYPE_SPECIFIER_VEC4:
+      spec->type = SLANG_SPEC_VEC4;
+      break;
+   case TYPE_SPECIFIER_MAT2:
+      spec->type = SLANG_SPEC_MAT2;
+      break;
+   case TYPE_SPECIFIER_MAT3:
+      spec->type = SLANG_SPEC_MAT3;
+      break;
+   case TYPE_SPECIFIER_MAT4:
+      spec->type = SLANG_SPEC_MAT4;
+      break;
+   case TYPE_SPECIFIER_MAT23:
+      spec->type = SLANG_SPEC_MAT23;
+      break;
+   case TYPE_SPECIFIER_MAT32:
+      spec->type = SLANG_SPEC_MAT32;
+      break;
+   case TYPE_SPECIFIER_MAT24:
+      spec->type = SLANG_SPEC_MAT24;
+      break;
+   case TYPE_SPECIFIER_MAT42:
+      spec->type = SLANG_SPEC_MAT42;
+      break;
+   case TYPE_SPECIFIER_MAT34:
+      spec->type = SLANG_SPEC_MAT34;
+      break;
+   case TYPE_SPECIFIER_MAT43:
+      spec->type = SLANG_SPEC_MAT43;
+      break;
+   case TYPE_SPECIFIER_SAMPLER1D:
+      spec->type = SLANG_SPEC_SAMPLER_1D;
+      break;
+   case TYPE_SPECIFIER_SAMPLER2D:
+      spec->type = SLANG_SPEC_SAMPLER_2D;
+      break;
+   case TYPE_SPECIFIER_SAMPLER3D:
+      spec->type = SLANG_SPEC_SAMPLER_3D;
+      break;
+   case TYPE_SPECIFIER_SAMPLERCUBE:
+      spec->type = SLANG_SPEC_SAMPLER_CUBE;
+      break;
+   case TYPE_SPECIFIER_SAMPLER2DRECT:
+      spec->type = SLANG_SPEC_SAMPLER_RECT;
+      break;
+   case TYPE_SPECIFIER_SAMPLER1DSHADOW:
+      spec->type = SLANG_SPEC_SAMPLER_1D_SHADOW;
+      break;
+   case TYPE_SPECIFIER_SAMPLER2DSHADOW:
+      spec->type = SLANG_SPEC_SAMPLER_2D_SHADOW;
+      break;
+   case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW:
+      spec->type = SLANG_SPEC_SAMPLER_RECT_SHADOW;
+      break;
+   case TYPE_SPECIFIER_SAMPLER_1D_ARRAY:
+      spec->type = SLANG_SPEC_SAMPLER_1D_ARRAY;
+      break;
+   case TYPE_SPECIFIER_SAMPLER_2D_ARRAY:
+      spec->type = SLANG_SPEC_SAMPLER_2D_ARRAY;
+      break;
+   case TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW:
+      spec->type = SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW;
+      break;
+   case TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW:
+      spec->type = SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW;
+      break;
+   case TYPE_SPECIFIER_STRUCT:
+      spec->type = SLANG_SPEC_STRUCT;
+      if (!parse_struct(C, O, &spec->_struct))
+         RETURN0;
+      break;
+   case TYPE_SPECIFIER_TYPENAME:
+      spec->type = SLANG_SPEC_STRUCT;
+      {
+         slang_atom a_name;
+         slang_struct *stru;
+
+         a_name = parse_identifier(C);
+         if (a_name == NULL)
+            RETURN0;
+
+         stru = slang_struct_scope_find(O->structs, a_name, 1);
+         if (stru == NULL) {
+            slang_info_log_error(C->L, "undeclared type name '%s'",
+                                 slang_atom_pool_id(C->atoms, a_name));
+            RETURN0;
+         }
+
+         spec->_struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
+         if (spec->_struct == NULL) {
+            slang_info_log_memory(C->L);
+            RETURN0;
+         }
+         if (!slang_struct_construct(spec->_struct)) {
+            _slang_free(spec->_struct);
+            spec->_struct = NULL;
+            RETURN0;
+         }
+         if (!slang_struct_copy(spec->_struct, stru))
+            RETURN0;
+      }
+      break;
+   default:
+      RETURN0;
+   }
+   return 1;
+}
+
+#define TYPE_SPECIFIER_NONARRAY 0
+#define TYPE_SPECIFIER_ARRAY    1
+
+static int
+parse_type_array_size(slang_parse_ctx *C,
+                      slang_output_ctx *O,
+                      GLint *array_len)
+{
+   GLuint size;
+
+   switch (*C->I++) {
+   case TYPE_SPECIFIER_NONARRAY:
+      *array_len = -1; /* -1 = not an array */
+      break;
+   case TYPE_SPECIFIER_ARRAY:
+      if (!parse_array_len(C, O, &size))
+         RETURN0;
+      *array_len = (GLint) size;
+      break;
+   default:
+      assert(0);
+      RETURN0;
+   }
+   return 1;
+}
+
+#define PRECISION_DEFAULT 0
+#define PRECISION_LOW     1
+#define PRECISION_MEDIUM  2
+#define PRECISION_HIGH    3
+
+static int
+parse_type_precision(slang_parse_ctx *C,
+                     slang_type_precision *precision)
+{
+   GLint prec = *C->I++;
+   switch (prec) {
+   case PRECISION_DEFAULT:
+      *precision = SLANG_PREC_DEFAULT;
+      return 1;
+   case PRECISION_LOW:
+      *precision = SLANG_PREC_LOW;
+      return 1;
+   case PRECISION_MEDIUM:
+      *precision = SLANG_PREC_MEDIUM;
+      return 1;
+   case PRECISION_HIGH:
+      *precision = SLANG_PREC_HIGH;
+      return 1;
+   default:
+      RETURN0;
+   }
+}
+
+static int
+parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
+                           slang_fully_specified_type * type)
+{
+   if (!parse_layout_qualifiers(C, &type->layout))
+      RETURN0;
+
+   if (!parse_type_variant(C, &type->variant))
+      RETURN0;
+
+   if (!parse_type_centroid(C, &type->centroid))
+      RETURN0;
+
+   if (!parse_type_qualifier(C, &type->qualifier))
+      RETURN0;
+
+   if (!parse_type_precision(C, &type->precision))
+      RETURN0;
+
+   if (!parse_type_specifier(C, O, &type->specifier))
+      RETURN0;
+
+   if (!parse_type_array_size(C, O, &type->array_len))
+      RETURN0;
+
+   if (!O->allow_invariant && type->variant == SLANG_INVARIANT) {
+      slang_info_log_error(C->L,
+         "'invariant' keyword not allowed (perhaps set #version 120)");
+      RETURN0;
+   }
+
+   if (!O->allow_centroid && type->centroid == SLANG_CENTROID) {
+      slang_info_log_error(C->L,
+         "'centroid' keyword not allowed (perhaps set #version 120)");
+      RETURN0;
+   }
+   else if (type->centroid == SLANG_CENTROID &&
+            type->qualifier != SLANG_QUAL_VARYING) {
+      slang_info_log_error(C->L,
+         "'centroid' keyword only allowed for varying vars");
+      RETURN0;
+   }
+
+
+   /* need this?
+   if (type->qualifier != SLANG_QUAL_VARYING &&
+       type->variant == SLANG_INVARIANT) {
+      slang_info_log_error(C->L,
+                           "invariant qualifer only allowed for varying vars");
+      RETURN0;
+   }
+   */
+
+   if (O->allow_precision) {
+      if (type->precision == SLANG_PREC_DEFAULT) {
+         assert(type->specifier.type < TYPE_SPECIFIER_COUNT);
+         /* use the default precision for this datatype */
+         type->precision = O->default_precision[type->specifier.type];
+      }
+   }
+   else {
+      /* only default is allowed */
+      if (type->precision != SLANG_PREC_DEFAULT) {
+         slang_info_log_error(C->L, "precision qualifiers not allowed");
+         RETURN0;
+      }
+   }
+
+   if (!O->allow_array_types && type->array_len >= 0) {
+      slang_info_log_error(C->L, "first-class array types not allowed");
+      RETURN0;
+   }
+
+   if (type->array_len >= 0) {
+      /* convert type to array type (ex: convert "int" to "array of int" */
+      promote_type_to_array(C, type, type->array_len);
+   }
+
+   return 1;
+}
+
+/* operation */
+#define OP_END 0
+#define OP_BLOCK_BEGIN_NO_NEW_SCOPE 1
+#define OP_BLOCK_BEGIN_NEW_SCOPE 2
+#define OP_DECLARE 3
+#define OP_ASM 4
+#define OP_BREAK 5
+#define OP_CONTINUE 6
+#define OP_DISCARD 7
+#define OP_RETURN 8
+#define OP_EXPRESSION 9
+#define OP_IF 10
+#define OP_WHILE 11
+#define OP_DO 12
+#define OP_FOR 13
+#define OP_PUSH_VOID 14
+#define OP_PUSH_BOOL 15
+#define OP_PUSH_INT 16
+#define OP_PUSH_FLOAT 17
+#define OP_PUSH_IDENTIFIER 18
+#define OP_SEQUENCE 19
+#define OP_ASSIGN 20
+#define OP_ADDASSIGN 21
+#define OP_SUBASSIGN 22
+#define OP_MULASSIGN 23
+#define OP_DIVASSIGN 24
+/*#define OP_MODASSIGN 25*/
+/*#define OP_LSHASSIGN 26*/
+/*#define OP_RSHASSIGN 27*/
+/*#define OP_ORASSIGN 28*/
+/*#define OP_XORASSIGN 29*/
+/*#define OP_ANDASSIGN 30*/
+#define OP_SELECT 31
+#define OP_LOGICALOR 32
+#define OP_LOGICALXOR 33
+#define OP_LOGICALAND 34
+/*#define OP_BITOR 35*/
+/*#define OP_BITXOR 36*/
+/*#define OP_BITAND 37*/
+#define OP_EQUAL 38
+#define OP_NOTEQUAL 39
+#define OP_LESS 40
+#define OP_GREATER 41
+#define OP_LESSEQUAL 42
+#define OP_GREATEREQUAL 43
+/*#define OP_LSHIFT 44*/
+/*#define OP_RSHIFT 45*/
+#define OP_ADD 46
+#define OP_SUBTRACT 47
+#define OP_MULTIPLY 48
+#define OP_DIVIDE 49
+/*#define OP_MODULUS 50*/
+#define OP_PREINCREMENT 51
+#define OP_PREDECREMENT 52
+#define OP_PLUS 53
+#define OP_MINUS 54
+/*#define OP_COMPLEMENT 55*/
+#define OP_NOT 56
+#define OP_SUBSCRIPT 57
+#define OP_CALL 58
+#define OP_FIELD 59
+#define OP_POSTINCREMENT 60
+#define OP_POSTDECREMENT 61
+#define OP_PRECISION 62
+#define OP_METHOD 63
+
+
+/**
+ * When parsing a compound production, this function is used to parse the
+ * children.
+ * For example, a while-loop compound will have two children, the
+ * while condition expression and the loop body.  So, this function will
+ * be called twice to parse those two sub-expressions.
+ * \param C  the parsing context
+ * \param O  the output context
+ * \param oper  the operation we're parsing
+ * \param statement  indicates whether parsing a statement, or expression
+ * \return 1 if success, 0 if error
+ */
+static int
+parse_child_operation(slang_parse_ctx * C, slang_output_ctx * O,
+                      slang_operation * oper, GLboolean statement)
+{
+   slang_operation *ch;
+
+   /* grow child array */
+   ch = slang_operation_grow(&oper->num_children, &oper->children);
+   if (statement)
+      return parse_statement(C, O, ch);
+   return parse_expression(C, O, ch);
+}
+
+static int parse_declaration(slang_parse_ctx * C, slang_output_ctx * O);
+
+static int
+parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
+                slang_operation * oper)
+{
+   int op;
+
+   oper->locals->outer_scope = O->vars;
+
+   op = *C->I++;
+   switch (op) {
+   case OP_BLOCK_BEGIN_NO_NEW_SCOPE:
+      /* parse child statements, do not create new variable scope */
+      oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
+      while (*C->I != OP_END)
+         if (!parse_child_operation(C, O, oper, GL_TRUE))
+            RETURN0;
+      C->I++;
+      break;
+   case OP_BLOCK_BEGIN_NEW_SCOPE:
+      /* parse child statements, create new variable scope */
+      {
+         slang_output_ctx o = *O;
+
+         oper->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+         o.vars = oper->locals;
+         while (*C->I != OP_END)
+            if (!parse_child_operation(C, &o, oper, GL_TRUE))
+               RETURN0;
+         C->I++;
+      }
+      break;
+   case OP_DECLARE:
+      /* local variable declaration, individual declarators are stored as
+       * children identifiers
+       */
+      oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
+      {
+         const unsigned int first_var = O->vars->num_variables;
+
+         /* parse the declaration, note that there can be zero or more
+          * than one declarators
+          */
+         if (!parse_declaration(C, O))
+            RETURN0;
+         if (first_var < O->vars->num_variables) {
+            const unsigned int num_vars = O->vars->num_variables - first_var;
+            unsigned int i;
+            assert(oper->num_children == 0);
+            oper->num_children = num_vars;
+            oper->children = slang_operation_new(num_vars);
+            if (oper->children == NULL) {
+               slang_info_log_memory(C->L);
+               RETURN0;
+            }
+            for (i = first_var; i < O->vars->num_variables; i++) {
+               slang_operation *o = &oper->children[i - first_var];
+               slang_variable *var = O->vars->variables[i];
+               o->type = SLANG_OPER_VARIABLE_DECL;
+               o->locals->outer_scope = O->vars;
+               o->a_id = var->a_name;
+
+               /* new/someday...
+               calculate_var_size(C, O, var);
+               */
+
+               if (!legal_identifier(o->a_id)) {
+                  slang_info_log_error(C->L, "illegal variable name '%s'",
+                                       (char *) o->a_id);
+                  RETURN0;
+               }
+            }
+         }
+      }
+      break;
+   case OP_ASM:
+      /* the __asm statement, parse the mnemonic and all its arguments
+       * as expressions
+       */
+      oper->type = SLANG_OPER_ASM;
+      oper->a_id = parse_identifier(C);
+      if (oper->a_id == SLANG_ATOM_NULL)
+         RETURN0;
+      while (*C->I != OP_END) {
+         if (!parse_child_operation(C, O, oper, GL_FALSE))
+            RETURN0;
+      }
+      C->I++;
+      break;
+   case OP_BREAK:
+      oper->type = SLANG_OPER_BREAK;
+      break;
+   case OP_CONTINUE:
+      oper->type = SLANG_OPER_CONTINUE;
+      break;
+   case OP_DISCARD:
+      oper->type = SLANG_OPER_DISCARD;
+      break;
+   case OP_RETURN:
+      oper->type = SLANG_OPER_RETURN;
+      if (!parse_child_operation(C, O, oper, GL_FALSE))
+         RETURN0;
+      break;
+   case OP_EXPRESSION:
+      oper->type = SLANG_OPER_EXPRESSION;
+      if (!parse_child_operation(C, O, oper, GL_FALSE))
+         RETURN0;
+      break;
+   case OP_IF:
+      oper->type = SLANG_OPER_IF;
+      if (!parse_child_operation(C, O, oper, GL_FALSE))
+         RETURN0;
+      if (!parse_child_operation(C, O, oper, GL_TRUE))
+         RETURN0;
+      if (!parse_child_operation(C, O, oper, GL_TRUE))
+         RETURN0;
+      break;
+   case OP_WHILE:
+      {
+         slang_output_ctx o = *O;
+
+         oper->type = SLANG_OPER_WHILE;
+         o.vars = oper->locals;
+         if (!parse_child_operation(C, &o, oper, GL_TRUE))
+            RETURN0;
+         if (!parse_child_operation(C, &o, oper, GL_TRUE))
+            RETURN0;
+      }
+      break;
+   case OP_DO:
+      oper->type = SLANG_OPER_DO;
+      if (!parse_child_operation(C, O, oper, GL_TRUE))
+         RETURN0;
+      if (!parse_child_operation(C, O, oper, GL_FALSE))
+         RETURN0;
+      break;
+   case OP_FOR:
+      {
+         slang_output_ctx o = *O;
+
+         oper->type = SLANG_OPER_FOR;
+         o.vars = oper->locals;
+         if (!parse_child_operation(C, &o, oper, GL_TRUE))
+            RETURN0;
+         if (!parse_child_operation(C, &o, oper, GL_TRUE))
+            RETURN0;
+         if (!parse_child_operation(C, &o, oper, GL_FALSE))
+            RETURN0;
+         if (!parse_child_operation(C, &o, oper, GL_TRUE))
+            RETURN0;
+      }
+      break;
+   case OP_PRECISION:
+      {
+         /* set default precision for a type in this scope */
+         /* ignored at this time */
+         int prec_qual = *C->I++;
+         int datatype = *C->I++;
+         (void) prec_qual;
+         (void) datatype;
+      }
+      break;
+   default:
+      /*printf("Unexpected operation %d\n", op);*/
+      RETURN0;
+   }
+   return 1;
+}
+
+static int
+handle_nary_expression(slang_parse_ctx * C, slang_operation * op,
+                       slang_operation ** ops, unsigned int *total_ops,
+                       unsigned int n)
+{
+   unsigned int i;
+
+   op->children = slang_operation_new(n);
+   if (op->children == NULL) {
+      slang_info_log_memory(C->L);
+      RETURN0;
+   }
+   op->num_children = n;
+
+   for (i = 0; i < n; i++) {
+      slang_operation_destruct(&op->children[i]);
+      op->children[i] = (*ops)[*total_ops - (n + 1 - i)];
+   }
+
+   (*ops)[*total_ops - (n + 1)] = (*ops)[*total_ops - 1];
+   *total_ops -= n;
+
+   *ops = (slang_operation *)
+      _slang_realloc(*ops,
+                     (*total_ops + n) * sizeof(slang_operation),
+                     *total_ops * sizeof(slang_operation));
+   if (*ops == NULL) {
+      slang_info_log_memory(C->L);
+      RETURN0;
+   }
+   return 1;
+}
+
+static int
+is_constructor_name(const char *name, slang_atom a_name,
+                    slang_struct_scope * structs)
+{
+   if (slang_type_specifier_type_from_string(name) != SLANG_SPEC_VOID)
+      return 1;
+   return slang_struct_scope_find(structs, a_name, 1) != NULL;
+}
+
+#define FUNCTION_CALL_NONARRAY 0
+#define FUNCTION_CALL_ARRAY    1
+
+static int
+parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
+                 slang_operation * oper)
+{
+   slang_operation *ops = NULL;
+   unsigned int num_ops = 0;
+   int number;
+
+   while (*C->I != OP_END) {
+      slang_operation *op;
+      const unsigned int op_code = *C->I++;
+
+      /* allocate default operation, becomes a no-op if not used  */
+      ops = (slang_operation *)
+         _slang_realloc(ops,
+                        num_ops * sizeof(slang_operation),
+                        (num_ops + 1) * sizeof(slang_operation));
+      if (ops == NULL) {
+         slang_info_log_memory(C->L);
+         RETURN0;
+      }
+      op = &ops[num_ops];
+      if (!slang_operation_construct(op)) {
+         slang_info_log_memory(C->L);
+         RETURN0;
+      }
+      num_ops++;
+      op->locals->outer_scope = O->vars;
+
+      switch (op_code) {
+      case OP_PUSH_VOID:
+         op->type = SLANG_OPER_VOID;
+         break;
+      case OP_PUSH_BOOL:
+         op->type = SLANG_OPER_LITERAL_BOOL;
+         if (!parse_number(C, &number))
+            RETURN0;
+         op->literal[0] =
+         op->literal[1] =
+         op->literal[2] =
+         op->literal[3] = (GLfloat) number;
+         op->literal_size = 1;
+         break;
+      case OP_PUSH_INT:
+         op->type = SLANG_OPER_LITERAL_INT;
+         if (!parse_number(C, &number))
+            RETURN0;
+         op->literal[0] =
+         op->literal[1] =
+         op->literal[2] =
+         op->literal[3] = (GLfloat) number;
+         op->literal_size = 1;
+         break;
+      case OP_PUSH_FLOAT:
+         op->type = SLANG_OPER_LITERAL_FLOAT;
+         if (!parse_float(C, &op->literal[0]))
+            RETURN0;
+         op->literal[1] =
+         op->literal[2] =
+         op->literal[3] = op->literal[0];
+         op->literal_size = 1;
+         break;
+      case OP_PUSH_IDENTIFIER:
+         op->type = SLANG_OPER_IDENTIFIER;
+         op->a_id = parse_identifier(C);
+         if (op->a_id == SLANG_ATOM_NULL)
+            RETURN0;
+         break;
+      case OP_SEQUENCE:
+         op->type = SLANG_OPER_SEQUENCE;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_ASSIGN:
+         op->type = SLANG_OPER_ASSIGN;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_ADDASSIGN:
+         op->type = SLANG_OPER_ADDASSIGN;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_SUBASSIGN:
+         op->type = SLANG_OPER_SUBASSIGN;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_MULASSIGN:
+         op->type = SLANG_OPER_MULASSIGN;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_DIVASSIGN:
+         op->type = SLANG_OPER_DIVASSIGN;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+         /*case OP_MODASSIGN: */
+         /*case OP_LSHASSIGN: */
+         /*case OP_RSHASSIGN: */
+         /*case OP_ORASSIGN: */
+         /*case OP_XORASSIGN: */
+         /*case OP_ANDASSIGN: */
+      case OP_SELECT:
+         op->type = SLANG_OPER_SELECT;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 3))
+            RETURN0;
+         break;
+      case OP_LOGICALOR:
+         op->type = SLANG_OPER_LOGICALOR;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_LOGICALXOR:
+         op->type = SLANG_OPER_LOGICALXOR;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_LOGICALAND:
+         op->type = SLANG_OPER_LOGICALAND;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+         /*case OP_BITOR: */
+         /*case OP_BITXOR: */
+         /*case OP_BITAND: */
+      case OP_EQUAL:
+         op->type = SLANG_OPER_EQUAL;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_NOTEQUAL:
+         op->type = SLANG_OPER_NOTEQUAL;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_LESS:
+         op->type = SLANG_OPER_LESS;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_GREATER:
+         op->type = SLANG_OPER_GREATER;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_LESSEQUAL:
+         op->type = SLANG_OPER_LESSEQUAL;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_GREATEREQUAL:
+         op->type = SLANG_OPER_GREATEREQUAL;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+         /*case OP_LSHIFT: */
+         /*case OP_RSHIFT: */
+      case OP_ADD:
+         op->type = SLANG_OPER_ADD;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_SUBTRACT:
+         op->type = SLANG_OPER_SUBTRACT;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_MULTIPLY:
+         op->type = SLANG_OPER_MULTIPLY;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_DIVIDE:
+         op->type = SLANG_OPER_DIVIDE;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+         /*case OP_MODULUS: */
+      case OP_PREINCREMENT:
+         op->type = SLANG_OPER_PREINCREMENT;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+            RETURN0;
+         break;
+      case OP_PREDECREMENT:
+         op->type = SLANG_OPER_PREDECREMENT;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+            RETURN0;
+         break;
+      case OP_PLUS:
+         op->type = SLANG_OPER_PLUS;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+            RETURN0;
+         break;
+      case OP_MINUS:
+         op->type = SLANG_OPER_MINUS;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+            RETURN0;
+         break;
+      case OP_NOT:
+         op->type = SLANG_OPER_NOT;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+            RETURN0;
+         break;
+         /*case OP_COMPLEMENT: */
+      case OP_SUBSCRIPT:
+         op->type = SLANG_OPER_SUBSCRIPT;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+            RETURN0;
+         break;
+      case OP_METHOD:
+         op->type = SLANG_OPER_METHOD;
+         op->a_obj = parse_identifier(C);
+         if (op->a_obj == SLANG_ATOM_NULL)
+            RETURN0;
+
+         op->a_id = parse_identifier(C);
+         if (op->a_id == SLANG_ATOM_NULL)
+            RETURN0;
+
+         assert(*C->I == OP_END);
+         C->I++;
+
+         while (*C->I != OP_END)
+            if (!parse_child_operation(C, O, op, GL_FALSE))
+               RETURN0;
+         C->I++;
+#if 0
+         /* don't lookup the method (not yet anyway) */
+         if (!C->parsing_builtin
+             && !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) {
+            const char *id;
+
+            id = slang_atom_pool_id(C->atoms, op->a_id);
+            if (!is_constructor_name(id, op->a_id, O->structs)) {
+               slang_info_log_error(C->L, "%s: undeclared function name.", id);
+               RETURN0;
+            }
+         }
+#endif
+         break;
+      case OP_CALL:
+         {
+            GLboolean array_constructor = GL_FALSE;
+            GLint array_constructor_size = 0;
+
+            op->type = SLANG_OPER_CALL;
+            op->a_id = parse_identifier(C);
+            if (op->a_id == SLANG_ATOM_NULL)
+               RETURN0;
+            switch (*C->I++) {
+            case FUNCTION_CALL_NONARRAY:
+               /* Nothing to do. */
+               break;
+            case FUNCTION_CALL_ARRAY:
+               /* Calling an array constructor. For example:
+                *   float[3](1.1, 2.2, 3.3);
+                */
+               if (!O->allow_array_types) {
+                  slang_info_log_error(C->L,
+                                       "array constructors not allowed "
+                                       "in this GLSL version");
+                  RETURN0;
+               }
+               else {
+                  /* parse the array constructor size */
+                  slang_operation array_size;
+                  array_constructor = GL_TRUE;
+                  slang_operation_construct(&array_size);
+                  if (!parse_expression(C, O, &array_size)) {
+                     slang_operation_destruct(&array_size);
+                     return GL_FALSE;
+                  }
+                  if (array_size.type != SLANG_OPER_LITERAL_INT) {
+                     slang_info_log_error(C->L,
+                        "constructor array size is not an integer");
+                     slang_operation_destruct(&array_size);
+                     RETURN0;
+                  }
+                  array_constructor_size = (int) array_size.literal[0];
+                  op->array_constructor = GL_TRUE;
+                  slang_operation_destruct(&array_size);
+               }
+               break;
+            default:
+               assert(0);
+               RETURN0;
+            }
+            while (*C->I != OP_END)
+               if (!parse_child_operation(C, O, op, GL_FALSE))
+                  RETURN0;
+            C->I++;
+
+            if (array_constructor &&
+                array_constructor_size != op->num_children) {
+               slang_info_log_error(C->L, "number of parameters to array"
+                                    " constructor does not match array size");
+               RETURN0;
+            }
+
+            if (!C->parsing_builtin
+                && !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) {
+               const char *id;
+
+               id = slang_atom_pool_id(C->atoms, op->a_id);
+               if (!is_constructor_name(id, op->a_id, O->structs)) {
+                  slang_info_log_error(C->L, "%s: undeclared function name.", id);
+                  RETURN0;
+               }
+            }
+         }
+         break;
+      case OP_FIELD:
+         op->type = SLANG_OPER_FIELD;
+         op->a_id = parse_identifier(C);
+         if (op->a_id == SLANG_ATOM_NULL)
+            RETURN0;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+            RETURN0;
+         break;
+      case OP_POSTINCREMENT:
+         op->type = SLANG_OPER_POSTINCREMENT;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+            RETURN0;
+         break;
+      case OP_POSTDECREMENT:
+         op->type = SLANG_OPER_POSTDECREMENT;
+         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+            RETURN0;
+         break;
+      default:
+         RETURN0;
+      }
+   }
+   C->I++;
+
+   slang_operation_destruct(oper);
+   *oper = *ops; /* struct copy */
+   _slang_free(ops);
+
+   return 1;
+}
+
+/* parameter qualifier */
+#define PARAM_QUALIFIER_IN 0
+#define PARAM_QUALIFIER_OUT 1
+#define PARAM_QUALIFIER_INOUT 2
+
+/* function parameter array presence */
+#define PARAMETER_ARRAY_NOT_PRESENT 0
+#define PARAMETER_ARRAY_PRESENT 1
+
+static int
+parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
+                            slang_variable * param)
+{
+   int param_qual, precision_qual;
+
+   /* parse and validate the parameter's type qualifiers (there can be
+    * two at most) because not all combinations are valid
+    */
+   if (!parse_type_qualifier(C, &param->type.qualifier))
+      RETURN0;
+
+   param_qual = *C->I++;
+   switch (param_qual) {
+   case PARAM_QUALIFIER_IN:
+      if (param->type.qualifier != SLANG_QUAL_CONST
+          && param->type.qualifier != SLANG_QUAL_NONE) {
+         slang_info_log_error(C->L, "Invalid type qualifier.");
+         RETURN0;
+      }
+      break;
+   case PARAM_QUALIFIER_OUT:
+      if (param->type.qualifier == SLANG_QUAL_NONE)
+         param->type.qualifier = SLANG_QUAL_OUT;
+      else {
+         slang_info_log_error(C->L, "Invalid type qualifier.");
+         RETURN0;
+      }
+      break;
+   case PARAM_QUALIFIER_INOUT:
+      if (param->type.qualifier == SLANG_QUAL_NONE)
+         param->type.qualifier = SLANG_QUAL_INOUT;
+      else {
+         slang_info_log_error(C->L, "Invalid type qualifier.");
+         RETURN0;
+      }
+      break;
+   default:
+      RETURN0;
+   }
+
+   /* parse precision qualifier (lowp, mediump, highp */
+   precision_qual = *C->I++;
+   /* ignored at this time */
+   (void) precision_qual;
+
+   /* parse parameter's type specifier and name */
+   if (!parse_type_specifier(C, O, &param->type.specifier))
+      RETURN0;
+   if (!parse_type_array_size(C, O, &param->type.array_len))
+      RETURN0;
+   param->a_name = parse_identifier(C);
+   if (param->a_name == SLANG_ATOM_NULL)
+      RETURN0;
+
+   /* first-class array
+    */
+   if (param->type.array_len >= 0) {
+      slang_type_specifier p;
+
+      slang_type_specifier_ctr(&p);
+      if (!slang_type_specifier_copy(&p, &param->type.specifier)) {
+         slang_type_specifier_dtr(&p);
+         RETURN0;
+      }
+      if (!convert_to_array(C, param, &p)) {
+         slang_type_specifier_dtr(&p);
+         RETURN0;
+      }
+      slang_type_specifier_dtr(&p);
+      param->array_len = param->type.array_len;
+   }
+
+   /* if the parameter is an array, parse its size (the size must be
+    * explicitly defined
+    */
+   if (*C->I++ == PARAMETER_ARRAY_PRESENT) {
+      slang_type_specifier p;
+
+      if (param->type.array_len >= 0) {
+         slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
+         RETURN0;
+      }
+      slang_type_specifier_ctr(&p);
+      if (!slang_type_specifier_copy(&p, &param->type.specifier)) {
+         slang_type_specifier_dtr(&p);
+         RETURN0;
+      }
+      if (!convert_to_array(C, param, &p)) {
+         slang_type_specifier_dtr(&p);
+         RETURN0;
+      }
+      slang_type_specifier_dtr(&p);
+      if (!parse_array_len(C, O, &param->array_len))
+         RETURN0;
+   }
+
+#if 0
+   /* calculate the parameter size */
+   if (!calculate_var_size(C, O, param))
+      RETURN0;
+#endif
+   /* TODO: allocate the local address here? */
+   return 1;
+}
+
+/* function type */
+#define FUNCTION_ORDINARY 0
+#define FUNCTION_CONSTRUCTOR 1
+#define FUNCTION_OPERATOR 2
+
+/* function parameter */
+#define PARAMETER_NONE 0
+#define PARAMETER_NEXT 1
+
+/* operator type */
+#define OPERATOR_ADDASSIGN 1
+#define OPERATOR_SUBASSIGN 2
+#define OPERATOR_MULASSIGN 3
+#define OPERATOR_DIVASSIGN 4
+/*#define OPERATOR_MODASSIGN 5*/
+/*#define OPERATOR_LSHASSIGN 6*/
+/*#define OPERATOR_RSHASSIGN 7*/
+/*#define OPERATOR_ANDASSIGN 8*/
+/*#define OPERATOR_XORASSIGN 9*/
+/*#define OPERATOR_ORASSIGN 10*/
+#define OPERATOR_LOGICALXOR 11
+/*#define OPERATOR_BITOR 12*/
+/*#define OPERATOR_BITXOR 13*/
+/*#define OPERATOR_BITAND 14*/
+#define OPERATOR_LESS 15
+#define OPERATOR_GREATER 16
+#define OPERATOR_LESSEQUAL 17
+#define OPERATOR_GREATEREQUAL 18
+/*#define OPERATOR_LSHIFT 19*/
+/*#define OPERATOR_RSHIFT 20*/
+#define OPERATOR_MULTIPLY 21
+#define OPERATOR_DIVIDE 22
+/*#define OPERATOR_MODULUS 23*/
+#define OPERATOR_INCREMENT 24
+#define OPERATOR_DECREMENT 25
+#define OPERATOR_PLUS 26
+#define OPERATOR_MINUS 27
+/*#define OPERATOR_COMPLEMENT 28*/
+#define OPERATOR_NOT 29
+
+static const struct
+{
+   unsigned int o_code;
+   const char *o_name;
+} operator_names[] = {
+   {OPERATOR_INCREMENT, "++"},
+   {OPERATOR_ADDASSIGN, "+="},
+   {OPERATOR_PLUS, "+"},
+   {OPERATOR_DECREMENT, "--"},
+   {OPERATOR_SUBASSIGN, "-="},
+   {OPERATOR_MINUS, "-"},
+   {OPERATOR_NOT, "!"},
+   {OPERATOR_MULASSIGN, "*="},
+   {OPERATOR_MULTIPLY, "*"},
+   {OPERATOR_DIVASSIGN, "/="},
+   {OPERATOR_DIVIDE, "/"},
+   {OPERATOR_LESSEQUAL, "<="},
+   /*{ OPERATOR_LSHASSIGN, "<<=" }, */
+   /*{ OPERATOR_LSHIFT, "<<" }, */
+   {OPERATOR_LESS, "<"},
+   {OPERATOR_GREATEREQUAL, ">="},
+   /*{ OPERATOR_RSHASSIGN, ">>=" }, */
+   /*{ OPERATOR_RSHIFT, ">>" }, */
+   {OPERATOR_GREATER, ">"},
+   /*{ OPERATOR_MODASSIGN, "%=" }, */
+   /*{ OPERATOR_MODULUS, "%" }, */
+   /*{ OPERATOR_ANDASSIGN, "&=" }, */
+   /*{ OPERATOR_BITAND, "&" }, */
+   /*{ OPERATOR_ORASSIGN, "|=" }, */
+   /*{ OPERATOR_BITOR, "|" }, */
+   /*{ OPERATOR_COMPLEMENT, "~" }, */
+   /*{ OPERATOR_XORASSIGN, "^=" }, */
+   {OPERATOR_LOGICALXOR, "^^"},
+   /*{ OPERATOR_BITXOR, "^" } */
+};
+
+static slang_atom
+parse_operator_name(slang_parse_ctx * C)
+{
+   unsigned int i;
+
+   for (i = 0; i < sizeof(operator_names) / sizeof(*operator_names); i++) {
+      if (operator_names[i].o_code == (unsigned int) (*C->I)) {
+         slang_atom atom =
+            slang_atom_pool_atom(C->atoms, operator_names[i].o_name);
+         if (atom == SLANG_ATOM_NULL) {
+            slang_info_log_memory(C->L);
+            RETURN0;
+         }
+         C->I++;
+         return atom;
+      }
+   }
+   RETURN0;
+}
+
+
+static int
+parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O,
+                         slang_function * func)
+{
+   GLuint functype;
+   /* parse function type and name */
+   if (!parse_fully_specified_type(C, O, &func->header.type))
+      RETURN0;
+
+   functype = *C->I++;
+   switch (functype) {
+   case FUNCTION_ORDINARY:
+      func->kind = SLANG_FUNC_ORDINARY;
+      func->header.a_name = parse_identifier(C);
+      if (func->header.a_name == SLANG_ATOM_NULL)
+         RETURN0;
+      break;
+   case FUNCTION_CONSTRUCTOR:
+      func->kind = SLANG_FUNC_CONSTRUCTOR;
+      if (func->header.type.specifier.type == SLANG_SPEC_STRUCT)
+         RETURN0;
+      func->header.a_name =
+         slang_atom_pool_atom(C->atoms,
+                              slang_type_specifier_type_to_string
+                              (func->header.type.specifier.type));
+      if (func->header.a_name == SLANG_ATOM_NULL) {
+         slang_info_log_memory(C->L);
+         RETURN0;
+      }
+      break;
+   case FUNCTION_OPERATOR:
+      func->kind = SLANG_FUNC_OPERATOR;
+      func->header.a_name = parse_operator_name(C);
+      if (func->header.a_name == SLANG_ATOM_NULL)
+         RETURN0;
+      break;
+   default:
+      RETURN0;
+   }
+
+   if (!legal_identifier(func->header.a_name)) {
+      slang_info_log_error(C->L, "illegal function name '%s'",
+                           (char *) func->header.a_name);
+      RETURN0;
+   }
+
+   /* parse function parameters */
+   while (*C->I++ == PARAMETER_NEXT) {
+      slang_variable *p = slang_variable_scope_grow(func->parameters);
+      if (!p) {
+         slang_info_log_memory(C->L);
+         RETURN0;
+      }
+      if (!parse_parameter_declaration(C, O, p))
+         RETURN0;
+   }
+
+   /* if the function returns a value, append a hidden __retVal 'out'
+    * parameter that corresponds to the return value.
+    */
+   if (_slang_function_has_return_value(func)) {
+      slang_variable *p = slang_variable_scope_grow(func->parameters);
+      slang_atom a_retVal = slang_atom_pool_atom(C->atoms, "__retVal");
+      assert(a_retVal);
+      p->a_name = a_retVal;
+      p->type = func->header.type;
+      p->type.qualifier = SLANG_QUAL_OUT;
+   }
+
+   /* function formal parameters and local variables share the same
+    * scope, so save the information about param count in a seperate
+    * place also link the scope to the global variable scope so when a
+    * given identifier is not found here, the search process continues
+    * in the global space
+    */
+   func->param_count = func->parameters->num_variables;
+   func->parameters->outer_scope = O->vars;
+
+   return 1;
+}
+
+static int
+parse_function_definition(slang_parse_ctx * C, slang_output_ctx * O,
+                          slang_function * func)
+{
+   slang_output_ctx o = *O;
+
+   if (!parse_function_prototype(C, O, func))
+      RETURN0;
+
+   /* create function's body operation */
+   func->body = (slang_operation *) _slang_alloc(sizeof(slang_operation));
+   if (func->body == NULL) {
+      slang_info_log_memory(C->L);
+      RETURN0;
+   }
+   if (!slang_operation_construct(func->body)) {
+      _slang_free(func->body);
+      func->body = NULL;
+      slang_info_log_memory(C->L);
+      RETURN0;
+   }
+
+   /* to parse the body the parse context is modified in order to
+    * capture parsed variables into function's local variable scope
+    */
+   C->global_scope = GL_FALSE;
+   o.vars = func->parameters;
+   if (!parse_statement(C, &o, func->body))
+      RETURN0;
+
+   C->global_scope = GL_TRUE;
+   return 1;
+}
+
+static GLboolean
+initialize_global(slang_assemble_ctx * A, slang_variable * var)
+{
+   slang_operation op_id, op_assign;
+   GLboolean result;
+
+   /* construct the left side of assignment */
+   if (!slang_operation_construct(&op_id))
+      return GL_FALSE;
+   op_id.type = SLANG_OPER_IDENTIFIER;
+   op_id.a_id = var->a_name;
+
+   /* put the variable into operation's scope */
+   op_id.locals->variables =
+      (slang_variable **) _slang_alloc(sizeof(slang_variable *));
+   if (op_id.locals->variables == NULL) {
+      slang_operation_destruct(&op_id);
+      return GL_FALSE;
+   }
+   op_id.locals->num_variables = 1;
+   op_id.locals->variables[0] = var;
+
+   /* construct the assignment expression */
+   if (!slang_operation_construct(&op_assign)) {
+      op_id.locals->num_variables = 0;
+      slang_operation_destruct(&op_id);
+      return GL_FALSE;
+   }
+   op_assign.type = SLANG_OPER_ASSIGN;
+   op_assign.children =
+      (slang_operation *) _slang_alloc(2 * sizeof(slang_operation));
+   if (op_assign.children == NULL) {
+      slang_operation_destruct(&op_assign);
+      op_id.locals->num_variables = 0;
+      slang_operation_destruct(&op_id);
+      return GL_FALSE;
+   }
+   op_assign.num_children = 2;
+   op_assign.children[0] = op_id;
+   op_assign.children[1] = *var->initializer;
+
+   result = 1;
+
+   /* carefully destroy the operations */
+   op_assign.num_children = 0;
+   _slang_free(op_assign.children);
+   op_assign.children = NULL;
+   slang_operation_destruct(&op_assign);
+   op_id.locals->num_variables = 0;
+   slang_operation_destruct(&op_id);
+
+   if (!result)
+      return GL_FALSE;
+
+   return GL_TRUE;
+}
+
+/* init declarator list */
+#define DECLARATOR_NONE 0
+#define DECLARATOR_NEXT 1
+
+/* variable declaration */
+#define VARIABLE_NONE 0
+#define VARIABLE_IDENTIFIER 1
+#define VARIABLE_INITIALIZER 2
+#define VARIABLE_ARRAY_EXPLICIT 3
+#define VARIABLE_ARRAY_UNKNOWN 4
+
+
+/**
+ * Check if it's OK to re-declare a variable with the given new type.
+ * This happens when applying layout qualifiers to gl_FragCoord or
+ * (re)setting an array size.
+ * If redeclaration is OK, return a pointer to the incoming variable
+ * updated with new type info.  Else return NULL;
+ */
+static slang_variable *
+redeclare_variable(slang_variable *var, 
+                   const slang_fully_specified_type *type)
+{
+   if (slang_fully_specified_types_compatible(&var->type, type)) {
+      /* replace orig var layout with new layout */
+      var->type.layout = type->layout;
+
+      /* XXX there may be other type updates in the future here */
+
+      return var;
+   }
+   else
+      return NULL;
+}
+
+
+/**
+ * Parse the initializer for a variable declaration.
+ */
+static int
+parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
+                      const slang_fully_specified_type * type)
+{
+   GET_CURRENT_CONTEXT(ctx); /* a hack */
+   slang_variable *var = NULL, *prevDecl;
+   slang_atom a_name;
+
+   /* empty init declatator (without name, e.g. "float ;") */
+   if (*C->I++ == VARIABLE_NONE)
+      return 1;
+
+   a_name = parse_identifier(C);
+
+   /* check if name is already in this scope */
+   prevDecl = _slang_variable_locate(O->vars, a_name, C->global_scope);
+   if (prevDecl) {
+      /* A var with this name has already been declared.
+       * Check if redeclaring the var with a different type/layout is legal.
+       */
+      if (C->global_scope) {
+         var = redeclare_variable(prevDecl, type);
+      }
+      if (!var) {
+         slang_info_log_error(C->L,
+                   "declaration of '%s' conflicts with previous declaration",
+                   (char *) a_name);
+         RETURN0;
+      }
+   }
+
+   if (!var) {
+      /* make room for a new variable and initialize it */
+      var = slang_variable_scope_grow(O->vars);
+      if (!var) {
+         slang_info_log_memory(C->L);
+         RETURN0;
+      }
+
+      /* copy the declarator type qualifier/etc info, parse the identifier */
+      var->type.qualifier = type->qualifier;
+      var->type.centroid = type->centroid;
+      var->type.precision = type->precision;
+      var->type.specifier = type->specifier;/*new*/
+      var->type.variant = type->variant;
+      var->type.layout = type->layout;
+      var->type.array_len = type->array_len;
+      var->a_name = a_name;
+      if (var->a_name == SLANG_ATOM_NULL)
+         RETURN0;
+   }
+
+   switch (*C->I++) {
+   case VARIABLE_NONE:
+      /* simple variable declarator - just copy the specifier */
+      if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
+         RETURN0;
+      break;
+   case VARIABLE_INITIALIZER:
+      /* initialized variable - copy the specifier and parse the expression */
+      if (0 && type->array_len >= 0) {
+         /* The type was something like "float[4]" */
+         convert_to_array(C, var, &type->specifier);
+         var->array_len = type->array_len;
+      }
+      else {
+         if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
+            RETURN0;
+      }
+      var->initializer =
+         (slang_operation *) _slang_alloc(sizeof(slang_operation));
+      if (var->initializer == NULL) {
+         slang_info_log_memory(C->L);
+         RETURN0;
+      }
+      if (!slang_operation_construct(var->initializer)) {
+         _slang_free(var->initializer);
+         var->initializer = NULL;
+         slang_info_log_memory(C->L);
+         RETURN0;
+      }
+      if (!parse_expression(C, O, var->initializer))
+         RETURN0;
+      break;
+   case VARIABLE_ARRAY_UNKNOWN:
+      /* unsized array - mark it as array and copy the specifier to
+       * the array element
+       */
+      if (type->array_len >= 0) {
+         slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
+         RETURN0;
+      }
+      if (!convert_to_array(C, var, &type->specifier))
+         return GL_FALSE;
+      break;
+   case VARIABLE_ARRAY_EXPLICIT:
+      if (type->array_len >= 0) {
+         /* the user is trying to do something like: float[2] x[3]; */
+         slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
+         RETURN0;
+      }
+      if (!convert_to_array(C, var, &type->specifier))
+         return GL_FALSE;
+      if (!parse_array_len(C, O, &var->array_len))
+         return GL_FALSE;
+      break;
+   default:
+      RETURN0;
+   }
+
+   /* allocate global address space for a variable with a known size */
+   if (C->global_scope
+       && !(var->type.specifier.type == SLANG_SPEC_ARRAY
+            && var->array_len == 0)) {
+      if (!calculate_var_size(C, O, var))
+         return GL_FALSE;
+   }
+
+   /* emit code for global var decl */
+   if (C->global_scope) {
+      slang_assemble_ctx A;
+      memset(&A, 0, sizeof(slang_assemble_ctx));
+      A.allow_uniform_initializers = C->version > 110;
+      A.atoms = C->atoms;
+      A.space.funcs = O->funs;
+      A.space.structs = O->structs;
+      A.space.vars = O->vars;
+      A.program = O->program;
+      A.pragmas = O->pragmas;
+      A.vartable = O->vartable;
+      A.log = C->L;
+      A.curFuncEndLabel = NULL;
+      A.EmitContReturn = ctx->Shader.EmitContReturn;
+      if (!_slang_codegen_global_variable(&A, var, C->type))
+         RETURN0;
+   }
+
+   /* initialize global variable */
+   if (C->global_scope) {
+      if (var->initializer != NULL) {
+         slang_assemble_ctx A;
+         memset(&A, 0, sizeof(slang_assemble_ctx));
+         A.allow_uniform_initializers = C->version > 110;
+         A.atoms = C->atoms;
+         A.space.funcs = O->funs;
+         A.space.structs = O->structs;
+         A.space.vars = O->vars;
+         if (!initialize_global(&A, var))
+            RETURN0;
+      }
+   }
+
+   if (var->type.qualifier == SLANG_QUAL_FIXEDINPUT &&
+       var->a_name == slang_atom_pool_atom(C->atoms, "gl_FragCoord")) {
+      /* set the program's PixelCenterInteger, OriginUpperLeft fields */
+      struct gl_fragment_program *fragProg =
+         (struct gl_fragment_program *) O->program;
+
+      if (var->type.layout & SLANG_LAYOUT_UPPER_LEFT_BIT) {
+         fragProg->OriginUpperLeft = GL_TRUE;
+      }
+      if (var->type.layout & SLANG_LAYOUT_PIXEL_CENTER_INTEGER_BIT) {
+         fragProg->PixelCenterInteger = GL_TRUE;
+      }
+   }
+
+   return 1;
+}
+
+/**
+ * Parse a list of variable declarations.  Each variable may have an
+ * initializer.
+ */
+static int
+parse_init_declarator_list(slang_parse_ctx * C, slang_output_ctx * O)
+{
+   slang_fully_specified_type type;
+
+   /* parse the fully specified type, common to all declarators */
+   if (!slang_fully_specified_type_construct(&type))
+      RETURN0;
+   if (!parse_fully_specified_type(C, O, &type)) {
+      slang_fully_specified_type_destruct(&type);
+      RETURN0;
+   }
+
+   /* parse declarators, pass-in the parsed type */
+   do {
+      if (!parse_init_declarator(C, O, &type)) {
+         slang_fully_specified_type_destruct(&type);
+         RETURN0;
+      }
+   }
+   while (*C->I++ == DECLARATOR_NEXT);
+
+   slang_fully_specified_type_destruct(&type);
+   return 1;
+}
+
+
+/**
+ * Parse a function definition or declaration.
+ * \param C  parsing context
+ * \param O  output context
+ * \param definition if non-zero expect a definition, else a declaration
+ * \param parsed_func_ret  returns the parsed function
+ * \return GL_TRUE if success, GL_FALSE if failure
+ */
+static GLboolean
+parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
+               slang_function ** parsed_func_ret)
+{
+   slang_function parsed_func, *found_func;
+
+   /* parse function definition/declaration */
+   if (!slang_function_construct(&parsed_func))
+      return GL_FALSE;
+   if (definition) {
+      if (!parse_function_definition(C, O, &parsed_func)) {
+         slang_function_destruct(&parsed_func);
+         return GL_FALSE;
+      }
+   }
+   else {
+      if (!parse_function_prototype(C, O, &parsed_func)) {
+         slang_function_destruct(&parsed_func);
+         return GL_FALSE;
+      }
+   }
+
+   /* find a function with a prototype matching the parsed one - only
+    * the current scope is being searched to allow built-in function
+    * overriding
+    */
+   found_func = slang_function_scope_find(O->funs, &parsed_func, 0);
+   if (found_func == NULL) {
+      /* New function, add it to the function list */
+      O->funs->functions =
+         (slang_function *) _slang_realloc(O->funs->functions,
+                                           O->funs->num_functions
+                                           * sizeof(slang_function),
+                                           (O->funs->num_functions + 1)
+                                           * sizeof(slang_function));
+      if (O->funs->functions == NULL) {
+         /* Make sure that there are no functions marked, as the
+          * allocation is currently NULL, in order to avoid
+          * a potental segfault as we clean up later.
+          */
+         O->funs->num_functions = 0;
+
+         slang_info_log_memory(C->L);
+         slang_function_destruct(&parsed_func);
+         return GL_FALSE;
+      }
+      O->funs->functions[O->funs->num_functions] = parsed_func;
+      O->funs->num_functions++;
+
+      /* return the newly parsed function */
+      *parsed_func_ret = &O->funs->functions[O->funs->num_functions - 1];
+   }
+   else {
+      /* previously defined or declared */
+      /* TODO: check function return type qualifiers and specifiers */
+      if (definition) {
+         if (found_func->body != NULL) {
+            slang_info_log_error(C->L, "%s: function already has a body.",
+                                 slang_atom_pool_id(C->atoms,
+                                                    parsed_func.header.
+                                                    a_name));
+            slang_function_destruct(&parsed_func);
+            return GL_FALSE;
+         }
+
+         /* destroy the existing function declaration and replace it
+          * with the new one
+          */
+         slang_function_destruct(found_func);
+         *found_func = parsed_func;
+      }
+      else {
+         /* another declaration of the same function prototype - ignore it */
+         slang_function_destruct(&parsed_func);
+      }
+
+      /* return the found function */
+      *parsed_func_ret = found_func;
+   }
+
+   return GL_TRUE;
+}
+
+/* declaration */
+#define DECLARATION_FUNCTION_PROTOTYPE 1
+#define DECLARATION_INIT_DECLARATOR_LIST 2
+
+static int
+parse_declaration(slang_parse_ctx * C, slang_output_ctx * O)
+{
+   switch (*C->I++) {
+   case DECLARATION_INIT_DECLARATOR_LIST:
+      if (!parse_init_declarator_list(C, O))
+         RETURN0;
+      break;
+   case DECLARATION_FUNCTION_PROTOTYPE:
+      {
+         slang_function *dummy_func;
+
+         if (!parse_function(C, O, 0, &dummy_func))
+            RETURN0;
+      }
+      break;
+   default:
+      RETURN0;
+   }
+   return 1;
+}
+
+static int
+parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O)
+{
+   int precision, type;
+
+   if (!O->allow_precision) {
+      slang_info_log_error(C->L, "syntax error at \"precision\"");
+      RETURN0;
+   }
+
+   precision = *C->I++;
+   switch (precision) {
+   case PRECISION_LOW:
+   case PRECISION_MEDIUM:
+   case PRECISION_HIGH:
+      /* OK */
+      break;
+   default:
+      _mesa_problem(NULL, "unexpected precision %d at %s:%d\n",
+                    precision, __FILE__, __LINE__);
+      RETURN0;
+   }
+
+   type = *C->I++;
+   switch (type) {
+   case TYPE_SPECIFIER_FLOAT:
+   case TYPE_SPECIFIER_INT:
+   case TYPE_SPECIFIER_SAMPLER1D:
+   case TYPE_SPECIFIER_SAMPLER2D:
+   case TYPE_SPECIFIER_SAMPLER3D:
+   case TYPE_SPECIFIER_SAMPLERCUBE:
+   case TYPE_SPECIFIER_SAMPLER1DSHADOW:
+   case TYPE_SPECIFIER_SAMPLER2DSHADOW:
+   case TYPE_SPECIFIER_SAMPLER2DRECT:
+   case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW:
+   case TYPE_SPECIFIER_SAMPLER_1D_ARRAY:
+   case TYPE_SPECIFIER_SAMPLER_2D_ARRAY:
+   case TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW:
+   case TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW:
+      /* OK */
+      break;
+   default:
+      _mesa_problem(NULL, "unexpected type %d at %s:%d\n",
+                    type, __FILE__, __LINE__);
+      RETURN0;
+   }
+
+   assert(type < TYPE_SPECIFIER_COUNT);
+   O->default_precision[type] = precision;
+
+   return 1;
+}
+
+
+/**
+ * Initialize the default precision for all types.
+ * XXX this info isn't used yet.
+ */
+static void
+init_default_precision(slang_output_ctx *O, slang_unit_type type)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLuint i;
+   for (i = 0; i < TYPE_SPECIFIER_COUNT; i++) {
+#if FEATURE_es2_glsl
+      if (ctx->API == API_OPENGLES2)
+        O->default_precision[i] = PRECISION_LOW;
+      else
+        O->default_precision[i] = PRECISION_HIGH;
+#else
+      (void) ctx;
+      O->default_precision[i] = PRECISION_HIGH;
+#endif
+   }
+
+   if (type == SLANG_UNIT_VERTEX_SHADER) {
+      O->default_precision[TYPE_SPECIFIER_FLOAT] = PRECISION_HIGH;
+      O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_HIGH;
+   }
+   else {
+      O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_MEDIUM;
+   }
+}
+
+
+static int
+parse_invariant(slang_parse_ctx * C, slang_output_ctx * O)
+{
+   if (O->allow_invariant) {
+      slang_atom *a = parse_identifier(C);
+      /* XXX not doing anything with this var yet */
+      /*printf("ID: %s\n", (char*) a);*/
+      return a ? 1 : 0;
+   }
+   else {
+      slang_info_log_error(C->L, "syntax error at \"invariant\"");
+      RETURN0;
+   }
+}
+      
+
+/* external declaration or default precision specifier */
+#define EXTERNAL_NULL 0
+#define EXTERNAL_FUNCTION_DEFINITION 1
+#define EXTERNAL_DECLARATION 2
+#define DEFAULT_PRECISION 3
+#define INVARIANT_STMT 4
+
+
+static GLboolean
+parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
+                struct gl_shader *shader)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   slang_output_ctx o;
+   GLboolean success;
+   GLuint maxRegs;
+   slang_function *mainFunc = NULL;
+
+   if (unit->type == SLANG_UNIT_FRAGMENT_BUILTIN ||
+       unit->type == SLANG_UNIT_FRAGMENT_SHADER) {
+      maxRegs = ctx->Const.FragmentProgram.MaxTemps;
+   }
+   else {
+      assert(unit->type == SLANG_UNIT_VERTEX_BUILTIN ||
+             unit->type == SLANG_UNIT_VERTEX_SHADER);
+      maxRegs = ctx->Const.VertexProgram.MaxTemps;
+   }
+
+   /* setup output context */
+   o.funs = &unit->funs;
+   o.structs = &unit->structs;
+   o.vars = &unit->vars;
+   o.program = shader ? shader->Program : NULL;
+   o.pragmas = shader ? &shader->Pragmas : NULL;
+   o.vartable = _slang_new_var_table(maxRegs);
+   _slang_push_var_table(o.vartable);
+
+   /* allow 'invariant' keyword? */
+#if FEATURE_es2_glsl
+   o.allow_invariant =
+      (ctx->API == API_OPENGLES2 || C->version >= 120) ? GL_TRUE : GL_FALSE;
+#else
+   o.allow_invariant = (C->version >= 120) ? GL_TRUE : GL_FALSE;
+#endif
+
+   /* allow 'centroid' keyword? */
+   o.allow_centroid = (C->version >= 120) ? GL_TRUE : GL_FALSE;
+
+   /* allow 'lowp/mediump/highp' keywords? */
+#if FEATURE_es2_glsl
+   o.allow_precision =
+      (ctx->API == API_OPENGLES2 || C->version >= 120) ? GL_TRUE : GL_FALSE;
+#else
+   o.allow_precision = (C->version >= 120) ? GL_TRUE : GL_FALSE;
+#endif
+   init_default_precision(&o, unit->type);
+
+   /* allow 'float[]' keyword? */
+   o.allow_array_types = (C->version >= 120) ? GL_TRUE : GL_FALSE;
+
+   /* parse individual functions and declarations */
+   while (*C->I != EXTERNAL_NULL) {
+      switch (*C->I++) {
+      case EXTERNAL_FUNCTION_DEFINITION:
+         {
+            slang_function *func;
+            success = parse_function(C, &o, 1, &func);
+            if (success && strcmp((char *) func->header.a_name, "main") == 0) {
+               /* found main() */
+               mainFunc = func;
+            }
+         }
+         break;
+      case EXTERNAL_DECLARATION:
+         success = parse_declaration(C, &o);
+         break;
+      case DEFAULT_PRECISION:
+         success = parse_default_precision(C, &o);
+         break;
+      case INVARIANT_STMT:
+         success = parse_invariant(C, &o);
+         break;
+      default:
+         success = GL_FALSE;
+      }
+
+      if (!success) {
+         /* xxx free codegen */
+         _slang_pop_var_table(o.vartable);
+         return GL_FALSE;
+      }
+   }
+   C->I++;
+
+   if (mainFunc) {
+      /* assemble (generate code) for main() */
+      slang_assemble_ctx A;
+      memset(&A, 0, sizeof(slang_assemble_ctx));
+      A.atoms = C->atoms;
+      A.space.funcs = o.funs;
+      A.space.structs = o.structs;
+      A.space.vars = o.vars;
+      A.program = o.program;
+      A.pragmas = &shader->Pragmas;
+      A.vartable = o.vartable;
+      A.EmitContReturn = ctx->Shader.EmitContReturn;
+      A.log = C->L;
+      A.allow_uniform_initializers = C->version > 110;
+
+      /* main() takes no parameters */
+      if (mainFunc->param_count > 0) {
+         slang_info_log_error(A.log, "main() takes no arguments");
+         return GL_FALSE;
+      }
+
+      _slang_codegen_function(&A, mainFunc);
+
+      shader->Main = GL_TRUE; /* this shader defines main() */
+
+      shader->UnresolvedRefs = A.UnresolvedRefs;
+   }
+
+   _slang_pop_var_table(o.vartable);
+   _slang_delete_var_table(o.vartable);
+
+   return GL_TRUE;
+}
+
+static GLboolean
+compile_binary(const unsigned char * prod, slang_code_unit * unit,
+               GLuint version,
+               slang_unit_type type, slang_info_log * infolog,
+               slang_code_unit * builtin, slang_code_unit * downlink,
+               struct gl_shader *shader)
+{
+   slang_parse_ctx C;
+
+   unit->type = type;
+
+   /* setup parse context */
+   C.I = prod;
+   C.L = infolog;
+   C.parsing_builtin = (builtin == NULL);
+   C.global_scope = GL_TRUE;
+   C.atoms = &unit->object->atompool;
+   C.type = type;
+   C.version = version;
+
+   if (!check_revision(&C))
+      return GL_FALSE;
+
+   if (downlink != NULL) {
+      unit->vars.outer_scope = &downlink->vars;
+      unit->funs.outer_scope = &downlink->funs;
+      unit->structs.outer_scope = &downlink->structs;
+   }
+
+   /* parse translation unit */
+   return parse_code_unit(&C, unit, shader);
+}
+
+static GLboolean
+compile_with_grammar(const char *source,
+                     slang_code_unit *unit,
+                     slang_unit_type type,
+                     slang_info_log *infolog,
+                     slang_code_unit *builtin,
+                     struct gl_shader *shader,
+                     struct gl_sl_pragmas *pragmas,
+                     unsigned int shader_type,
+                     unsigned int parsing_builtin)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct sl_pp_purify_options options;
+   struct sl_pp_context *context;
+   unsigned char *prod;
+   GLuint size;
+   unsigned int version;
+   unsigned int maxVersion;
+   int result;
+   char errmsg[200] = "";
+
+   assert(shader_type == 1 || shader_type == 2);
+
+   memset(&options, 0, sizeof(options));
+
+   context = sl_pp_context_create(source, &options);
+   if (!context) {
+      slang_info_log_error(infolog, "out of memory");
+      return GL_FALSE;
+   }
+
+   if (sl_pp_version(context, &version)) {
+      slang_info_log_error(infolog, "%s", sl_pp_context_error_message(context));
+      sl_pp_context_destroy(context);
+      return GL_FALSE;
+   }
+
+   if (sl_pp_context_add_extension(context, "GL_ARB_draw_buffers") ||
+       sl_pp_context_add_extension(context, "GL_ARB_texture_rectangle")) {
+      slang_info_log_error(infolog, "%s", sl_pp_context_error_message(context));
+      sl_pp_context_destroy(context);
+      return GL_FALSE;
+   }
+
+   if (type == SLANG_UNIT_FRAGMENT_SHADER) {
+      sl_pp_context_add_extension(context, "GL_ARB_fragment_coord_conventions");
+   }
+
+
+#if FEATURE_es2_glsl
+   if (ctx->API == API_OPENGLES2) {
+      if (sl_pp_context_add_predefined(context, "GL_ES", "1") ||
+         sl_pp_context_add_predefined(context, "GL_FRAGMENT_PRECISION_HIGH", "1")) {
+        slang_info_log_error(infolog, "%s", sl_pp_context_error_message(context));
+        sl_pp_context_destroy(context);
+        return GL_FALSE;
+      }
+   }
+#else
+   (void) ctx;
+#endif
+
+#if FEATURE_ARB_shading_language_120
+   maxVersion = 120;
+#elif FEATURE_es2_glsl
+   maxVersion = 100;
+#else
+   maxVersion = 110;
+#endif
+
+   if (version > maxVersion ||
+       (version != 100 && version != 110 && version != 120)) {
+      slang_info_log_error(infolog,
+                           "language version %.2f is not supported.",
+                           version * 0.01);
+      sl_pp_context_destroy(context);
+      return GL_FALSE;
+   }
+
+   /* Finally check the syntax and generate its binary representation. */
+   result = sl_cl_compile(context,
+                          shader_type,
+                          parsing_builtin,
+                          &prod,
+                          &size,
+                          errmsg,
+                          sizeof(errmsg));
+
+   sl_pp_context_destroy(context);
+
+   if (result) {
+      /*GLint pos;*/
+
+      slang_info_log_error(infolog, errmsg);
+      /* syntax error (possibly in library code) */
+#if 0
+      {
+         int line, col;
+         char *s;
+         s = (char *) _mesa_find_line_column((const GLubyte *) source,
+                                             (const GLubyte *) source + pos,
+                                             &line, &col);
+         printf("Error on line %d, col %d: %s\n", line, col, s);
+      }
+#endif
+      return GL_FALSE;
+   }
+
+   /* Syntax is okay - translate it to internal representation. */
+   if (!compile_binary(prod, unit, version, type, infolog, builtin,
+                       &builtin[SLANG_BUILTIN_TOTAL - 1],
+                       shader)) {
+      free(prod);
+      return GL_FALSE;
+   }
+   free(prod);
+   return GL_TRUE;
+}
+
+static const unsigned char slang_core_gc[] = {
+#include "library/slang_core_gc.h"
+};
+
+static const unsigned char slang_120_core_gc[] = {
+#include "library/slang_120_core_gc.h"
+};
+
+static const unsigned char slang_120_fragment_gc[] = {
+#include "library/slang_builtin_120_fragment_gc.h"
+};
+
+static const unsigned char slang_common_builtin_gc[] = {
+#include "library/slang_common_builtin_gc.h"
+};
+
+static const unsigned char slang_fragment_builtin_gc[] = {
+#include "library/slang_fragment_builtin_gc.h"
+};
+
+static const unsigned char slang_vertex_builtin_gc[] = {
+#include "library/slang_vertex_builtin_gc.h"
+};
+
+static GLboolean
+compile_object(const char *source,
+               slang_code_object *object,
+               slang_unit_type type,
+               slang_info_log *infolog,
+               struct gl_shader *shader,
+               struct gl_sl_pragmas *pragmas)
+{
+   slang_code_unit *builtins = NULL;
+   GLuint base_version = 110;
+   unsigned int shader_type;
+   unsigned int parsing_builtin;
+
+   /* set shader type - the syntax is slightly different for different shaders */
+   if (type == SLANG_UNIT_FRAGMENT_SHADER || type == SLANG_UNIT_FRAGMENT_BUILTIN) {
+      shader_type = 1;
+   } else {
+      shader_type = 2;
+   }
+
+   /* enable language extensions */
+   parsing_builtin = 1;
+
+   /* if parsing user-specified shader, load built-in library */
+   if (type == SLANG_UNIT_FRAGMENT_SHADER || type == SLANG_UNIT_VERTEX_SHADER) {
+      /* compile core functionality first */
+      if (!compile_binary(slang_core_gc,
+                          &object->builtin[SLANG_BUILTIN_CORE],
+                          base_version,
+                          SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
+                          NULL, NULL, NULL))
+         return GL_FALSE;
+
+#if FEATURE_ARB_shading_language_120
+      if (!compile_binary(slang_120_core_gc,
+                          &object->builtin[SLANG_BUILTIN_120_CORE],
+                          120,
+                          SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
+                          NULL, &object->builtin[SLANG_BUILTIN_CORE], NULL))
+         return GL_FALSE;
+#endif
+
+      /* compile common functions and variables, link to core */
+      if (!compile_binary(slang_common_builtin_gc,
+                          &object->builtin[SLANG_BUILTIN_COMMON],
+#if FEATURE_ARB_shading_language_120
+                          120,
+#else
+                          base_version,
+#endif
+                          SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
+#if FEATURE_ARB_shading_language_120
+                          &object->builtin[SLANG_BUILTIN_120_CORE],
+#else
+                          &object->builtin[SLANG_BUILTIN_CORE],
+#endif
+                          NULL))
+         return GL_FALSE;
+
+      /* compile target-specific functions and variables, link to common */
+      if (type == SLANG_UNIT_FRAGMENT_SHADER) {
+         if (!compile_binary(slang_fragment_builtin_gc,
+                             &object->builtin[SLANG_BUILTIN_TARGET],
+                             base_version,
+                             SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
+                             &object->builtin[SLANG_BUILTIN_COMMON], NULL))
+            return GL_FALSE;
+#if FEATURE_ARB_shading_language_120
+         if (!compile_binary(slang_120_fragment_gc,
+                             &object->builtin[SLANG_BUILTIN_TARGET],
+                             120,
+                             SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
+                             &object->builtin[SLANG_BUILTIN_COMMON], NULL))
+            return GL_FALSE;
+#endif
+      }
+      else if (type == SLANG_UNIT_VERTEX_SHADER) {
+         if (!compile_binary(slang_vertex_builtin_gc,
+                             &object->builtin[SLANG_BUILTIN_TARGET],
+                             base_version,
+                             SLANG_UNIT_VERTEX_BUILTIN, infolog, NULL,
+                             &object->builtin[SLANG_BUILTIN_COMMON], NULL))
+            return GL_FALSE;
+      }
+
+      /* disable language extensions */
+      parsing_builtin = 0;
+
+      builtins = object->builtin;
+   }
+
+   /* compile the actual shader - pass-in built-in library for external shader */
+   return compile_with_grammar(source,
+                               &object->unit,
+                               type,
+                               infolog,
+                               builtins,
+                               shader,
+                               pragmas,
+                               shader_type,
+                               parsing_builtin);
+}
+
+
+GLboolean
+_slang_compile(GLcontext *ctx, struct gl_shader *shader)
+{
+   GLboolean success;
+   slang_info_log info_log;
+   slang_code_object obj;
+   slang_unit_type type;
+   GLenum progTarget;
+
+   if (shader->Type == GL_VERTEX_SHADER) {
+      type = SLANG_UNIT_VERTEX_SHADER;
+   }
+   else {
+      assert(shader->Type == GL_FRAGMENT_SHADER);
+      type = SLANG_UNIT_FRAGMENT_SHADER;
+   }
+
+   if (!shader->Source)
+      return GL_FALSE;
+
+   ctx->Shader.MemPool = _slang_new_mempool(1024*1024);
+
+   shader->Main = GL_FALSE;
+
+   /* free the shader's old instructions, etc */
+   _mesa_reference_program(ctx, &shader->Program, NULL);
+
+   /* allocate new GPU program, parameter lists, etc. */
+   if (shader->Type == GL_VERTEX_SHADER)
+      progTarget = GL_VERTEX_PROGRAM_ARB;
+   else
+      progTarget = GL_FRAGMENT_PROGRAM_ARB;
+   shader->Program = ctx->Driver.NewProgram(ctx, progTarget, 1);
+   shader->Program->Parameters = _mesa_new_parameter_list();
+   shader->Program->Varying = _mesa_new_parameter_list();
+   shader->Program->Attributes = _mesa_new_parameter_list();
+
+   slang_info_log_construct(&info_log);
+   _slang_code_object_ctr(&obj);
+
+   success = compile_object(shader->Source,
+                            &obj,
+                            type,
+                            &info_log,
+                            shader,
+                            &shader->Pragmas);
+
+   /* free shader's prev info log */
+   if (shader->InfoLog) {
+      free(shader->InfoLog);
+      shader->InfoLog = NULL;
+   }
+
+   if (info_log.text) {
+      /* copy info-log string to shader object */
+      shader->InfoLog = _mesa_strdup(info_log.text);
+   }
+
+   if (info_log.error_flag) {
+      success = GL_FALSE;
+   }
+
+   slang_info_log_destruct(&info_log);
+   _slang_code_object_dtr(&obj);
+
+   _slang_delete_mempool((slang_mempool *) ctx->Shader.MemPool);
+   ctx->Shader.MemPool = NULL;
+
+   /* remove any reads of output registers */
+#if 0
+   printf("Pre-remove output reads:\n");
+   _mesa_print_program(shader->Program);
+#endif
+   _mesa_remove_output_reads(shader->Program, PROGRAM_OUTPUT);
+   if (shader->Type == GL_VERTEX_SHADER) {
+      /* and remove writes to varying vars in vertex programs */
+      _mesa_remove_output_reads(shader->Program, PROGRAM_VARYING);
+   }
+#if 0
+   printf("Post-remove output reads:\n");
+   _mesa_print_program(shader->Program);
+#endif
+
+   shader->CompileStatus = success;
+
+   if (success) {
+      if (shader->Pragmas.Optimize &&
+          (ctx->Shader.Flags & GLSL_NO_OPT) == 0) {
+         _mesa_optimize_program(ctx, shader->Program);
+      }
+      if ((ctx->Shader.Flags & GLSL_NOP_VERT) &&
+          shader->Program->Target == GL_VERTEX_PROGRAM_ARB) {
+         _mesa_nop_vertex_program(ctx,
+                                  (struct gl_vertex_program *) shader->Program);
+      }
+      if ((ctx->Shader.Flags & GLSL_NOP_FRAG) &&
+          shader->Program->Target == GL_FRAGMENT_PROGRAM_ARB) {
+         _mesa_nop_fragment_program(ctx,
+                                (struct gl_fragment_program *) shader->Program);
+      }
+   }
+
+   if (ctx->Shader.Flags & GLSL_LOG) {
+      _mesa_write_shader_to_file(shader);
+   }
+
+   return success;
+}
+
diff --git a/src/mesa/slang/slang_compile.h b/src/mesa/slang/slang_compile.h
new file mode 100644 (file)
index 0000000..7fb549d
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#if !defined SLANG_COMPILE_H
+#define SLANG_COMPILE_H
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "slang_typeinfo.h"
+#include "slang_compile_variable.h"
+#include "slang_compile_struct.h"
+#include "slang_compile_operation.h"
+#include "slang_compile_function.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+typedef struct slang_name_space_
+{
+   struct slang_function_scope_ *funcs;
+   struct slang_struct_scope_ *structs;
+   struct slang_variable_scope_ *vars;
+} slang_name_space;
+
+typedef enum slang_unit_type_
+{
+   SLANG_UNIT_FRAGMENT_SHADER,
+   SLANG_UNIT_VERTEX_SHADER,
+   SLANG_UNIT_FRAGMENT_BUILTIN,
+   SLANG_UNIT_VERTEX_BUILTIN
+} slang_unit_type;
+
+
+typedef struct slang_code_unit_
+{
+   slang_variable_scope vars;
+   slang_function_scope funs;
+   slang_struct_scope structs;
+   slang_unit_type type;
+   struct slang_code_object_ *object;
+} slang_code_unit;
+
+
+extern GLvoid
+_slang_code_unit_ctr (slang_code_unit *, struct slang_code_object_ *);
+
+extern GLvoid
+_slang_code_unit_dtr (slang_code_unit *);
+
+#define SLANG_BUILTIN_CORE   0
+#define SLANG_BUILTIN_120_CORE   1
+#define SLANG_BUILTIN_COMMON 2
+#define SLANG_BUILTIN_TARGET 3
+
+#define SLANG_BUILTIN_TOTAL  4
+
+typedef struct slang_code_object_
+{
+   slang_code_unit builtin[SLANG_BUILTIN_TOTAL];
+   slang_code_unit unit;
+   slang_atom_pool atompool;
+} slang_code_object;
+
+extern GLvoid
+_slang_code_object_ctr (slang_code_object *);
+
+extern GLvoid
+_slang_code_object_dtr (slang_code_object *);
+
+extern GLboolean
+_slang_compile (GLcontext *ctx, struct gl_shader *shader);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/mesa/slang/slang_compile_function.c b/src/mesa/slang/slang_compile_function.c
new file mode 100644 (file)
index 0000000..4dd8851
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_compile_function.c
+ * slang front-end compiler
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "slang_compile.h"
+#include "slang_mem.h"
+
+
+int
+slang_function_construct(slang_function * func)
+{
+   func->kind = SLANG_FUNC_ORDINARY;
+   if (!slang_variable_construct(&func->header))
+      return 0;
+
+   func->parameters = (slang_variable_scope *)
+      _slang_alloc(sizeof(slang_variable_scope));
+   if (func->parameters == NULL) {
+      slang_variable_destruct(&func->header);
+      return 0;
+   }
+
+   _slang_variable_scope_ctr(func->parameters);
+   func->param_count = 0;
+   func->body = NULL;
+   return 1;
+}
+
+void
+slang_function_destruct(slang_function * func)
+{
+   slang_variable_destruct(&func->header);
+   slang_variable_scope_destruct(func->parameters);
+   _slang_free(func->parameters);
+   if (func->body != NULL) {
+      slang_operation_destruct(func->body);
+      _slang_free(func->body);
+   }
+}
+
+
+slang_function *
+slang_function_new(slang_function_kind kind)
+{
+   slang_function *fun = (slang_function *)
+      _slang_alloc(sizeof(slang_function));
+   if (fun) {
+      slang_function_construct(fun);
+      fun->kind = kind;
+   }
+   return fun;
+}
+
+
+/*
+ * slang_function_scope
+ */
+
+GLvoid
+_slang_function_scope_ctr(slang_function_scope * self)
+{
+   self->functions = NULL;
+   self->num_functions = 0;
+   self->outer_scope = NULL;
+}
+
+void
+slang_function_scope_destruct(slang_function_scope * scope)
+{
+   unsigned int i;
+
+   for (i = 0; i < scope->num_functions; i++)
+      slang_function_destruct(scope->functions + i);
+   _slang_free(scope->functions);
+}
+
+
+/**
+ * Does this function have a non-void return value?
+ */
+GLboolean
+_slang_function_has_return_value(const slang_function *fun)
+{
+   return fun->header.type.specifier.type != SLANG_SPEC_VOID;
+}
+
+
+/**
+ * Search a list of functions for a particular function by name.
+ * \param funcs  the list of functions to search
+ * \param a_name  the name to search for
+ * \param all_scopes  if non-zero, search containing scopes too.
+ * \return pointer to found function, or NULL.
+ */
+int
+slang_function_scope_find_by_name(slang_function_scope * funcs,
+                                  slang_atom a_name, int all_scopes)
+{
+   unsigned int i;
+
+   for (i = 0; i < funcs->num_functions; i++)
+      if (a_name == funcs->functions[i].header.a_name)
+         return 1;
+   if (all_scopes && funcs->outer_scope != NULL)
+      return slang_function_scope_find_by_name(funcs->outer_scope, a_name, 1);
+   return 0;
+}
+
+
+/**
+ * Search a list of functions for a particular function (for implementing
+ * function calls.  Matching is done by first comparing the function's name,
+ * then the function's parameter list.
+ *
+ * \param funcs  the list of functions to search
+ * \param fun  the function to search for
+ * \param all_scopes  if non-zero, search containing scopes too.
+ * \return pointer to found function, or NULL.
+ */
+slang_function *
+slang_function_scope_find(slang_function_scope * funcs, slang_function * fun,
+                          int all_scopes)
+{
+   unsigned int i;
+
+   for (i = 0; i < funcs->num_functions; i++) {
+      slang_function *f = &funcs->functions[i];
+      const GLuint haveRetValue = 0;
+#if 0
+         = (f->header.type.specifier.type != SLANG_SPEC_VOID);
+#endif
+      unsigned int j;
+
+      /*
+      printf("Compare name %s to %s  (ret %u, %d, %d)\n",
+             (char *) fun->header.a_name, (char *) f->header.a_name,
+             haveRetValue,
+             fun->param_count, f->param_count);
+      */
+
+      if (fun->header.a_name != f->header.a_name)
+         continue;
+      if (fun->param_count != f->param_count)
+         continue;
+      for (j = haveRetValue; j < fun->param_count; j++) {
+         if (!slang_type_specifier_equal
+             (&fun->parameters->variables[j]->type.specifier,
+              &f->parameters->variables[j]->type.specifier))
+            break;
+      }
+      if (j == fun->param_count) {
+         /*
+         printf("Found match\n");
+         */
+         return f;
+      }
+   }
+   /*
+   printf("Not found\n");
+   */
+   if (all_scopes && funcs->outer_scope != NULL)
+      return slang_function_scope_find(funcs->outer_scope, fun, 1);
+   return NULL;
+}
+
+
+/**
+ * Lookup a function according to name and parameter count/types.
+ */
+slang_function *
+_slang_function_locate(const slang_function_scope * funcs, slang_atom a_name,
+                       slang_operation * args, GLuint num_args,
+                       const slang_name_space * space, slang_atom_pool * atoms,
+                       slang_info_log *log, GLboolean *error)
+{
+   slang_typeinfo arg_ti[100];
+   GLuint i;
+
+   *error = GL_FALSE;
+
+   /* determine type of each argument */
+   assert(num_args < 100);
+   for (i = 0; i < num_args; i++) {
+      if (!slang_typeinfo_construct(&arg_ti[i]))
+         return NULL;
+      if (!_slang_typeof_operation(&args[i], space, &arg_ti[i], atoms, log)) {
+         return NULL;
+      }
+   }
+
+   /* loop over function scopes */
+   while (funcs) {
+
+      /* look for function with matching name and argument/param types */
+      for (i = 0; i < funcs->num_functions; i++) {
+         slang_function *f = &funcs->functions[i];
+         const GLuint haveRetValue = _slang_function_has_return_value(f);
+         GLuint j;
+
+         if (a_name != f->header.a_name)
+            continue;
+         if (f->param_count - haveRetValue != num_args)
+            continue;
+
+         /* compare parameter / argument types */
+         for (j = 0; j < num_args; j++) {
+            if (!slang_type_specifier_compatible(&arg_ti[j].spec,
+                              &f->parameters->variables[j]->type.specifier)) {
+               /* param/arg types don't match */
+               break;
+            }
+
+            /* "out" and "inout" formal parameter requires the actual
+             * argument to be an l-value.
+             */
+            if (!arg_ti[j].can_be_referenced &&
+                (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT ||
+                 f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT)) {
+               /* param is not an lvalue! */
+               *error = GL_TRUE;
+               return NULL;
+            }
+         }
+
+         if (j == num_args) {
+            /* name and args match! */
+            return f;
+         }
+      }
+
+      funcs = funcs->outer_scope;
+   }
+
+   return NULL;
+}
diff --git a/src/mesa/slang/slang_compile_function.h b/src/mesa/slang/slang_compile_function.h
new file mode 100644 (file)
index 0000000..a5445ec
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.2
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SLANG_COMPILE_FUNCTION_H
+#define SLANG_COMPILE_FUNCTION_H
+
+
+/**
+ * Types of functions.
+ */
+typedef enum slang_function_kind_
+{
+   SLANG_FUNC_ORDINARY,
+   SLANG_FUNC_CONSTRUCTOR,
+   SLANG_FUNC_OPERATOR
+} slang_function_kind;
+
+
+/**
+ * Description of a compiled shader function.
+ */
+typedef struct slang_function_
+{
+   slang_function_kind kind;
+   slang_variable header;      /**< The function's name and return type */
+   slang_variable_scope *parameters; /**< formal parameters AND local vars */
+   unsigned int param_count;   /**< number of formal params (no locals) */
+   slang_operation *body;      /**< The instruction tree */
+} slang_function;
+
+extern int slang_function_construct(slang_function *);
+extern void slang_function_destruct(slang_function *);
+extern slang_function *slang_function_new(slang_function_kind kind);
+
+extern GLboolean
+_slang_function_has_return_value(const slang_function *fun);
+
+
+/**
+ * Basically, a list of compiled functions.
+ */
+typedef struct slang_function_scope_
+{
+   slang_function *functions;
+   GLuint num_functions;
+   struct slang_function_scope_ *outer_scope;
+} slang_function_scope;
+
+
+extern GLvoid
+_slang_function_scope_ctr(slang_function_scope *);
+
+extern void
+slang_function_scope_destruct(slang_function_scope *);
+
+extern int
+slang_function_scope_find_by_name(slang_function_scope *, slang_atom, int);
+
+extern slang_function *
+slang_function_scope_find(slang_function_scope *, slang_function *, int);
+
+extern struct slang_function_ *
+_slang_function_locate(const struct slang_function_scope_ *funcs,
+                       slang_atom name, struct slang_operation_ *params,
+                       GLuint num_params,
+                       const struct slang_name_space_ *space,
+                       slang_atom_pool *atoms, slang_info_log *log,
+                       GLboolean *error);
+
+
+#endif /* SLANG_COMPILE_FUNCTION_H */
diff --git a/src/mesa/slang/slang_compile_operation.c b/src/mesa/slang/slang_compile_operation.c
new file mode 100644 (file)
index 0000000..5441d60
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.2
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_compile_operation.c
+ * slang front-end compiler
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "slang_compile.h"
+#include "slang_mem.h"
+
+
+/**
+ * Init a slang_operation object
+ */
+GLboolean
+slang_operation_construct(slang_operation * oper)
+{
+   oper->type = SLANG_OPER_NONE;
+   oper->children = NULL;
+   oper->num_children = 0;
+   oper->literal[0] = 0.0;
+   oper->literal_size = 1;
+   oper->array_constructor = GL_FALSE;
+   oper->a_id = SLANG_ATOM_NULL;
+   oper->a_obj = SLANG_ATOM_NULL;
+   oper->locals = _slang_variable_scope_new(NULL);
+   if (oper->locals == NULL)
+      return GL_FALSE;
+   _slang_variable_scope_ctr(oper->locals);
+   oper->fun = NULL;
+   oper->var = NULL;
+   oper->label = NULL;
+   return GL_TRUE;
+}
+
+void
+slang_operation_destruct(slang_operation * oper)
+{
+   GLuint i;
+
+   for (i = 0; i < oper->num_children; i++)
+      slang_operation_destruct(oper->children + i);
+   _slang_free(oper->children);
+   slang_variable_scope_destruct(oper->locals);
+   _slang_free(oper->locals);
+   oper->children = NULL;
+   oper->num_children = 0;
+   oper->locals = NULL;
+}
+
+
+/**
+ * Recursively traverse 'oper', replacing occurances of 'oldScope' with
+ * 'newScope' in the oper->locals->outer_scope field.
+ */
+void
+slang_replace_scope(slang_operation *oper,
+                    slang_variable_scope *oldScope,
+                    slang_variable_scope *newScope)
+{
+   GLuint i;
+
+   if (oper->locals != newScope &&
+       oper->locals->outer_scope == oldScope) {
+      /* found.  replace old w/ new */
+      oper->locals->outer_scope = newScope;
+   }
+
+   if (oper->type == SLANG_OPER_VARIABLE_DECL) {
+      /* search/replace in the initializer */
+      slang_variable *var;
+      var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
+      if (var && var->initializer) {
+         slang_replace_scope(var->initializer, oldScope, newScope);
+      }
+   }
+
+   /* search/replace in children */
+   for (i = 0; i < oper->num_children; i++) {
+      slang_replace_scope(&oper->children[i], oldScope, newScope);
+   }
+}
+
+
+/**
+ * Recursively copy a slang_operation node.
+ * \param x  copy target
+ * \param y  copy source
+ * \return GL_TRUE for success, GL_FALSE if failure
+ */
+GLboolean
+slang_operation_copy(slang_operation * x, const slang_operation * y)
+{
+   slang_operation z;
+   GLuint i;
+
+   if (!slang_operation_construct(&z))
+      return GL_FALSE;
+   z.type = y->type;
+   if (y->num_children > 0) {
+      z.children = (slang_operation *)
+         _slang_alloc(y->num_children * sizeof(slang_operation));
+      if (z.children == NULL) {
+         slang_operation_destruct(&z);
+         return GL_FALSE;
+      }
+   }
+   for (z.num_children = 0; z.num_children < y->num_children;
+        z.num_children++) {
+      if (!slang_operation_construct(&z.children[z.num_children])) {
+         slang_operation_destruct(&z);
+         return GL_FALSE;
+      }
+   }
+   for (i = 0; i < z.num_children; i++) {
+      if (!slang_operation_copy(&z.children[i], &y->children[i])) {
+         slang_operation_destruct(&z);
+         return GL_FALSE;
+      }
+   }
+   z.literal[0] = y->literal[0];
+   z.literal[1] = y->literal[1];
+   z.literal[2] = y->literal[2];
+   z.literal[3] = y->literal[3];
+   z.literal_size = y->literal_size;
+   assert(y->literal_size >= 1);
+   assert(y->literal_size <= 4);
+   z.a_id = y->a_id;
+   if (y->locals) {
+      if (!slang_variable_scope_copy(z.locals, y->locals)) {
+         slang_operation_destruct(&z);
+         return GL_FALSE;
+      }
+   }
+
+   /* update scoping for children */
+   for (i = 0; i < y->num_children; i++) {
+      if (y->children[i].locals &&
+          y->children[i].locals->outer_scope == y->locals) {
+         z.children[i].locals->outer_scope = z.locals;
+      }
+   }
+
+#if 0
+   z.var = y->var;
+   z.fun = y->fun;
+#endif
+   slang_operation_destruct(x);
+   *x = z;
+
+   /* If this operation declares a new scope, we need to make sure
+    * all children point to it, not the original operation's scope!
+    */
+   if (x->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+       x->type == SLANG_OPER_WHILE ||
+       x->type == SLANG_OPER_FOR) {
+      slang_replace_scope(x, y->locals, x->locals);
+   }
+
+   return GL_TRUE;
+}
+
+
+slang_operation *
+slang_operation_new(GLuint count)
+{
+   slang_operation *ops
+       = (slang_operation *) _slang_alloc(count * sizeof(slang_operation));
+   assert(count > 0);
+   if (ops) {
+      GLuint i;
+      for (i = 0; i < count; i++)
+         slang_operation_construct(ops + i);
+   }
+   return ops;
+}
+
+
+/**
+ * Delete operation and all children
+ */
+void
+slang_operation_delete(slang_operation *oper)
+{
+   slang_operation_destruct(oper);
+   _slang_free(oper);
+}
+
+
+void
+slang_operation_free_children(slang_operation *oper)
+{
+   GLuint i;
+   for (i = 0; i < slang_oper_num_children(oper); i++) {
+      slang_operation *child = slang_oper_child(oper, i);
+      slang_operation_destruct(child);
+   }
+   _slang_free(oper->children);
+   oper->children = NULL;
+   oper->num_children = 0;
+}
+
+
+slang_operation *
+slang_operation_grow(GLuint *numChildren, slang_operation **children)
+{
+   slang_operation *ops;
+
+   ops = (slang_operation *)
+      _slang_realloc(*children,
+                     *numChildren * sizeof(slang_operation),
+                     (*numChildren + 1) * sizeof(slang_operation));
+   if (ops) {
+      slang_operation *newOp = ops + *numChildren;
+      if (!slang_operation_construct(newOp)) {
+         _slang_free(ops);
+         *children = NULL;
+         return NULL;
+      }
+      *children = ops;
+      (*numChildren)++;
+      return newOp;
+   }
+   return NULL;
+}
+
+/**
+ * Insert a new slang_operation into an array.
+ * \param numElements  pointer to current array size (in/out)
+ * \param array  address of the array (in/out)
+ * \param pos  position to insert new element
+ * \return  pointer to the new operation/element
+ */
+slang_operation *
+slang_operation_insert(GLuint *numElements, slang_operation **array,
+                       GLuint pos)
+{
+   slang_operation *ops;
+
+   assert(pos <= *numElements);
+
+   ops = (slang_operation *)
+      _slang_alloc((*numElements + 1) * sizeof(slang_operation));
+   if (ops) {
+      slang_operation *newOp;
+      newOp = ops + pos;
+      if (pos > 0)
+         memcpy(ops, *array, pos * sizeof(slang_operation));
+      if (pos < *numElements)
+         memcpy(newOp + 1, (*array) + pos,
+                (*numElements - pos) * sizeof(slang_operation));
+
+      if (!slang_operation_construct(newOp)) {
+         _slang_free(ops);
+         *numElements = 0;
+         *array = NULL;
+         return NULL;
+      }
+      if (*array)
+         _slang_free(*array);
+      *array = ops;
+      (*numElements)++;
+      return newOp;
+   }
+   return NULL;
+}
+
+
+/**
+ * Add/insert new child into given node at given position.
+ * \return pointer to the new child node
+ */
+slang_operation *
+slang_operation_insert_child(slang_operation *oper, GLuint pos)
+{
+   slang_operation *newOp;
+
+   newOp = slang_operation_insert(&oper->num_children,
+                                  &oper->children,
+                                  pos);
+   if (newOp) {
+      newOp->locals->outer_scope = oper->locals;
+   }
+
+   return newOp;
+}
+
+
+void
+_slang_operation_swap(slang_operation *oper0, slang_operation *oper1)
+{
+   slang_operation tmp = *oper0;
+   *oper0 = *oper1;
+   *oper1 = tmp;
+}
+
+
+void
+slang_operation_add_children(slang_operation *oper, GLuint num_children)
+{
+   GLuint i;
+   assert(oper->num_children == 0);
+   assert(oper->children == NULL);
+   oper->num_children = num_children;
+   oper->children = slang_operation_new(num_children);
+   for (i = 0; i < num_children; i++) {
+      oper->children[i].locals = _slang_variable_scope_new(oper->locals);
+   }
+}
+
diff --git a/src/mesa/slang/slang_compile_operation.h b/src/mesa/slang/slang_compile_operation.h
new file mode 100644 (file)
index 0000000..1f15c19
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.2
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SLANG_COMPILE_OPERATION_H
+#define SLANG_COMPILE_OPERATION_H
+
+
+/**
+ * Types of slang operations.
+ * These are the types of the AST (abstract syntax tree) nodes.
+ * [foo] indicates a sub-tree or reference to another type of node
+ */
+typedef enum slang_operation_type_
+{
+   SLANG_OPER_NONE,
+   SLANG_OPER_BLOCK_NO_NEW_SCOPE,       /* "{" sequence "}" */
+   SLANG_OPER_BLOCK_NEW_SCOPE,  /* "{" sequence "}" */
+   SLANG_OPER_VARIABLE_DECL,    /* [type] [var] or [var] = [expr] */
+   SLANG_OPER_ASM,
+   SLANG_OPER_BREAK,            /* "break" statement */
+   SLANG_OPER_CONTINUE,         /* "continue" statement */
+   SLANG_OPER_DISCARD,          /* "discard" (kill fragment) statement */
+   SLANG_OPER_RETURN,           /* "return" [expr]  */
+   SLANG_OPER_RETURN_INLINED,   /* "return" [expr] from inlined function  */
+   SLANG_OPER_LABEL,            /* a jump target */
+   SLANG_OPER_EXPRESSION,       /* [expr] */
+   SLANG_OPER_IF,               /* "if" [0] then [1] else [2] */
+   SLANG_OPER_WHILE,            /* "while" [cond] [body] */
+   SLANG_OPER_DO,               /* "do" [body] "while" [cond] */
+   SLANG_OPER_FOR,              /* "for" [init] [while] [incr] [body] */
+   SLANG_OPER_VOID,             /* nop */
+   SLANG_OPER_LITERAL_BOOL,     /* "true" or "false" */
+   SLANG_OPER_LITERAL_INT,      /* integer literal */
+   SLANG_OPER_LITERAL_FLOAT,    /* float literal */
+   SLANG_OPER_IDENTIFIER,       /* var name, func name, etc */
+   SLANG_OPER_SEQUENCE,         /* [expr] "," [expr] "," etc */
+   SLANG_OPER_ASSIGN,           /* [var] "=" [expr] */
+   SLANG_OPER_ADDASSIGN,        /* [var] "+=" [expr] */
+   SLANG_OPER_SUBASSIGN,        /* [var] "-=" [expr] */
+   SLANG_OPER_MULASSIGN,        /* [var] "*=" [expr] */
+   SLANG_OPER_DIVASSIGN,        /* [var] "/=" [expr] */
+   /*SLANG_OPER_MODASSIGN, */
+   /*SLANG_OPER_LSHASSIGN, */
+   /*SLANG_OPER_RSHASSIGN, */
+   /*SLANG_OPER_ORASSIGN, */
+   /*SLANG_OPER_XORASSIGN, */
+   /*SLANG_OPER_ANDASSIGN, */
+   SLANG_OPER_SELECT,           /* [expr] "?" [expr] ":" [expr] */
+   SLANG_OPER_LOGICALOR,        /* [expr] "||" [expr] */
+   SLANG_OPER_LOGICALXOR,       /* [expr] "^^" [expr] */
+   SLANG_OPER_LOGICALAND,       /* [expr] "&&" [expr] */
+   /*SLANG_OPER_BITOR, */
+   /*SLANG_OPER_BITXOR, */
+   /*SLANG_OPER_BITAND, */
+   SLANG_OPER_EQUAL,            /* [expr] "==" [expr] */
+   SLANG_OPER_NOTEQUAL,         /* [expr] "!=" [expr] */
+   SLANG_OPER_LESS,             /* [expr] "<" [expr] */
+   SLANG_OPER_GREATER,          /* [expr] ">" [expr] */
+   SLANG_OPER_LESSEQUAL,        /* [expr] "<=" [expr] */
+   SLANG_OPER_GREATEREQUAL,     /* [expr] ">=" [expr] */
+   /*SLANG_OPER_LSHIFT, */
+   /*SLANG_OPER_RSHIFT, */
+   SLANG_OPER_ADD,              /* [expr] "+" [expr] */
+   SLANG_OPER_SUBTRACT,         /* [expr] "-" [expr] */
+   SLANG_OPER_MULTIPLY,         /* [expr] "*" [expr] */
+   SLANG_OPER_DIVIDE,           /* [expr] "/" [expr] */
+   /*SLANG_OPER_MODULUS, */
+   SLANG_OPER_PREINCREMENT,     /* "++" [var] */
+   SLANG_OPER_PREDECREMENT,     /* "--" [var] */
+   SLANG_OPER_PLUS,             /* "-" [expr] */
+   SLANG_OPER_MINUS,            /* "+" [expr] */
+   /*SLANG_OPER_COMPLEMENT, */
+   SLANG_OPER_NOT,              /* "!" [expr] */
+   SLANG_OPER_SUBSCRIPT,        /* [expr] "[" [expr] "]" */
+   SLANG_OPER_CALL,             /* [func name] [param] [param] [...] */
+   SLANG_OPER_NON_INLINED_CALL, /* a real function call */
+   SLANG_OPER_METHOD,           /* method call, such as  v.length() */
+   SLANG_OPER_FIELD,            /* i.e.: ".next" or ".xzy" or ".xxx" etc */
+   SLANG_OPER_POSTINCREMENT,    /* [var] "++" */
+   SLANG_OPER_POSTDECREMENT     /* [var] "--" */
+} slang_operation_type;
+
+
+/**
+ * A slang_operation is basically a compiled instruction (such as assignment,
+ * a while-loop, a conditional, a multiply, a function call, etc).
+ * The AST (abstract syntax tree) is built from these nodes.
+ * NOTE: This structure could have been implemented as a union of simpler
+ * structs which would correspond to the operation types above.
+ */
+typedef struct slang_operation_
+{
+   slang_operation_type type;
+   struct slang_operation_ *children;
+   GLuint num_children;
+   GLfloat literal[4];           /**< Used for float, int and bool values */
+   GLuint literal_size;          /**< 1, 2, 3, or 4 */
+   slang_atom a_id;              /**< type: asm, identifier, call, field */
+   slang_atom a_obj;             /**< object in a method call */
+   slang_variable_scope *locals; /**< local vars for scope */
+   struct slang_function_ *fun;  /**< If type == SLANG_OPER_CALL */
+   struct slang_variable_ *var;  /**< If type == slang_oper_identier */
+   struct slang_label_ *label;   /**< If type == SLANG_OPER_LABEL */
+   /** If type==SLANG_OPER_CALL and we're calling an array constructor,
+    * for which there's no real function, we need to have a flag to
+    * indicate such.  num_children indicates number of elements.
+    */
+   GLboolean array_constructor;
+} slang_operation;
+
+
+extern GLboolean
+slang_operation_construct(slang_operation *);
+
+extern void
+slang_operation_destruct(slang_operation *);
+
+extern void
+slang_replace_scope(slang_operation *oper,
+                    slang_variable_scope *oldScope,
+                    slang_variable_scope *newScope);
+
+extern GLboolean
+slang_operation_copy(slang_operation *, const slang_operation *);
+
+extern slang_operation *
+slang_operation_new(GLuint count);
+
+extern void
+slang_operation_delete(slang_operation *oper);
+
+extern void
+slang_operation_free_children(slang_operation *oper);
+
+extern slang_operation *
+slang_operation_grow(GLuint *numChildren, slang_operation **children);
+
+extern slang_operation *
+slang_operation_insert(GLuint *numChildren, slang_operation **children,
+                       GLuint pos);
+
+extern slang_operation *
+slang_operation_insert_child(slang_operation *oper, GLuint pos);
+
+extern void
+_slang_operation_swap(slang_operation *oper0, slang_operation *oper1);
+
+
+extern void
+slang_operation_add_children(slang_operation *oper, GLuint num_children);
+
+
+/** Return number of children of given node */
+static INLINE GLuint
+slang_oper_num_children(const slang_operation *oper)
+{
+   return oper->num_children;
+}
+
+/** Return child of given operation node */
+static INLINE slang_operation *
+slang_oper_child(slang_operation *oper, GLuint child)
+{
+   assert(child < oper->num_children);
+   return &oper->children[child];
+}
+
+
+/** Return child of given operation node, const version */
+static INLINE const slang_operation *
+slang_oper_child_const(const slang_operation *oper, GLuint child)
+{
+   assert(child < oper->num_children);
+   return &oper->children[child];
+}
+
+
+/** Init oper to a boolean literal. */
+static INLINE void
+slang_operation_literal_bool(slang_operation *oper, GLboolean value)
+{
+   oper->type = SLANG_OPER_LITERAL_BOOL;
+   oper->literal[0] =
+   oper->literal[1] =
+   oper->literal[2] =
+   oper->literal[3] = (float) value;
+   oper->literal_size = 1;
+}
+
+
+/** Init oper to an int literal. */
+static INLINE void
+slang_operation_literal_int(slang_operation *oper, GLint value)
+{
+   oper->type = SLANG_OPER_LITERAL_INT;
+   oper->literal[0] =
+   oper->literal[1] =
+   oper->literal[2] =
+   oper->literal[3] = (float) value;
+   oper->literal_size = 1;
+}
+
+
+#endif /* SLANG_COMPILE_OPERATION_H */
diff --git a/src/mesa/slang/slang_compile_struct.c b/src/mesa/slang/slang_compile_struct.c
new file mode 100644 (file)
index 0000000..e6c3873
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_compile_struct.c
+ * slang front-end compiler
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "slang_mem.h"
+#include "slang_compile.h"
+
+
+GLvoid
+_slang_struct_scope_ctr(slang_struct_scope * self)
+{
+   self->structs = NULL;
+   self->num_structs = 0;
+   self->outer_scope = NULL;
+}
+
+void
+slang_struct_scope_destruct(slang_struct_scope * scope)
+{
+   GLuint i;
+
+   for (i = 0; i < scope->num_structs; i++)
+      slang_struct_destruct(scope->structs + i);
+   _slang_free(scope->structs);
+   /* do not free scope->outer_scope */
+}
+
+int
+slang_struct_scope_copy(slang_struct_scope * x, const slang_struct_scope * y)
+{
+   slang_struct_scope z;
+   GLuint i;
+
+   _slang_struct_scope_ctr(&z);
+   z.structs = (slang_struct *)
+      _slang_alloc(y->num_structs * sizeof(slang_struct));
+   if (z.structs == NULL) {
+      slang_struct_scope_destruct(&z);
+      return 0;
+   }
+   for (z.num_structs = 0; z.num_structs < y->num_structs; z.num_structs++)
+      if (!slang_struct_construct(&z.structs[z.num_structs])) {
+         slang_struct_scope_destruct(&z);
+         return 0;
+      }
+   for (i = 0; i < z.num_structs; i++)
+      if (!slang_struct_copy(&z.structs[i], &y->structs[i])) {
+         slang_struct_scope_destruct(&z);
+         return 0;
+      }
+   z.outer_scope = y->outer_scope;
+   slang_struct_scope_destruct(x);
+   *x = z;
+   return 1;
+}
+
+slang_struct *
+slang_struct_scope_find(slang_struct_scope * stru, slang_atom a_name,
+                        int all_scopes)
+{
+   GLuint i;
+
+   for (i = 0; i < stru->num_structs; i++)
+      if (a_name == stru->structs[i].a_name)
+         return &stru->structs[i];
+   if (all_scopes && stru->outer_scope != NULL)
+      return slang_struct_scope_find(stru->outer_scope, a_name, 1);
+   return NULL;
+}
+
+/* slang_struct */
+
+int
+slang_struct_construct(slang_struct * stru)
+{
+   stru->a_name = SLANG_ATOM_NULL;
+   stru->fields = (slang_variable_scope *)
+      _slang_alloc(sizeof(slang_variable_scope));
+   if (stru->fields == NULL)
+      return 0;
+   _slang_variable_scope_ctr(stru->fields);
+
+   stru->structs =
+      (slang_struct_scope *) _slang_alloc(sizeof(slang_struct_scope));
+   if (stru->structs == NULL) {
+      slang_variable_scope_destruct(stru->fields);
+      _slang_free(stru->fields);
+      return 0;
+   }
+   _slang_struct_scope_ctr(stru->structs);
+   stru->constructor = NULL;
+   return 1;
+}
+
+void
+slang_struct_destruct(slang_struct * stru)
+{
+   slang_variable_scope_destruct(stru->fields);
+   _slang_free(stru->fields);
+   slang_struct_scope_destruct(stru->structs);
+   _slang_free(stru->structs);
+}
+
+int
+slang_struct_copy(slang_struct * x, const slang_struct * y)
+{
+   slang_struct z;
+
+   if (!slang_struct_construct(&z))
+      return 0;
+   z.a_name = y->a_name;
+   if (!slang_variable_scope_copy(z.fields, y->fields)) {
+      slang_struct_destruct(&z);
+      return 0;
+   }
+   if (!slang_struct_scope_copy(z.structs, y->structs)) {
+      slang_struct_destruct(&z);
+      return 0;
+   }
+   slang_struct_destruct(x);
+   *x = z;
+   return 1;
+}
+
+int
+slang_struct_equal(const slang_struct * x, const slang_struct * y)
+{
+   GLuint i;
+
+   if (x->fields->num_variables != y->fields->num_variables)
+      return 0;
+
+   for (i = 0; i < x->fields->num_variables; i++) {
+      const slang_variable *varx = x->fields->variables[i];
+      const slang_variable *vary = y->fields->variables[i];
+
+      if (varx->a_name != vary->a_name)
+         return 0;
+      if (!slang_type_specifier_equal(&varx->type.specifier,
+                                      &vary->type.specifier))
+         return 0;
+      if (varx->type.specifier.type == SLANG_SPEC_ARRAY)
+         if (varx->array_len != vary->array_len)
+            return GL_FALSE;
+   }
+   return 1;
+}
diff --git a/src/mesa/slang/slang_compile_struct.h b/src/mesa/slang/slang_compile_struct.h
new file mode 100644 (file)
index 0000000..90c5512
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#if !defined SLANG_COMPILE_STRUCT_H
+#define SLANG_COMPILE_STRUCT_H
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+struct slang_function_;
+
+typedef struct slang_struct_scope_
+{
+   struct slang_struct_ *structs;
+   GLuint num_structs;
+   struct slang_struct_scope_ *outer_scope;
+} slang_struct_scope;
+
+extern GLvoid
+_slang_struct_scope_ctr (slang_struct_scope *);
+
+void slang_struct_scope_destruct (slang_struct_scope *);
+int slang_struct_scope_copy (slang_struct_scope *, const slang_struct_scope *);
+struct slang_struct_ *slang_struct_scope_find (slang_struct_scope *, slang_atom, int);
+
+typedef struct slang_struct_
+{
+   slang_atom a_name;
+   struct slang_variable_scope_ *fields;
+   slang_struct_scope *structs;
+   struct slang_function_ *constructor;
+} slang_struct;
+
+int slang_struct_construct (slang_struct *);
+void slang_struct_destruct (slang_struct *);
+int slang_struct_copy (slang_struct *, const slang_struct *);
+int slang_struct_equal (const slang_struct *, const slang_struct *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/mesa/slang/slang_compile_variable.c b/src/mesa/slang/slang_compile_variable.c
new file mode 100644 (file)
index 0000000..23c08a9
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_compile_variable.c
+ * slang front-end compiler
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "slang_compile.h"
+#include "slang_mem.h"
+
+
+static slang_variable *
+slang_variable_new(void)
+{
+   slang_variable *v = (slang_variable *) _slang_alloc(sizeof(slang_variable));
+   if (v) {
+      if (!slang_variable_construct(v)) {
+         _slang_free(v);
+         v = NULL;
+      }
+   }
+   return v;
+}
+
+
+static void
+slang_variable_delete(slang_variable * var)
+{
+   slang_variable_destruct(var);
+   _slang_free(var);
+}
+
+
+/*
+ * slang_variable_scope
+ */
+
+slang_variable_scope *
+_slang_variable_scope_new(slang_variable_scope *parent)
+{
+   slang_variable_scope *s;
+   s = (slang_variable_scope *) _slang_alloc(sizeof(slang_variable_scope));
+   if (s)
+      s->outer_scope = parent;
+   return s;
+}
+
+
+GLvoid
+_slang_variable_scope_ctr(slang_variable_scope * self)
+{
+   self->variables = NULL;
+   self->num_variables = 0;
+   self->outer_scope = NULL;
+}
+
+void
+slang_variable_scope_destruct(slang_variable_scope * scope)
+{
+   unsigned int i;
+
+   if (!scope)
+      return;
+   for (i = 0; i < scope->num_variables; i++) {
+      if (scope->variables[i])
+         slang_variable_delete(scope->variables[i]);
+   }
+   _slang_free(scope->variables);
+   /* do not free scope->outer_scope */
+}
+
+int
+slang_variable_scope_copy(slang_variable_scope * x,
+                          const slang_variable_scope * y)
+{
+   slang_variable_scope z;
+   unsigned int i;
+
+   _slang_variable_scope_ctr(&z);
+   z.variables = (slang_variable **)
+      _slang_alloc(y->num_variables * sizeof(slang_variable *));
+   if (z.variables == NULL) {
+      slang_variable_scope_destruct(&z);
+      return 0;
+   }
+   for (z.num_variables = 0; z.num_variables < y->num_variables;
+        z.num_variables++) {
+      z.variables[z.num_variables] = slang_variable_new();
+      if (!z.variables[z.num_variables]) {
+         slang_variable_scope_destruct(&z);
+         return 0;
+      }
+   }
+   for (i = 0; i < z.num_variables; i++) {
+      if (!slang_variable_copy(z.variables[i], y->variables[i])) {
+         slang_variable_scope_destruct(&z);
+         return 0;
+      }
+   }
+   z.outer_scope = y->outer_scope;
+   slang_variable_scope_destruct(x);
+   *x = z;
+   return 1;
+}
+
+
+/**
+ * Grow the variable list by one.
+ * \return  pointer to space for the new variable (will be initialized)
+ */
+slang_variable *
+slang_variable_scope_grow(slang_variable_scope *scope)
+{
+   const int n = scope->num_variables;
+   scope->variables = (slang_variable **)
+         _slang_realloc(scope->variables,
+                        n * sizeof(slang_variable *),
+                        (n + 1) * sizeof(slang_variable *));
+   if (!scope->variables)
+      return NULL;
+
+   scope->num_variables++;
+
+   scope->variables[n] = slang_variable_new();
+   if (!scope->variables[n])
+      return NULL;
+
+   return scope->variables[n];
+}
+
+
+
+/* slang_variable */
+
+int
+slang_variable_construct(slang_variable * var)
+{
+   if (!slang_fully_specified_type_construct(&var->type))
+      return 0;
+   var->a_name = SLANG_ATOM_NULL;
+   var->array_len = 0;
+   var->initializer = NULL;
+   var->size = 0;
+   var->isTemp = GL_FALSE;
+   var->store = NULL;
+   var->declared = 0;
+   return 1;
+}
+
+
+void
+slang_variable_destruct(slang_variable * var)
+{
+   slang_fully_specified_type_destruct(&var->type);
+   if (var->initializer != NULL) {
+      slang_operation_destruct(var->initializer);
+      _slang_free(var->initializer);
+   }
+#if 0
+   if (var->aux) {
+      free(var->aux);
+   }
+#endif
+}
+
+
+int
+slang_variable_copy(slang_variable * x, const slang_variable * y)
+{
+   slang_variable z;
+
+   if (!slang_variable_construct(&z))
+      return 0;
+   if (!slang_fully_specified_type_copy(&z.type, &y->type)) {
+      slang_variable_destruct(&z);
+      return 0;
+   }
+   z.a_name = y->a_name;
+   z.array_len = y->array_len;
+   if (y->initializer != NULL) {
+      z.initializer
+         = (slang_operation *) _slang_alloc(sizeof(slang_operation));
+      if (z.initializer == NULL) {
+         slang_variable_destruct(&z);
+         return 0;
+      }
+      if (!slang_operation_construct(z.initializer)) {
+         _slang_free(z.initializer);
+         slang_variable_destruct(&z);
+         return 0;
+      }
+      if (!slang_operation_copy(z.initializer, y->initializer)) {
+         slang_variable_destruct(&z);
+         return 0;
+      }
+   }
+   z.size = y->size;
+   slang_variable_destruct(x);
+   *x = z;
+   return 1;
+}
+
+
+/**
+ * Search for named variable in given scope.
+ * \param all  if true, search parent scopes too.
+ */
+slang_variable *
+_slang_variable_locate(const slang_variable_scope * scope,
+                       const slang_atom a_name, GLboolean all)
+{
+   while (scope) {
+      GLuint i;
+      for (i = 0; i < scope->num_variables; i++)
+         if (a_name == scope->variables[i]->a_name)
+            return scope->variables[i];
+      if (all)
+         scope = scope->outer_scope;
+      else
+         scope = NULL;
+   }
+   return NULL;
+}
diff --git a/src/mesa/slang/slang_compile_variable.h b/src/mesa/slang/slang_compile_variable.h
new file mode 100644 (file)
index 0000000..5c9d248
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.2
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SLANG_COMPILE_VARIABLE_H
+#define SLANG_COMPILE_VARIABLE_H
+
+
+struct slang_ir_storage_;
+
+
+/**
+ * A shading language program variable.
+ */
+typedef struct slang_variable_
+{
+   slang_fully_specified_type type; /**< Variable's data type */
+   slang_atom a_name;               /**< The variable's name (char *) */
+   GLuint array_len;                /**< only if type == SLANG_SPEC_ARRAy */
+   struct slang_operation_ *initializer; /**< Optional initializer code */
+   GLuint size;                     /**< Variable's size in bytes */
+   GLboolean is_global;
+   GLboolean isTemp;                /**< a named temporary (__resultTmp) */
+   GLboolean declared;              /**< has the var been declared? */
+   struct slang_ir_storage_ *store; /**< Storage for this var */
+} slang_variable;
+
+
+/**
+ * Basically a list of variables, with a pointer to the parent scope.
+ */
+typedef struct slang_variable_scope_
+{
+   slang_variable **variables;  /**< Array [num_variables] of ptrs to vars */
+   GLuint num_variables;
+   struct slang_variable_scope_ *outer_scope;
+} slang_variable_scope;
+
+
+extern slang_variable_scope *
+_slang_variable_scope_new(slang_variable_scope *parent);
+
+extern GLvoid
+_slang_variable_scope_ctr(slang_variable_scope *);
+
+extern void
+slang_variable_scope_destruct(slang_variable_scope *);
+
+extern int
+slang_variable_scope_copy(slang_variable_scope *,
+                          const slang_variable_scope *);
+
+extern slang_variable *
+slang_variable_scope_grow(slang_variable_scope *);
+
+extern int
+slang_variable_construct(slang_variable *);
+
+extern void
+slang_variable_destruct(slang_variable *);
+
+extern int
+slang_variable_copy(slang_variable *, const slang_variable *);
+
+extern slang_variable *
+_slang_variable_locate(const slang_variable_scope *, const slang_atom a_name,
+                       GLboolean all);
+
+
+#endif /* SLANG_COMPILE_VARIABLE_H */
diff --git a/src/mesa/slang/slang_emit.c b/src/mesa/slang/slang_emit.c
new file mode 100644 (file)
index 0000000..4d4c611
--- /dev/null
@@ -0,0 +1,2666 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc.   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_emit.c
+ * Emit program instructions (PI code) from IR trees.
+ * \author Brian Paul
+ */
+
+/***
+ *** NOTES
+ ***
+ *** To emit GPU instructions, we basically just do an in-order traversal
+ *** of the IR tree.
+ ***/
+
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "slang_builtin.h"
+#include "slang_emit.h"
+#include "slang_mem.h"
+
+
+#define PEEPHOLE_OPTIMIZATIONS 1
+#define ANNOTATE 0
+
+
+typedef struct
+{
+   slang_info_log *log;
+   slang_var_table *vt;
+   struct gl_program *prog;
+   struct gl_program **Subroutines;
+   GLuint NumSubroutines;
+
+   GLuint MaxInstructions;  /**< size of prog->Instructions[] buffer */
+
+   GLboolean UnresolvedFunctions;
+
+   /* code-gen options */
+   GLboolean EmitHighLevelInstructions;
+   GLboolean EmitCondCodes;
+   GLboolean EmitComments;
+   GLboolean EmitBeginEndSub; /* XXX TEMPORARY */
+} slang_emit_info;
+
+
+
+static struct gl_program *
+new_subroutine(slang_emit_info *emitInfo, GLuint *id)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   const GLuint n = emitInfo->NumSubroutines;
+
+   emitInfo->Subroutines = (struct gl_program **)
+      _mesa_realloc(emitInfo->Subroutines,
+                    n * sizeof(struct gl_program *),
+                    (n + 1) * sizeof(struct gl_program *));
+   emitInfo->Subroutines[n] = ctx->Driver.NewProgram(ctx, emitInfo->prog->Target, 0);
+   emitInfo->Subroutines[n]->Parameters = emitInfo->prog->Parameters;
+   emitInfo->NumSubroutines++;
+   *id = n;
+   return emitInfo->Subroutines[n];
+}
+
+
+/**
+ * Convert a writemask to a swizzle.  Used for testing cond codes because
+ * we only want to test the cond code component(s) that was set by the
+ * previous instruction.
+ */
+static GLuint
+writemask_to_swizzle(GLuint writemask)
+{
+   if (writemask == WRITEMASK_X)
+      return SWIZZLE_XXXX;
+   if (writemask == WRITEMASK_Y)
+      return SWIZZLE_YYYY;
+   if (writemask == WRITEMASK_Z)
+      return SWIZZLE_ZZZZ;
+   if (writemask == WRITEMASK_W)
+      return SWIZZLE_WWWW;
+   return SWIZZLE_XYZW;  /* shouldn't be hit */
+}
+
+
+/**
+ * Convert a swizzle mask to a writemask.
+ * Note that the slang_ir_storage->Swizzle field can represent either a
+ * swizzle mask or a writemask, depending on how it's used.  For example,
+ * when we parse "direction.yz" alone, we don't know whether .yz is a
+ * writemask or a swizzle.  In this case, we encode ".yz" in store->Swizzle
+ * as a swizzle mask (.yz?? actually).  Later, if direction.yz is used as
+ * an R-value, we use store->Swizzle as-is.  Otherwise, if direction.yz is
+ * used as an L-value, we convert it to a writemask.
+ */
+static GLuint
+swizzle_to_writemask(GLuint swizzle)
+{
+   GLuint i, writemask = 0x0;
+   for (i = 0; i < 4; i++) {
+      GLuint swz = GET_SWZ(swizzle, i);
+      if (swz <= SWIZZLE_W) {
+         writemask |= (1 << swz);
+      }
+   }
+   return writemask;
+}
+
+
+/**
+ * Swizzle a swizzle (function composition).
+ * That is, return swz2(swz1), or said another way: swz1.szw2
+ * Example: swizzle_swizzle(".zwxx", ".xxyw") yields ".zzwx"
+ */
+GLuint
+_slang_swizzle_swizzle(GLuint swz1, GLuint swz2)
+{
+   GLuint i, swz, s[4];
+   for (i = 0; i < 4; i++) {
+      GLuint c = GET_SWZ(swz2, i);
+      if (c <= SWIZZLE_W)
+         s[i] = GET_SWZ(swz1, c);
+      else
+         s[i] = c;
+   }
+   swz = MAKE_SWIZZLE4(s[0], s[1], s[2], s[3]);
+   return swz;
+}
+
+
+/**
+ * Return the default swizzle mask for accessing a variable of the
+ * given size (in floats).  If size = 1, comp is used to identify
+ * which component [0..3] of the register holds the variable.
+ */
+GLuint
+_slang_var_swizzle(GLint size, GLint comp)
+{
+   switch (size) {
+   case 1:
+      return MAKE_SWIZZLE4(comp, SWIZZLE_NIL, SWIZZLE_NIL, SWIZZLE_NIL);
+   case 2:
+      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL);
+   case 3:
+      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_NIL);
+   default:
+      return SWIZZLE_XYZW;
+   }
+}
+
+
+
+/**
+ * Allocate storage for the given node (if it hasn't already been allocated).
+ *
+ * Typically this is temporary storage for an intermediate result (such as
+ * for a multiply or add, etc).
+ *
+ * If n->Store does not exist it will be created and will be of the size
+ * specified by defaultSize.
+ */
+static GLboolean
+alloc_node_storage(slang_emit_info *emitInfo, slang_ir_node *n,
+                   GLint defaultSize)
+{
+   assert(!n->Var);
+   if (!n->Store) {
+      assert(defaultSize > 0);
+      n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, defaultSize);
+      if (!n->Store) {
+         return GL_FALSE;
+      }
+   }
+
+   /* now allocate actual register(s).  I.e. set n->Store->Index >= 0 */
+   if (n->Store->Index < 0) {
+      if (!_slang_alloc_temp(emitInfo->vt, n->Store)) {
+         slang_info_log_error(emitInfo->log,
+                              "Ran out of registers, too many temporaries");
+         _slang_free(n->Store);
+         n->Store = NULL;
+         return GL_FALSE;
+      }
+   }
+   return GL_TRUE;
+}
+
+
+/**
+ * Free temporary storage, if n->Store is, in fact, temp storage.
+ * Otherwise, no-op.
+ */
+static void
+free_node_storage(slang_var_table *vt, slang_ir_node *n)
+{
+   if (n->Store->File == PROGRAM_TEMPORARY &&
+       n->Store->Index >= 0 &&
+       n->Opcode != IR_SWIZZLE) {
+      if (_slang_is_temp(vt, n->Store)) {
+         _slang_free_temp(vt, n->Store);
+         n->Store->Index = -1;
+         n->Store = NULL; /* XXX this may not be needed */
+      }
+   }
+}
+
+
+/**
+ * Helper function to allocate a short-term temporary.
+ * Free it with _slang_free_temp().
+ */
+static GLboolean
+alloc_local_temp(slang_emit_info *emitInfo, slang_ir_storage *temp, GLint size)
+{
+   assert(size >= 1);
+   assert(size <= 4);
+   memset(temp, 0, sizeof(*temp));
+   temp->Size = size;
+   temp->File = PROGRAM_TEMPORARY;
+   temp->Index = -1;
+   return _slang_alloc_temp(emitInfo->vt, temp);
+}
+
+
+/**
+ * Remove any SWIZZLE_NIL terms from given swizzle mask.
+ * For a swizzle like .z??? generate .zzzz (replicate single component).
+ * Else, for .wx?? generate .wxzw (insert default component for the position).
+ */
+static GLuint
+fix_swizzle(GLuint swizzle)
+{
+   GLuint c0 = GET_SWZ(swizzle, 0),
+      c1 = GET_SWZ(swizzle, 1),
+      c2 = GET_SWZ(swizzle, 2),
+      c3 = GET_SWZ(swizzle, 3);
+   if (c1 == SWIZZLE_NIL && c2 == SWIZZLE_NIL && c3 == SWIZZLE_NIL) {
+      /* smear first component across all positions */
+      c1 = c2 = c3 = c0;
+   }
+   else {
+      /* insert default swizzle components */
+      if (c0 == SWIZZLE_NIL)
+         c0 = SWIZZLE_X;
+      if (c1 == SWIZZLE_NIL)
+         c1 = SWIZZLE_Y;
+      if (c2 == SWIZZLE_NIL)
+         c2 = SWIZZLE_Z;
+      if (c3 == SWIZZLE_NIL)
+         c3 = SWIZZLE_W;
+   }
+   return MAKE_SWIZZLE4(c0, c1, c2, c3);
+}
+
+
+
+/**
+ * Convert IR storage to an instruction dst register.
+ */
+static void
+storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st)
+{
+   const GLboolean relAddr = st->RelAddr;
+   const GLint size = st->Size;
+   GLint index = st->Index;
+   GLuint swizzle = st->Swizzle;
+
+   assert(index >= 0);
+   /* if this is storage relative to some parent storage, walk up the tree */
+   while (st->Parent) {
+      st = st->Parent;
+      assert(st->Index >= 0);
+      index += st->Index;
+      swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
+   }
+
+   assert(st->File != PROGRAM_UNDEFINED);
+   dst->File = st->File;
+
+   assert(index >= 0);
+   dst->Index = index;
+
+   assert(size >= 1);
+   assert(size <= 4);
+
+   if (swizzle != SWIZZLE_XYZW) {
+      dst->WriteMask = swizzle_to_writemask(swizzle);
+   }
+   else {
+      switch (size) {
+      case 1:
+         dst->WriteMask = WRITEMASK_X << GET_SWZ(st->Swizzle, 0);
+         break;
+      case 2:
+         dst->WriteMask = WRITEMASK_XY;
+         break;
+      case 3:
+         dst->WriteMask = WRITEMASK_XYZ;
+         break;
+      case 4:
+         dst->WriteMask = WRITEMASK_XYZW;
+         break;
+      default:
+         ; /* error would have been caught above */
+      }
+   }
+
+   dst->RelAddr = relAddr;
+}
+
+
+/**
+ * Convert IR storage to an instruction src register.
+ */
+static void
+storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
+{
+   const GLboolean relAddr = st->RelAddr;
+   GLint index = st->Index;
+   GLuint swizzle = st->Swizzle;
+
+   /* if this is storage relative to some parent storage, walk up the tree */
+   assert(index >= 0);
+   while (st->Parent) {
+      st = st->Parent;
+      if (st->Index < 0) {
+         /* an error should have been reported already */
+         return;
+      }
+      assert(st->Index >= 0);
+      index += st->Index;
+      swizzle = _slang_swizzle_swizzle(fix_swizzle(st->Swizzle), swizzle);
+   }
+
+   assert(st->File >= 0);
+#if 1 /* XXX temporary */
+   if (st->File == PROGRAM_UNDEFINED) {
+      slang_ir_storage *st0 = (slang_ir_storage *) st;
+      st0->File = PROGRAM_TEMPORARY;
+   }
+#endif
+   assert(st->File < PROGRAM_FILE_MAX);
+   src->File = st->File;
+
+   assert(index >= 0);
+   src->Index = index;
+
+   swizzle = fix_swizzle(swizzle);
+   assert(GET_SWZ(swizzle, 0) <= SWIZZLE_W);
+   assert(GET_SWZ(swizzle, 1) <= SWIZZLE_W);
+   assert(GET_SWZ(swizzle, 2) <= SWIZZLE_W);
+   assert(GET_SWZ(swizzle, 3) <= SWIZZLE_W);
+   src->Swizzle = swizzle;
+
+   src->RelAddr = relAddr;
+}
+
+
+/*
+ * Setup storage pointing to a scalar constant/literal.
+ */
+static void
+constant_to_storage(slang_emit_info *emitInfo,
+                    GLfloat val,
+                    slang_ir_storage *store)
+{
+   GLuint swizzle;
+   GLint reg;
+   GLfloat value[4];
+
+   value[0] = val;
+   reg = _mesa_add_unnamed_constant(emitInfo->prog->Parameters,
+                                        value, 1, &swizzle);
+
+   memset(store, 0, sizeof(*store));
+   store->File = PROGRAM_CONSTANT;
+   store->Index = reg;
+   store->Swizzle = swizzle;
+}
+
+
+/**
+ * Add new instruction at end of given program.
+ * \param prog  the program to append instruction onto
+ * \param opcode  opcode for the new instruction
+ * \return pointer to the new instruction
+ */
+static struct prog_instruction *
+new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode)
+{
+   struct gl_program *prog = emitInfo->prog;
+   struct prog_instruction *inst;
+
+#if 0
+   /* print prev inst */
+   if (prog->NumInstructions > 0) {
+      _mesa_print_instruction(prog->Instructions + prog->NumInstructions - 1);
+   }
+#endif
+   assert(prog->NumInstructions <= emitInfo->MaxInstructions);
+
+   if (prog->NumInstructions == emitInfo->MaxInstructions) {
+      /* grow the instruction buffer */
+      emitInfo->MaxInstructions += 20;
+      prog->Instructions =
+         _mesa_realloc_instructions(prog->Instructions,
+                                    prog->NumInstructions,
+                                    emitInfo->MaxInstructions);
+      if (!prog->Instructions) {
+         return NULL;
+      }
+   }
+
+   inst = prog->Instructions + prog->NumInstructions;
+   prog->NumInstructions++;
+   _mesa_init_instructions(inst, 1);
+   inst->Opcode = opcode;
+   inst->BranchTarget = -1; /* invalid */
+   /*
+   printf("New inst %d: %p %s\n", prog->NumInstructions-1,(void*)inst,
+          _mesa_opcode_string(inst->Opcode));
+   */
+   return inst;
+}
+
+
+static struct prog_instruction *
+emit_arl_load(slang_emit_info *emitInfo,
+              gl_register_file file, GLint index, GLuint swizzle)
+{
+   struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ARL);
+   if (inst) {
+      inst->SrcReg[0].File = file;
+      inst->SrcReg[0].Index = index;
+      inst->SrcReg[0].Swizzle = fix_swizzle(swizzle);
+      inst->DstReg.File = PROGRAM_ADDRESS;
+      inst->DstReg.Index = 0;
+      inst->DstReg.WriteMask = WRITEMASK_X;
+   }
+   return inst;
+}
+
+
+/**
+ * Emit a new instruction with given opcode, operands.
+ * At this point the instruction may have multiple indirect register
+ * loads/stores.  We convert those into ARL loads and address-relative
+ * operands.  See comments inside.
+ * At some point in the future we could directly emit indirectly addressed
+ * registers in Mesa GPU instructions.
+ */
+static struct prog_instruction *
+emit_instruction(slang_emit_info *emitInfo,
+                 gl_inst_opcode opcode,
+                 const slang_ir_storage *dst,
+                 const slang_ir_storage *src0,
+                 const slang_ir_storage *src1,
+                 const slang_ir_storage *src2)
+{
+   struct prog_instruction *inst;
+   GLuint numIndirect = 0;
+   const slang_ir_storage *src[3];
+   slang_ir_storage newSrc[3], newDst;
+   GLuint i;
+   GLboolean isTemp[3];
+
+   isTemp[0] = isTemp[1] = isTemp[2] = GL_FALSE;
+
+   src[0] = src0;
+   src[1] = src1;
+   src[2] = src2;
+
+   /* count up how many operands are indirect loads */
+   for (i = 0; i < 3; i++) {
+      if (src[i] && src[i]->IsIndirect)
+         numIndirect++;
+   }
+   if (dst && dst->IsIndirect)
+      numIndirect++;
+
+   /* Take special steps for indirect register loads.
+    * If we had multiple address registers this would be simpler.
+    * For example, this GLSL code:
+    *    x[i] = y[j] + z[k];
+    * would translate into something like:
+    *    ARL ADDR.x, i;
+    *    ARL ADDR.y, j;
+    *    ARL ADDR.z, k;
+    *    ADD TEMP[ADDR.x+5], TEMP[ADDR.y+9], TEMP[ADDR.z+4];
+    * But since we currently only have one address register we have to do this:
+    *    ARL ADDR.x, i;
+    *    MOV t1, TEMP[ADDR.x+9];
+    *    ARL ADDR.x, j;
+    *    MOV t2, TEMP[ADDR.x+4];
+    *    ARL ADDR.x, k;
+    *    ADD TEMP[ADDR.x+5], t1, t2;
+    * The code here figures this out...
+    */
+   if (numIndirect > 0) {
+      for (i = 0; i < 3; i++) {
+         if (src[i] && src[i]->IsIndirect) {
+            /* load the ARL register with the indirect register */
+            emit_arl_load(emitInfo,
+                          src[i]->IndirectFile,
+                          src[i]->IndirectIndex,
+                          src[i]->IndirectSwizzle);
+
+            if (numIndirect > 1) {
+               /* Need to load src[i] into a temporary register */
+               slang_ir_storage srcRelAddr;
+               alloc_local_temp(emitInfo, &newSrc[i], src[i]->Size);
+               isTemp[i] = GL_TRUE;
+
+               /* set RelAddr flag on src register */
+               srcRelAddr = *src[i];
+               srcRelAddr.RelAddr = GL_TRUE;
+               srcRelAddr.IsIndirect = GL_FALSE; /* not really needed */
+
+               /* MOV newSrc, srcRelAddr; */
+               inst = emit_instruction(emitInfo,
+                                       OPCODE_MOV,
+                                       &newSrc[i],
+                                       &srcRelAddr,
+                                       NULL,
+                                       NULL);
+               if (!inst) {
+                  return NULL;
+               }
+
+               src[i] = &newSrc[i];
+            }
+            else {
+               /* just rewrite the src[i] storage to be ARL-relative */
+               newSrc[i] = *src[i];
+               newSrc[i].RelAddr = GL_TRUE;
+               newSrc[i].IsIndirect = GL_FALSE; /* not really needed */
+               src[i] = &newSrc[i];
+            }
+         }
+      }
+   }
+
+   /* Take special steps for indirect dest register write */
+   if (dst && dst->IsIndirect) {
+      /* load the ARL register with the indirect register */
+      emit_arl_load(emitInfo,
+                    dst->IndirectFile,
+                    dst->IndirectIndex,
+                    dst->IndirectSwizzle);
+      newDst = *dst;
+      newDst.RelAddr = GL_TRUE;
+      newDst.IsIndirect = GL_FALSE;
+      dst = &newDst;
+   }
+
+   /* OK, emit the instruction and its dst, src regs */
+   inst = new_instruction(emitInfo, opcode);
+   if (!inst)
+      return NULL;
+
+   if (dst)
+      storage_to_dst_reg(&inst->DstReg, dst);
+
+   for (i = 0; i < 3; i++) {
+      if (src[i])
+         storage_to_src_reg(&inst->SrcReg[i], src[i]);
+   }
+
+   /* Free any temp registers that we allocated above */
+   for (i = 0; i < 3; i++) {
+      if (isTemp[i])
+         _slang_free_temp(emitInfo->vt, &newSrc[i]);
+   }
+
+   return inst;
+}
+
+
+
+/**
+ * Put a comment on the given instruction.
+ */
+static void
+inst_comment(struct prog_instruction *inst, const char *comment)
+{
+   if (inst)
+      inst->Comment = _mesa_strdup(comment);
+}
+
+
+
+/**
+ * Return pointer to last instruction in program.
+ */
+static struct prog_instruction *
+prev_instruction(slang_emit_info *emitInfo)
+{
+   struct gl_program *prog = emitInfo->prog;
+   if (prog->NumInstructions == 0)
+      return NULL;
+   else
+      return prog->Instructions + prog->NumInstructions - 1;
+}
+
+
+static struct prog_instruction *
+emit(slang_emit_info *emitInfo, slang_ir_node *n);
+
+
+/**
+ * Return an annotation string for given node's storage.
+ */
+static char *
+storage_annotation(const slang_ir_node *n, const struct gl_program *prog)
+{
+#if ANNOTATE
+   const slang_ir_storage *st = n->Store;
+   static char s[100] = "";
+
+   if (!st)
+      return _mesa_strdup("");
+
+   switch (st->File) {
+   case PROGRAM_CONSTANT:
+      if (st->Index >= 0) {
+         const GLfloat *val = prog->Parameters->ParameterValues[st->Index];
+         if (st->Swizzle == SWIZZLE_NOOP)
+            _mesa_snprintf(s, sizeof(s), "{%g, %g, %g, %g}", val[0], val[1], val[2], val[3]);
+         else {
+            _mesa_snprintf(s, sizeof(s), "%g", val[GET_SWZ(st->Swizzle, 0)]);
+         }
+      }
+      break;
+   case PROGRAM_TEMPORARY:
+      if (n->Var)
+         _mesa_snprintf(s, sizeof(s), "%s", (char *) n->Var->a_name);
+      else
+         _mesa_snprintf(s, sizeof(s), "t[%d]", st->Index);
+      break;
+   case PROGRAM_STATE_VAR:
+   case PROGRAM_UNIFORM:
+      _mesa_snprintf(s, sizeof(s), "%s", prog->Parameters->Parameters[st->Index].Name);
+      break;
+   case PROGRAM_VARYING:
+      _mesa_snprintf(s, sizeof(s), "%s", prog->Varying->Parameters[st->Index].Name);
+      break;
+   case PROGRAM_INPUT:
+      _mesa_snprintf(s, sizeof(s), "input[%d]", st->Index);
+      break;
+   case PROGRAM_OUTPUT:
+      _mesa_snprintf(s, sizeof(s), "output[%d]", st->Index);
+      break;
+   default:
+      s[0] = 0;
+   }
+   return _mesa_strdup(s);
+#else
+   return NULL;
+#endif
+}
+
+
+/**
+ * Return an annotation string for an instruction.
+ */
+static char *
+instruction_annotation(gl_inst_opcode opcode, char *dstAnnot,
+                       char *srcAnnot0, char *srcAnnot1, char *srcAnnot2)
+{
+#if ANNOTATE
+   const char *operator;
+   char *s;
+   int len = 50;
+
+   if (dstAnnot)
+      len += strlen(dstAnnot);
+   else
+      dstAnnot = _mesa_strdup("");
+
+   if (srcAnnot0)
+      len += strlen(srcAnnot0);
+   else
+      srcAnnot0 = _mesa_strdup("");
+
+   if (srcAnnot1)
+      len += strlen(srcAnnot1);
+   else
+      srcAnnot1 = _mesa_strdup("");
+
+   if (srcAnnot2)
+      len += strlen(srcAnnot2);
+   else
+      srcAnnot2 = _mesa_strdup("");
+
+   switch (opcode) {
+   case OPCODE_ADD:
+      operator = "+";
+      break;
+   case OPCODE_SUB:
+      operator = "-";
+      break;
+   case OPCODE_MUL:
+      operator = "*";
+      break;
+   case OPCODE_DP2:
+      operator = "DP2";
+      break;
+   case OPCODE_DP3:
+      operator = "DP3";
+      break;
+   case OPCODE_DP4:
+      operator = "DP4";
+      break;
+   case OPCODE_XPD:
+      operator = "XPD";
+      break;
+   case OPCODE_RSQ:
+      operator = "RSQ";
+      break;
+   case OPCODE_SGT:
+      operator = ">";
+      break;
+   default:
+      operator = ",";
+   }
+
+   s = (char *) malloc(len);
+   _mesa_snprintf(s, len, "%s = %s %s %s %s", dstAnnot,
+                  srcAnnot0, operator, srcAnnot1, srcAnnot2);
+
+   free(dstAnnot);
+   free(srcAnnot0);
+   free(srcAnnot1);
+   free(srcAnnot2);
+
+   return s;
+#else
+   return NULL;
+#endif
+}
+
+
+/**
+ * Emit an instruction that's just a comment.
+ */
+static struct prog_instruction *
+emit_comment(slang_emit_info *emitInfo, const char *comment)
+{
+   struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_NOP);
+   if (inst) {
+      inst_comment(inst, comment);
+   }
+   return inst;
+}
+
+
+/**
+ * Generate code for a simple arithmetic instruction.
+ * Either 1, 2 or 3 operands.
+ */
+static struct prog_instruction *
+emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   const slang_ir_info *info = _slang_ir_info(n->Opcode);
+   struct prog_instruction *inst;
+   GLuint i;
+
+   assert(info);
+   assert(info->InstOpcode != OPCODE_NOP);
+
+#if PEEPHOLE_OPTIMIZATIONS
+   /* Look for MAD opportunity */
+   if (info->NumParams == 2 &&
+       n->Opcode == IR_ADD && n->Children[0]->Opcode == IR_MUL) {
+      /* found pattern IR_ADD(IR_MUL(A, B), C) */
+      emit(emitInfo, n->Children[0]->Children[0]);  /* A */
+      emit(emitInfo, n->Children[0]->Children[1]);  /* B */
+      emit(emitInfo, n->Children[1]);  /* C */
+      if (!alloc_node_storage(emitInfo, n, -1)) {  /* dest */
+         return NULL;
+      }
+
+      inst = emit_instruction(emitInfo,
+                              OPCODE_MAD,
+                              n->Store,
+                              n->Children[0]->Children[0]->Store,
+                              n->Children[0]->Children[1]->Store,
+                              n->Children[1]->Store);
+
+      free_node_storage(emitInfo->vt, n->Children[0]->Children[0]);
+      free_node_storage(emitInfo->vt, n->Children[0]->Children[1]);
+      free_node_storage(emitInfo->vt, n->Children[1]);
+      return inst;
+   }
+
+   if (info->NumParams == 2 &&
+       n->Opcode == IR_ADD && n->Children[1]->Opcode == IR_MUL) {
+      /* found pattern IR_ADD(A, IR_MUL(B, C)) */
+      emit(emitInfo, n->Children[0]);  /* A */
+      emit(emitInfo, n->Children[1]->Children[0]);  /* B */
+      emit(emitInfo, n->Children[1]->Children[1]);  /* C */
+      if (!alloc_node_storage(emitInfo, n, -1)) {  /* dest */
+         return NULL;
+      }
+
+      inst = emit_instruction(emitInfo,
+                              OPCODE_MAD,
+                              n->Store,
+                              n->Children[1]->Children[0]->Store,
+                              n->Children[1]->Children[1]->Store,
+                              n->Children[0]->Store);
+
+      free_node_storage(emitInfo->vt, n->Children[1]->Children[0]);
+      free_node_storage(emitInfo->vt, n->Children[1]->Children[1]);
+      free_node_storage(emitInfo->vt, n->Children[0]);
+      return inst;
+   }
+#endif
+
+   /* gen code for children, may involve temp allocation */
+   for (i = 0; i < info->NumParams; i++) {
+      emit(emitInfo, n->Children[i]);
+      if (!n->Children[i] || !n->Children[i]->Store) {
+         /* error recovery */
+         return NULL;
+      }
+   }
+
+   /* result storage */
+   if (!alloc_node_storage(emitInfo, n, -1)) {
+      return NULL;
+   }
+
+   inst = emit_instruction(emitInfo,
+                           info->InstOpcode,
+                           n->Store,  /* dest */
+                           (info->NumParams > 0 ? n->Children[0]->Store : NULL),
+                           (info->NumParams > 1 ? n->Children[1]->Store : NULL),
+                           (info->NumParams > 2 ? n->Children[2]->Store : NULL)
+                           );
+
+   /* free temps */
+   for (i = 0; i < info->NumParams; i++)
+      free_node_storage(emitInfo->vt, n->Children[i]);
+
+   return inst;
+}
+
+
+/**
+ * Emit code for == and != operators.  These could normally be handled
+ * by emit_arith() except we need to be able to handle structure comparisons.
+ */
+static struct prog_instruction *
+emit_compare(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   struct prog_instruction *inst = NULL;
+   GLint size;
+
+   assert(n->Opcode == IR_EQUAL || n->Opcode == IR_NOTEQUAL);
+
+   /* gen code for children */
+   emit(emitInfo, n->Children[0]);
+   emit(emitInfo, n->Children[1]);
+
+   if (n->Children[0]->Store->Size != n->Children[1]->Store->Size) {
+      /* XXX this error should have been caught in slang_codegen.c */
+      slang_info_log_error(emitInfo->log, "invalid operands to == or !=");
+      n->Store = NULL;
+      return NULL;
+   }
+
+   /* final result is 1 bool */
+   if (!alloc_node_storage(emitInfo, n, 1))
+      return NULL;
+
+   size = n->Children[0]->Store->Size;
+
+   if (size == 1) {
+      gl_inst_opcode opcode = n->Opcode == IR_EQUAL ? OPCODE_SEQ : OPCODE_SNE;
+      inst =  emit_instruction(emitInfo,
+                               opcode,
+                               n->Store, /* dest */
+                               n->Children[0]->Store,
+                               n->Children[1]->Store,
+                               NULL);
+   }
+   else if (size <= 4) {
+      /* compare two vectors.
+       * Unfortunately, there's no instruction to compare vectors and
+       * return a scalar result.  Do it with some compare and dot product
+       * instructions...
+       */
+      GLuint swizzle;
+      gl_inst_opcode dotOp;
+      slang_ir_storage tempStore;
+
+      if (!alloc_local_temp(emitInfo, &tempStore, 4)) {
+         n->Store = NULL;
+         return NULL;
+         /* out of temps */
+      }
+
+      if (size == 4) {
+         dotOp = OPCODE_DP4;
+         swizzle = SWIZZLE_XYZW;
+      }
+      else if (size == 3) {
+         dotOp = OPCODE_DP3;
+         swizzle = SWIZZLE_XYZW;
+      }
+      else {
+         assert(size == 2);
+         dotOp = OPCODE_DP3; /* XXX use OPCODE_DP2 eventually */
+         swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y);
+      }
+
+      /* Compute inequality (temp = (A != B)) */
+      inst = emit_instruction(emitInfo,
+                              OPCODE_SNE,
+                              &tempStore,
+                              n->Children[0]->Store,
+                              n->Children[1]->Store,
+                              NULL);
+      if (!inst) {
+         return NULL;
+      }
+      inst_comment(inst, "Compare values");
+
+      /* Compute val = DOT(temp, temp)  (reduction) */
+      inst = emit_instruction(emitInfo,
+                              dotOp,
+                              n->Store,
+                              &tempStore,
+                              &tempStore,
+                              NULL);
+      if (!inst) {
+         return NULL;
+      }
+      inst->SrcReg[0].Swizzle = inst->SrcReg[1].Swizzle = swizzle; /*override*/
+      inst_comment(inst, "Reduce vec to bool");
+
+      _slang_free_temp(emitInfo->vt, &tempStore); /* free temp */
+
+      if (n->Opcode == IR_EQUAL) {
+         /* compute val = !val.x  with SEQ val, val, 0; */
+         slang_ir_storage zero;
+         constant_to_storage(emitInfo, 0.0, &zero);
+         inst = emit_instruction(emitInfo,
+                                 OPCODE_SEQ,
+                                 n->Store, /* dest */
+                                 n->Store,
+                                 &zero,
+                                 NULL);
+         if (!inst) {
+            return NULL;
+         }
+         inst_comment(inst, "Invert true/false");
+      }
+   }
+   else {
+      /* size > 4, struct or array compare.
+       * XXX this won't work reliably for structs with padding!!
+       */
+      GLint i, num = (n->Children[0]->Store->Size + 3) / 4;
+      slang_ir_storage accTemp, sneTemp;
+
+      if (!alloc_local_temp(emitInfo, &accTemp, 4))
+         return NULL;
+
+      if (!alloc_local_temp(emitInfo, &sneTemp, 4))
+         return NULL;
+
+      for (i = 0; i < num; i++) {
+         slang_ir_storage srcStore0 = *n->Children[0]->Store;
+         slang_ir_storage srcStore1 = *n->Children[1]->Store;
+         srcStore0.Index += i;
+         srcStore1.Index += i;
+
+         if (i == 0) {
+            /* SNE accTemp, left[i], right[i] */
+            inst = emit_instruction(emitInfo, OPCODE_SNE,
+                                    &accTemp, /* dest */
+                                    &srcStore0,
+                                    &srcStore1,
+                                    NULL);
+            if (!inst) {
+               return NULL;
+            }
+            inst_comment(inst, "Begin struct/array comparison");
+         }
+         else {
+            /* SNE sneTemp, left[i], right[i] */
+            inst = emit_instruction(emitInfo, OPCODE_SNE,
+                                    &sneTemp, /* dest */
+                                    &srcStore0,
+                                    &srcStore1,
+                                    NULL);
+            if (!inst) {
+               return NULL;
+            }
+            /* ADD accTemp, accTemp, sneTemp; # like logical-OR */
+            inst = emit_instruction(emitInfo, OPCODE_ADD,
+                                    &accTemp, /* dest */
+                                    &accTemp,
+                                    &sneTemp,
+                                    NULL);
+            if (!inst) {
+               return NULL;
+            }
+         }
+      }
+
+      /* compute accTemp.x || accTemp.y || accTemp.z || accTemp.w with DOT4 */
+      inst = emit_instruction(emitInfo, OPCODE_DP4,
+                              n->Store,
+                              &accTemp,
+                              &accTemp,
+                              NULL);
+      if (!inst) {
+         return NULL;
+      }
+      inst_comment(inst, "End struct/array comparison");
+
+      if (n->Opcode == IR_EQUAL) {
+         /* compute tmp.x = !tmp.x  via tmp.x = (tmp.x == 0) */
+         slang_ir_storage zero;
+         constant_to_storage(emitInfo, 0.0, &zero);
+         inst = emit_instruction(emitInfo, OPCODE_SEQ,
+                                 n->Store, /* dest */
+                                 n->Store,
+                                 &zero,
+                                 NULL);
+         if (!inst) {
+            return NULL;
+         }
+         inst_comment(inst, "Invert true/false");
+      }
+
+      _slang_free_temp(emitInfo->vt, &accTemp);
+      _slang_free_temp(emitInfo->vt, &sneTemp);
+   }
+
+   /* free temps */
+   free_node_storage(emitInfo->vt, n->Children[0]);
+   free_node_storage(emitInfo->vt, n->Children[1]);
+
+   return inst;
+}
+
+
+
+/**
+ * Generate code for an IR_CLAMP instruction.
+ */
+static struct prog_instruction *
+emit_clamp(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   struct prog_instruction *inst;
+   slang_ir_node tmpNode;
+
+   assert(n->Opcode == IR_CLAMP);
+   /* ch[0] = value
+    * ch[1] = min limit
+    * ch[2] = max limit
+    */
+
+   inst = emit(emitInfo, n->Children[0]);
+
+   /* If lower limit == 0.0 and upper limit == 1.0,
+    *    set prev instruction's SaturateMode field to SATURATE_ZERO_ONE.
+    * Else,
+    *    emit OPCODE_MIN, OPCODE_MAX sequence.
+    */
+#if 0
+   /* XXX this isn't quite finished yet */
+   if (n->Children[1]->Opcode == IR_FLOAT &&
+       n->Children[1]->Value[0] == 0.0 &&
+       n->Children[1]->Value[1] == 0.0 &&
+       n->Children[1]->Value[2] == 0.0 &&
+       n->Children[1]->Value[3] == 0.0 &&
+       n->Children[2]->Opcode == IR_FLOAT &&
+       n->Children[2]->Value[0] == 1.0 &&
+       n->Children[2]->Value[1] == 1.0 &&
+       n->Children[2]->Value[2] == 1.0 &&
+       n->Children[2]->Value[3] == 1.0) {
+      if (!inst) {
+         inst = prev_instruction(prog);
+      }
+      if (inst && inst->Opcode != OPCODE_NOP) {
+         /* and prev instruction's DstReg matches n->Children[0]->Store */
+         inst->SaturateMode = SATURATE_ZERO_ONE;
+         n->Store = n->Children[0]->Store;
+         return inst;
+      }
+   }
+#else
+   (void) inst;
+#endif
+
+   if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
+      return NULL;
+
+   emit(emitInfo, n->Children[1]);
+   emit(emitInfo, n->Children[2]);
+
+   /* Some GPUs don't allow reading from output registers.  So if the
+    * dest for this clamp() is an output reg, we can't use that reg for
+    * the intermediate result.  Use a temp register instead.
+    */
+   memset(&tmpNode, 0, sizeof(tmpNode));
+   if (!alloc_node_storage(emitInfo, &tmpNode, n->Store->Size)) {
+      return NULL;
+   }
+
+   /* tmp = max(ch[0], ch[1]) */
+   inst = emit_instruction(emitInfo, OPCODE_MAX,
+                           tmpNode.Store, /* dest */
+                           n->Children[0]->Store,
+                           n->Children[1]->Store,
+                           NULL);
+   if (!inst) {
+      return NULL;
+   }
+
+   /* n->dest = min(tmp, ch[2]) */
+   inst = emit_instruction(emitInfo, OPCODE_MIN,
+                           n->Store, /* dest */
+                           tmpNode.Store,
+                           n->Children[2]->Store,
+                           NULL);
+
+   free_node_storage(emitInfo->vt, &tmpNode);
+
+   return inst;
+}
+
+
+static struct prog_instruction *
+emit_negation(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   /* Implement as MOV dst, -src; */
+   /* XXX we could look at the previous instruction and in some circumstances
+    * modify it to accomplish the negation.
+    */
+   struct prog_instruction *inst;
+
+   emit(emitInfo, n->Children[0]);
+
+   if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
+      return NULL;
+
+   inst = emit_instruction(emitInfo,
+                           OPCODE_MOV,
+                           n->Store, /* dest */
+                           n->Children[0]->Store,
+                           NULL,
+                           NULL);
+   if (inst) {
+      inst->SrcReg[0].Negate = NEGATE_XYZW;
+   }
+   return inst;
+}
+
+
+static struct prog_instruction *
+emit_label(slang_emit_info *emitInfo, const slang_ir_node *n)
+{
+   assert(n->Label);
+#if 0
+   /* XXX this fails in loop tail code - investigate someday */
+   assert(_slang_label_get_location(n->Label) < 0);
+   _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
+                             emitInfo->prog);
+#else
+   if (_slang_label_get_location(n->Label) < 0)
+      _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
+                                emitInfo->prog);
+#endif
+   return NULL;
+}
+
+
+/**
+ * Emit code for a function call.
+ * Note that for each time a function is called, we emit the function's
+ * body code again because the set of available registers may be different.
+ */
+static struct prog_instruction *
+emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   struct gl_program *progSave;
+   struct prog_instruction *inst;
+   GLuint subroutineId;
+   GLuint maxInstSave;
+
+   assert(n->Opcode == IR_CALL);
+   assert(n->Label);
+
+   /* save/push cur program */
+   maxInstSave = emitInfo->MaxInstructions;
+   progSave = emitInfo->prog;
+
+   emitInfo->prog = new_subroutine(emitInfo, &subroutineId);
+   emitInfo->MaxInstructions = emitInfo->prog->NumInstructions;
+
+   _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
+                             emitInfo->prog);
+
+   if (emitInfo->EmitBeginEndSub) {
+      /* BGNSUB isn't a real instruction.
+       * We require a label (i.e. "foobar:") though, if we're going to
+       * print the program in the NV format.  The BNGSUB instruction is
+       * really just a NOP to attach the label to.
+       */
+      inst = new_instruction(emitInfo, OPCODE_BGNSUB);
+      if (!inst) {
+         return NULL;
+      }
+      inst_comment(inst, n->Label->Name);
+   }
+
+   /* body of function: */
+   emit(emitInfo, n->Children[0]);
+   n->Store = n->Children[0]->Store;
+
+   /* add RET instruction now, if needed */
+   inst = prev_instruction(emitInfo);
+   if (inst && inst->Opcode != OPCODE_RET) {
+      inst = new_instruction(emitInfo, OPCODE_RET);
+      if (!inst) {
+         return NULL;
+      }
+   }
+
+   if (emitInfo->EmitBeginEndSub) {
+      inst = new_instruction(emitInfo, OPCODE_ENDSUB);
+      if (!inst) {
+         return NULL;
+      }
+      inst_comment(inst, n->Label->Name);
+   }
+
+   /* pop/restore cur program */
+   emitInfo->prog = progSave;
+   emitInfo->MaxInstructions = maxInstSave;
+
+   /* emit the function call */
+   inst = new_instruction(emitInfo, OPCODE_CAL);
+   if (!inst) {
+      return NULL;
+   }
+   /* The branch target is just the subroutine number (changed later) */
+   inst->BranchTarget = subroutineId;
+   inst_comment(inst, n->Label->Name);
+   assert(inst->BranchTarget >= 0);
+
+   return inst;
+}
+
+
+/**
+ * Emit code for a 'return' statement.
+ */
+static struct prog_instruction *
+emit_return(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   struct prog_instruction *inst;
+   assert(n);
+   assert(n->Opcode == IR_RETURN);
+   assert(n->Label);
+   inst = new_instruction(emitInfo, OPCODE_RET);
+   if (inst) {
+      inst->DstReg.CondMask = COND_TR;  /* always return */
+   }
+   return inst;
+}
+
+
+static struct prog_instruction *
+emit_kill(slang_emit_info *emitInfo)
+{
+   struct gl_fragment_program *fp;
+   struct prog_instruction *inst;
+   /* NV-KILL - discard fragment depending on condition code.
+    * Note that ARB-KILL depends on sign of vector operand.
+    */
+   inst = new_instruction(emitInfo, OPCODE_KIL_NV);
+   if (!inst) {
+      return NULL;
+   }
+   inst->DstReg.CondMask = COND_TR;  /* always kill */
+
+   assert(emitInfo->prog->Target == GL_FRAGMENT_PROGRAM_ARB);
+   fp = (struct gl_fragment_program *) emitInfo->prog;
+   fp->UsesKill = GL_TRUE;
+
+   return inst;
+}
+
+
+static struct prog_instruction *
+emit_tex(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   struct prog_instruction *inst;
+   gl_inst_opcode opcode;
+   GLboolean shadow = GL_FALSE;
+
+   switch (n->Opcode) {
+   case IR_TEX:
+      opcode = OPCODE_TEX;
+      break;
+   case IR_TEX_SH:
+      opcode = OPCODE_TEX;
+      shadow = GL_TRUE;
+      break;
+   case IR_TEXB:
+      opcode = OPCODE_TXB;
+      break;
+   case IR_TEXB_SH:
+      opcode = OPCODE_TXB;
+      shadow = GL_TRUE;
+      break;
+   case IR_TEXP:
+      opcode = OPCODE_TXP;
+      break;
+   case IR_TEXP_SH:
+      opcode = OPCODE_TXP;
+      shadow = GL_TRUE;
+      break;
+   default:
+      _mesa_problem(NULL, "Bad IR TEX code");
+      return NULL;
+   }
+
+   if (n->Children[0]->Opcode == IR_ELEMENT) {
+      /* array is the sampler (a uniform which'll indicate the texture unit) */
+      assert(n->Children[0]->Children[0]->Store);
+      assert(n->Children[0]->Children[0]->Store->File == PROGRAM_SAMPLER);
+
+      emit(emitInfo, n->Children[0]);
+
+      n->Children[0]->Var = n->Children[0]->Children[0]->Var;
+   } else {
+      /* this is the sampler (a uniform which'll indicate the texture unit) */
+      assert(n->Children[0]->Store);
+      assert(n->Children[0]->Store->File == PROGRAM_SAMPLER);
+   }
+
+   /* emit code for the texcoord operand */
+   (void) emit(emitInfo, n->Children[1]);
+
+   /* alloc storage for result of texture fetch */
+   if (!alloc_node_storage(emitInfo, n, 4))
+      return NULL;
+
+   /* emit TEX instruction;  Child[1] is the texcoord */
+   inst = emit_instruction(emitInfo,
+                           opcode,
+                           n->Store,
+                           n->Children[1]->Store,
+                           NULL,
+                           NULL);
+   if (!inst) {
+      return NULL;
+   }
+
+   inst->TexShadow = shadow;
+
+   /* Store->Index is the uniform/sampler index */
+   assert(n->Children[0]->Store->Index >= 0);
+   inst->TexSrcUnit = n->Children[0]->Store->Index;
+   inst->TexSrcTarget = n->Children[0]->Store->TexTarget;
+
+   /* mark the sampler as being used */
+   _mesa_use_uniform(emitInfo->prog->Parameters,
+                     (char *) n->Children[0]->Var->a_name);
+
+   return inst;
+}
+
+
+/**
+ * Assignment/copy
+ */
+static struct prog_instruction *
+emit_copy(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   struct prog_instruction *inst;
+
+   assert(n->Opcode == IR_COPY);
+
+   /* lhs */
+   emit(emitInfo, n->Children[0]);
+   if (!n->Children[0]->Store || n->Children[0]->Store->Index < 0) {
+      /* an error should have been already recorded */
+      return NULL;
+   }
+
+   /* rhs */
+   assert(n->Children[1]);
+   inst = emit(emitInfo, n->Children[1]);
+
+   if (!n->Children[1]->Store || n->Children[1]->Store->Index < 0) {
+      if (!emitInfo->log->text && !emitInfo->UnresolvedFunctions) {
+         /* XXX this error should have been caught in slang_codegen.c */
+         slang_info_log_error(emitInfo->log, "invalid assignment");
+      }
+      return NULL;
+   }
+
+   assert(n->Children[1]->Store->Index >= 0);
+
+   /*assert(n->Children[0]->Store->Size == n->Children[1]->Store->Size);*/
+
+   n->Store = n->Children[0]->Store;
+
+   if (n->Store->File == PROGRAM_SAMPLER) {
+      /* no code generated for sampler assignments,
+       * just copy the sampler index/target at compile time.
+       */
+      n->Store->Index = n->Children[1]->Store->Index;
+      n->Store->TexTarget = n->Children[1]->Store->TexTarget;
+      return NULL;
+   }
+
+#if PEEPHOLE_OPTIMIZATIONS
+   if (inst &&
+       (n->Children[1]->Opcode != IR_SWIZZLE) &&
+       _slang_is_temp(emitInfo->vt, n->Children[1]->Store) &&
+       (inst->DstReg.File == n->Children[1]->Store->File) &&
+       (inst->DstReg.Index == n->Children[1]->Store->Index) &&
+       !n->Children[0]->Store->IsIndirect &&
+       n->Children[0]->Store->Size <= 4) {
+      /* Peephole optimization:
+       * The Right-Hand-Side has its results in a temporary place.
+       * Modify the RHS (and the prev instruction) to store its results
+       * in the destination specified by n->Children[0].
+       * Then, this MOVE is a no-op.
+       * Ex:
+       *   MUL tmp, x, y;
+       *   MOV a, tmp;
+       * becomes:
+       *   MUL a, x, y;
+       */
+
+      /* fixup the previous instruction (which stored the RHS result) */
+      assert(n->Children[0]->Store->Index >= 0);
+      storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store);
+      return inst;
+   }
+   else
+#endif
+   {
+      if (n->Children[0]->Store->Size > 4) {
+         /* move matrix/struct etc (block of registers) */
+         slang_ir_storage dstStore = *n->Children[0]->Store;
+         slang_ir_storage srcStore = *n->Children[1]->Store;
+         GLint size = srcStore.Size;
+         ASSERT(n->Children[1]->Store->Swizzle == SWIZZLE_NOOP);
+         dstStore.Size = 4;
+         srcStore.Size = 4;
+         while (size >= 4) {
+            inst = emit_instruction(emitInfo, OPCODE_MOV,
+                                    &dstStore,
+                                    &srcStore,
+                                    NULL,
+                                    NULL);
+            if (!inst) {
+               return NULL;
+            }
+            inst_comment(inst, "IR_COPY block");
+            srcStore.Index++;
+            dstStore.Index++;
+            size -= 4;
+         }
+      }
+      else {
+         /* single register move */
+         char *srcAnnot, *dstAnnot;
+         assert(n->Children[0]->Store->Index >= 0);
+         inst = emit_instruction(emitInfo, OPCODE_MOV,
+                                 n->Children[0]->Store, /* dest */
+                                 n->Children[1]->Store,
+                                 NULL,
+                                 NULL);
+         if (!inst) {
+            return NULL;
+         }
+         dstAnnot = storage_annotation(n->Children[0], emitInfo->prog);
+         srcAnnot = storage_annotation(n->Children[1], emitInfo->prog);
+         inst->Comment = instruction_annotation(inst->Opcode, dstAnnot,
+                                                srcAnnot, NULL, NULL);
+      }
+      free_node_storage(emitInfo->vt, n->Children[1]);
+      return inst;
+   }
+}
+
+
+/**
+ * An IR_COND node wraps a boolean expression which is used by an
+ * IF or WHILE test.  This is where we'll set condition codes, if needed.
+ */
+static struct prog_instruction *
+emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   struct prog_instruction *inst;
+
+   assert(n->Opcode == IR_COND);
+
+   if (!n->Children[0])
+      return NULL;
+
+   /* emit code for the expression */
+   inst = emit(emitInfo, n->Children[0]);
+
+   if (!n->Children[0]->Store) {
+      /* error recovery */
+      return NULL;
+   }
+
+   assert(n->Children[0]->Store);
+   /*assert(n->Children[0]->Store->Size == 1);*/
+
+   if (emitInfo->EmitCondCodes) {
+      if (inst &&
+          n->Children[0]->Store &&
+          inst->DstReg.File == n->Children[0]->Store->File &&
+          inst->DstReg.Index == n->Children[0]->Store->Index) {
+         /* The previous instruction wrote to the register who's value
+          * we're testing.  Just fix that instruction so that the
+          * condition codes are computed.
+          */
+         inst->CondUpdate = GL_TRUE;
+         n->Store = n->Children[0]->Store;
+         return inst;
+      }
+      else {
+         /* This'll happen for things like "if (i) ..." where no code
+          * is normally generated for the expression "i".
+          * Generate a move instruction just to set condition codes.
+          */
+         if (!alloc_node_storage(emitInfo, n, 1))
+            return NULL;
+         inst = emit_instruction(emitInfo, OPCODE_MOV,
+                                 n->Store, /* dest */
+                                 n->Children[0]->Store,
+                                 NULL,
+                                 NULL);
+         if (!inst) {
+            return NULL;
+         }
+         inst->CondUpdate = GL_TRUE;
+         inst_comment(inst, "COND expr");
+         _slang_free_temp(emitInfo->vt, n->Store);
+         return inst;
+      }
+   }
+   else {
+      /* No-op: the boolean result of the expression is in a regular reg */
+      n->Store = n->Children[0]->Store;
+      return inst;
+   }
+}
+
+
+/**
+ * Logical-NOT
+ */
+static struct prog_instruction *
+emit_not(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   static const struct {
+      gl_inst_opcode op, opNot;
+   } operators[] = {
+      { OPCODE_SLT, OPCODE_SGE },
+      { OPCODE_SLE, OPCODE_SGT },
+      { OPCODE_SGT, OPCODE_SLE },
+      { OPCODE_SGE, OPCODE_SLT },
+      { OPCODE_SEQ, OPCODE_SNE },
+      { OPCODE_SNE, OPCODE_SEQ },
+      { 0, 0 }
+   };
+   struct prog_instruction *inst;
+   slang_ir_storage zero;
+   GLuint i;
+
+   /* child expr */
+   inst = emit(emitInfo, n->Children[0]);
+
+#if PEEPHOLE_OPTIMIZATIONS
+   if (inst) {
+      /* if the prev instruction was a comparison instruction, invert it */
+      for (i = 0; operators[i].op; i++) {
+         if (inst->Opcode == operators[i].op) {
+            inst->Opcode = operators[i].opNot;
+            n->Store = n->Children[0]->Store;
+            return inst;
+         }
+      }
+   }
+#endif
+
+   /* else, invert using SEQ (v = v == 0) */
+   if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
+      return NULL;
+
+   constant_to_storage(emitInfo, 0.0, &zero);
+   inst = emit_instruction(emitInfo,
+                           OPCODE_SEQ,
+                           n->Store,
+                           n->Children[0]->Store,
+                           &zero,
+                           NULL);
+   if (!inst) {
+      return NULL;
+   }
+   inst_comment(inst, "NOT");
+
+   free_node_storage(emitInfo->vt, n->Children[0]);
+
+   return inst;
+}
+
+
+static struct prog_instruction *
+emit_if(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   struct gl_program *prog = emitInfo->prog;
+   GLuint ifInstLoc, elseInstLoc = 0;
+   GLuint condWritemask = 0;
+
+   /* emit condition expression code */
+   {
+      struct prog_instruction *inst;
+      inst = emit(emitInfo, n->Children[0]);
+      if (emitInfo->EmitCondCodes) {
+         if (!inst) {
+            /* error recovery */
+            return NULL;
+         }
+         condWritemask = inst->DstReg.WriteMask;
+      }
+   }
+
+   if (!n->Children[0]->Store)
+      return NULL;
+
+#if 0
+   assert(n->Children[0]->Store->Size == 1); /* a bool! */
+#endif
+
+   ifInstLoc = prog->NumInstructions;
+   if (emitInfo->EmitHighLevelInstructions) {
+      if (emitInfo->EmitCondCodes) {
+         /* IF condcode THEN ... */
+         struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_IF);
+         if (!ifInst) {
+            return NULL;
+         }
+         ifInst->DstReg.CondMask = COND_NE;  /* if cond is non-zero */
+         /* only test the cond code (1 of 4) that was updated by the
+          * previous instruction.
+          */
+         ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
+      }
+      else {
+         struct prog_instruction *inst;
+
+         /* IF src[0] THEN ... */
+         inst = emit_instruction(emitInfo, OPCODE_IF,
+                                 NULL, /* dst */
+                                 n->Children[0]->Store, /* op0 */
+                                 NULL,
+                                 NULL);
+         if (!inst) {
+            return NULL;
+         }
+      }
+   }
+   else {
+      /* conditional jump to else, or endif */
+      struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_BRA);
+      if (!ifInst) {
+         return NULL;
+      }
+      ifInst->DstReg.CondMask = COND_EQ;  /* BRA if cond is zero */
+      inst_comment(ifInst, "if zero");
+      ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
+   }
+
+   /* if body */
+   emit(emitInfo, n->Children[1]);
+
+   if (n->Children[2]) {
+      /* have else body */
+      elseInstLoc = prog->NumInstructions;
+      if (emitInfo->EmitHighLevelInstructions) {
+         struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ELSE);
+         if (!inst) {
+            return NULL;
+         }
+         prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions - 1;
+      }
+      else {
+         /* jump to endif instruction */
+         struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_BRA);
+         if (!inst) {
+            return NULL;
+         }
+         inst_comment(inst, "else");
+         inst->DstReg.CondMask = COND_TR;  /* always branch */
+         prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions;
+      }
+      emit(emitInfo, n->Children[2]);
+   }
+   else {
+      /* no else body */
+      prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions;
+   }
+
+   if (emitInfo->EmitHighLevelInstructions) {
+      struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ENDIF);
+      if (!inst) {
+         return NULL;
+      }
+   }
+
+   if (elseInstLoc) {
+      /* point ELSE instruction BranchTarget at ENDIF */
+      if (emitInfo->EmitHighLevelInstructions) {
+         prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions - 1;
+      }
+      else {
+         prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions;
+      }
+   }
+   return NULL;
+}
+
+
+static struct prog_instruction *
+emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   struct gl_program *prog = emitInfo->prog;
+   struct prog_instruction *endInst;
+   GLuint beginInstLoc, tailInstLoc, endInstLoc;
+   slang_ir_node *ir;
+
+   /* emit OPCODE_BGNLOOP */
+   beginInstLoc = prog->NumInstructions;
+   if (emitInfo->EmitHighLevelInstructions) {
+      struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_BGNLOOP);
+      if (!inst) {
+         return NULL;
+      }
+   }
+
+   /* body */
+   emit(emitInfo, n->Children[0]);
+
+   /* tail */
+   tailInstLoc = prog->NumInstructions;
+   if (n->Children[1]) {
+      if (emitInfo->EmitComments)
+         emit_comment(emitInfo, "Loop tail code:");
+      emit(emitInfo, n->Children[1]);
+   }
+
+   endInstLoc = prog->NumInstructions;
+   if (emitInfo->EmitHighLevelInstructions) {
+      /* emit OPCODE_ENDLOOP */
+      endInst = new_instruction(emitInfo, OPCODE_ENDLOOP);
+      if (!endInst) {
+         return NULL;
+      }
+   }
+   else {
+      /* emit unconditional BRA-nch */
+      endInst = new_instruction(emitInfo, OPCODE_BRA);
+      if (!endInst) {
+         return NULL;
+      }
+      endInst->DstReg.CondMask = COND_TR;  /* always true */
+   }
+   /* ENDLOOP's BranchTarget points to the BGNLOOP inst */
+   endInst->BranchTarget = beginInstLoc;
+
+   if (emitInfo->EmitHighLevelInstructions) {
+      /* BGNLOOP's BranchTarget points to the ENDLOOP inst */
+      prog->Instructions[beginInstLoc].BranchTarget = prog->NumInstructions -1;
+   }
+
+   /* Done emitting loop code.  Now walk over the loop's linked list of
+    * BREAK and CONT nodes, filling in their BranchTarget fields (which
+    * will point to the corresponding ENDLOOP instruction.
+    */
+   for (ir = n->List; ir; ir = ir->List) {
+      struct prog_instruction *inst = prog->Instructions + ir->InstLocation;
+      assert(inst->BranchTarget < 0);
+      if (ir->Opcode == IR_BREAK ||
+          ir->Opcode == IR_BREAK_IF_TRUE) {
+         assert(inst->Opcode == OPCODE_BRK ||
+                inst->Opcode == OPCODE_BRA);
+         /* go to instruction at end of loop */
+         if (emitInfo->EmitHighLevelInstructions) {
+            inst->BranchTarget = endInstLoc;
+         }
+         else {
+            inst->BranchTarget = endInstLoc + 1;
+         }
+      }
+      else {
+         assert(ir->Opcode == IR_CONT ||
+                ir->Opcode == IR_CONT_IF_TRUE);
+         assert(inst->Opcode == OPCODE_CONT ||
+                inst->Opcode == OPCODE_BRA);
+         /* go to instruction at tail of loop */
+         inst->BranchTarget = endInstLoc;
+      }
+   }
+   return NULL;
+}
+
+
+/**
+ * Unconditional "continue" or "break" statement.
+ * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted.
+ */
+static struct prog_instruction *
+emit_cont_break(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   gl_inst_opcode opcode;
+   struct prog_instruction *inst;
+
+   if (n->Opcode == IR_CONT) {
+      /* we need to execute the loop's tail code before doing CONT */
+      assert(n->Parent);
+      assert(n->Parent->Opcode == IR_LOOP);
+      if (n->Parent->Children[1]) {
+         /* emit tail code */
+         if (emitInfo->EmitComments) {
+            emit_comment(emitInfo, "continue - tail code:");
+         }
+         emit(emitInfo, n->Parent->Children[1]);
+      }
+   }
+
+   /* opcode selection */
+   if (emitInfo->EmitHighLevelInstructions) {
+      opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
+   }
+   else {
+      opcode = OPCODE_BRA;
+   }
+   n->InstLocation = emitInfo->prog->NumInstructions;
+   inst = new_instruction(emitInfo, opcode);
+   if (inst) {
+      inst->DstReg.CondMask = COND_TR;  /* always true */
+   }
+   return inst;
+}
+
+
+/**
+ * Conditional "continue" or "break" statement.
+ * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted.
+ */
+static struct prog_instruction *
+emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   struct prog_instruction *inst;
+
+   assert(n->Opcode == IR_CONT_IF_TRUE ||
+          n->Opcode == IR_BREAK_IF_TRUE);
+
+   /* evaluate condition expr, setting cond codes */
+   inst = emit(emitInfo, n->Children[0]);
+   if (emitInfo->EmitCondCodes) {
+      assert(inst);
+      inst->CondUpdate = GL_TRUE;
+   }
+
+   n->InstLocation = emitInfo->prog->NumInstructions;
+
+   /* opcode selection */
+   if (emitInfo->EmitHighLevelInstructions) {
+      const gl_inst_opcode opcode
+         = (n->Opcode == IR_CONT_IF_TRUE) ? OPCODE_CONT : OPCODE_BRK;
+      if (emitInfo->EmitCondCodes) {
+         /* Get the writemask from the previous instruction which set
+          * the condcodes.  Use that writemask as the CondSwizzle.
+          */
+         const GLuint condWritemask = inst->DstReg.WriteMask;
+         inst = new_instruction(emitInfo, opcode);
+         if (inst) {
+            inst->DstReg.CondMask = COND_NE;
+            inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
+         }
+         return inst;
+      }
+      else {
+         /* IF reg
+          *    BRK/CONT;
+          * ENDIF
+          */
+         GLint ifInstLoc;
+         ifInstLoc = emitInfo->prog->NumInstructions;
+         inst = emit_instruction(emitInfo, OPCODE_IF,
+                                 NULL, /* dest */
+                                 n->Children[0]->Store,
+                                 NULL,
+                                 NULL);
+         if (!inst) {
+            return NULL;
+         }
+         n->InstLocation = emitInfo->prog->NumInstructions;
+
+         inst = new_instruction(emitInfo, opcode);
+         if (!inst) {
+            return NULL;
+         }
+         inst = new_instruction(emitInfo, OPCODE_ENDIF);
+         if (!inst) {
+            return NULL;
+         }
+
+         emitInfo->prog->Instructions[ifInstLoc].BranchTarget
+            = emitInfo->prog->NumInstructions - 1;
+         return inst;
+      }
+   }
+   else {
+      const GLuint condWritemask = inst->DstReg.WriteMask;
+      assert(emitInfo->EmitCondCodes);
+      inst = new_instruction(emitInfo, OPCODE_BRA);
+      if (inst) {
+         inst->DstReg.CondMask = COND_NE;
+         inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
+      }
+      return inst;
+   }
+}
+
+
+/**
+ * Return the size of a swizzle mask given that some swizzle components
+ * may be NIL/undefined.  For example:
+ *  swizzle_size(".zzxx") = 4
+ *  swizzle_size(".xy??") = 2
+ *  swizzle_size(".w???") = 1
+ */
+static GLuint
+swizzle_size(GLuint swizzle)
+{
+   GLuint i;
+   for (i = 0; i < 4; i++) {
+      if (GET_SWZ(swizzle, i) == SWIZZLE_NIL)
+         return i;
+   }
+   return 4;
+}
+
+
+static struct prog_instruction *
+emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   struct prog_instruction *inst;
+
+   inst = emit(emitInfo, n->Children[0]);
+
+   if (!n->Store->Parent) {
+      /* this covers a case such as "(b ? p : q).x" */
+      n->Store->Parent = n->Children[0]->Store;
+      assert(n->Store->Parent);
+   }
+
+   {
+      const GLuint swizzle = n->Store->Swizzle;
+      /* new storage is parent storage with updated Swizzle + Size fields */
+      _slang_copy_ir_storage(n->Store, n->Store->Parent);
+      /* Apply this node's swizzle to parent's storage */
+      n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle);
+      /* Update size */
+      n->Store->Size = swizzle_size(n->Store->Swizzle);
+   }
+
+   assert(!n->Store->Parent);
+   assert(n->Store->Index >= 0);
+
+   return inst;
+}
+
+
+/**
+ * Dereference array element:  element == array[index]
+ * This basically involves emitting code for computing the array index
+ * and updating the node/element's storage info.
+ */
+static struct prog_instruction *
+emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   slang_ir_storage *arrayStore, *indexStore;
+   const int elemSize = n->Store->Size;           /* number of floats */
+   const GLint elemSizeVec = (elemSize + 3) / 4;  /* number of vec4 */
+   struct prog_instruction *inst;
+
+   assert(n->Opcode == IR_ELEMENT);
+   assert(elemSize > 0);
+
+   /* special case for built-in state variables, like light state */
+   {
+      slang_ir_storage *root = n->Store;
+      assert(!root->Parent);
+      while (root->Parent)
+         root = root->Parent;
+
+      if (root->File == PROGRAM_STATE_VAR) {
+         GLboolean direct;
+         GLint index =
+            _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
+         if (index < 0) {
+            /* error */
+            return NULL;
+         }
+         if (direct) {
+            n->Store->Index = index;
+            return NULL; /* all done */
+         }
+      }
+   }
+
+   /* do codegen for array itself */
+   emit(emitInfo, n->Children[0]);
+   arrayStore = n->Children[0]->Store;
+
+   /* The initial array element storage is the array's storage,
+    * then modified below.
+    */
+   _slang_copy_ir_storage(n->Store, arrayStore);
+
+
+   if (n->Children[1]->Opcode == IR_FLOAT) {
+      /* Constant array index */
+      const GLint element = (GLint) n->Children[1]->Value[0];
+
+      /* this element's storage is the array's storage, plus constant offset */
+      n->Store->Index += elemSizeVec * element;
+   }
+   else {
+      /* Variable array index */
+
+      /* do codegen for array index expression */
+      emit(emitInfo, n->Children[1]);
+      indexStore = n->Children[1]->Store;
+
+      if (indexStore->IsIndirect) {
+         /* need to put the array index into a temporary since we can't
+          * directly support a[b[i]] constructs.
+          */
+
+
+         /*indexStore = tempstore();*/
+      }
+
+
+      if (elemSize > 4) {
+         /* need to multiply array index by array element size */
+         struct prog_instruction *inst;
+         slang_ir_storage *indexTemp;
+         slang_ir_storage elemSizeStore;
+
+         /* allocate 1 float indexTemp */
+         indexTemp = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
+         _slang_alloc_temp(emitInfo->vt, indexTemp);
+
+         /* allocate a constant containing the element size */
+         constant_to_storage(emitInfo, (float) elemSizeVec, &elemSizeStore);
+
+         /* multiply array index by element size */
+         inst = emit_instruction(emitInfo,
+                                 OPCODE_MUL,
+                                 indexTemp, /* dest */
+                                 indexStore, /* the index */
+                                 &elemSizeStore,
+                                 NULL);
+         if (!inst) {
+            return NULL;
+         }
+
+         indexStore = indexTemp;
+      }
+
+      if (arrayStore->IsIndirect) {
+         /* ex: in a[i][j], a[i] (the arrayStore) is indirect */
+         /* Need to add indexStore to arrayStore->Indirect store */
+         slang_ir_storage indirectArray;
+         slang_ir_storage *indexTemp;
+
+         _slang_init_ir_storage(&indirectArray,
+                                arrayStore->IndirectFile,
+                                arrayStore->IndirectIndex,
+                                1,
+                                arrayStore->IndirectSwizzle);
+
+         /* allocate 1 float indexTemp */
+         indexTemp = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
+         _slang_alloc_temp(emitInfo->vt, indexTemp);
+
+         inst = emit_instruction(emitInfo,
+                                 OPCODE_ADD,
+                                 indexTemp,      /* dest */
+                                 indexStore,     /* the index */
+                                 &indirectArray, /* indirect array base */
+                                 NULL);
+         if (!inst) {
+            return NULL;
+         }
+
+         indexStore = indexTemp;
+      }
+
+      /* update the array element storage info */
+      n->Store->IsIndirect = GL_TRUE;
+      n->Store->IndirectFile = indexStore->File;
+      n->Store->IndirectIndex = indexStore->Index;
+      n->Store->IndirectSwizzle = indexStore->Swizzle;
+   }
+
+   n->Store->Size = elemSize;
+   n->Store->Swizzle = _slang_var_swizzle(elemSize, 0);
+
+   return NULL; /* no instruction */
+}
+
+
+/**
+ * Resolve storage for accessing a structure field.
+ */
+static struct prog_instruction *
+emit_struct_field(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   slang_ir_storage *root = n->Store;
+   GLint fieldOffset, fieldSize;
+
+   assert(n->Opcode == IR_FIELD);
+
+   assert(!root->Parent);
+   while (root->Parent)
+      root = root->Parent;
+
+   /* If this is the field of a state var, allocate constant/uniform
+    * storage for it now if we haven't already.
+    * Note that we allocate storage (uniform/constant slots) for state
+    * variables here rather than at declaration time so we only allocate
+    * space for the ones that we actually use!
+    */
+   if (root->File == PROGRAM_STATE_VAR) {
+      GLboolean direct;
+      GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
+      if (index < 0) {
+         slang_info_log_error(emitInfo->log, "Error parsing state variable");
+         return NULL;
+      }
+      if (direct) {
+         root->Index = index;
+         return NULL; /* all done */
+      }
+   }
+
+   /* do codegen for struct */
+   emit(emitInfo, n->Children[0]);
+   assert(n->Children[0]->Store->Index >= 0);
+
+
+   fieldOffset = n->Store->Index;
+   fieldSize = n->Store->Size;
+
+   _slang_copy_ir_storage(n->Store, n->Children[0]->Store);
+
+   n->Store->Index = n->Children[0]->Store->Index + fieldOffset / 4;
+   n->Store->Size = fieldSize;
+
+   switch (fieldSize) {
+   case 1:
+      {
+         GLint swz = fieldOffset % 4;
+         n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz);
+      }
+      break;
+   case 2:
+      n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
+                                        SWIZZLE_NIL, SWIZZLE_NIL);
+      break;
+   case 3:
+      n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
+                                        SWIZZLE_Z, SWIZZLE_NIL);
+      break;
+   default:
+      n->Store->Swizzle = SWIZZLE_XYZW;
+   }
+
+   assert(n->Store->Index >= 0);
+
+   return NULL; /* no instruction */
+}
+
+
+/**
+ * Emit code for a variable declaration.
+ * This usually doesn't result in any code generation, but just
+ * memory allocation.
+ */
+static struct prog_instruction *
+emit_var_decl(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   assert(n->Store);
+   assert(n->Store->File != PROGRAM_UNDEFINED);
+   assert(n->Store->Size > 0);
+   /*assert(n->Store->Index < 0);*/
+
+   if (!n->Var || n->Var->isTemp) {
+      /* a nameless/temporary variable, will be freed after first use */
+      /*NEW*/
+      if (n->Store->Index < 0 && !_slang_alloc_temp(emitInfo->vt, n->Store)) {
+         slang_info_log_error(emitInfo->log,
+                              "Ran out of registers, too many temporaries");
+         return NULL;
+      }
+   }
+   else {
+      /* a regular variable */
+      _slang_add_variable(emitInfo->vt, n->Var);
+      if (!_slang_alloc_var(emitInfo->vt, n->Store)) {
+         slang_info_log_error(emitInfo->log,
+                              "Ran out of registers, too many variables");
+         return NULL;
+      }
+      /*
+        printf("IR_VAR_DECL %s %d store %p\n",
+        (char*) n->Var->a_name, n->Store->Index, (void*) n->Store);
+      */
+      assert(n->Var->store == n->Store);
+   }
+   if (emitInfo->EmitComments) {
+      /* emit NOP with comment describing the variable's storage location */
+      char s[1000];
+      _mesa_snprintf(s, sizeof(s), "TEMP[%d]%s = variable %s (size %d)",
+                     n->Store->Index,
+                     _mesa_swizzle_string(n->Store->Swizzle, 0, GL_FALSE), 
+                     (n->Var ? (char *) n->Var->a_name : "anonymous"),
+                     n->Store->Size);
+      emit_comment(emitInfo, s);
+   }
+   return NULL;
+}
+
+
+/**
+ * Emit code for a reference to a variable.
+ * Actually, no code is generated but we may do some memory allocation.
+ * In particular, state vars (uniforms) are allocated on an as-needed basis.
+ */
+static struct prog_instruction *
+emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   assert(n->Store);
+   assert(n->Store->File != PROGRAM_UNDEFINED);
+
+   if (n->Store->File == PROGRAM_STATE_VAR && n->Store->Index < 0) {
+      GLboolean direct;
+      GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
+      if (index < 0) {
+         /* error */
+         char s[100];
+         /* XXX isn't this really an out of memory/resources error? */
+         _mesa_snprintf(s, sizeof(s), "Undefined variable '%s'",
+                 (char *) n->Var->a_name);
+         slang_info_log_error(emitInfo->log, s);
+         return NULL;
+      }
+
+      n->Store->Index = index;
+   }
+   else if (n->Store->File == PROGRAM_UNIFORM ||
+            n->Store->File == PROGRAM_SAMPLER) {
+      /* mark var as used */
+      _mesa_use_uniform(emitInfo->prog->Parameters, (char *) n->Var->a_name);
+   }
+   else if (n->Store->File == PROGRAM_INPUT) {
+      assert(n->Store->Index >= 0);
+      emitInfo->prog->InputsRead |= (1 << n->Store->Index);
+   }
+
+   if (n->Store->Index < 0) {
+      /* probably ran out of registers */
+      return NULL;
+   }
+   assert(n->Store->Size > 0);
+
+   return NULL;
+}
+
+
+static struct prog_instruction *
+emit(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+   struct prog_instruction *inst;
+   if (!n)
+      return NULL;
+
+   if (emitInfo->log->error_flag) {
+      return NULL;
+   }
+
+   if (n->Comment) {
+      inst = new_instruction(emitInfo, OPCODE_NOP);
+      if (inst) {
+         inst->Comment = _mesa_strdup(n->Comment);
+      }
+      inst = NULL;
+   }
+
+   switch (n->Opcode) {
+   case IR_SEQ:
+      /* sequence of two sub-trees */
+      assert(n->Children[0]);
+      assert(n->Children[1]);
+      emit(emitInfo, n->Children[0]);
+      if (emitInfo->log->error_flag)
+         return NULL;
+      inst = emit(emitInfo, n->Children[1]);
+#if 0
+      assert(!n->Store);
+#endif
+      n->Store = n->Children[1]->Store;
+      return inst;
+
+   case IR_SCOPE:
+      /* new variable scope */
+      _slang_push_var_table(emitInfo->vt);
+      inst = emit(emitInfo, n->Children[0]);
+      _slang_pop_var_table(emitInfo->vt);
+      return inst;
+
+   case IR_VAR_DECL:
+      /* Variable declaration - allocate a register for it */
+      inst = emit_var_decl(emitInfo, n);
+      return inst;
+
+   case IR_VAR:
+      /* Reference to a variable
+       * Storage should have already been resolved/allocated.
+       */
+      return emit_var_ref(emitInfo, n);
+
+   case IR_ELEMENT:
+      return emit_array_element(emitInfo, n);
+   case IR_FIELD:
+      return emit_struct_field(emitInfo, n);
+   case IR_SWIZZLE:
+      return emit_swizzle(emitInfo, n);
+
+   /* Simple arithmetic */
+   /* unary */
+   case IR_MOVE:
+   case IR_RSQ:
+   case IR_RCP:
+   case IR_FLOOR:
+   case IR_FRAC:
+   case IR_F_TO_I:
+   case IR_I_TO_F:
+   case IR_ABS:
+   case IR_SIN:
+   case IR_COS:
+   case IR_DDX:
+   case IR_DDY:
+   case IR_EXP:
+   case IR_EXP2:
+   case IR_LOG2:
+   case IR_NOISE1:
+   case IR_NOISE2:
+   case IR_NOISE3:
+   case IR_NOISE4:
+   case IR_NRM4:
+   case IR_NRM3:
+   /* binary */
+   case IR_ADD:
+   case IR_SUB:
+   case IR_MUL:
+   case IR_DOT4:
+   case IR_DOT3:
+   case IR_DOT2:
+   case IR_CROSS:
+   case IR_MIN:
+   case IR_MAX:
+   case IR_SEQUAL:
+   case IR_SNEQUAL:
+   case IR_SGE:
+   case IR_SGT:
+   case IR_SLE:
+   case IR_SLT:
+   case IR_POW:
+   /* trinary operators */
+   case IR_LRP:
+   case IR_CMP:
+      return emit_arith(emitInfo, n);
+
+   case IR_EQUAL:
+   case IR_NOTEQUAL:
+      return emit_compare(emitInfo, n);
+
+   case IR_CLAMP:
+      return emit_clamp(emitInfo, n);
+   case IR_TEX:
+   case IR_TEXB:
+   case IR_TEXP:
+   case IR_TEX_SH:
+   case IR_TEXB_SH:
+   case IR_TEXP_SH:
+      return emit_tex(emitInfo, n);
+   case IR_NEG:
+      return emit_negation(emitInfo, n);
+   case IR_FLOAT:
+      /* find storage location for this float constant */
+      n->Store->Index = _mesa_add_unnamed_constant(emitInfo->prog->Parameters,
+                                                   n->Value,
+                                                   n->Store->Size,
+                                                   &n->Store->Swizzle);
+      if (n->Store->Index < 0) {
+         slang_info_log_error(emitInfo->log, "Ran out of space for constants");
+         return NULL;
+      }
+      return NULL;
+
+   case IR_COPY:
+      return emit_copy(emitInfo, n);
+
+   case IR_COND:
+      return emit_cond(emitInfo, n);
+
+   case IR_NOT:
+      return emit_not(emitInfo, n);
+
+   case IR_LABEL:
+      return emit_label(emitInfo, n);
+
+   case IR_KILL:
+      return emit_kill(emitInfo);
+
+   case IR_CALL:
+      /* new variable scope for subroutines/function calls */
+      _slang_push_var_table(emitInfo->vt);
+      inst = emit_fcall(emitInfo, n);
+      _slang_pop_var_table(emitInfo->vt);
+      return inst;
+
+   case IR_IF:
+      return emit_if(emitInfo, n);
+
+   case IR_LOOP:
+      return emit_loop(emitInfo, n);
+   case IR_BREAK_IF_TRUE:
+   case IR_CONT_IF_TRUE:
+      return emit_cont_break_if_true(emitInfo, n);
+   case IR_BREAK:
+      /* fall-through */
+   case IR_CONT:
+      return emit_cont_break(emitInfo, n);
+
+   case IR_BEGIN_SUB:
+      return new_instruction(emitInfo, OPCODE_BGNSUB);
+   case IR_END_SUB:
+      return new_instruction(emitInfo, OPCODE_ENDSUB);
+   case IR_RETURN:
+      return emit_return(emitInfo, n);
+
+   case IR_NOP:
+      return NULL;
+
+   default:
+      _mesa_problem(NULL, "Unexpected IR opcode in emit()\n");
+   }
+   return NULL;
+}
+
+
+/**
+ * After code generation, any subroutines will be in separate program
+ * objects.  This function appends all the subroutines onto the main
+ * program and resolves the linking of all the branch/call instructions.
+ * XXX this logic should really be part of the linking process...
+ */
+static void
+_slang_resolve_subroutines(slang_emit_info *emitInfo)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_program *mainP = emitInfo->prog;
+   GLuint *subroutineLoc, i, total;
+
+   subroutineLoc
+      = (GLuint *) malloc(emitInfo->NumSubroutines * sizeof(GLuint));
+
+   /* total number of instructions */
+   total = mainP->NumInstructions;
+   for (i = 0; i < emitInfo->NumSubroutines; i++) {
+      subroutineLoc[i] = total;
+      total += emitInfo->Subroutines[i]->NumInstructions;
+   }
+
+   /* adjust BranchTargets within the functions */
+   for (i = 0; i < emitInfo->NumSubroutines; i++) {
+      struct gl_program *sub = emitInfo->Subroutines[i];
+      GLuint j;
+      for (j = 0; j < sub->NumInstructions; j++) {
+         struct prog_instruction *inst = sub->Instructions + j;
+         if (inst->Opcode != OPCODE_CAL && inst->BranchTarget >= 0) {
+            inst->BranchTarget += subroutineLoc[i];
+         }
+      }
+   }
+
+   /* append subroutines' instructions after main's instructions */
+   mainP->Instructions = _mesa_realloc_instructions(mainP->Instructions,
+                                                    mainP->NumInstructions,
+                                                    total);
+   mainP->NumInstructions = total;
+   for (i = 0; i < emitInfo->NumSubroutines; i++) {
+      struct gl_program *sub = emitInfo->Subroutines[i];
+      _mesa_copy_instructions(mainP->Instructions + subroutineLoc[i],
+                              sub->Instructions,
+                              sub->NumInstructions);
+      /* delete subroutine code */
+      sub->Parameters = NULL; /* prevent double-free */
+      _mesa_reference_program(ctx, &emitInfo->Subroutines[i], NULL);
+   }
+
+   /* free subroutine list */
+   if (emitInfo->Subroutines) {
+      free(emitInfo->Subroutines);
+      emitInfo->Subroutines = NULL;
+   }
+   emitInfo->NumSubroutines = 0;
+
+   /* Examine CAL instructions.
+    * At this point, the BranchTarget field of the CAL instruction is
+    * the number/id of the subroutine to call (an index into the
+    * emitInfo->Subroutines list).
+    * Translate that into an actual instruction location now.
+    */
+   for (i = 0; i < mainP->NumInstructions; i++) {
+      struct prog_instruction *inst = mainP->Instructions + i;
+      if (inst->Opcode == OPCODE_CAL) {
+         const GLuint f = inst->BranchTarget;
+         inst->BranchTarget = subroutineLoc[f];
+      }
+   }
+
+   free(subroutineLoc);
+}
+
+
+
+/**
+ * Convert the IR tree into GPU instructions.
+ * \param n  root of IR tree
+ * \param vt  variable table
+ * \param prog  program to put GPU instructions into
+ * \param pragmas  controls codegen options
+ * \param withEnd  if true, emit END opcode at end
+ * \param log  log for emitting errors/warnings/info
+ */
+GLboolean
+_slang_emit_code(slang_ir_node *n, slang_var_table *vt,
+                 struct gl_program *prog,
+                 const struct gl_sl_pragmas *pragmas,
+                 GLboolean withEnd,
+                 slang_info_log *log)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLboolean success;
+   slang_emit_info emitInfo;
+   GLuint maxUniforms;
+
+   emitInfo.log = log;
+   emitInfo.vt = vt;
+   emitInfo.prog = prog;
+   emitInfo.Subroutines = NULL;
+   emitInfo.NumSubroutines = 0;
+   emitInfo.MaxInstructions = prog->NumInstructions;
+
+   emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
+   emitInfo.EmitCondCodes = ctx->Shader.EmitCondCodes;
+   emitInfo.EmitComments = ctx->Shader.EmitComments || pragmas->Debug;
+   emitInfo.EmitBeginEndSub = GL_TRUE;
+
+   if (!emitInfo.EmitCondCodes) {
+      emitInfo.EmitHighLevelInstructions = GL_TRUE;
+   }      
+
+   /* Check uniform/constant limits */
+   if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
+      maxUniforms = ctx->Const.FragmentProgram.MaxUniformComponents / 4;
+   }
+   else {
+      assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
+      maxUniforms = ctx->Const.VertexProgram.MaxUniformComponents / 4;
+   }
+   if (prog->Parameters->NumParameters > maxUniforms) {
+      slang_info_log_error(log, "Constant/uniform register limit exceeded "
+                           "(max=%u vec4)", maxUniforms);
+
+      return GL_FALSE;
+   }
+
+   (void) emit(&emitInfo, n);
+
+   /* finish up by adding the END opcode to program */
+   if (withEnd) {
+      struct prog_instruction *inst;
+      inst = new_instruction(&emitInfo, OPCODE_END);
+      if (!inst) {
+         return GL_FALSE;
+      }
+   }
+
+   _slang_resolve_subroutines(&emitInfo);
+
+   success = GL_TRUE;
+
+#if 0
+   printf("*********** End emit code (%u inst):\n", prog->NumInstructions);
+   _mesa_print_program(prog);
+   _mesa_print_program_parameters(ctx,prog);
+#endif
+
+   return success;
+}
diff --git a/src/mesa/slang/slang_emit.h b/src/mesa/slang/slang_emit.h
new file mode 100644 (file)
index 0000000..ab4c202
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.1
+ *
+ * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SLANG_EMIT_H
+#define SLANG_EMIT_H
+
+
+#include "main/imports.h"
+#include "slang_compile.h"
+#include "slang_ir.h"
+#include "main/mtypes.h"
+
+
+extern GLuint
+_slang_swizzle_swizzle(GLuint swz1, GLuint swz2);
+
+
+extern GLuint
+_slang_var_swizzle(GLint size, GLint comp);
+
+
+extern GLboolean
+_slang_emit_code(slang_ir_node *n, slang_var_table *vartable,
+                 struct gl_program *prog,
+                 const struct gl_sl_pragmas *pragmas,
+                 GLboolean withEnd,
+                 slang_info_log *log);
+
+
+#endif /* SLANG_EMIT_H */
diff --git a/src/mesa/slang/slang_ir.c b/src/mesa/slang/slang_ir.c
new file mode 100644 (file)
index 0000000..c223004
--- /dev/null
@@ -0,0 +1,498 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2009  VMware, Inc.   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "slang_ir.h"
+#include "slang_mem.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_print.h"
+
+
+static const slang_ir_info IrInfo[] = {
+   /* binary ops */
+   { IR_ADD, "IR_ADD", OPCODE_ADD, 4, 2 },
+   { IR_SUB, "IR_SUB", OPCODE_SUB, 4, 2 },
+   { IR_MUL, "IR_MUL", OPCODE_MUL, 4, 2 },
+   { IR_DIV, "IR_DIV", OPCODE_NOP, 0, 2 }, /* XXX broke */
+   { IR_DOT4, "IR_DOT4", OPCODE_DP4, 1, 2 },
+   { IR_DOT3, "IR_DOT3", OPCODE_DP3, 1, 2 },
+   { IR_DOT2, "IR_DOT2", OPCODE_DP2, 1, 2 },
+   { IR_NRM4, "IR_NRM4", OPCODE_NRM4, 1, 1 },
+   { IR_NRM3, "IR_NRM3", OPCODE_NRM3, 1, 1 },
+   { IR_CROSS, "IR_CROSS", OPCODE_XPD, 3, 2 },
+   { IR_LRP, "IR_LRP", OPCODE_LRP, 4, 3 },
+   { IR_MIN, "IR_MIN", OPCODE_MIN, 4, 2 },
+   { IR_MAX, "IR_MAX", OPCODE_MAX, 4, 2 },
+   { IR_CLAMP, "IR_CLAMP", OPCODE_NOP, 4, 3 }, /* special case: emit_clamp() */
+   { IR_SEQUAL, "IR_SEQUAL", OPCODE_SEQ, 4, 2 },
+   { IR_SNEQUAL, "IR_SNEQUAL", OPCODE_SNE, 4, 2 },
+   { IR_SGE, "IR_SGE", OPCODE_SGE, 4, 2 },
+   { IR_SGT, "IR_SGT", OPCODE_SGT, 4, 2 },
+   { IR_SLE, "IR_SLE", OPCODE_SLE, 4, 2 },
+   { IR_SLT, "IR_SLT", OPCODE_SLT, 4, 2 },
+   { IR_POW, "IR_POW", OPCODE_POW, 1, 2 },
+   { IR_EQUAL, "IR_EQUAL", OPCODE_NOP, 1, 2 },
+   { IR_NOTEQUAL, "IR_NOTEQUAL", OPCODE_NOP, 1, 2 },
+
+   /* unary ops */
+   { IR_MOVE, "IR_MOVE", OPCODE_MOV, 4, 1 },
+   { IR_I_TO_F, "IR_I_TO_F", OPCODE_MOV, 4, 1 },  /* int[4] to float[4] */
+   { IR_F_TO_I, "IR_F_TO_I", OPCODE_TRUNC, 4, 1 },
+   { IR_EXP, "IR_EXP", OPCODE_EXP, 1, 1 },
+   { IR_EXP2, "IR_EXP2", OPCODE_EX2, 1, 1 },
+   { IR_LOG2, "IR_LOG2", OPCODE_LG2, 1, 1 },
+   { IR_RSQ, "IR_RSQ", OPCODE_RSQ, 1, 1 },
+   { IR_RCP, "IR_RCP", OPCODE_RCP, 1, 1 },
+   { IR_FLOOR, "IR_FLOOR", OPCODE_FLR, 4, 1 },
+   { IR_FRAC, "IR_FRAC", OPCODE_FRC, 4, 1 },
+   { IR_ABS, "IR_ABS", OPCODE_ABS, 4, 1 },
+   { IR_NEG, "IR_NEG", OPCODE_NOP, 4, 1 }, /* special case: emit_negation() */
+   { IR_DDX, "IR_DDX", OPCODE_DDX, 4, 1 },
+   { IR_DDY, "IR_DDY", OPCODE_DDY, 4, 1 },
+   { IR_SIN, "IR_SIN", OPCODE_SIN, 1, 1 },
+   { IR_COS, "IR_COS", OPCODE_COS, 1, 1 },
+   { IR_NOISE1, "IR_NOISE1", OPCODE_NOISE1, 1, 1 },
+   { IR_NOISE2, "IR_NOISE2", OPCODE_NOISE2, 1, 1 },
+   { IR_NOISE3, "IR_NOISE3", OPCODE_NOISE3, 1, 1 },
+   { IR_NOISE4, "IR_NOISE4", OPCODE_NOISE4, 1, 1 },
+
+   /* other */
+   { IR_CMP, "IR_CMP", OPCODE_CMP, 4, 3 },  /* compare/select */
+   { IR_SEQ, "IR_SEQ", OPCODE_NOP, 0, 0 },
+   { IR_SCOPE, "IR_SCOPE", OPCODE_NOP, 0, 0 },
+   { IR_LABEL, "IR_LABEL", OPCODE_NOP, 0, 0 },
+   { IR_IF, "IR_IF", OPCODE_NOP, 0, 0 },
+   { IR_KILL, "IR_KILL", OPCODE_NOP, 0, 0 },
+   { IR_COND, "IR_COND", OPCODE_NOP, 0, 0 },
+   { IR_CALL, "IR_CALL", OPCODE_NOP, 0, 0 },
+   { IR_COPY, "IR_COPY", OPCODE_NOP, 0, 1 },
+   { IR_NOT, "IR_NOT", OPCODE_NOP, 1, 1 },
+   { IR_VAR, "IR_VAR", OPCODE_NOP, 0, 0 },
+   { IR_VAR_DECL, "IR_VAR_DECL", OPCODE_NOP, 0, 0 },
+   { IR_TEX, "IR_TEX", OPCODE_TEX, 4, 1 },
+   { IR_TEXB, "IR_TEXB", OPCODE_TXB, 4, 1 },
+   { IR_TEXP, "IR_TEXP", OPCODE_TXP, 4, 1 },
+   { IR_TEX_SH, "IR_TEX_SH", OPCODE_TEX, 4, 1 },
+   { IR_TEXB_SH, "IR_TEXB_SH", OPCODE_TXB, 4, 1 },
+   { IR_TEXP_SH, "IR_TEXP_SH", OPCODE_TXP, 4, 1 },
+   { IR_FLOAT, "IR_FLOAT", OPCODE_NOP, 0, 0 }, /* float literal */
+   { IR_FIELD, "IR_FIELD", OPCODE_NOP, 0, 0 },
+   { IR_ELEMENT, "IR_ELEMENT", OPCODE_NOP, 0, 0 },
+   { IR_SWIZZLE, "IR_SWIZZLE", OPCODE_NOP, 0, 0 },
+   { IR_NOP, "IR_NOP", OPCODE_NOP, 0, 0 },
+   { 0, NULL, 0, 0, 0 }
+};
+
+
+const slang_ir_info *
+_slang_ir_info(slang_ir_opcode opcode)
+{
+   GLuint i;
+   for (i = 0; IrInfo[i].IrName; i++) {
+      if (IrInfo[i].IrOpcode == opcode) {
+        return IrInfo + i;
+      }
+   }
+   return NULL;
+}
+
+
+void
+_slang_init_ir_storage(slang_ir_storage *st,
+                       gl_register_file file, GLint index, GLint size,
+                       GLuint swizzle)
+{
+   st->File = file;
+   st->Index = index;
+   st->Size = size;
+   st->Swizzle = swizzle;
+   st->Parent = NULL;
+   st->IsIndirect = GL_FALSE;
+}
+
+
+/**
+ * Return a new slang_ir_storage object.
+ */
+slang_ir_storage *
+_slang_new_ir_storage(gl_register_file file, GLint index, GLint size)
+{
+   slang_ir_storage *st;
+   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
+   if (st) {
+      st->File = file;
+      st->Index = index;
+      st->Size = size;
+      st->Swizzle = SWIZZLE_NOOP;
+      st->Parent = NULL;
+      st->IsIndirect = GL_FALSE;
+   }
+   return st;
+}
+
+
+/**
+ * Return a new slang_ir_storage object.
+ */
+slang_ir_storage *
+_slang_new_ir_storage_swz(gl_register_file file, GLint index, GLint size,
+                          GLuint swizzle)
+{
+   slang_ir_storage *st;
+   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
+   if (st) {
+      st->File = file;
+      st->Index = index;
+      st->Size = size;
+      st->Swizzle = swizzle;
+      st->Parent = NULL;
+      st->IsIndirect = GL_FALSE;
+   }
+   return st;
+}
+
+
+/**
+ * Return a new slang_ir_storage object.
+ */
+slang_ir_storage *
+_slang_new_ir_storage_relative(GLint index, GLint size,
+                               slang_ir_storage *parent)
+{
+   slang_ir_storage *st;
+   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
+   if (st) {
+      st->File = PROGRAM_UNDEFINED;
+      st->Index = index;
+      st->Size = size;
+      st->Swizzle = SWIZZLE_NOOP;
+      st->Parent = parent;
+      st->IsIndirect = GL_FALSE;
+   }
+   return st;
+}
+
+
+slang_ir_storage *
+_slang_new_ir_storage_indirect(gl_register_file file,
+                               GLint index,
+                               GLint size,
+                               gl_register_file indirectFile,
+                               GLint indirectIndex,
+                               GLuint indirectSwizzle)
+{
+   slang_ir_storage *st;
+   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
+   if (st) {
+      st->File = file;
+      st->Index = index;
+      st->Size = size;
+      st->Swizzle = SWIZZLE_NOOP;
+      st->IsIndirect = GL_TRUE;
+      st->IndirectFile = indirectFile;
+      st->IndirectIndex = indirectIndex;
+      st->IndirectSwizzle = indirectSwizzle;
+   }
+   return st;
+}
+
+
+/**
+ * Allocate IR storage for a texture sampler.
+ * \param sampNum  the sampler number/index
+ * \param texTarget  one of TEXTURE_x_INDEX values
+ * \param size  number of samplers (in case of sampler array)
+ */
+slang_ir_storage *
+_slang_new_ir_storage_sampler(GLint sampNum, GLuint texTarget, GLint size)
+{
+   slang_ir_storage *st;
+   assert(texTarget < NUM_TEXTURE_TARGETS);
+   st = _slang_new_ir_storage(PROGRAM_SAMPLER, sampNum, size);
+   if (st) {
+      st->TexTarget = texTarget;
+   }
+   return st;
+}
+
+
+
+/* XXX temporary function */
+void
+_slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src)
+{
+   *dst = *src;
+   dst->Parent = NULL;
+}
+
+
+
+static const char *
+_slang_ir_name(slang_ir_opcode opcode)
+{
+   return _slang_ir_info(opcode)->IrName;
+}
+
+
+
+#if 0 /* no longer needed with mempool */
+/**
+ * Since many IR nodes might point to the same IR storage info, we need
+ * to be careful when deleting things.
+ * Before deleting an IR tree, traverse it and do refcounting on the
+ * IR storage nodes.  Use the refcount info during delete to free things
+ * properly.
+ */
+static void
+_slang_refcount_storage(slang_ir_node *n)
+{
+   GLuint i;
+   if (!n)
+      return;
+   if (n->Store)
+      n->Store->RefCount++;
+   for (i = 0; i < 3; i++)
+      _slang_refcount_storage(n->Children[i]);
+}
+#endif
+
+
+static void
+_slang_free_ir(slang_ir_node *n)
+{
+   GLuint i;
+   if (!n)
+      return;
+
+#if 0
+   if (n->Store) {
+      n->Store->RefCount--;
+      if (n->Store->RefCount == 0) {
+         _slang_free(n->Store);
+         n->Store = NULL;
+      }
+   }
+#endif
+
+   for (i = 0; i < 3; i++)
+      _slang_free_ir(n->Children[i]);
+   /* Do not free n->List since it's a child elsewhere */
+   _slang_free(n);
+}
+
+
+/**
+ * Recursively free an IR tree.
+ */
+void
+_slang_free_ir_tree(slang_ir_node *n)
+{
+#if 0
+   _slang_refcount_storage(n);
+#endif
+   _slang_free_ir(n);
+}
+
+
+static const char *
+storage_string(const slang_ir_storage *st)
+{
+   static const char *files[] = {
+      "TEMP",
+      "LOCAL_PARAM",
+      "ENV_PARAM",
+      "STATE",
+      "INPUT",
+      "OUTPUT",
+      "NAMED_PARAM",
+      "CONSTANT",
+      "UNIFORM",
+      "VARYING",
+      "WRITE_ONLY",
+      "ADDRESS",
+      "SAMPLER",
+      "UNDEFINED"
+   };
+   static char s[100];
+   assert(Elements(files) == PROGRAM_FILE_MAX);
+#if 0
+   if (st->Size == 1)
+      _mesa_snprintf(s, "%s[%d]", files[st->File], st->Index);
+   else
+      _mesa_snprintf(s, "%s[%d..%d]", files[st->File], st->Index,
+                     st->Index + st->Size - 1);
+#endif
+   assert(st->File < (GLint) (sizeof(files) / sizeof(files[0])));
+   _mesa_snprintf(s, sizeof(s), "%s[%d]", files[st->File], st->Index);
+   return s;
+}
+
+
+static void
+spaces(int n)
+{
+   while (n-- > 0) {
+      printf(" ");
+   }
+}
+
+
+void
+_slang_print_ir_tree(const slang_ir_node *n, int indent)
+{
+#define IND 0
+
+   if (!n)
+      return;
+#if !IND
+   if (n->Opcode != IR_SEQ)
+#else
+      printf("%3d:", indent);
+#endif
+      spaces(indent);
+
+   switch (n->Opcode) {
+   case IR_SEQ:
+#if IND
+      printf("SEQ  at %p\n", (void*) n);
+#endif
+      assert(n->Children[0]);
+      assert(n->Children[1]);
+      _slang_print_ir_tree(n->Children[0], indent + IND);
+      _slang_print_ir_tree(n->Children[1], indent + IND);
+      break;
+   case IR_SCOPE:
+      printf("NEW SCOPE\n");
+      assert(!n->Children[1]);
+      _slang_print_ir_tree(n->Children[0], indent + 3);
+      break;
+   case IR_COPY:
+      printf("COPY\n");
+      _slang_print_ir_tree(n->Children[0], indent+3);
+      _slang_print_ir_tree(n->Children[1], indent+3);
+      break;
+   case IR_LABEL:
+      printf("LABEL: %s\n", n->Label->Name);
+      break;
+   case IR_COND:
+      printf("COND\n");
+      _slang_print_ir_tree(n->Children[0], indent + 3);
+      break;
+
+   case IR_IF:
+      printf("IF \n");
+      _slang_print_ir_tree(n->Children[0], indent+3);
+      spaces(indent);
+      printf("THEN\n");
+      _slang_print_ir_tree(n->Children[1], indent+3);
+      if (n->Children[2]) {
+         spaces(indent);
+         printf("ELSE\n");
+         _slang_print_ir_tree(n->Children[2], indent+3);
+      }
+      spaces(indent);
+      printf("ENDIF\n");
+      break;
+
+   case IR_BEGIN_SUB:
+      printf("BEGIN_SUB\n");
+      break;
+   case IR_END_SUB:
+      printf("END_SUB\n");
+      break;
+   case IR_RETURN:
+      printf("RETURN\n");
+      break;
+   case IR_CALL:
+      printf("CALL %s\n", n->Label->Name);
+      break;
+
+   case IR_LOOP:
+      printf("LOOP\n");
+      _slang_print_ir_tree(n->Children[0], indent+3);
+      if (n->Children[1]) {
+         spaces(indent);
+         printf("TAIL:\n");
+         _slang_print_ir_tree(n->Children[1], indent+3);
+      }
+      spaces(indent);
+      printf("ENDLOOP\n");
+      break;
+   case IR_CONT:
+      printf("CONT\n");
+      break;
+   case IR_BREAK:
+      printf("BREAK\n");
+      break;
+   case IR_BREAK_IF_TRUE:
+      printf("BREAK_IF_TRUE\n");
+      _slang_print_ir_tree(n->Children[0], indent+3);
+      break;
+   case IR_CONT_IF_TRUE:
+      printf("CONT_IF_TRUE\n");
+      _slang_print_ir_tree(n->Children[0], indent+3);
+      break;
+
+   case IR_VAR:
+      printf("VAR %s%s at %s  store %p\n",
+             (n->Var ? (char *) n->Var->a_name : "TEMP"),
+             _mesa_swizzle_string(n->Store->Swizzle, 0, 0),
+             storage_string(n->Store), (void*) n->Store);
+      break;
+   case IR_VAR_DECL:
+      printf("VAR_DECL %s (%p) at %s  store %p\n",
+             (n->Var ? (char *) n->Var->a_name : "TEMP"),
+             (void*) n->Var, storage_string(n->Store),
+             (void*) n->Store);
+      break;
+   case IR_FIELD:
+      printf("FIELD %s of\n", n->Field);
+      _slang_print_ir_tree(n->Children[0], indent+3);
+      break;
+   case IR_FLOAT:
+      printf("FLOAT %g %g %g %g\n",
+             n->Value[0], n->Value[1], n->Value[2], n->Value[3]);
+      break;
+   case IR_I_TO_F:
+      printf("INT_TO_FLOAT\n");
+      _slang_print_ir_tree(n->Children[0], indent+3);
+      break;
+   case IR_F_TO_I:
+      printf("FLOAT_TO_INT\n");
+      _slang_print_ir_tree(n->Children[0], indent+3);
+      break;
+   case IR_SWIZZLE:
+      printf("SWIZZLE %s of  (store %p) \n",
+             _mesa_swizzle_string(n->Store->Swizzle, 0, 0), (void*) n->Store);
+      _slang_print_ir_tree(n->Children[0], indent + 3);
+      break;
+   default:
+      printf("%s (%p, %p)  (store %p)\n", _slang_ir_name(n->Opcode),
+             (void*) n->Children[0], (void*) n->Children[1], (void*) n->Store);
+      _slang_print_ir_tree(n->Children[0], indent+3);
+      _slang_print_ir_tree(n->Children[1], indent+3);
+   }
+}
diff --git a/src/mesa/slang/slang_ir.h b/src/mesa/slang/slang_ir.h
new file mode 100644 (file)
index 0000000..166b4e8
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2009  VMware, Inc.   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_ir.h
+ * Mesa GLSL Intermediate Representation tree types and constants.
+ * \author Brian Paul
+ */
+
+
+#ifndef SLANG_IR_H
+#define SLANG_IR_H
+
+
+#include "main/imports.h"
+#include "slang_compile.h"
+#include "slang_label.h"
+#include "main/mtypes.h"
+
+
+/**
+ * Intermediate Representation opcodes
+ */
+typedef enum
+{
+   IR_NOP = 0,
+   IR_SEQ,     /* sequence (eval left, then right) */
+   IR_SCOPE,   /* new variable scope (one child) */
+
+   IR_LABEL,   /* target of a jump or cjump */
+
+   IR_COND,    /* conditional expression/predicate */
+
+   IR_IF,      /* high-level IF/then/else */
+               /* Children[0] = conditional expression */
+               /* Children[1] = if-true part */
+               /* Children[2] = if-else part, or NULL */
+
+   IR_BEGIN_SUB, /* begin subroutine */
+   IR_END_SUB,   /* end subroutine */
+   IR_RETURN,    /* return from subroutine */
+   IR_CALL,      /* call subroutine */
+
+   IR_LOOP,      /* high-level loop-begin / loop-end */
+                 /* Children[0] = loop body */
+                 /* Children[1] = loop tail code, or NULL */
+
+   IR_CONT,      /* continue loop */
+                 /* n->Parent = ptr to parent IR_LOOP Node */
+   IR_BREAK,     /* break loop */
+
+   IR_BREAK_IF_TRUE, /**< Children[0] = the condition expression */
+   IR_CONT_IF_TRUE,
+
+   IR_COPY,       /**< assignment/copy */
+   IR_MOVE,       /**< assembly MOV instruction */
+
+   /* vector ops: */
+   IR_ADD,        /**< assembly ADD instruction */
+   IR_SUB,
+   IR_MUL,
+   IR_DIV,
+   IR_DOT4,
+   IR_DOT3,
+   IR_DOT2,
+   IR_NRM4,
+   IR_NRM3,
+   IR_CROSS,   /* vec3 cross product */
+   IR_LRP,
+   IR_CLAMP,
+   IR_MIN,
+   IR_MAX,
+   IR_CMP,     /* = (op0 < 0) ? op1 : op2 */
+   IR_SEQUAL,  /* Set if args are equal (vector) */
+   IR_SNEQUAL, /* Set if args are not equal (vector) */
+   IR_SGE,     /* Set if greater or equal (vector) */
+   IR_SGT,     /* Set if greater than (vector) */
+   IR_SLE,     /* Set if less or equal (vector) */
+   IR_SLT,     /* Set if less than (vector) */
+   IR_POW,     /* x^y */
+   IR_EXP,     /* e^x */
+   IR_EXP2,    /* 2^x */
+   IR_LOG2,    /* log base 2 */
+   IR_RSQ,     /* 1/sqrt() */
+   IR_RCP,     /* reciprocol */
+   IR_FLOOR,
+   IR_FRAC,
+   IR_ABS,     /* absolute value */
+   IR_NEG,     /* negate */
+   IR_DDX,     /* derivative w.r.t. X */
+   IR_DDY,     /* derivative w.r.t. Y */
+   IR_SIN,     /* sine */
+   IR_COS,     /* cosine */
+   IR_NOISE1,  /* noise(x) */
+   IR_NOISE2,  /* noise(x, y) */
+   IR_NOISE3,  /* noise(x, y, z) */
+   IR_NOISE4,  /* noise(x, y, z, w) */
+
+   IR_EQUAL,   /* boolean equality */
+   IR_NOTEQUAL,/* boolean inequality */
+   IR_NOT,     /* boolean not */
+
+   IR_VAR,     /* variable reference */
+   IR_VAR_DECL,/* var declaration */
+
+   IR_ELEMENT, /* array element */
+   IR_FIELD,   /* struct field */
+   IR_SWIZZLE, /* swizzled storage access */
+
+   IR_TEX,     /* texture lookup */
+   IR_TEXB,    /* texture lookup with LOD bias */
+   IR_TEXP,    /* texture lookup with projection */
+
+   IR_TEX_SH,     /* texture lookup, shadow compare */
+   IR_TEXB_SH,    /* texture lookup with LOD bias, shadow compare */
+   IR_TEXP_SH,    /* texture lookup with projection, shadow compare */
+
+   IR_FLOAT,
+   IR_I_TO_F,  /* int[4] to float[4] conversion */
+   IR_F_TO_I,  /* float[4] to int[4] conversion */
+
+   IR_KILL     /* fragment kill/discard */
+} slang_ir_opcode;
+
+
+/**
+ * Describes where data/variables are stored in the various register files.
+ *
+ * In the simple case, the File, Index and Size fields indicate where
+ * a variable is stored.  For example, a vec3 variable may be stored
+ * as (File=PROGRAM_TEMPORARY, Index=6, Size=3).  Or, File[Index].
+ * Or, a program input like color may be stored as
+ * (File=PROGRAM_INPUT,Index=3,Size=4);
+ *
+ * For single-float values, the Swizzle field indicates which component
+ * of the vector contains the float.
+ *
+ * If IsIndirect is set, the storage is accessed through an indirect
+ * register lookup.  The value in question will be located at:
+ *   File[Index + IndirectFile[IndirectIndex]]
+ *
+ * This is primary used for indexing arrays.  For example, consider this
+ * GLSL code:
+ *   uniform int i;
+ *   float a[10];
+ *   float x = a[i];
+ *
+ * here, storage for a[i] would be described by (File=PROGRAM_TEMPORAY,
+ * Index=aPos, IndirectFile=PROGRAM_UNIFORM, IndirectIndex=iPos), which
+ * would mean TEMP[aPos + UNIFORM[iPos]]
+ */
+struct slang_ir_storage_
+{
+   gl_register_file File;  /**< PROGRAM_TEMPORARY, PROGRAM_INPUT, etc */
+   GLint Index;    /**< -1 means unallocated */
+   GLint Size;     /**< number of floats or ints */
+   GLuint Swizzle; /**< Swizzle AND writemask info */
+   GLint RefCount; /**< Used during IR tree delete */
+
+   GLboolean RelAddr; /* we'll remove this eventually */
+
+   GLboolean IsIndirect;
+   gl_register_file IndirectFile;
+   GLint IndirectIndex;
+   GLuint IndirectSwizzle;
+   GLuint TexTarget;  /**< If File==PROGRAM_SAMPLER, one of TEXTURE_x_INDEX */
+
+   /** If Parent is non-null, Index is relative to parent.
+    * The other fields are ignored.
+    */
+   struct slang_ir_storage_ *Parent;
+};
+
+typedef struct slang_ir_storage_ slang_ir_storage;
+
+
+/**
+ * Intermediate Representation (IR) tree node
+ * Basically a binary tree, but IR_LRP and IR_CLAMP have three children.
+ */
+typedef struct slang_ir_node_
+{
+   slang_ir_opcode Opcode;
+   struct slang_ir_node_ *Children[3];
+   slang_ir_storage *Store;  /**< location of result of this operation */
+   GLint InstLocation;  /**< Location of instruction emitted for this node */
+
+   /** special fields depending on Opcode: */
+   const char *Field;  /**< If Opcode == IR_FIELD */
+   GLfloat Value[4];    /**< If Opcode == IR_FLOAT */
+   slang_variable *Var;  /**< If Opcode == IR_VAR or IR_VAR_DECL */
+   struct slang_ir_node_ *List;  /**< For various linked lists */
+   struct slang_ir_node_ *Parent;  /**< Pointer to logical parent (ie. loop) */
+   slang_label *Label;  /**< Used for branches */
+   const char *Comment; /**< If Opcode == IR_COMMENT */
+} slang_ir_node;
+
+
+
+/**
+ * Assembly and IR info
+ */
+typedef struct
+{
+   slang_ir_opcode IrOpcode;
+   const char *IrName;
+   gl_inst_opcode InstOpcode;
+   GLuint ResultSize, NumParams;
+} slang_ir_info;
+
+
+
+extern const slang_ir_info *
+_slang_ir_info(slang_ir_opcode opcode);
+
+
+extern void
+_slang_init_ir_storage(slang_ir_storage *st,
+                       gl_register_file file, GLint index, GLint size,
+                       GLuint swizzle);
+
+extern slang_ir_storage *
+_slang_new_ir_storage(gl_register_file file, GLint index, GLint size);
+
+
+extern slang_ir_storage *
+_slang_new_ir_storage_swz(gl_register_file file, GLint index, GLint size,
+                          GLuint swizzle);
+
+extern slang_ir_storage *
+_slang_new_ir_storage_relative(GLint index, GLint size,
+                               slang_ir_storage *parent);
+
+
+extern slang_ir_storage *
+_slang_new_ir_storage_indirect(gl_register_file file,
+                               GLint index,
+                               GLint size,
+                               gl_register_file indirectFile,
+                               GLint indirectIndex,
+                               GLuint indirectSwizzle);
+
+extern slang_ir_storage *
+_slang_new_ir_storage_sampler(GLint sampNum, GLuint texTarget, GLint size);
+
+
+extern void
+_slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src);
+
+
+extern void
+_slang_free_ir_tree(slang_ir_node *n);
+
+
+extern void
+_slang_print_ir_tree(const slang_ir_node *n, int indent);
+
+
+#endif /* SLANG_IR_H */
diff --git a/src/mesa/slang/slang_label.c b/src/mesa/slang/slang_label.c
new file mode 100644 (file)
index 0000000..8e3a8eb
--- /dev/null
@@ -0,0 +1,104 @@
+
+
+/**
+ * Functions for managing instruction labels.
+ * Basically, this is used to manage the problem of forward branches where
+ * we have a branch instruciton but don't know the target address yet.
+ */
+
+
+#include "slang_label.h"
+#include "slang_mem.h"
+
+
+
+slang_label *
+_slang_label_new(const char *name)
+{
+   slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label));
+   if (l) {
+      l->Name = _slang_strdup(name);
+      l->Location = -1;
+   }
+   return l;
+}
+
+/**
+ * As above, but suffix the name with a unique number.
+ */
+slang_label *
+_slang_label_new_unique(const char *name)
+{
+   static int id = 1;
+   slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label));
+   if (l) {
+      l->Name = (char *) _slang_alloc(strlen(name) + 10);
+      if (!l->Name) {
+         free(l);
+         return NULL;
+      }
+      _mesa_snprintf(l->Name, strlen(name) + 10, "%s_%d", name, id);
+      id++;
+      l->Location = -1;
+   }
+   return l;
+}
+
+void
+_slang_label_delete(slang_label *l)
+{
+   if (l->Name) {
+      _slang_free(l->Name);
+      l->Name = NULL;
+   }
+   if (l->References) {
+      _slang_free(l->References);
+      l->References = NULL;
+   }
+   _slang_free(l);
+}
+
+
+void
+_slang_label_add_reference(slang_label *l, GLuint inst)
+{
+   const GLuint oldSize = l->NumReferences * sizeof(GLuint);
+   assert(l->Location < 0);
+   l->References = _slang_realloc(l->References,
+                                  oldSize, oldSize + sizeof(GLuint));
+   if (l->References) {
+      l->References[l->NumReferences] = inst;
+      l->NumReferences++;
+   }
+}
+
+
+GLint
+_slang_label_get_location(const slang_label *l)
+{
+   return l->Location;
+}
+
+
+void
+_slang_label_set_location(slang_label *l, GLint location,
+                          struct gl_program *prog)
+{
+   GLuint i;
+
+   assert(l->Location < 0);
+   assert(location >= 0);
+
+   l->Location = location;
+
+   /* for the instructions that were waiting to learn the label's location: */
+   for (i = 0; i < l->NumReferences; i++) {
+      const GLuint j = l->References[i];
+      prog->Instructions[j].BranchTarget = location;
+   }
+
+   if (l->References) {
+      _slang_free(l->References);
+      l->References = NULL;
+   }
+}
diff --git a/src/mesa/slang/slang_label.h b/src/mesa/slang/slang_label.h
new file mode 100644 (file)
index 0000000..87068ae
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef SLANG_LABEL_H
+#define SLANG_LABEL_H 1
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "shader/prog_instruction.h"
+
+
+struct slang_label_
+{
+   char *Name;
+   GLint Location;
+   /**
+    * List of instruction references (numbered starting at zero) which need
+    * their BranchTarget field filled in with the location eventually
+    * assigned to the label.
+    */
+   GLuint NumReferences;
+   GLuint *References;   /** Array [NumReferences] */
+};
+
+typedef struct slang_label_ slang_label;
+
+
+extern slang_label *
+_slang_label_new(const char *name);
+
+extern slang_label *
+_slang_label_new_unique(const char *name);
+
+extern void
+_slang_label_delete(slang_label *l);
+
+extern void
+_slang_label_add_reference(slang_label *l, GLuint inst);
+
+extern GLint
+_slang_label_get_location(const slang_label *l);
+
+extern void
+_slang_label_set_location(slang_label *l, GLint location,
+                          struct gl_program *prog);
+
+
+#endif /* SLANG_LABEL_H */
diff --git a/src/mesa/slang/slang_link.c b/src/mesa/slang/slang_link.c
new file mode 100644 (file)
index 0000000..56d42ca
--- /dev/null
@@ -0,0 +1,1124 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.3
+ *
+ * Copyright (C) 2008  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_link.c
+ * GLSL linker
+ * \author Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/shaderapi.h"
+#include "main/shaderobj.h"
+#include "main/uniforms.h"
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "shader/prog_statevars.h"
+#include "shader/prog_uniform.h"
+#include "slang_builtin.h"
+#include "slang_link.h"
+
+
+/** cast wrapper */
+static struct gl_vertex_program *
+vertex_program(struct gl_program *prog)
+{
+   assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
+   return (struct gl_vertex_program *) prog;
+}
+
+
+/** cast wrapper */
+static struct gl_fragment_program *
+fragment_program(struct gl_program *prog)
+{
+   assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
+   return (struct gl_fragment_program *) prog;
+}
+
+
+/**
+ * Record a linking error.
+ */
+static void
+link_error(struct gl_shader_program *shProg, const char *msg)
+{
+   if (shProg->InfoLog) {
+      free(shProg->InfoLog);
+   }
+   shProg->InfoLog = _mesa_strdup(msg);
+   shProg->LinkStatus = GL_FALSE;
+}
+
+
+
+/**
+ * Check if the given bit is either set or clear in both bitfields.
+ */
+static GLboolean
+bits_agree(GLbitfield flags1, GLbitfield flags2, GLbitfield bit)
+{
+   return (flags1 & bit) == (flags2 & bit);
+}
+
+
+/**
+ * Examine the outputs/varyings written by the vertex shader and
+ * append the names of those outputs onto the Varyings list.
+ * This will only capture the pre-defined/built-in varyings like
+ * gl_Position, not user-defined varyings.
+ */
+static void
+update_varying_var_list(GLcontext *ctx, struct gl_shader_program *shProg)
+{
+   if (shProg->VertexProgram) {
+      GLbitfield64 written = shProg->VertexProgram->Base.OutputsWritten;
+      GLuint i;
+      for (i = 0; written && i < VERT_RESULT_MAX; i++) {
+         if (written & BITFIELD64_BIT(i)) {
+            const char *name = _slang_vertex_output_name(i);            
+            if (name)
+               _mesa_add_varying(shProg->Varying, name, 1, GL_FLOAT_VEC4, 0x0);
+            written &= ~BITFIELD64_BIT(i);
+         }
+      }
+   }
+}
+
+
+/**
+ * Do link error checking related to transform feedback.
+ */
+static GLboolean
+link_transform_feedback(GLcontext *ctx, struct gl_shader_program *shProg)
+{
+   GLbitfield varyingMask;
+   GLuint totalComps, maxComps, i;
+
+   if (shProg->TransformFeedback.NumVarying == 0) {
+      /* nothing to do */
+      return GL_TRUE;
+   }
+
+   /* Check that there's a vertex shader */
+   if (shProg->TransformFeedback.NumVarying > 0 &&
+       !shProg->VertexProgram) {
+      link_error(shProg, "Transform feedback without vertex shader");
+      return GL_FALSE;
+   }
+
+   /* Check that all named variables exist, and that none are duplicated.
+    * Also, build a count of the number of varying components to feedback.
+    */
+   totalComps = 0;
+   varyingMask = 0x0;
+   for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
+      const GLchar *name = shProg->TransformFeedback.VaryingNames[i];
+      GLint v = _mesa_lookup_parameter_index(shProg->Varying, -1, name);
+      struct gl_program_parameter *p;
+
+      if (v < 0) {
+         char msg[100];
+         _mesa_snprintf(msg, sizeof(msg),
+                        "vertex shader does not emit %s", name);
+         link_error(shProg, msg);
+         return GL_FALSE;
+      }
+
+      assert(v < MAX_VARYING);
+
+      /* already seen this varying name? */
+      if (varyingMask & (1 << v)) {
+         char msg[100];
+         _mesa_snprintf(msg, sizeof(msg),
+                        "duplicated transform feedback varying name: %s",
+                        name);
+         link_error(shProg, msg);
+         return GL_FALSE;
+      }
+
+      varyingMask |= (1 << v);
+
+      p = &shProg->Varying->Parameters[v];
+      
+      totalComps += _mesa_sizeof_glsl_type(p->DataType);
+   }
+
+   if (shProg->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS)
+      maxComps = ctx->Const.MaxTransformFeedbackInterleavedComponents;
+   else
+      maxComps = ctx->Const.MaxTransformFeedbackSeparateComponents;
+
+   /* check max varying components against the limit */
+   if (totalComps > maxComps) {
+      char msg[100];
+      _mesa_snprintf(msg, sizeof(msg),
+                     "Too many feedback components: %u, max is %u",
+                     totalComps, maxComps);
+      link_error(shProg, msg);
+      return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
+
+/**
+ * Linking varying vars involves rearranging varying vars so that the
+ * vertex program's output varyings matches the order of the fragment
+ * program's input varyings.
+ * We'll then rewrite instructions to replace PROGRAM_VARYING with either
+ * PROGRAM_INPUT or PROGRAM_OUTPUT depending on whether it's a vertex or
+ * fragment shader.
+ * This is also where we set program Input/OutputFlags to indicate
+ * which inputs are centroid-sampled, invariant, etc.
+ */
+static GLboolean
+link_varying_vars(GLcontext *ctx,
+                  struct gl_shader_program *shProg, struct gl_program *prog)
+{
+   GLuint *map, i, firstVarying, newFile;
+   GLbitfield *inOutFlags;
+
+   map = (GLuint *) malloc(prog->Varying->NumParameters * sizeof(GLuint));
+   if (!map)
+      return GL_FALSE;
+
+   /* Varying variables are treated like other vertex program outputs
+    * (and like other fragment program inputs).  The position of the
+    * first varying differs for vertex/fragment programs...
+    * Also, replace File=PROGRAM_VARYING with File=PROGRAM_INPUT/OUTPUT.
+    */
+   if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
+      firstVarying = VERT_RESULT_VAR0;
+      newFile = PROGRAM_OUTPUT;
+      inOutFlags = prog->OutputFlags;
+   }
+   else {
+      assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
+      firstVarying = FRAG_ATTRIB_VAR0;
+      newFile = PROGRAM_INPUT;
+      inOutFlags = prog->InputFlags;
+   }
+
+   for (i = 0; i < prog->Varying->NumParameters; i++) {
+      /* see if this varying is in the linked varying list */
+      const struct gl_program_parameter *var = prog->Varying->Parameters + i;
+      GLint j = _mesa_lookup_parameter_index(shProg->Varying, -1, var->Name);
+      if (j >= 0) {
+         /* varying is already in list, do some error checking */
+         const struct gl_program_parameter *v =
+            &shProg->Varying->Parameters[j];
+         if (var->Size != v->Size) {
+            link_error(shProg, "mismatched varying variable types");
+            free(map);
+            return GL_FALSE;
+         }
+         if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_CENTROID)) {
+            char msg[100];
+            _mesa_snprintf(msg, sizeof(msg),
+                    "centroid modifier mismatch for '%s'", var->Name);
+            link_error(shProg, msg);
+            free(map);
+            return GL_FALSE;
+         }
+         if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_INVARIANT)) {
+            char msg[100];
+            _mesa_snprintf(msg, sizeof(msg),
+                    "invariant modifier mismatch for '%s'", var->Name);
+            link_error(shProg, msg);
+            free(map);
+            return GL_FALSE;
+         }
+      }
+      else {
+         /* not already in linked list */
+         j = _mesa_add_varying(shProg->Varying, var->Name, var->Size,
+                               var->DataType, var->Flags);
+      }
+
+      if (shProg->Varying->NumParameters > ctx->Const.MaxVarying) {
+         link_error(shProg, "Too many varying variables");
+         free(map);
+         return GL_FALSE;
+      }
+
+      /* Map varying[i] to varying[j].
+       * Note: the loop here takes care of arrays or large (sz>4) vars.
+       */
+      {
+         GLint sz = var->Size;
+         while (sz > 0) {
+            inOutFlags[firstVarying + j] = var->Flags;
+            /*printf("Link varying from %d to %d\n", i, j);*/
+            map[i++] = j++;
+            sz -= 4;
+         }
+         i--; /* go back one */
+      }
+   }
+
+
+   /* OK, now scan the program/shader instructions looking for varying vars,
+    * replacing the old index with the new index.
+    */
+   for (i = 0; i < prog->NumInstructions; i++) {
+      struct prog_instruction *inst = prog->Instructions + i;
+      GLuint j;
+
+      if (inst->DstReg.File == PROGRAM_VARYING) {
+         inst->DstReg.File = newFile;
+         inst->DstReg.Index = map[ inst->DstReg.Index ] + firstVarying;
+      }
+
+      for (j = 0; j < 3; j++) {
+         if (inst->SrcReg[j].File == PROGRAM_VARYING) {
+            inst->SrcReg[j].File = newFile;
+            inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ] + firstVarying;
+         }
+      }
+   }
+
+   free(map);
+
+   /* these will get recomputed before linking is completed */
+   prog->InputsRead = 0x0;
+   prog->OutputsWritten = 0x0;
+
+   return GL_TRUE;
+}
+
+
+/**
+ * Build the shProg->Uniforms list.
+ * This is basically a list/index of all uniforms found in either/both of
+ * the vertex and fragment shaders.
+ *
+ * About uniforms:
+ * Each uniform has two indexes, one that points into the vertex
+ * program's parameter array and another that points into the fragment
+ * program's parameter array.  When the user changes a uniform's value
+ * we have to change the value in the vertex and/or fragment program's
+ * parameter array.
+ *
+ * This function will be called twice to set up the two uniform->parameter
+ * mappings.
+ *
+ * If a uniform is only present in the vertex program OR fragment program
+ * then the fragment/vertex parameter index, respectively, will be -1.
+ */
+static GLboolean
+link_uniform_vars(GLcontext *ctx,
+                  struct gl_shader_program *shProg,
+                  struct gl_program *prog,
+                  GLuint *numSamplers)
+{
+   GLuint samplerMap[200]; /* max number of samplers declared, not used */
+   GLuint i;
+
+   for (i = 0; i < prog->Parameters->NumParameters; i++) {
+      const struct gl_program_parameter *p = prog->Parameters->Parameters + i;
+
+      /*
+       * XXX FIX NEEDED HERE
+       * We should also be adding a uniform if p->Type == PROGRAM_STATE_VAR.
+       * For example, modelview matrix, light pos, etc.
+       * Also, we need to update the state-var name-generator code to
+       * generate GLSL-style names, like "gl_LightSource[0].position".
+       * Furthermore, we'll need to fix the state-var's size/datatype info.
+       */
+
+      if ((p->Type == PROGRAM_UNIFORM || p->Type == PROGRAM_SAMPLER)
+          && p->Used) {
+         /* add this uniform, indexing into the target's Parameters list */
+         struct gl_uniform *uniform =
+            _mesa_append_uniform(shProg->Uniforms, p->Name, prog->Target, i);
+         if (uniform)
+            uniform->Initialized = p->Initialized;
+      }
+
+      /* The samplerMap[] table we build here is used to remap/re-index
+       * sampler references by TEX instructions.
+       */
+      if (p->Type == PROGRAM_SAMPLER && p->Used) {
+         /* Allocate a new sampler index */
+         GLuint oldSampNum = (GLuint) prog->Parameters->ParameterValues[i][0];
+         GLuint newSampNum = *numSamplers;
+         if (newSampNum >= ctx->Const.MaxTextureImageUnits) {
+            char s[100];
+            _mesa_snprintf(s, sizeof(s),
+                           "Too many texture samplers (%u, max is %u)",
+                           newSampNum, ctx->Const.MaxTextureImageUnits);
+            link_error(shProg, s);
+            return GL_FALSE;
+         }
+         /* save old->new mapping in the table */
+         if (oldSampNum < Elements(samplerMap))
+            samplerMap[oldSampNum] = newSampNum;
+         /* update parameter's sampler index */
+         prog->Parameters->ParameterValues[i][0] = (GLfloat) newSampNum;
+         (*numSamplers)++;
+      }
+   }
+
+   /* OK, now scan the program/shader instructions looking for texture
+    * instructions using sampler vars.  Replace old sampler indexes with
+    * new ones.
+    */
+   prog->SamplersUsed = 0x0;
+   for (i = 0; i < prog->NumInstructions; i++) {
+      struct prog_instruction *inst = prog->Instructions + i;
+      if (_mesa_is_tex_instruction(inst->Opcode)) {
+         /* here, inst->TexSrcUnit is really the sampler unit */
+         const GLint oldSampNum = inst->TexSrcUnit;
+
+#if 0
+         printf("====== remap sampler from %d to %d\n",
+                inst->TexSrcUnit, samplerMap[ inst->TexSrcUnit ]);
+#endif
+
+         if (oldSampNum < Elements(samplerMap)) {
+            const GLuint newSampNum = samplerMap[oldSampNum];
+            inst->TexSrcUnit = newSampNum;
+            prog->SamplerTargets[newSampNum] = inst->TexSrcTarget;
+            prog->SamplersUsed |= (1 << newSampNum);
+            if (inst->TexShadow) {
+               prog->ShadowSamplers |= (1 << newSampNum);
+            }
+         }
+      }
+   }
+
+   return GL_TRUE;
+}
+
+
+/**
+ * Resolve binding of generic vertex attributes.
+ * For example, if the vertex shader declared "attribute vec4 foobar" we'll
+ * allocate a generic vertex attribute for "foobar" and plug that value into
+ * the vertex program instructions.
+ * But if the user called glBindAttributeLocation(), those bindings will
+ * have priority.
+ */
+static GLboolean
+_slang_resolve_attributes(struct gl_shader_program *shProg,
+                          const struct gl_program *origProg,
+                          struct gl_program *linkedProg)
+{
+   GLint attribMap[MAX_VERTEX_GENERIC_ATTRIBS];
+   GLuint i, j;
+   GLbitfield usedAttributes; /* generics only, not legacy attributes */
+   GLbitfield inputsRead = 0x0;
+
+   assert(origProg != linkedProg);
+   assert(origProg->Target == GL_VERTEX_PROGRAM_ARB);
+   assert(linkedProg->Target == GL_VERTEX_PROGRAM_ARB);
+
+   if (!shProg->Attributes)
+      shProg->Attributes = _mesa_new_parameter_list();
+
+   if (linkedProg->Attributes) {
+      _mesa_free_parameter_list(linkedProg->Attributes);
+   }
+   linkedProg->Attributes = _mesa_new_parameter_list();
+
+
+   /* Build a bitmask indicating which attribute indexes have been
+    * explicitly bound by the user with glBindAttributeLocation().
+    */
+   usedAttributes = 0x0;
+   for (i = 0; i < shProg->Attributes->NumParameters; i++) {
+      GLint attr = shProg->Attributes->Parameters[i].StateIndexes[0];
+      usedAttributes |= (1 << attr);
+   }
+
+   /* If gl_Vertex is used, that actually counts against the limit
+    * on generic vertex attributes.  This avoids the ambiguity of
+    * whether glVertexAttrib4fv(0, v) sets legacy attribute 0 (vert pos)
+    * or generic attribute[0].  If gl_Vertex is used, we want the former.
+    */
+   if (origProg->InputsRead & VERT_BIT_POS) {
+      usedAttributes |= 0x1;
+   }
+
+   /* initialize the generic attribute map entries to -1 */
+   for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
+      attribMap[i] = -1;
+   }
+
+   /*
+    * Scan program for generic attribute references
+    */
+   for (i = 0; i < linkedProg->NumInstructions; i++) {
+      struct prog_instruction *inst = linkedProg->Instructions + i;
+      for (j = 0; j < 3; j++) {
+         if (inst->SrcReg[j].File == PROGRAM_INPUT) {
+            inputsRead |= (1 << inst->SrcReg[j].Index);
+         }
+
+         if (inst->SrcReg[j].File == PROGRAM_INPUT &&
+             inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) {
+            /*
+             * OK, we've found a generic vertex attribute reference.
+             */
+            const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0;
+
+            GLint attr = attribMap[k];
+
+            if (attr < 0) {
+               /* Need to figure out attribute mapping now.
+                */
+               const char *name = origProg->Attributes->Parameters[k].Name;
+               const GLint size = origProg->Attributes->Parameters[k].Size;
+               const GLenum type =origProg->Attributes->Parameters[k].DataType;
+               GLint index;
+
+               /* See if there's a user-defined attribute binding for
+                * this name.
+                */
+               index = _mesa_lookup_parameter_index(shProg->Attributes,
+                                                    -1, name);
+               if (index >= 0) {
+                  /* Found a user-defined binding */
+                  attr = shProg->Attributes->Parameters[index].StateIndexes[0];
+               }
+               else {
+                  /* No user-defined binding, choose our own attribute number.
+                   * Start at 1 since generic attribute 0 always aliases
+                   * glVertex/position.
+                   */
+                  for (attr = 0; attr < MAX_VERTEX_GENERIC_ATTRIBS; attr++) {
+                     if (((1 << attr) & usedAttributes) == 0)
+                        break;
+                  }
+                  if (attr == MAX_VERTEX_GENERIC_ATTRIBS) {
+                     link_error(shProg, "Too many vertex attributes");
+                     return GL_FALSE;
+                  }
+
+                  /* mark this attribute as used */
+                  usedAttributes |= (1 << attr);
+               }
+
+               attribMap[k] = attr;
+
+               /* Save the final name->attrib binding so it can be queried
+                * with glGetAttributeLocation().
+                */
+               _mesa_add_attribute(linkedProg->Attributes, name,
+                                   size, type, attr);
+            }
+
+            assert(attr >= 0);
+
+            /* update the instruction's src reg */
+            inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + attr;
+         }
+      }
+   }
+
+   /* Handle pre-defined attributes here (gl_Vertex, gl_Normal, etc).
+    * When the user queries the active attributes we need to include both
+    * the user-defined attributes and the built-in ones.
+    */
+   for (i = VERT_ATTRIB_POS; i < VERT_ATTRIB_GENERIC0; i++) {
+      if (inputsRead & (1 << i)) {
+         _mesa_add_attribute(linkedProg->Attributes,
+                             _slang_vert_attrib_name(i),
+                             4, /* size in floats */
+                             _slang_vert_attrib_type(i),
+                             -1 /* attrib/input */);
+      }
+   }
+
+   return GL_TRUE;
+}
+
+
+/**
+ * Scan program instructions to update the program's NumTemporaries field.
+ * Note: this implemenation relies on the code generator allocating
+ * temps in increasing order (0, 1, 2, ... ).
+ */
+static void
+_slang_count_temporaries(struct gl_program *prog)
+{
+   GLuint i, j;
+   GLint maxIndex = -1;
+
+   for (i = 0; i < prog->NumInstructions; i++) {
+      const struct prog_instruction *inst = prog->Instructions + i;
+      const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+      for (j = 0; j < numSrc; j++) {
+         if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
+            if (maxIndex < inst->SrcReg[j].Index)
+               maxIndex = inst->SrcReg[j].Index;
+         }
+         if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+            if (maxIndex < (GLint) inst->DstReg.Index)
+               maxIndex = inst->DstReg.Index;
+         }
+      }
+   }
+
+   prog->NumTemporaries = (GLuint) (maxIndex + 1);
+}
+
+
+/**
+ * If an input attribute is indexed with relative addressing we have
+ * to compute a gl_program::InputsRead bitmask which reflects the fact
+ * that any input may be referenced by array element.  Ex: gl_TexCoord[i].
+ * This function computes the bitmask of potentially read inputs.
+ */
+static GLbitfield
+get_inputs_read_mask(GLenum target, GLuint index, GLboolean relAddr)
+{
+   GLbitfield mask;
+
+   mask = 1 << index;
+
+   if (relAddr) {
+      if (target == GL_VERTEX_PROGRAM_ARB) {
+         switch (index) {
+         case VERT_ATTRIB_TEX0:
+            mask = ((1U << (VERT_ATTRIB_TEX7 + 1)) - 1)
+                 - ((1U << VERT_ATTRIB_TEX0) - 1);
+            break;
+         case VERT_ATTRIB_GENERIC0:
+            /* different code to avoid uint overflow */
+            mask = ~0x0U - ((1U << VERT_ATTRIB_GENERIC0) - 1);
+            break;
+         default:
+            ; /* a non-array input attribute */
+         }
+      }
+      else if (target == GL_FRAGMENT_PROGRAM_ARB) {
+         switch (index) {
+         case FRAG_ATTRIB_TEX0:
+            mask = ((1U << (FRAG_ATTRIB_TEX7 + 1)) - 1)
+                 - ((1U << FRAG_ATTRIB_TEX0) - 1);
+            break;
+         case FRAG_ATTRIB_VAR0:
+            mask = ((1U << (FRAG_ATTRIB_VAR0 + MAX_VARYING)) - 1)
+                 - ((1U << FRAG_ATTRIB_VAR0) - 1);
+            break;
+         default:
+            ; /* a non-array input attribute */
+         }
+      }
+      else {
+         assert(0 && "bad program target");
+      }
+   }
+   else {
+   }
+
+   return mask;
+}
+
+
+/**
+ * If an output attribute is indexed with relative addressing we have
+ * to compute a gl_program::OutputsWritten bitmask which reflects the fact
+ * that any output may be referenced by array element.  Ex: gl_TexCoord[i].
+ * This function computes the bitmask of potentially written outputs.
+ */
+static GLbitfield64
+get_outputs_written_mask(GLenum target, GLuint index, GLboolean relAddr)
+{
+   GLbitfield64 mask;
+
+   mask = BITFIELD64_BIT(index);
+
+   if (relAddr) {
+      if (target == GL_VERTEX_PROGRAM_ARB) {
+         switch (index) {
+         case VERT_RESULT_TEX0:
+            mask = BITFIELD64_RANGE(VERT_RESULT_TEX0,
+                                    (VERT_RESULT_TEX0
+                                     + MAX_TEXTURE_COORD_UNITS - 1));
+            break;
+         case VERT_RESULT_VAR0:
+            mask = BITFIELD64_RANGE(VERT_RESULT_VAR0,
+                                    (VERT_RESULT_VAR0 + MAX_VARYING - 1));
+            break;
+         default:
+            ; /* a non-array output attribute */
+         }
+      }
+      else if (target == GL_FRAGMENT_PROGRAM_ARB) {
+         switch (index) {
+         case FRAG_RESULT_DATA0:
+            mask = BITFIELD64_RANGE(FRAG_RESULT_DATA0,
+                                    (FRAG_RESULT_DATA0
+                                     + MAX_DRAW_BUFFERS - 1));
+            break;
+         default:
+            ; /* a non-array output attribute */
+         }
+      }
+      else {
+         assert(0 && "bad program target");
+      }
+   }
+
+   return mask;
+}
+
+
+/**
+ * Scan program instructions to update the program's InputsRead and
+ * OutputsWritten fields.
+ */
+static void
+_slang_update_inputs_outputs(struct gl_program *prog)
+{
+   GLuint i, j;
+   GLuint maxAddrReg = 0;
+
+   prog->InputsRead = 0x0;
+   prog->OutputsWritten = 0x0;
+
+   for (i = 0; i < prog->NumInstructions; i++) {
+      const struct prog_instruction *inst = prog->Instructions + i;
+      const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+      for (j = 0; j < numSrc; j++) {
+         if (inst->SrcReg[j].File == PROGRAM_INPUT) {
+            prog->InputsRead |= get_inputs_read_mask(prog->Target,
+                                                     inst->SrcReg[j].Index,
+                                                     inst->SrcReg[j].RelAddr);
+         }
+         else if (inst->SrcReg[j].File == PROGRAM_ADDRESS) {
+            maxAddrReg = MAX2(maxAddrReg, (GLuint) (inst->SrcReg[j].Index + 1));
+         }
+      }
+
+      if (inst->DstReg.File == PROGRAM_OUTPUT) {
+         prog->OutputsWritten |= get_outputs_written_mask(prog->Target,
+                                                          inst->DstReg.Index,
+                                                          inst->DstReg.RelAddr);
+      }
+      else if (inst->DstReg.File == PROGRAM_ADDRESS) {
+         maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1);
+      }
+   }
+   prog->NumAddressRegs = maxAddrReg;
+}
+
+
+
+/**
+ * Remove extra #version directives from the concatenated source string.
+ * Disable the extra ones by converting first two chars to //, a comment.
+ * This is a bit of hack to work around a preprocessor bug that only
+ * allows one #version directive per source.
+ */
+static void
+remove_extra_version_directives(GLchar *source)
+{
+   GLuint verCount = 0;
+   while (1) {
+      char *ver = strstr(source, "#version");
+      if (ver) {
+         verCount++;
+         if (verCount > 1) {
+            ver[0] = '/';
+            ver[1] = '/';
+         }
+         source += 8;
+      }
+      else {
+         break;
+      }
+   }
+}
+
+
+
+/**
+ * Return a new shader whose source code is the concatenation of
+ * all the shader sources of the given type.
+ */
+static struct gl_shader *
+concat_shaders(struct gl_shader_program *shProg, GLenum shaderType)
+{
+   struct gl_shader *newShader;
+   const struct gl_shader *firstShader = NULL;
+   GLuint *shaderLengths;
+   GLchar *source;
+   GLuint totalLen = 0, len = 0;
+   GLuint i;
+
+   shaderLengths = (GLuint *)malloc(shProg->NumShaders * sizeof(GLuint));
+   if (!shaderLengths) {
+      return NULL;
+   }
+
+   /* compute total size of new shader source code */
+   for (i = 0; i < shProg->NumShaders; i++) {
+      const struct gl_shader *shader = shProg->Shaders[i];
+      if (shader->Type == shaderType) {
+         shaderLengths[i] = strlen(shader->Source);
+         totalLen += shaderLengths[i];
+         if (!firstShader)
+            firstShader = shader;
+      }
+   }
+
+   if (totalLen == 0) {
+      free(shaderLengths);
+      return NULL;
+   }
+
+   source = (GLchar *) malloc(totalLen + 1);
+   if (!source) {
+      free(shaderLengths);
+      return NULL;
+   }
+
+   /* concatenate shaders */
+   for (i = 0; i < shProg->NumShaders; i++) {
+      const struct gl_shader *shader = shProg->Shaders[i];
+      if (shader->Type == shaderType) {
+         memcpy(source + len, shader->Source, shaderLengths[i]);
+         len += shaderLengths[i];
+      }
+   }
+   source[len] = '\0';
+   /*
+   printf("---NEW CONCATENATED SHADER---:\n%s\n------------\n", source);
+   */
+
+   free(shaderLengths);
+
+   remove_extra_version_directives(source);
+
+   newShader = CALLOC_STRUCT(gl_shader);
+   if (!newShader) {
+      free(source);
+      return NULL;
+   }
+
+   newShader->Type = shaderType;
+   newShader->Source = source;
+   newShader->Pragmas = firstShader->Pragmas;
+
+   return newShader;
+}
+
+
+/**
+ * Search the shader program's list of shaders to find the one that
+ * defines main().
+ * This will involve shader concatenation and recompilation if needed.
+ */
+static struct gl_shader *
+get_main_shader(GLcontext *ctx,
+                struct gl_shader_program *shProg, GLenum type)
+{
+   struct gl_shader *shader = NULL;
+   GLuint i;
+
+   /*
+    * Look for a shader that defines main() and has no unresolved references.
+    */
+   for (i = 0; i < shProg->NumShaders; i++) {
+      shader = shProg->Shaders[i];
+      if (shader->Type == type &&
+          shader->Main &&
+          !shader->UnresolvedRefs) {
+         /* All set! */
+         return shader;
+      }
+   }
+
+   /*
+    * There must have been unresolved references during the original
+    * compilation.  Try concatenating all the shaders of the given type
+    * and recompile that.
+    */
+   shader = concat_shaders(shProg, type);
+
+   if (shader) {
+      _slang_compile(ctx, shader);
+
+      /* Finally, check if recompiling failed */
+      if (!shader->CompileStatus ||
+          !shader->Main ||
+          shader->UnresolvedRefs) {
+         link_error(shProg, "Unresolved symbols");
+         ctx->Driver.DeleteShader(ctx, shader);
+         return NULL;
+      }
+   }
+
+   return shader;
+}
+
+
+/**
+ * Shader linker.  Currently:
+ *
+ * 1. The last attached vertex shader and fragment shader are linked.
+ * 2. Varying vars in the two shaders are combined so their locations
+ *    agree between the vertex and fragment stages.  They're treated as
+ *    vertex program output attribs and as fragment program input attribs.
+ * 3. The vertex and fragment programs are cloned and modified to update
+ *    src/dst register references so they use the new, linked varying
+ *    storage locations.
+ */
+void
+_slang_link(GLcontext *ctx,
+            GLhandleARB programObj,
+            struct gl_shader_program *shProg)
+{
+   const struct gl_vertex_program *vertProg = NULL;
+   const struct gl_fragment_program *fragProg = NULL;
+   GLboolean vertNotify = GL_TRUE, fragNotify = GL_TRUE;
+   GLuint numSamplers = 0;
+   GLuint i;
+
+   _mesa_clear_shader_program_data(ctx, shProg);
+
+   /* Initialize LinkStatus to "success".  Will be cleared if error. */
+   shProg->LinkStatus = GL_TRUE;
+
+   /* check that all programs compiled successfully */
+   for (i = 0; i < shProg->NumShaders; i++) {
+      if (!shProg->Shaders[i]->CompileStatus) {
+         link_error(shProg, "linking with uncompiled shader\n");
+         return;
+      }
+   }
+
+   shProg->Uniforms = _mesa_new_uniform_list();
+   shProg->Varying = _mesa_new_parameter_list();
+
+   /*
+    * Find the vertex and fragment shaders which define main()
+    */
+   {
+      struct gl_shader *vertShader, *fragShader;
+      vertShader = get_main_shader(ctx, shProg, GL_VERTEX_SHADER);
+      fragShader = get_main_shader(ctx, shProg, GL_FRAGMENT_SHADER);
+      if (vertShader)
+         vertProg = vertex_program(vertShader->Program);
+      if (fragShader)
+         fragProg = fragment_program(fragShader->Program);
+      if (!shProg->LinkStatus)
+         return;
+   }
+
+#if FEATURE_es2_glsl
+   /* must have both a vertex and fragment program for ES2 */
+   if (ctx->API == API_OPENGLES2) {
+      if (!vertProg) {
+        link_error(shProg, "missing vertex shader\n");
+        return;
+      }
+      if (!fragProg) {
+        link_error(shProg, "missing fragment shader\n");
+        return;
+      }
+   }
+#endif
+
+   /*
+    * Make copies of the vertex/fragment programs now since we'll be
+    * changing src/dst registers after merging the uniforms and varying vars.
+    */
+   _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
+   if (vertProg) {
+      struct gl_vertex_program *linked_vprog =
+         _mesa_clone_vertex_program(ctx, vertProg);
+      shProg->VertexProgram = linked_vprog; /* refcount OK */
+      /* vertex program ID not significant; just set Id for debugging purposes */
+      shProg->VertexProgram->Base.Id = shProg->Name;
+      ASSERT(shProg->VertexProgram->Base.RefCount == 1);
+   }
+
+   _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
+   if (fragProg) {
+      struct gl_fragment_program *linked_fprog = 
+         _mesa_clone_fragment_program(ctx, fragProg);
+      shProg->FragmentProgram = linked_fprog; /* refcount OK */
+      /* vertex program ID not significant; just set Id for debugging purposes */
+      shProg->FragmentProgram->Base.Id = shProg->Name;
+      ASSERT(shProg->FragmentProgram->Base.RefCount == 1);
+   }
+
+   /* link varying vars */
+   if (shProg->VertexProgram) {
+      if (!link_varying_vars(ctx, shProg, &shProg->VertexProgram->Base))
+         return;
+   }
+   if (shProg->FragmentProgram) {
+      if (!link_varying_vars(ctx, shProg, &shProg->FragmentProgram->Base))
+         return;
+   }
+
+   /* link uniform vars */
+   if (shProg->VertexProgram) {
+      if (!link_uniform_vars(ctx, shProg, &shProg->VertexProgram->Base,
+                             &numSamplers)) {
+         return;
+      }
+   }
+   if (shProg->FragmentProgram) {
+      if (!link_uniform_vars(ctx, shProg, &shProg->FragmentProgram->Base,
+                             &numSamplers)) {
+         return;
+      }
+   }
+
+   /*_mesa_print_uniforms(shProg->Uniforms);*/
+
+   if (shProg->VertexProgram) {
+      if (!_slang_resolve_attributes(shProg, &vertProg->Base,
+                                     &shProg->VertexProgram->Base)) {
+         return;
+      }
+   }
+
+   if (shProg->VertexProgram) {
+      _slang_update_inputs_outputs(&shProg->VertexProgram->Base);
+      _slang_count_temporaries(&shProg->VertexProgram->Base);
+      if (!(shProg->VertexProgram->Base.OutputsWritten
+           & BITFIELD64_BIT(VERT_RESULT_HPOS))) {
+         /* the vertex program did not compute a vertex position */
+         link_error(shProg,
+                    "gl_Position was not written by vertex shader\n");
+         return;
+      }
+   }
+   if (shProg->FragmentProgram) {
+      _slang_count_temporaries(&shProg->FragmentProgram->Base);
+      _slang_update_inputs_outputs(&shProg->FragmentProgram->Base);
+   }
+
+   /* Check that all the varying vars needed by the fragment shader are
+    * actually produced by the vertex shader.
+    */
+   if (shProg->FragmentProgram) {
+      const GLbitfield varyingRead
+         = shProg->FragmentProgram->Base.InputsRead >> FRAG_ATTRIB_VAR0;
+      const GLbitfield64 varyingWritten = shProg->VertexProgram ?
+         shProg->VertexProgram->Base.OutputsWritten >> VERT_RESULT_VAR0 : 0x0;
+      if ((varyingRead & varyingWritten) != varyingRead) {
+         link_error(shProg,
+          "Fragment program using varying vars not written by vertex shader\n");
+         return;
+      }         
+   }
+
+   /* check that gl_FragColor and gl_FragData are not both written to */
+   if (shProg->FragmentProgram) {
+      const GLbitfield64 outputsWritten =
+        shProg->FragmentProgram->Base.OutputsWritten;
+      if ((outputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) &&
+          (outputsWritten >= BITFIELD64_BIT(FRAG_RESULT_DATA0))) {
+         link_error(shProg, "Fragment program cannot write both gl_FragColor"
+                    " and gl_FragData[].\n");
+         return;
+      }         
+   }
+
+   update_varying_var_list(ctx, shProg);
+
+   /* checks related to transform feedback */
+   if (!link_transform_feedback(ctx, shProg)) {
+      return;
+   }
+
+   if (fragProg && shProg->FragmentProgram) {
+      /* Compute initial program's TexturesUsed info */
+      _mesa_update_shader_textures_used(&shProg->FragmentProgram->Base);
+
+      /* notify driver that a new fragment program has been compiled/linked */
+      vertNotify = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
+                                                 &shProg->FragmentProgram->Base);
+      if (ctx->Shader.Flags & GLSL_DUMP) {
+         printf("Mesa pre-link fragment program:\n");
+         _mesa_print_program(&fragProg->Base);
+         _mesa_print_program_parameters(ctx, &fragProg->Base);
+
+         printf("Mesa post-link fragment program:\n");
+         _mesa_print_program(&shProg->FragmentProgram->Base);
+         _mesa_print_program_parameters(ctx, &shProg->FragmentProgram->Base);
+      }
+   }
+
+   if (vertProg && shProg->VertexProgram) {
+      /* Compute initial program's TexturesUsed info */
+      _mesa_update_shader_textures_used(&shProg->VertexProgram->Base);
+
+      /* notify driver that a new vertex program has been compiled/linked */
+      fragNotify = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
+                                                   &shProg->VertexProgram->Base);
+      if (ctx->Shader.Flags & GLSL_DUMP) {
+         printf("Mesa pre-link vertex program:\n");
+         _mesa_print_program(&vertProg->Base);
+         _mesa_print_program_parameters(ctx, &vertProg->Base);
+
+         printf("Mesa post-link vertex program:\n");
+         _mesa_print_program(&shProg->VertexProgram->Base);
+         _mesa_print_program_parameters(ctx, &shProg->VertexProgram->Base);
+      }
+   }
+
+   /* Debug: */
+   if (0) {
+      if (shProg->VertexProgram)
+         _mesa_postprocess_program(ctx, &shProg->VertexProgram->Base);
+      if (shProg->FragmentProgram)
+         _mesa_postprocess_program(ctx, &shProg->FragmentProgram->Base);
+   }
+
+   if (ctx->Shader.Flags & GLSL_DUMP) {
+      printf("Varying vars:\n");
+      _mesa_print_parameter_list(shProg->Varying);
+      if (shProg->InfoLog) {
+         printf("Info Log: %s\n", shProg->InfoLog);
+      }
+   }
+
+   if (!vertNotify || !fragNotify) {
+      /* driver rejected one/both of the vertex/fragment programs */
+      if (!shProg->InfoLog) {
+        link_error(shProg,
+                   "Vertex and/or fragment program rejected by driver\n");
+      }
+   }
+   else {
+      shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram);
+   }
+}
+
diff --git a/src/mesa/slang/slang_link.h b/src/mesa/slang/slang_link.h
new file mode 100644 (file)
index 0000000..2b44d20
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.2
+ *
+ * Copyright (C) 2008  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SLANG_LINK_H
+#define SLANG_LINK_H 1
+
+#include "slang_compile.h"
+
+
+extern void
+_slang_link(GLcontext *ctx, GLhandleARB h,
+            struct gl_shader_program *shProg);
+
+
+#endif
+
diff --git a/src/mesa/slang/slang_log.c b/src/mesa/slang/slang_log.c
new file mode 100644 (file)
index 0000000..9ff2141
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "main/imports.h"
+#include "slang_log.h"
+#include "slang_utility.h"
+
+
+
+static char *out_of_memory = "Error: Out of memory.\n";
+
+void
+slang_info_log_construct(slang_info_log * log)
+{
+   log->text = NULL;
+   log->dont_free_text = GL_FALSE;
+   log->error_flag = GL_FALSE;
+}
+
+void
+slang_info_log_destruct(slang_info_log * log)
+{
+   if (!log->dont_free_text)
+      free(log->text);
+}
+
+static int
+slang_info_log_message(slang_info_log * log, const char *prefix,
+                       const char *msg)
+{
+   GLuint size;
+
+   if (log->dont_free_text)
+      return 0;
+   size = slang_string_length(msg) + 2;
+   if (prefix != NULL)
+      size += slang_string_length(prefix) + 2;
+   if (log->text != NULL) {
+      GLuint old_len = slang_string_length(log->text);
+      log->text = (char *)
+        _mesa_realloc(log->text, old_len + 1, old_len + size);
+   }
+   else {
+      log->text = (char *) (malloc(size));
+      if (log->text != NULL)
+         log->text[0] = '\0';
+   }
+   if (log->text == NULL)
+      return 0;
+   if (prefix != NULL) {
+      slang_string_concat(log->text, prefix);
+      slang_string_concat(log->text, ": ");
+   }
+   slang_string_concat(log->text, msg);
+   slang_string_concat(log->text, "\n");
+
+   return 1;
+}
+
+int
+slang_info_log_print(slang_info_log * log, const char *msg, ...)
+{
+   va_list va;
+   char buf[1024];
+
+   va_start(va, msg);
+   vsprintf(buf, msg, va);
+   va_end(va);
+   return slang_info_log_message(log, NULL, buf);
+}
+
+int
+slang_info_log_error(slang_info_log * log, const char *msg, ...)
+{
+   va_list va;
+   char buf[1024];
+
+   va_start(va, msg);
+   vsprintf(buf, msg, va);
+   va_end(va);
+   log->error_flag = GL_TRUE;
+   if (slang_info_log_message(log, "Error", buf))
+      return 1;
+   slang_info_log_memory(log);
+   return 0;
+}
+
+int
+slang_info_log_warning(slang_info_log * log, const char *msg, ...)
+{
+   va_list va;
+   char buf[1024];
+
+   va_start(va, msg);
+   vsprintf(buf, msg, va);
+   va_end(va);
+   if (slang_info_log_message(log, "Warning", buf))
+      return 1;
+   slang_info_log_memory(log);
+   return 0;
+}
+
+void
+slang_info_log_memory(slang_info_log * log)
+{
+   if (!slang_info_log_message(log, "Error", "Out of memory.")) {
+      log->dont_free_text = GL_TRUE;
+      log->error_flag = GL_TRUE;
+      log->text = out_of_memory;
+   }
+}
diff --git a/src/mesa/slang/slang_log.h b/src/mesa/slang/slang_log.h
new file mode 100644 (file)
index 0000000..dcaba02
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef SLANG_LOG_H
+#define SLANG_LOG_H
+
+
+typedef struct slang_info_log_
+{
+   char *text;
+   GLboolean dont_free_text;
+   GLboolean error_flag;
+} slang_info_log;
+
+
+extern void
+slang_info_log_construct(slang_info_log *);
+
+extern void
+slang_info_log_destruct(slang_info_log *);
+
+extern int
+slang_info_log_print(slang_info_log *, const char *, ...);
+
+extern int
+slang_info_log_error(slang_info_log *, const char *, ...);
+
+extern int
+slang_info_log_warning(slang_info_log *, const char *, ...);
+
+extern void
+slang_info_log_memory(slang_info_log *);
+
+
+#endif /* SLANG_LOG_H */
diff --git a/src/mesa/slang/slang_mem.c b/src/mesa/slang/slang_mem.c
new file mode 100644 (file)
index 0000000..5eaa7c4
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_mem.c
+ *
+ * Memory manager for GLSL compiler.  The general idea is to do all
+ * allocations out of a large pool then just free the pool when done
+ * compiling to avoid intricate malloc/free tracking and memory leaks.
+ *
+ * \author Brian Paul
+ */
+
+#include "main/context.h"
+#include "main/macros.h"
+#include "slang_mem.h"
+
+
+#define GRANULARITY 8
+#define ROUND_UP(B)  ( ((B) + (GRANULARITY - 1)) & ~(GRANULARITY - 1) )
+
+
+/** If 1, use conventional malloc/free.  Helpful for debugging */
+#define USE_MALLOC_FREE 0
+
+
+struct slang_mempool_
+{
+   GLuint Size, Used, Count, Largest;
+   char *Data;
+   struct slang_mempool_ *Next;
+};
+
+
+slang_mempool *
+_slang_new_mempool(GLuint initialSize)
+{
+   slang_mempool *pool = (slang_mempool *) calloc(1, sizeof(slang_mempool));
+   if (pool) {
+      pool->Data = (char *) calloc(1, initialSize);
+      /*printf("ALLOC MEMPOOL %d at %p\n", initialSize, pool->Data);*/
+      if (!pool->Data) {
+         free(pool);
+         return NULL;
+      }
+      pool->Size = initialSize;
+      pool->Used = 0;
+   }
+   return pool;
+}
+
+
+void
+_slang_delete_mempool(slang_mempool *pool)
+{
+   GLuint total = 0;
+   while (pool) {
+      slang_mempool *next = pool->Next;
+      /*
+      printf("DELETE MEMPOOL %u / %u  count=%u largest=%u\n",
+             pool->Used, pool->Size, pool->Count, pool->Largest);
+      */
+      total += pool->Used;
+      free(pool->Data);
+      free(pool);
+      pool = next;
+   }
+   /*printf("TOTAL ALLOCATED: %u\n", total);*/
+}
+
+
+#ifdef DEBUG
+static void
+check_zero(const char *addr, GLuint n)
+{
+   GLuint i;
+   for (i = 0; i < n; i++) {
+      assert(addr[i]==0);
+   }
+}
+#endif
+
+
+#ifdef DEBUG
+static GLboolean
+is_valid_address(const slang_mempool *pool, void *addr)
+{
+   while (pool) {
+      if ((char *) addr >= pool->Data &&
+          (char *) addr < pool->Data + pool->Used)
+         return GL_TRUE;
+
+      pool = pool->Next;
+   }
+   return GL_FALSE;
+}
+#endif
+
+
+/**
+ * Alloc 'bytes' from shader mempool.
+ */
+void *
+_slang_alloc(GLuint bytes)
+{
+#if USE_MALLOC_FREE
+   return calloc(1, bytes);
+#else
+   slang_mempool *pool;
+   GET_CURRENT_CONTEXT(ctx);
+   pool = (slang_mempool *) ctx->Shader.MemPool;
+
+   if (bytes == 0)
+      bytes = 1;
+
+   while (pool) {
+      if (pool->Used + bytes <= pool->Size) {
+         /* found room */
+         void *addr = (void *) (pool->Data + pool->Used);
+#ifdef DEBUG
+         check_zero((char*) addr, bytes);
+#endif
+         pool->Used += ROUND_UP(bytes);
+         pool->Largest = MAX2(pool->Largest, bytes);
+         pool->Count++;
+         /*printf("alloc %u  Used %u\n", bytes, pool->Used);*/
+         return addr;
+      }
+      else if (pool->Next) {
+         /* try next block */
+         pool = pool->Next;
+      }
+      else {
+         /* alloc new pool */
+         const GLuint sz = MAX2(bytes, pool->Size);
+         pool->Next = _slang_new_mempool(sz);
+         if (!pool->Next) {
+            /* we're _really_ out of memory */
+            return NULL;
+         }
+         else {
+            pool = pool->Next;
+            pool->Largest = bytes;
+            pool->Count++;
+            pool->Used = ROUND_UP(bytes);
+#ifdef DEBUG
+            check_zero((char*) pool->Data, bytes);
+#endif
+            return (void *) pool->Data;
+         }
+      }
+   }
+   return NULL;
+#endif
+}
+
+
+void *
+_slang_realloc(void *oldBuffer, GLuint oldSize, GLuint newSize)
+{
+#if USE_MALLOC_FREE
+   return _mesa_realloc(oldBuffer, oldSize, newSize);
+#else
+   GET_CURRENT_CONTEXT(ctx);
+   slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool;
+   (void) pool;
+
+   if (newSize < oldSize) {
+      return oldBuffer;
+   }
+   else {
+      const GLuint copySize = (oldSize < newSize) ? oldSize : newSize;
+      void *newBuffer = _slang_alloc(newSize);
+
+      if (oldBuffer)
+         ASSERT(is_valid_address(pool, oldBuffer));
+
+      if (newBuffer && oldBuffer && copySize > 0)
+         memcpy(newBuffer, oldBuffer, copySize);
+
+      return newBuffer;
+   }
+#endif
+}
+
+
+/**
+ * Clone string, storing in current mempool.
+ */
+char *
+_slang_strdup(const char *s)
+{
+   if (s) {
+      size_t l = strlen(s);
+      char *s2 = (char *) _slang_alloc(l + 1);
+      if (s2)
+         strcpy(s2, s);
+      return s2;
+   }
+   else {
+      return NULL;
+   }
+}
+
+
+/**
+ * Don't actually free memory, but mark it (for debugging).
+ */
+void
+_slang_free(void *addr)
+{
+#if USE_MALLOC_FREE
+   free(addr);
+#else
+   if (addr) {
+      GET_CURRENT_CONTEXT(ctx);
+      slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool;
+      (void) pool;
+      ASSERT(is_valid_address(pool, addr));
+   }
+#endif
+}
diff --git a/src/mesa/slang/slang_mem.h b/src/mesa/slang/slang_mem.h
new file mode 100644 (file)
index 0000000..b5bfae2
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef SLANG_MEM_H
+#define SLANG_MEM_H
+
+
+#include "main/imports.h"
+
+
+typedef struct slang_mempool_ slang_mempool;
+
+
+extern slang_mempool *
+_slang_new_mempool(GLuint initialSize);
+
+extern void
+_slang_delete_mempool(slang_mempool *pool);
+
+extern void *
+_slang_alloc(GLuint bytes);
+
+extern void *
+_slang_realloc(void *oldBuffer, GLuint oldSize, GLuint newSize);
+
+extern char *
+_slang_strdup(const char *s);
+
+extern void
+_slang_free(void *addr);
+
+
+#endif
diff --git a/src/mesa/slang/slang_print.c b/src/mesa/slang/slang_print.c
new file mode 100644 (file)
index 0000000..6b34f39
--- /dev/null
@@ -0,0 +1,883 @@
+
+/**
+ * Dump/print a slang_operation tree
+ */
+
+
+#include "main/imports.h"
+#include "slang_compile.h"
+#include "slang_print.h"
+
+
+static void
+spaces(int n)
+{
+   while (n--)
+      printf(" ");
+}
+
+
+static void
+print_type(const slang_fully_specified_type *t)
+{
+   switch (t->qualifier) {
+   case SLANG_QUAL_NONE:
+      /*printf("");*/
+      break;
+   case SLANG_QUAL_CONST:
+      printf("const ");
+      break;
+   case SLANG_QUAL_ATTRIBUTE:
+      printf("attrib ");
+      break;
+   case SLANG_QUAL_VARYING:
+      printf("varying ");
+      break;
+   case SLANG_QUAL_UNIFORM:
+      printf("uniform ");
+      break;
+   case SLANG_QUAL_OUT:
+      printf("output ");
+      break;
+   case SLANG_QUAL_INOUT:
+      printf("inout ");
+      break;
+   case SLANG_QUAL_FIXEDOUTPUT:
+      printf("fixedoutput");
+      break;
+   case SLANG_QUAL_FIXEDINPUT:
+      printf("fixedinput");
+      break;
+   default:
+      printf("unknown qualifer!");
+   }
+
+   switch (t->specifier.type) {
+   case SLANG_SPEC_VOID:
+      printf("void");
+      break;
+   case SLANG_SPEC_BOOL:
+      printf("bool");
+      break;
+   case SLANG_SPEC_BVEC2:
+      printf("bvec2");
+      break;
+   case SLANG_SPEC_BVEC3:
+      printf("bvec3");
+      break;
+   case SLANG_SPEC_BVEC4:
+      printf("bvec4");
+      break;
+   case SLANG_SPEC_INT:
+      printf("int");
+      break;
+   case SLANG_SPEC_IVEC2:
+      printf("ivec2");
+      break;
+   case SLANG_SPEC_IVEC3:
+      printf("ivec3");
+      break;
+   case SLANG_SPEC_IVEC4:
+      printf("ivec4");
+      break;
+   case SLANG_SPEC_FLOAT:
+      printf("float");
+      break;
+   case SLANG_SPEC_VEC2:
+      printf("vec2");
+      break;
+   case SLANG_SPEC_VEC3:
+      printf("vec3");
+      break;
+   case SLANG_SPEC_VEC4:
+      printf("vec4");
+      break;
+   case SLANG_SPEC_MAT2:
+      printf("mat2");
+      break;
+   case SLANG_SPEC_MAT3:
+      printf("mat3");
+      break;
+   case SLANG_SPEC_MAT4:
+      printf("mat4");
+      break;
+   case SLANG_SPEC_MAT23:
+      printf("mat2x3");
+      break;
+   case SLANG_SPEC_MAT32:
+      printf("mat3x2");
+      break;
+   case SLANG_SPEC_MAT24:
+      printf("mat2x4");
+      break;
+   case SLANG_SPEC_MAT42:
+      printf("mat4x2");
+      break;
+   case SLANG_SPEC_MAT34:
+      printf("mat3x4");
+      break;
+   case SLANG_SPEC_MAT43:
+      printf("mat4x3");
+      break;
+   case SLANG_SPEC_SAMPLER_1D:
+      printf("sampler1D");
+      break;
+   case SLANG_SPEC_SAMPLER_2D:
+      printf("sampler2D");
+      break;
+   case SLANG_SPEC_SAMPLER_3D:
+      printf("sampler3D");
+      break;
+   case SLANG_SPEC_SAMPLER_CUBE:
+      printf("samplerCube");
+      break;
+   case SLANG_SPEC_SAMPLER_1D_SHADOW:
+      printf("sampler1DShadow");
+      break;
+   case SLANG_SPEC_SAMPLER_2D_SHADOW:
+      printf("sampler2DShadow");
+      break;
+   case SLANG_SPEC_STRUCT:
+      printf("struct");
+      break;
+   case SLANG_SPEC_ARRAY:
+      printf("array");
+      break;
+   default:
+      printf("unknown type");
+   }
+   /*printf("\n");*/
+}
+
+
+static void
+print_variable(const slang_variable *v, int indent)
+{
+   spaces(indent);
+   printf("VAR ");
+   print_type(&v->type);
+   printf(" %s (at %p)", (char *) v->a_name, (void *) v);
+   if (v->initializer) {
+      printf(" :=\n");
+      slang_print_tree(v->initializer, indent + 3);
+   }
+   else {
+      printf(";\n");
+   }
+}
+
+
+static void
+print_binary(const slang_operation *op, const char *oper, int indent)
+{
+   assert(op->num_children == 2);
+#if 0
+   printf("binary at %p locals=%p outer=%p\n",
+          (void *) op,
+          (void *) op->locals,
+          (void *) op->locals->outer_scope);
+#endif
+   slang_print_tree(&op->children[0], indent + 3);
+   spaces(indent);
+   printf("%s at %p locals=%p outer=%p\n",
+          oper, (void *) op, (void *) op->locals,
+          (void *) op->locals->outer_scope);
+   slang_print_tree(&op->children[1], indent + 3);
+}
+
+
+static void
+print_generic2(const slang_operation *op, const char *oper,
+               const char *s, int indent)
+{
+   GLuint i;
+   if (oper) {
+      spaces(indent);
+      printf("%s %s at %p locals=%p outer=%p\n",
+             oper, s, (void *) op, (void *) op->locals, 
+             (void *) op->locals->outer_scope);
+   }
+   for (i = 0; i < op->num_children; i++) {
+      spaces(indent);
+      printf("//child %u of %u:\n", i, op->num_children);
+      slang_print_tree(&op->children[i], indent);
+   }
+}
+
+static void
+print_generic(const slang_operation *op, const char *oper, int indent)
+{
+   print_generic2(op, oper, "", indent);
+}
+
+
+static const slang_variable_scope *
+find_scope(const slang_variable_scope *s, slang_atom name)
+{
+   GLuint i;
+   for (i = 0; i < s->num_variables; i++) {
+      if (s->variables[i]->a_name == name)
+         return s;
+   }
+   if (s->outer_scope)
+      return find_scope(s->outer_scope, name);
+   else
+      return NULL;
+}
+
+static const slang_variable *
+find_var(const slang_variable_scope *s, slang_atom name)
+{
+   GLuint i;
+   for (i = 0; i < s->num_variables; i++) {
+      if (s->variables[i]->a_name == name)
+         return s->variables[i];
+   }
+   if (s->outer_scope)
+      return find_var(s->outer_scope, name);
+   else
+      return NULL;
+}
+
+
+void
+slang_print_tree(const slang_operation *op, int indent)
+{
+   GLuint i;
+
+   switch (op->type) {
+
+   case SLANG_OPER_NONE:
+      spaces(indent);
+      printf("SLANG_OPER_NONE\n");
+      break;
+
+   case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
+      spaces(indent);
+      printf("{ locals=%p  outer=%p\n", (void*)op->locals, (void*)op->locals->outer_scope);
+      print_generic(op, NULL, indent+3);
+      spaces(indent);
+      printf("}\n");
+      break;
+
+   case SLANG_OPER_BLOCK_NEW_SCOPE:
+   case SLANG_OPER_NON_INLINED_CALL:
+      spaces(indent);
+      printf("{{ // new scope  locals=%p outer=%p: ",
+             (void *) op->locals,
+             (void *) op->locals->outer_scope);
+      for (i = 0; i < op->locals->num_variables; i++) {
+         printf("%s ", (char *) op->locals->variables[i]->a_name);
+      }
+      printf("\n");
+      print_generic(op, NULL, indent+3);
+      spaces(indent);
+      printf("}}\n");
+      break;
+
+   case SLANG_OPER_VARIABLE_DECL:
+      assert(op->num_children == 0 || op->num_children == 1);
+      {
+         slang_variable *v;
+         v = _slang_variable_locate(op->locals, op->a_id, GL_TRUE);
+         if (v) {
+            const slang_variable_scope *scope;
+            spaces(indent);
+            printf("DECL (locals=%p outer=%p) ", (void*)op->locals, (void*) op->locals->outer_scope);
+            print_type(&v->type);
+            printf(" %s (%p)", (char *) op->a_id,
+                   (void *) find_var(op->locals, op->a_id));
+
+            scope = find_scope(op->locals, op->a_id);
+            printf(" (in scope %p) ", (void *) scope);
+            assert(scope);
+            if (op->num_children == 1) {
+               printf(" :=\n");
+               slang_print_tree(&op->children[0], indent + 3);
+            }
+            else if (v->initializer) {
+               printf(" := INITIALIZER\n");
+               slang_print_tree(v->initializer, indent + 3);
+            }
+            else {
+               printf(";\n");
+            }
+            /*
+            spaces(indent);
+            printf("TYPE: ");
+            print_type(&v->type);
+            spaces(indent);
+            printf("ADDR: %d  size: %d\n", v->address, v->size);
+            */
+         }
+         else {
+            spaces(indent);
+            printf("DECL %s (anonymous variable!!!!)\n", (char *) op->a_id);
+         }
+      }
+      break;
+
+   case SLANG_OPER_ASM:
+      spaces(indent);
+      printf("ASM: %s at %p locals=%p outer=%p\n",
+             (char *) op->a_id,
+             (void *) op,
+             (void *) op->locals,
+             (void *) op->locals->outer_scope);
+      print_generic(op, "ASM", indent+3);
+      break;
+
+   case SLANG_OPER_BREAK:
+      spaces(indent);
+      printf("BREAK\n");
+      break;
+
+   case SLANG_OPER_CONTINUE:
+      spaces(indent);
+      printf("CONTINUE\n");
+      break;
+
+   case SLANG_OPER_DISCARD:
+      spaces(indent);
+      printf("DISCARD\n");
+      break;
+
+   case SLANG_OPER_RETURN:
+      spaces(indent);
+      printf("RETURN\n");
+      if (op->num_children > 0)
+         slang_print_tree(&op->children[0], indent + 3);
+      break;
+
+   case SLANG_OPER_RETURN_INLINED:
+      spaces(indent);
+      printf("RETURN_INLINED\n");
+      if (op->num_children > 0)
+         slang_print_tree(&op->children[0], indent + 3);
+      break;
+
+   case SLANG_OPER_LABEL:
+      spaces(indent);
+      printf("LABEL %s\n", (char *) op->a_id);
+      break;
+
+   case SLANG_OPER_EXPRESSION:
+      spaces(indent);
+      printf("EXPR:  locals=%p outer=%p\n",
+             (void *) op->locals,
+             (void *) op->locals->outer_scope);
+      /*print_generic(op, "SLANG_OPER_EXPRESSION", indent);*/
+      slang_print_tree(&op->children[0], indent + 3);
+      break;
+
+   case SLANG_OPER_IF:
+      spaces(indent);
+      printf("IF\n");
+      slang_print_tree(&op->children[0], indent + 3);
+      spaces(indent);
+      printf("THEN\n");
+      slang_print_tree(&op->children[1], indent + 3);
+      spaces(indent);
+      printf("ELSE\n");
+      slang_print_tree(&op->children[2], indent + 3);
+      spaces(indent);
+      printf("ENDIF\n");
+      break;
+
+   case SLANG_OPER_WHILE:
+      assert(op->num_children == 2);
+      spaces(indent);
+      printf("WHILE LOOP: locals = %p\n", (void *) op->locals);
+      indent += 3;
+      spaces(indent);
+      printf("WHILE cond:\n");
+      slang_print_tree(&op->children[0], indent + 3);
+      spaces(indent);
+      printf("WHILE body:\n");
+      slang_print_tree(&op->children[1], indent + 3);
+      indent -= 3;
+      spaces(indent);
+      printf("END WHILE LOOP\n");
+      break;
+
+   case SLANG_OPER_DO:
+      spaces(indent);
+      printf("DO LOOP: locals = %p\n", (void *) op->locals);
+      indent += 3;
+      spaces(indent);
+      printf("DO body:\n");
+      slang_print_tree(&op->children[0], indent + 3);
+      spaces(indent);
+      printf("DO cond:\n");
+      slang_print_tree(&op->children[1], indent + 3);
+      indent -= 3;
+      spaces(indent);
+      printf("END DO LOOP\n");
+      break;
+
+   case SLANG_OPER_FOR:
+      spaces(indent);
+      printf("FOR LOOP: locals = %p\n", (void *) op->locals);
+      indent += 3;
+      spaces(indent);
+      printf("FOR init:\n");
+      slang_print_tree(&op->children[0], indent + 3);
+      spaces(indent);
+      printf("FOR condition:\n");
+      slang_print_tree(&op->children[1], indent + 3);
+      spaces(indent);
+      printf("FOR step:\n");
+      slang_print_tree(&op->children[2], indent + 3);
+      spaces(indent);
+      printf("FOR body:\n");
+      slang_print_tree(&op->children[3], indent + 3);
+      indent -= 3;
+      spaces(indent);
+      printf("ENDFOR\n");
+      /*
+      print_generic(op, "FOR", indent + 3);
+      */
+      break;
+
+   case SLANG_OPER_VOID:
+      spaces(indent);
+      printf("(oper-void)\n");
+      break;
+
+   case SLANG_OPER_LITERAL_BOOL:
+      spaces(indent);
+      printf("LITERAL (");
+      for (i = 0; i < op->literal_size; i++)
+         printf("%s ", op->literal[0] ? "TRUE" : "FALSE");
+      printf(")\n");
+
+      break;
+
+   case SLANG_OPER_LITERAL_INT:
+      spaces(indent);
+      printf("LITERAL (");
+      for (i = 0; i < op->literal_size; i++)
+         printf("%d ", (int) op->literal[i]);
+      printf(")\n");
+      break;
+
+   case SLANG_OPER_LITERAL_FLOAT:
+      spaces(indent);
+      printf("LITERAL (");
+      for (i = 0; i < op->literal_size; i++)
+         printf("%f ", op->literal[i]);
+      printf(")\n");
+      break;
+
+   case SLANG_OPER_IDENTIFIER:
+      {
+         const slang_variable_scope *scope;
+         spaces(indent);
+         if (op->var && op->var->a_name) {
+            scope = find_scope(op->locals, op->var->a_name);
+            printf("VAR %s  (in scope %p)\n", (char *) op->var->a_name,
+                   (void *) scope);
+            assert(scope);
+         }
+         else {
+            scope = find_scope(op->locals, op->a_id);
+            printf("VAR' %s  (in scope %p) locals=%p outer=%p\n",
+                   (char *) op->a_id,
+                   (void *) scope,
+                   (void *) op->locals,
+                   (void *) op->locals->outer_scope);
+            /*assert(scope);*/
+         }
+      }
+      break;
+
+   case SLANG_OPER_SEQUENCE:
+      print_generic(op, "COMMA-SEQ", indent+3);
+      break;
+
+   case SLANG_OPER_ASSIGN:
+      spaces(indent);
+      printf("ASSIGNMENT  locals=%p outer=%p\n",
+             (void *) op->locals,
+             (void *) op->locals->outer_scope);
+      print_binary(op, ":=", indent);
+      break;
+
+   case SLANG_OPER_ADDASSIGN:
+      spaces(indent);
+      printf("ASSIGN\n");
+      print_binary(op, "+=", indent);
+      break;
+
+   case SLANG_OPER_SUBASSIGN:
+      spaces(indent);
+      printf("ASSIGN\n");
+      print_binary(op, "-=", indent);
+      break;
+
+   case SLANG_OPER_MULASSIGN:
+      spaces(indent);
+      printf("ASSIGN\n");
+      print_binary(op, "*=", indent);
+      break;
+
+   case SLANG_OPER_DIVASSIGN:
+      spaces(indent);
+      printf("ASSIGN\n");
+      print_binary(op, "/=", indent);
+      break;
+
+       /*SLANG_OPER_MODASSIGN,*/
+       /*SLANG_OPER_LSHASSIGN,*/
+       /*SLANG_OPER_RSHASSIGN,*/
+       /*SLANG_OPER_ORASSIGN,*/
+       /*SLANG_OPER_XORASSIGN,*/
+       /*SLANG_OPER_ANDASSIGN,*/
+   case SLANG_OPER_SELECT:
+      spaces(indent);
+      printf("SLANG_OPER_SELECT n=%d\n", op->num_children);
+      assert(op->num_children == 3);
+      slang_print_tree(&op->children[0], indent+3);
+      spaces(indent);
+      printf("?\n");
+      slang_print_tree(&op->children[1], indent+3);
+      spaces(indent);
+      printf(":\n");
+      slang_print_tree(&op->children[2], indent+3);
+      break;
+
+   case SLANG_OPER_LOGICALOR:
+      print_binary(op, "||", indent);
+      break;
+
+   case SLANG_OPER_LOGICALXOR:
+      print_binary(op, "^^", indent);
+      break;
+
+   case SLANG_OPER_LOGICALAND:
+      print_binary(op, "&&", indent);
+      break;
+
+   /*SLANG_OPER_BITOR*/
+   /*SLANG_OPER_BITXOR*/
+   /*SLANG_OPER_BITAND*/
+   case SLANG_OPER_EQUAL:
+      print_binary(op, "==", indent);
+      break;
+
+   case SLANG_OPER_NOTEQUAL:
+      print_binary(op, "!=", indent);
+      break;
+
+   case SLANG_OPER_LESS:
+      print_binary(op, "<", indent);
+      break;
+
+   case SLANG_OPER_GREATER:
+      print_binary(op, ">", indent);
+      break;
+
+   case SLANG_OPER_LESSEQUAL:
+      print_binary(op, "<=", indent);
+      break;
+
+   case SLANG_OPER_GREATEREQUAL:
+      print_binary(op, ">=", indent);
+      break;
+
+   /*SLANG_OPER_LSHIFT*/
+   /*SLANG_OPER_RSHIFT*/
+   case SLANG_OPER_ADD:
+      print_binary(op, "+", indent);
+      break;
+
+   case SLANG_OPER_SUBTRACT:
+      print_binary(op, "-", indent);
+      break;
+
+   case SLANG_OPER_MULTIPLY:
+      print_binary(op, "*", indent);
+      break;
+
+   case SLANG_OPER_DIVIDE:
+      print_binary(op, "/", indent);
+      break;
+
+   /*SLANG_OPER_MODULUS*/
+   case SLANG_OPER_PREINCREMENT:
+      spaces(indent);
+      printf("PRE++\n");
+      slang_print_tree(&op->children[0], indent+3);
+      break;
+
+   case SLANG_OPER_PREDECREMENT:
+      spaces(indent);
+      printf("PRE--\n");
+      slang_print_tree(&op->children[0], indent+3);
+      break;
+
+   case SLANG_OPER_PLUS:
+      spaces(indent);
+      printf("SLANG_OPER_PLUS\n");
+      break;
+
+   case SLANG_OPER_MINUS:
+      spaces(indent);
+      printf("SLANG_OPER_MINUS\n");
+      break;
+
+   /*SLANG_OPER_COMPLEMENT*/
+   case SLANG_OPER_NOT:
+      spaces(indent);
+      printf("NOT\n");
+      slang_print_tree(&op->children[0], indent+3);
+      break;
+
+   case SLANG_OPER_SUBSCRIPT:
+      spaces(indent);
+      printf("SLANG_OPER_SUBSCRIPT locals=%p outer=%p\n",
+             (void *) op->locals,
+             (void *) op->locals->outer_scope);
+      print_generic(op, NULL, indent+3);
+      break;
+
+   case SLANG_OPER_CALL:
+#if 0
+         slang_function *fun
+            = _slang_function_locate(A->space.funcs, oper->a_id,
+                                     oper->children,
+                                     oper->num_children, &A->space, A->atoms);
+#endif
+      spaces(indent);
+      printf("CALL %s(\n", (char *) op->a_id);
+      for (i = 0; i < op->num_children; i++) {
+         slang_print_tree(&op->children[i], indent+3);
+         if (i + 1 < op->num_children) {
+            spaces(indent + 3);
+            printf(",\n");
+         }
+      }
+      spaces(indent);
+      printf(")\n");
+      break;
+
+   case SLANG_OPER_METHOD:
+      spaces(indent);
+      printf("METHOD CALL %s.%s\n", (char *) op->a_obj, (char *) op->a_id);
+      break;
+
+   case SLANG_OPER_FIELD:
+      spaces(indent);
+      printf("FIELD %s of\n", (char*) op->a_id);
+      slang_print_tree(&op->children[0], indent+3);
+      break;
+
+   case SLANG_OPER_POSTINCREMENT:
+      spaces(indent);
+      printf("POST++\n");
+      slang_print_tree(&op->children[0], indent+3);
+      break;
+
+   case SLANG_OPER_POSTDECREMENT:
+      spaces(indent);
+      printf("POST--\n");
+      slang_print_tree(&op->children[0], indent+3);
+      break;
+
+   default:
+      printf("unknown op->type %d\n", (int) op->type);
+   }
+
+}
+
+
+
+void
+slang_print_function(const slang_function *f, GLboolean body)
+{
+   GLuint i;
+
+#if 0
+   if (strcmp((char *) f->header.a_name, "main") != 0)
+     return;
+#endif
+
+   printf("FUNCTION %s ( scope=%p\n",
+          (char *) f->header.a_name, (void *) f->parameters);
+
+   for (i = 0; i < f->param_count; i++) {
+      print_variable(f->parameters->variables[i], 3);
+   }
+
+   printf(") param scope = %p\n", (void *) f->parameters);
+
+   if (body && f->body)
+      slang_print_tree(f->body, 0);
+}
+
+
+
+
+
+const char *
+slang_type_qual_string(slang_type_qualifier q)
+{
+   switch (q) {
+   case SLANG_QUAL_NONE:
+      return "none";
+   case SLANG_QUAL_CONST:
+      return "const";
+   case SLANG_QUAL_ATTRIBUTE:
+      return "attribute";
+   case SLANG_QUAL_VARYING:
+      return "varying";
+   case SLANG_QUAL_UNIFORM:
+      return "uniform";
+   case SLANG_QUAL_OUT:
+      return "out";
+   case SLANG_QUAL_INOUT:
+      return "inout";
+   case SLANG_QUAL_FIXEDOUTPUT:
+      return "fixedoutput";
+   case SLANG_QUAL_FIXEDINPUT:
+      return "fixedinputk";
+   default:
+      return "qual?";
+   }
+}
+
+
+static const char *
+slang_type_string(slang_type_specifier_type t)
+{
+   switch (t) {
+   case SLANG_SPEC_VOID:
+      return "void";
+   case SLANG_SPEC_BOOL:
+      return "bool";
+   case SLANG_SPEC_BVEC2:
+      return "bvec2";
+   case SLANG_SPEC_BVEC3:
+      return "bvec3";
+   case SLANG_SPEC_BVEC4:
+      return "bvec4";
+   case SLANG_SPEC_INT:
+      return "int";
+   case SLANG_SPEC_IVEC2:
+      return "ivec2";
+   case SLANG_SPEC_IVEC3:
+      return "ivec3";
+   case SLANG_SPEC_IVEC4:
+      return "ivec4";
+   case SLANG_SPEC_FLOAT:
+      return "float";
+   case SLANG_SPEC_VEC2:
+      return "vec2";
+   case SLANG_SPEC_VEC3:
+      return "vec3";
+   case SLANG_SPEC_VEC4:
+      return "vec4";
+   case SLANG_SPEC_MAT2:
+      return "mat2";
+   case SLANG_SPEC_MAT3:
+      return "mat3";
+   case SLANG_SPEC_MAT4:
+      return "mat4";
+   case SLANG_SPEC_SAMPLER_1D:
+      return "sampler1D";
+   case SLANG_SPEC_SAMPLER_2D:
+      return "sampler2D";
+   case SLANG_SPEC_SAMPLER_3D:
+      return "sampler3D";
+   case SLANG_SPEC_SAMPLER_CUBE:
+      return "samplerCube";
+   case SLANG_SPEC_SAMPLER_1D_SHADOW:
+      return "sampler1DShadow";
+   case SLANG_SPEC_SAMPLER_2D_SHADOW:
+      return "sampler2DShadow";
+   case SLANG_SPEC_SAMPLER_RECT:
+      return "sampler2DRect";
+   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
+      return "sampler2DRectShadow";
+   case SLANG_SPEC_STRUCT:
+      return "struct";
+   case SLANG_SPEC_ARRAY:
+      return "array";
+   default:
+      return "type?";
+   }
+}
+
+
+static const char *
+slang_fq_type_string(const slang_fully_specified_type *t)
+{
+   static char str[1000];
+   _mesa_snprintf(str, sizeof(str), "%s %s", slang_type_qual_string(t->qualifier),
+      slang_type_string(t->specifier.type));
+   return str;
+}
+
+
+void
+slang_print_type(const slang_fully_specified_type *t)
+{
+   printf("%s %s", slang_type_qual_string(t->qualifier),
+      slang_type_string(t->specifier.type));
+}
+
+
+#if 0
+static char *
+slang_var_string(const slang_variable *v)
+{
+   static char str[1000];
+   _mesa_snprintf(str, sizeof(str), "%s : %s",
+                  (char *) v->a_name,
+                  slang_fq_type_string(&v->type));
+   return str;
+}
+#endif
+
+
+void
+slang_print_variable(const slang_variable *v)
+{
+   printf("Name: %s\n", (char *) v->a_name);
+   printf("Type: %s\n", slang_fq_type_string(&v->type));
+}
+
+
+void
+_slang_print_var_scope(const slang_variable_scope *vars, int indent)
+{
+   GLuint i;
+
+   spaces(indent);
+   printf("Var scope %p  %d vars:\n", (void *) vars, vars->num_variables);
+   for (i = 0; i < vars->num_variables; i++) {
+      spaces(indent + 3);
+      printf("%s (at %p)\n", (char *) vars->variables[i]->a_name, (void*) (vars->variables + i));
+   }
+   spaces(indent + 3);
+   printf("outer_scope = %p\n", (void*) vars->outer_scope);
+
+   if (vars->outer_scope) {
+      /*spaces(indent + 3);*/
+      _slang_print_var_scope(vars->outer_scope, indent + 3);
+   }
+}
+
+
+
+int
+slang_checksum_tree(const slang_operation *op)
+{
+   int s = op->num_children;
+   GLuint i;
+
+   for (i = 0; i < op->num_children; i++) {
+      s += slang_checksum_tree(&op->children[i]);
+   }
+   return s;
+}
diff --git a/src/mesa/slang/slang_print.h b/src/mesa/slang/slang_print.h
new file mode 100644 (file)
index 0000000..46605c8
--- /dev/null
@@ -0,0 +1,29 @@
+
+
+#ifndef SLANG_PRINT
+#define SLANG_PRINT
+
+extern void
+slang_print_function(const slang_function *f, GLboolean body);
+
+extern void
+slang_print_tree(const slang_operation *op, int indent);
+
+extern const char *
+slang_type_qual_string(slang_type_qualifier q);
+
+extern void
+slang_print_type(const slang_fully_specified_type *t);
+
+extern void
+slang_print_variable(const slang_variable *v);
+
+extern void
+_slang_print_var_scope(const slang_variable_scope *s, int indent);
+
+
+extern int
+slang_checksum_tree(const slang_operation *op);
+
+#endif /* SLANG_PRINT */
+
diff --git a/src/mesa/slang/slang_simplify.c b/src/mesa/slang/slang_simplify.c
new file mode 100644 (file)
index 0000000..13b9ca3
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.1
+ *
+ * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Functions for constant folding, built-in constant lookup, and function
+ * call casting.
+ */
+
+
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/get.h"
+#include "slang_compile.h"
+#include "slang_codegen.h"
+#include "slang_simplify.h"
+#include "slang_print.h"
+
+
+#ifndef GL_MAX_FRAGMENT_UNIFORM_VECTORS
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS     0x8DFD
+#endif
+#ifndef GL_MAX_VERTEX_UNIFORM_VECTORS
+#define GL_MAX_VERTEX_UNIFORM_VECTORS       0x8DFB
+#endif
+#ifndef GL_MAX_VARYING_VECTORS
+#define GL_MAX_VARYING_VECTORS              0x8DFC
+#endif
+
+
+/**
+ * Lookup the value of named constant, such as gl_MaxLights.
+ * \return value of constant, or -1 if unknown
+ */
+GLint
+_slang_lookup_constant(const char *name)
+{
+   struct constant_info {
+      const char *Name;
+      const GLenum Token;
+   };
+   static const struct constant_info info[] = {
+      { "gl_MaxClipPlanes", GL_MAX_CLIP_PLANES },
+      { "gl_MaxCombinedTextureImageUnits", GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS },
+      { "gl_MaxDrawBuffers", GL_MAX_DRAW_BUFFERS },
+      { "gl_MaxFragmentUniformComponents", GL_MAX_FRAGMENT_UNIFORM_COMPONENTS },
+      { "gl_MaxLights", GL_MAX_LIGHTS },
+      { "gl_MaxTextureUnits", GL_MAX_TEXTURE_UNITS },
+      { "gl_MaxTextureCoords", GL_MAX_TEXTURE_COORDS },
+      { "gl_MaxVertexAttribs", GL_MAX_VERTEX_ATTRIBS },
+      { "gl_MaxVertexUniformComponents", GL_MAX_VERTEX_UNIFORM_COMPONENTS },
+      { "gl_MaxVaryingFloats", GL_MAX_VARYING_FLOATS },
+      { "gl_MaxVertexTextureImageUnits", GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS },
+      { "gl_MaxTextureImageUnits", GL_MAX_TEXTURE_IMAGE_UNITS },
+#if FEATURE_es2_glsl
+      { "gl_MaxVertexUniformVectors", GL_MAX_VERTEX_UNIFORM_VECTORS },
+      { "gl_MaxVaryingVectors", GL_MAX_VARYING_VECTORS },
+      { "gl_MaxFragmentUniformVectors", GL_MAX_FRAGMENT_UNIFORM_VECTORS },
+#endif
+      { NULL, 0 }
+   };
+   GLuint i;
+
+   for (i = 0; info[i].Name; i++) {
+      if (strcmp(info[i].Name, name) == 0) {
+         /* found */
+         GLint values[16];
+         values[0] = -1;
+         _mesa_GetIntegerv(info[i].Token, values);
+         ASSERT(values[0] >= 0);  /* sanity check that glGetFloatv worked */
+         return values[0];
+      }
+   }
+   return -1;
+}
+
+
+static slang_operation_type
+literal_type(slang_operation_type t1, slang_operation_type t2)
+{
+   if (t1 == SLANG_OPER_LITERAL_FLOAT || t2 == SLANG_OPER_LITERAL_FLOAT)
+      return SLANG_OPER_LITERAL_FLOAT;
+   else
+      return SLANG_OPER_LITERAL_INT;
+}
+
+
+/**
+ * Recursively traverse an AST tree, applying simplifications wherever
+ * possible.
+ * At the least, we do constant folding.  We need to do that much so that
+ * compile-time expressions can be evaluated for things like array
+ * declarations.  I.e.:  float foo[3 + 5];
+ */
+void
+_slang_simplify(slang_operation *oper,
+                const slang_name_space * space,
+                slang_atom_pool * atoms)
+{
+   GLboolean isFloat[4];
+   GLboolean isBool[4];
+   GLuint i, n;
+
+   if (oper->type == SLANG_OPER_IDENTIFIER) {
+      /* see if it's a named constant */
+      GLint value = _slang_lookup_constant((char *) oper->a_id);
+      /*printf("value[%s] = %d\n", (char*) oper->a_id, value);*/
+      if (value >= 0) {
+         oper->literal[0] =
+         oper->literal[1] =
+         oper->literal[2] =
+         oper->literal[3] = (GLfloat) value;
+         oper->type = SLANG_OPER_LITERAL_INT;
+         return;
+      }
+      /* look for user-defined constant */
+      {
+         slang_variable *var;
+         var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
+         if (var) {
+            if (var->type.qualifier == SLANG_QUAL_CONST &&
+                var->initializer &&
+                (var->initializer->type == SLANG_OPER_LITERAL_INT ||
+                 var->initializer->type == SLANG_OPER_LITERAL_FLOAT)) {
+               oper->literal[0] = var->initializer->literal[0];
+               oper->literal[1] = var->initializer->literal[1];
+               oper->literal[2] = var->initializer->literal[2];
+               oper->literal[3] = var->initializer->literal[3];
+               oper->literal_size = var->initializer->literal_size;
+               oper->type = var->initializer->type;
+               /*
+               printf("value[%s] = %f\n",
+                      (char*) oper->a_id, oper->literal[0]);
+               */
+               return;
+            }
+         }
+      }
+   }
+
+   /* first, simplify children */
+   for (i = 0; i < oper->num_children; i++) {
+      _slang_simplify(&oper->children[i], space, atoms);
+   }
+
+   /* examine children */
+   n = MIN2(oper->num_children, 4);
+   for (i = 0; i < n; i++) {
+      isFloat[i] = (oper->children[i].type == SLANG_OPER_LITERAL_FLOAT ||
+                   oper->children[i].type == SLANG_OPER_LITERAL_INT);
+      isBool[i] = (oper->children[i].type == SLANG_OPER_LITERAL_BOOL);
+   }
+                              
+   if (oper->num_children == 2 && isFloat[0] && isFloat[1]) {
+      /* probably simple arithmetic */
+      switch (oper->type) {
+      case SLANG_OPER_ADD:
+         for (i = 0; i < 4; i++) {
+            oper->literal[i]
+               = oper->children[0].literal[i] + oper->children[1].literal[i];
+         }
+         oper->literal_size = oper->children[0].literal_size;
+         oper->type = literal_type(oper->children[0].type, 
+                                   oper->children[1].type);
+         slang_operation_destruct(oper);  /* frees unused children */
+         return;
+      case SLANG_OPER_SUBTRACT:
+         for (i = 0; i < 4; i++) {
+            oper->literal[i]
+               = oper->children[0].literal[i] - oper->children[1].literal[i];
+         }
+         oper->literal_size = oper->children[0].literal_size;
+         oper->type = literal_type(oper->children[0].type, 
+                                   oper->children[1].type);
+         slang_operation_destruct(oper);
+         return;
+      case SLANG_OPER_MULTIPLY:
+         for (i = 0; i < 4; i++) {
+            oper->literal[i]
+               = oper->children[0].literal[i] * oper->children[1].literal[i];
+         }
+         oper->literal_size = oper->children[0].literal_size;
+         oper->type = literal_type(oper->children[0].type, 
+                                   oper->children[1].type);
+         slang_operation_destruct(oper);
+         return;
+      case SLANG_OPER_DIVIDE:
+         for (i = 0; i < 4; i++) {
+            oper->literal[i]
+               = oper->children[0].literal[i] / oper->children[1].literal[i];
+         }
+         oper->literal_size = oper->children[0].literal_size;
+         oper->type = literal_type(oper->children[0].type, 
+                                   oper->children[1].type);
+         slang_operation_destruct(oper);
+         return;
+      default:
+         ; /* nothing */
+      }
+   }
+
+   if (oper->num_children == 1 && isFloat[0]) {
+      switch (oper->type) {
+      case SLANG_OPER_MINUS:
+         for (i = 0; i < 4; i++) {
+            oper->literal[i] = -oper->children[0].literal[i];
+         }
+         oper->literal_size = oper->children[0].literal_size;
+         slang_operation_destruct(oper);
+         oper->type = SLANG_OPER_LITERAL_FLOAT;
+         return;
+      case SLANG_OPER_PLUS:
+         COPY_4V(oper->literal, oper->children[0].literal);
+         oper->literal_size = oper->children[0].literal_size;
+         slang_operation_destruct(oper);
+         oper->type = SLANG_OPER_LITERAL_FLOAT;
+         return;
+      default:
+         ; /* nothing */
+      }
+   }
+
+   if (oper->num_children == 2 && isBool[0] && isBool[1]) {
+      /* simple boolean expression */
+      switch (oper->type) {
+      case SLANG_OPER_LOGICALAND:
+         for (i = 0; i < 4; i++) {
+            const GLint a = oper->children[0].literal[i] ? 1 : 0;
+            const GLint b = oper->children[1].literal[i] ? 1 : 0;
+            oper->literal[i] = (GLfloat) (a && b);
+         }
+         oper->literal_size = oper->children[0].literal_size;
+         slang_operation_destruct(oper);
+         oper->type = SLANG_OPER_LITERAL_BOOL;
+         return;
+      case SLANG_OPER_LOGICALOR:
+         for (i = 0; i < 4; i++) {
+            const GLint a = oper->children[0].literal[i] ? 1 : 0;
+            const GLint b = oper->children[1].literal[i] ? 1 : 0;
+            oper->literal[i] = (GLfloat) (a || b);
+         }
+         oper->literal_size = oper->children[0].literal_size;
+         slang_operation_destruct(oper);
+         oper->type = SLANG_OPER_LITERAL_BOOL;
+         return;
+      case SLANG_OPER_LOGICALXOR:
+         for (i = 0; i < 4; i++) {
+            const GLint a = oper->children[0].literal[i] ? 1 : 0;
+            const GLint b = oper->children[1].literal[i] ? 1 : 0;
+            oper->literal[i] = (GLfloat) (a ^ b);
+         }
+         oper->literal_size = oper->children[0].literal_size;
+         slang_operation_destruct(oper);
+         oper->type = SLANG_OPER_LITERAL_BOOL;
+         return;
+      default:
+         ; /* nothing */
+      }
+   }
+
+   if (oper->num_children == 4
+       && isFloat[0] && isFloat[1] && isFloat[2] && isFloat[3]) {
+      /* vec4(flt, flt, flt, flt) constructor */
+      if (oper->type == SLANG_OPER_CALL) {
+         if (strcmp((char *) oper->a_id, "vec4") == 0) {
+            oper->literal[0] = oper->children[0].literal[0];
+            oper->literal[1] = oper->children[1].literal[0];
+            oper->literal[2] = oper->children[2].literal[0];
+            oper->literal[3] = oper->children[3].literal[0];
+            oper->literal_size = 4;
+            slang_operation_destruct(oper);
+            oper->type = SLANG_OPER_LITERAL_FLOAT;
+            return;
+         }
+      }
+   }
+
+   if (oper->num_children == 3 && isFloat[0] && isFloat[1] && isFloat[2]) {
+      /* vec3(flt, flt, flt) constructor */
+      if (oper->type == SLANG_OPER_CALL) {
+         if (strcmp((char *) oper->a_id, "vec3") == 0) {
+            oper->literal[0] = oper->children[0].literal[0];
+            oper->literal[1] = oper->children[1].literal[0];
+            oper->literal[2] = oper->children[2].literal[0];
+            oper->literal[3] = oper->literal[2];
+            oper->literal_size = 3;
+            slang_operation_destruct(oper);
+            oper->type = SLANG_OPER_LITERAL_FLOAT;
+            return;
+         }
+      }
+   }
+
+   if (oper->num_children == 2 && isFloat[0] && isFloat[1]) {
+      /* vec2(flt, flt) constructor */
+      if (oper->type == SLANG_OPER_CALL) {
+         if (strcmp((char *) oper->a_id, "vec2") == 0) {
+            oper->literal[0] = oper->children[0].literal[0];
+            oper->literal[1] = oper->children[1].literal[0];
+            oper->literal[2] = oper->literal[1];
+            oper->literal[3] = oper->literal[1];
+            oper->literal_size = 2;
+            slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */
+            oper->type = SLANG_OPER_LITERAL_FLOAT;
+            assert(oper->num_children == 0);
+            return;
+         }
+      }
+   }
+
+   if (oper->num_children == 1 && isFloat[0]) {
+      /* vec2/3/4(flt, flt) constructor */
+      if (oper->type == SLANG_OPER_CALL) {
+         const char *func = (const char *) oper->a_id;
+         if (strncmp(func, "vec", 3) == 0 && func[3] >= '2' && func[3] <= '4') {
+            oper->literal[0] =
+            oper->literal[1] =
+            oper->literal[2] =
+            oper->literal[3] = oper->children[0].literal[0];
+            oper->literal_size = func[3] - '0';
+            assert(oper->literal_size >= 2);
+            assert(oper->literal_size <= 4);
+            slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */
+            oper->type = SLANG_OPER_LITERAL_FLOAT;
+            assert(oper->num_children == 0);
+            return;
+         }
+      }
+   }
+}
+
+
+
+/**
+ * Insert casts to try to adapt actual parameters to formal parameters for a
+ * function call when an exact match for the parameter types is not found.
+ * Example:
+ *   void foo(int i, bool b) {}
+ *   x = foo(3.15, 9);
+ * Gets translated into:
+ *   x = foo(int(3.15), bool(9))
+ */
+GLboolean
+_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
+                        const slang_name_space * space,
+                        slang_atom_pool * atoms, slang_info_log *log)
+{
+   const GLboolean haveRetValue = _slang_function_has_return_value(fun);
+   const int numParams = fun->param_count - haveRetValue;
+   int i;
+   int dbg = 0;
+
+   if (dbg)
+      printf("Adapt call of %d args to func %s (%d params)\n",
+             callOper->num_children, (char*) fun->header.a_name, numParams);
+
+   for (i = 0; i < numParams; i++) {
+      slang_typeinfo argType;
+      slang_variable *paramVar = fun->parameters->variables[i];
+
+      /* Get type of arg[i] */
+      if (!slang_typeinfo_construct(&argType))
+         return GL_FALSE;
+      if (!_slang_typeof_operation(&callOper->children[i], space,
+                                    &argType, atoms, log)) {
+         slang_typeinfo_destruct(&argType);
+         return GL_FALSE;
+      }
+
+      /* see if arg type matches parameter type */
+      if (!slang_type_specifier_equal(&argType.spec,
+                                      &paramVar->type.specifier)) {
+         /* need to adapt arg type to match param type */
+         const char *constructorName =
+            slang_type_specifier_type_to_string(paramVar->type.specifier.type);
+         slang_operation *child = slang_operation_new(1);
+
+         if (dbg)
+            printf("Need to adapt types of arg %d\n", i);
+
+         slang_operation_copy(child, &callOper->children[i]);
+         child->locals->outer_scope = callOper->children[i].locals;
+
+#if 0
+         if (_slang_sizeof_type_specifier(&argType.spec) >
+             _slang_sizeof_type_specifier(&paramVar->type.specifier)) {
+         }
+#endif
+
+         callOper->children[i].type = SLANG_OPER_CALL;
+         callOper->children[i].a_id = slang_atom_pool_atom(atoms, constructorName);
+         callOper->children[i].num_children = 1;
+         callOper->children[i].children = child;
+      }
+
+      slang_typeinfo_destruct(&argType);
+   }
+
+   if (dbg) {
+      printf("===== New call to %s with cast arguments ===============\n",
+             (char*) fun->header.a_name);
+      slang_print_tree(callOper, 5);
+   }
+
+   return GL_TRUE;
+}
+
+
+/**
+ * Adapt the arguments for a function call to match the parameters of
+ * the given function.
+ * This is for:
+ * 1. converting/casting argument types to match parameters
+ * 2. breaking up vector/matrix types into individual components to
+ *    satisfy constructors.
+ */
+GLboolean
+_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
+                  const slang_name_space * space,
+                  slang_atom_pool * atoms, slang_info_log *log)
+{
+   const GLboolean haveRetValue = _slang_function_has_return_value(fun);
+   const int numParams = fun->param_count - haveRetValue;
+   int i;
+   int dbg = 0;
+
+   if (dbg)
+      printf("Adapt %d args to %d parameters for %s\n",
+             callOper->num_children, numParams, (char *) fun->header.a_name);
+
+   /* Only try adapting for constructors */
+   if (fun->kind != SLANG_FUNC_CONSTRUCTOR)
+      return GL_FALSE;
+
+   if (callOper->num_children != numParams) {
+      /* number of arguments doesn't match number of parameters */
+
+      /* For constructor calls, we can try to unroll vector/matrix args
+       * into individual floats/ints and try to match the function params.
+       */
+      for (i = 0; i < numParams; i++) {
+         slang_typeinfo argType;
+         GLint argSz, j;
+
+         /* Get type of arg[i] */
+         if (!slang_typeinfo_construct(&argType))
+            return GL_FALSE;
+         if (!_slang_typeof_operation(&callOper->children[i], space,
+                                       &argType, atoms, log)) {
+            slang_typeinfo_destruct(&argType);
+            return GL_FALSE;
+         }
+
+         /*
+           paramSz = _slang_sizeof_type_specifier(&paramVar->type.specifier);
+           assert(paramSz == 1);
+         */
+         argSz = _slang_sizeof_type_specifier(&argType.spec);
+         if (argSz > 1) {
+            slang_operation origArg;
+            /* break up arg[i] into components */
+            if (dbg)
+               printf("Break up arg %d from 1 to %d elements\n", i, argSz);
+
+            slang_operation_construct(&origArg);
+            slang_operation_copy(&origArg, &callOper->children[i]);
+
+            /* insert argSz-1 new children/args */
+            for (j = 0; j < argSz - 1; j++) {
+               (void) slang_operation_insert(&callOper->num_children,
+                                             &callOper->children, i);
+            }
+
+            /* replace arg[i+j] with subscript/index oper */
+            for (j = 0; j < argSz; j++) {
+               callOper->children[i + j].type = SLANG_OPER_SUBSCRIPT;
+               callOper->children[i + j].locals = _slang_variable_scope_new(callOper->locals);
+               callOper->children[i + j].num_children = 2;
+               callOper->children[i + j].children = slang_operation_new(2);
+               slang_operation_copy(&callOper->children[i + j].children[0],
+                                    &origArg);
+               callOper->children[i + j].children[1].type
+                  = SLANG_OPER_LITERAL_INT;
+               callOper->children[i + j].children[1].literal[0] = (GLfloat) j;
+            }
+         }
+      }
+   }
+
+   if (callOper->num_children < (GLuint) numParams) {
+      /* still not enough args for all params */
+      return GL_FALSE;
+   }
+   else if (callOper->num_children > (GLuint) numParams) {
+      /* now too many arguments */
+      /* just truncate */
+      callOper->num_children = (GLuint) numParams;
+   }
+
+   if (dbg) {
+      printf("===== New call to %s with adapted arguments ===============\n",
+             (char*) fun->header.a_name);
+      slang_print_tree(callOper, 5);
+   }
+
+   return GL_TRUE;
+}
diff --git a/src/mesa/slang/slang_simplify.h b/src/mesa/slang/slang_simplify.h
new file mode 100644 (file)
index 0000000..8689c23
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.1
+ *
+ * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SLANG_SIMPLIFY_H
+#define SLANG_SIMPLIFY_H
+
+
+extern GLint
+_slang_lookup_constant(const char *name);
+
+
+extern void
+_slang_simplify(slang_operation *oper,
+                const slang_name_space * space,
+                slang_atom_pool * atoms);
+
+
+extern GLboolean
+_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
+                        const slang_name_space * space,
+                        slang_atom_pool * atoms, slang_info_log *log);
+
+extern GLboolean
+_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
+                  const slang_name_space * space,
+                  slang_atom_pool * atoms, slang_info_log *log);
+
+
+#endif /* SLANG_SIMPLIFY_H */
diff --git a/src/mesa/slang/slang_storage.c b/src/mesa/slang/slang_storage.c
new file mode 100644 (file)
index 0000000..656e156
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_storage.c
+ * slang variable storage
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "slang_storage.h"
+#include "slang_mem.h"
+
+/* slang_storage_array */
+
+GLboolean
+slang_storage_array_construct(slang_storage_array * arr)
+{
+   arr->type = SLANG_STORE_AGGREGATE;
+   arr->aggregate = NULL;
+   arr->length = 0;
+   return GL_TRUE;
+}
+
+GLvoid
+slang_storage_array_destruct(slang_storage_array * arr)
+{
+   if (arr->aggregate != NULL) {
+      slang_storage_aggregate_destruct(arr->aggregate);
+      _slang_free(arr->aggregate);
+   }
+}
+
+/* slang_storage_aggregate */
+
+GLboolean
+slang_storage_aggregate_construct(slang_storage_aggregate * agg)
+{
+   agg->arrays = NULL;
+   agg->count = 0;
+   return GL_TRUE;
+}
+
+GLvoid
+slang_storage_aggregate_destruct(slang_storage_aggregate * agg)
+{
+   GLuint i;
+
+   for (i = 0; i < agg->count; i++)
+      slang_storage_array_destruct(agg->arrays + i);
+   _slang_free(agg->arrays);
+}
+
+static slang_storage_array *
+slang_storage_aggregate_push_new(slang_storage_aggregate * agg)
+{
+   slang_storage_array *arr = NULL;
+
+   agg->arrays = (slang_storage_array *)
+      _slang_realloc(agg->arrays,
+                     agg->count * sizeof(slang_storage_array),
+                     (agg->count + 1) * sizeof(slang_storage_array));
+   if (agg->arrays != NULL) {
+      arr = agg->arrays + agg->count;
+      if (!slang_storage_array_construct(arr))
+         return NULL;
+      agg->count++;
+   }
+   return arr;
+}
+
+/* _slang_aggregate_variable() */
+
+static GLboolean
+aggregate_vector(slang_storage_aggregate * agg, slang_storage_type basic_type,
+                 GLuint row_count)
+{
+   slang_storage_array *arr = slang_storage_aggregate_push_new(agg);
+   if (arr == NULL)
+      return GL_FALSE;
+   arr->type = basic_type;
+   arr->length = row_count;
+   return GL_TRUE;
+}
+
+static GLboolean
+aggregate_matrix(slang_storage_aggregate * agg, slang_storage_type basic_type,
+                 GLuint columns, GLuint rows)
+{
+   slang_storage_array *arr = slang_storage_aggregate_push_new(agg);
+   if (arr == NULL)
+      return GL_FALSE;
+   arr->type = SLANG_STORE_AGGREGATE;
+   arr->length = columns;
+   arr->aggregate = (slang_storage_aggregate *)
+      _slang_alloc(sizeof(slang_storage_aggregate));
+   if (arr->aggregate == NULL)
+      return GL_FALSE;
+   if (!slang_storage_aggregate_construct(arr->aggregate)) {
+      _slang_free(arr->aggregate);
+      arr->aggregate = NULL;
+      return GL_FALSE;
+   }
+   if (!aggregate_vector(arr->aggregate, basic_type, rows))
+      return GL_FALSE;
+   return GL_TRUE;
+}
+
+
+static GLboolean
+aggregate_variables(slang_storage_aggregate * agg,
+                    slang_variable_scope * vars, slang_function_scope * funcs,
+                    slang_struct_scope * structs,
+                    slang_variable_scope * globals,
+                    slang_atom_pool * atoms)
+{
+   GLuint i;
+
+   for (i = 0; i < vars->num_variables; i++)
+      if (!_slang_aggregate_variable(agg, &vars->variables[i]->type.specifier,
+                                     vars->variables[i]->array_len, funcs,
+                                     structs, globals, atoms))
+         return GL_FALSE;
+   return GL_TRUE;
+}
+
+
+GLboolean
+_slang_aggregate_variable(slang_storage_aggregate * agg,
+                          slang_type_specifier * spec, GLuint array_len,
+                          slang_function_scope * funcs,
+                          slang_struct_scope * structs,
+                          slang_variable_scope * vars,
+                          slang_atom_pool * atoms)
+{
+   switch (spec->type) {
+   case SLANG_SPEC_BOOL:
+      return aggregate_vector(agg, SLANG_STORE_BOOL, 1);
+   case SLANG_SPEC_BVEC2:
+      return aggregate_vector(agg, SLANG_STORE_BOOL, 2);
+   case SLANG_SPEC_BVEC3:
+      return aggregate_vector(agg, SLANG_STORE_BOOL, 3);
+   case SLANG_SPEC_BVEC4:
+      return aggregate_vector(agg, SLANG_STORE_BOOL, 4);
+   case SLANG_SPEC_INT:
+      return aggregate_vector(agg, SLANG_STORE_INT, 1);
+   case SLANG_SPEC_IVEC2:
+      return aggregate_vector(agg, SLANG_STORE_INT, 2);
+   case SLANG_SPEC_IVEC3:
+      return aggregate_vector(agg, SLANG_STORE_INT, 3);
+   case SLANG_SPEC_IVEC4:
+      return aggregate_vector(agg, SLANG_STORE_INT, 4);
+   case SLANG_SPEC_FLOAT:
+      return aggregate_vector(agg, SLANG_STORE_FLOAT, 1);
+   case SLANG_SPEC_VEC2:
+      return aggregate_vector(agg, SLANG_STORE_FLOAT, 2);
+   case SLANG_SPEC_VEC3:
+      return aggregate_vector(agg, SLANG_STORE_FLOAT, 3);
+   case SLANG_SPEC_VEC4:
+      return aggregate_vector(agg, SLANG_STORE_FLOAT, 4);
+   case SLANG_SPEC_MAT2:
+      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 2);
+   case SLANG_SPEC_MAT3:
+      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 3);
+   case SLANG_SPEC_MAT4:
+      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 4);
+
+   case SLANG_SPEC_MAT23:
+      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 3);
+   case SLANG_SPEC_MAT32:
+      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 2);
+   case SLANG_SPEC_MAT24:
+      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 4);
+   case SLANG_SPEC_MAT42:
+      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 2);
+   case SLANG_SPEC_MAT34:
+      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 4);
+   case SLANG_SPEC_MAT43:
+      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 3);
+
+   case SLANG_SPEC_SAMPLER_1D:
+   case SLANG_SPEC_SAMPLER_2D:
+   case SLANG_SPEC_SAMPLER_3D:
+   case SLANG_SPEC_SAMPLER_CUBE:
+   case SLANG_SPEC_SAMPLER_1D_SHADOW:
+   case SLANG_SPEC_SAMPLER_2D_SHADOW:
+   case SLANG_SPEC_SAMPLER_RECT:
+   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
+   case SLANG_SPEC_SAMPLER_1D_ARRAY:
+   case SLANG_SPEC_SAMPLER_2D_ARRAY:
+   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
+   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
+
+      return aggregate_vector(agg, SLANG_STORE_INT, 1);
+   case SLANG_SPEC_STRUCT:
+      return aggregate_variables(agg, spec->_struct->fields, funcs, structs,
+                                 vars, atoms);
+   case SLANG_SPEC_ARRAY:
+      {
+         slang_storage_array *arr;
+
+         arr = slang_storage_aggregate_push_new(agg);
+         if (arr == NULL)
+            return GL_FALSE;
+         arr->type = SLANG_STORE_AGGREGATE;
+         arr->aggregate = (slang_storage_aggregate *)
+            _slang_alloc(sizeof(slang_storage_aggregate));
+         if (arr->aggregate == NULL)
+            return GL_FALSE;
+         if (!slang_storage_aggregate_construct(arr->aggregate)) {
+            _slang_free(arr->aggregate);
+            arr->aggregate = NULL;
+            return GL_FALSE;
+         }
+         if (!_slang_aggregate_variable(arr->aggregate, spec->_array, 0,
+                                        funcs, structs, vars, atoms))
+            return GL_FALSE;
+         arr->length = array_len;
+         /* TODO: check if 0 < arr->length <= 65535 */
+      }
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+GLuint
+_slang_sizeof_type(slang_storage_type type)
+{
+   if (type == SLANG_STORE_AGGREGATE)
+      return 0;
+   if (type == SLANG_STORE_VEC4)
+      return 4 * sizeof(GLfloat);
+   return sizeof(GLfloat);
+}
+
+
+GLuint
+_slang_sizeof_aggregate(const slang_storage_aggregate * agg)
+{
+   GLuint i, size = 0;
+
+   for (i = 0; i < agg->count; i++) {
+      slang_storage_array *arr = &agg->arrays[i];
+      GLuint element_size;
+
+      if (arr->type == SLANG_STORE_AGGREGATE)
+         element_size = _slang_sizeof_aggregate(arr->aggregate);
+      else
+         element_size = _slang_sizeof_type(arr->type);
+      size += element_size * arr->length;
+   }
+   return size;
+}
+
+
+#if 0
+GLboolean
+_slang_flatten_aggregate(slang_storage_aggregate * flat,
+                         const slang_storage_aggregate * agg)
+{
+   GLuint i;
+
+   for (i = 0; i < agg->count; i++) {
+      GLuint j;
+
+      for (j = 0; j < agg->arrays[i].length; j++) {
+         if (agg->arrays[i].type == SLANG_STORE_AGGREGATE) {
+            if (!_slang_flatten_aggregate(flat, agg->arrays[i].aggregate))
+               return GL_FALSE;
+         }
+         else {
+            GLuint k, count;
+            slang_storage_type type;
+
+            if (agg->arrays[i].type == SLANG_STORE_VEC4) {
+               count = 4;
+               type = SLANG_STORE_FLOAT;
+            }
+            else {
+               count = 1;
+               type = agg->arrays[i].type;
+            }
+
+            for (k = 0; k < count; k++) {
+               slang_storage_array *arr;
+
+               arr = slang_storage_aggregate_push_new(flat);
+               if (arr == NULL)
+                  return GL_FALSE;
+               arr->type = type;
+               arr->length = 1;
+            }
+         }
+      }
+   }
+   return GL_TRUE;
+}
+#endif
diff --git a/src/mesa/slang/slang_storage.h b/src/mesa/slang/slang_storage.h
new file mode 100644 (file)
index 0000000..1876a36
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SLANG_STORAGE_H
+#define SLANG_STORAGE_H
+
+#include "slang_compile.h"
+
+
+/*
+ * Program variable data storage is kept completely transparent to the
+ * front-end compiler. It is up to the back-end how the data is
+ * actually allocated. The slang_storage_type enum provides the basic
+ * information about how the memory is interpreted. This abstract
+ * piece of memory is called a data slot. A data slot of a particular
+ * type has a fixed size.
+ *
+ * For now, only the three basic types are supported, that is bool,
+ * int and float. Other built-in types like vector or matrix can
+ * easily be decomposed into a series of basic types.
+ *
+ * If the vec4 module is enabled, 4-component vectors of floats are
+ * used when possible. 4x4 matrices are constructed of 4 vec4 slots.
+ */
+typedef enum slang_storage_type_
+{
+   /* core */
+   SLANG_STORE_AGGREGATE,
+   SLANG_STORE_BOOL,
+   SLANG_STORE_INT,
+   SLANG_STORE_FLOAT,
+   /* vec4 */
+   SLANG_STORE_VEC4
+} slang_storage_type;
+
+
+/**
+ * The slang_storage_array structure groups data slots of the same
+ * type into an array. This array has a fixed length. Arrays are
+ * required to have a size equal to the sum of sizes of its
+ * elements. They are also required to support indirect
+ * addressing. That is, if B references first data slot in the array,
+ * S is the size of the data slot and I is the integral index that is
+ * not known at compile time, B+I*S references I-th data slot.
+ *
+ * This structure is also used to break down built-in data types that
+ * are not supported directly.  Vectors, like vec3, are constructed
+ * from arrays of their basic types. Matrices are formed of an array
+ * of column vectors, which are in turn processed as other vectors.
+ */
+typedef struct slang_storage_array_
+{
+   slang_storage_type type;
+   struct slang_storage_aggregate_ *aggregate;
+   GLuint length;
+} slang_storage_array;
+
+GLboolean slang_storage_array_construct (slang_storage_array *);
+GLvoid slang_storage_array_destruct (slang_storage_array *);
+
+
+/**
+ * The slang_storage_aggregate structure relaxes the indirect
+ * addressing requirement for slang_storage_array
+ * structure. Aggregates are always accessed statically - its member
+ * addresses are well-known at compile time. For example, user-defined
+ * types are implemented as aggregates. Aggregates can collect data of
+ * a different type.
+ */
+typedef struct slang_storage_aggregate_
+{
+   slang_storage_array *arrays;
+   GLuint count;
+} slang_storage_aggregate;
+
+GLboolean slang_storage_aggregate_construct (slang_storage_aggregate *);
+GLvoid slang_storage_aggregate_destruct (slang_storage_aggregate *);
+
+
+extern GLboolean
+_slang_aggregate_variable(slang_storage_aggregate *agg,
+                          slang_type_specifier *spec,
+                          GLuint array_len,
+                          slang_function_scope *funcs,
+                          slang_struct_scope *structs,
+                          slang_variable_scope *vars,
+                          slang_atom_pool *atoms);
+
+/*
+ * Returns the size (in machine units) of the given storage type.
+ * It is an error to pass-in SLANG_STORE_AGGREGATE.
+ * Returns 0 on error.
+ */
+extern GLuint
+_slang_sizeof_type (slang_storage_type);
+
+
+/**
+ * Returns total size (in machine units) of the given aggregate.
+ * Returns 0 on error.
+ */
+extern GLuint
+_slang_sizeof_aggregate (const slang_storage_aggregate *);
+
+
+#if 0
+/**
+ * Converts structured aggregate to a flat one, with arrays of generic
+ * type being one-element long.  Returns GL_TRUE on success.  Returns
+ * GL_FALSE otherwise.
+ */
+extern GLboolean
+_slang_flatten_aggregate (slang_storage_aggregate *,
+                          const slang_storage_aggregate *);
+
+#endif
+
+#endif /* SLANG_STORAGE_H */
diff --git a/src/mesa/slang/slang_typeinfo.c b/src/mesa/slang/slang_typeinfo.c
new file mode 100644 (file)
index 0000000..0f96768
--- /dev/null
@@ -0,0 +1,1177 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_typeinfo.c
+ * slang type info
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "shader/prog_instruction.h"
+#include "slang_typeinfo.h"
+#include "slang_compile.h"
+#include "slang_log.h"
+#include "slang_mem.h"
+
+
+/**
+ * Checks if a field selector is a general swizzle (an r-value swizzle
+ * with replicated components or an l-value swizzle mask) for a
+ * vector.  Returns GL_TRUE if this is the case, <swz> is filled with
+ * swizzle information.  Returns GL_FALSE otherwise.
+ */
+GLboolean
+_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz)
+{
+   GLuint i;
+   GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE;
+
+   /* init to undefined.
+    * We rely on undefined/nil values to distinguish between
+    * regular swizzles and writemasks.
+    * For example, the swizzle ".xNNN" is the writemask ".x".
+    * That's different than the swizzle ".xxxx".
+    */
+   for (i = 0; i < 4; i++)
+      swz->swizzle[i] = SWIZZLE_NIL;
+
+   /* the swizzle can be at most 4-component long */
+   swz->num_components = slang_string_length(field);
+   if (swz->num_components > 4)
+      return GL_FALSE;
+
+   for (i = 0; i < swz->num_components; i++) {
+      /* mark which swizzle group is used */
+      switch (field[i]) {
+      case 'x':
+      case 'y':
+      case 'z':
+      case 'w':
+         xyzw = GL_TRUE;
+         break;
+      case 'r':
+      case 'g':
+      case 'b':
+      case 'a':
+         rgba = GL_TRUE;
+         break;
+      case 's':
+      case 't':
+      case 'p':
+      case 'q':
+         stpq = GL_TRUE;
+         break;
+      default:
+         return GL_FALSE;
+      }
+
+      /* collect swizzle component */
+      switch (field[i]) {
+      case 'x':
+      case 'r':
+      case 's':
+         swz->swizzle[i] = 0;
+         break;
+      case 'y':
+      case 'g':
+      case 't':
+         swz->swizzle[i] = 1;
+         break;
+      case 'z':
+      case 'b':
+      case 'p':
+         swz->swizzle[i] = 2;
+         break;
+      case 'w':
+      case 'a':
+      case 'q':
+         swz->swizzle[i] = 3;
+         break;
+      }
+
+      /* check if the component is valid for given vector's row count */
+      if (rows <= swz->swizzle[i])
+         return GL_FALSE;
+   }
+
+   /* only one swizzle group can be used */
+   if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
+      return GL_FALSE;
+
+   return GL_TRUE;
+}
+
+
+
+/**
+ * Checks if a general swizzle is an l-value swizzle - these swizzles
+ * do not have duplicated fields.  Returns GL_TRUE if this is a
+ * swizzle mask.  Returns GL_FALSE otherwise
+ */
+static GLboolean
+_slang_is_swizzle_mask(const slang_swizzle * swz, GLuint rows)
+{
+   GLuint i, c = 0;
+
+   /* the swizzle may not be longer than the vector dim */
+   if (swz->num_components > rows)
+      return GL_FALSE;
+
+   /* the swizzle components cannot be duplicated */
+   for (i = 0; i < swz->num_components; i++) {
+      if ((c & (1 << swz->swizzle[i])) != 0)
+         return GL_FALSE;
+      c |= 1 << swz->swizzle[i];
+   }
+
+   return GL_TRUE;
+}
+
+
+/**
+ * Combines (multiplies) two swizzles to form single swizzle.
+ * Example: "vec.wzyx.yx" --> "vec.zw".
+ */
+static void
+_slang_multiply_swizzles(slang_swizzle * dst, const slang_swizzle * left,
+                         const slang_swizzle * right)
+{
+   GLuint i;
+
+   dst->num_components = right->num_components;
+   for (i = 0; i < right->num_components; i++)
+      dst->swizzle[i] = left->swizzle[right->swizzle[i]];
+}
+
+
+typedef struct
+{
+   const char *name;
+   slang_type_specifier_type type;
+} type_specifier_type_name;
+
+static const type_specifier_type_name type_specifier_type_names[] = {
+   {"void", SLANG_SPEC_VOID},
+   {"bool", SLANG_SPEC_BOOL},
+   {"bvec2", SLANG_SPEC_BVEC2},
+   {"bvec3", SLANG_SPEC_BVEC3},
+   {"bvec4", SLANG_SPEC_BVEC4},
+   {"int", SLANG_SPEC_INT},
+   {"ivec2", SLANG_SPEC_IVEC2},
+   {"ivec3", SLANG_SPEC_IVEC3},
+   {"ivec4", SLANG_SPEC_IVEC4},
+   {"float", SLANG_SPEC_FLOAT},
+   {"vec2", SLANG_SPEC_VEC2},
+   {"vec3", SLANG_SPEC_VEC3},
+   {"vec4", SLANG_SPEC_VEC4},
+   {"mat2", SLANG_SPEC_MAT2},
+   {"mat3", SLANG_SPEC_MAT3},
+   {"mat4", SLANG_SPEC_MAT4},
+   {"mat2x3", SLANG_SPEC_MAT23},
+   {"mat3x2", SLANG_SPEC_MAT32},
+   {"mat2x4", SLANG_SPEC_MAT24},
+   {"mat4x2", SLANG_SPEC_MAT42},
+   {"mat3x4", SLANG_SPEC_MAT34},
+   {"mat4x3", SLANG_SPEC_MAT43},
+   {"sampler1D", SLANG_SPEC_SAMPLER_1D},
+   {"sampler2D", SLANG_SPEC_SAMPLER_2D},
+   {"sampler3D", SLANG_SPEC_SAMPLER_3D},
+   {"samplerCube", SLANG_SPEC_SAMPLER_CUBE},
+   {"sampler1DShadow", SLANG_SPEC_SAMPLER_1D_SHADOW},
+   {"sampler2DShadow", SLANG_SPEC_SAMPLER_2D_SHADOW},
+   {"sampler2DRect", SLANG_SPEC_SAMPLER_RECT},
+   {"sampler2DRectShadow", SLANG_SPEC_SAMPLER_RECT_SHADOW},
+   {"sampler1DArray", SLANG_SPEC_SAMPLER_1D_ARRAY},
+   {"sampler2DArray", SLANG_SPEC_SAMPLER_2D_ARRAY},
+   {"sampler1DArrayShadow", SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW},
+   {"sampler2DArrayShadow", SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW},
+   {NULL, SLANG_SPEC_VOID}
+};
+
+slang_type_specifier_type
+slang_type_specifier_type_from_string(const char *name)
+{
+   const type_specifier_type_name *p = type_specifier_type_names;
+   while (p->name != NULL) {
+      if (slang_string_compare(p->name, name) == 0)
+         break;
+      p++;
+   }
+   return p->type;
+}
+
+const char *
+slang_type_specifier_type_to_string(slang_type_specifier_type type)
+{
+   const type_specifier_type_name *p = type_specifier_type_names;
+   while (p->name != NULL) {
+      if (p->type == type)
+         break;
+      p++;
+   }
+   return p->name;
+}
+
+/* slang_fully_specified_type */
+
+int
+slang_fully_specified_type_construct(slang_fully_specified_type * type)
+{
+   type->qualifier = SLANG_QUAL_NONE;
+   slang_type_specifier_ctr(&type->specifier);
+   return 1;
+}
+
+void
+slang_fully_specified_type_destruct(slang_fully_specified_type * type)
+{
+   slang_type_specifier_dtr(&type->specifier);
+}
+
+int
+slang_fully_specified_type_copy(slang_fully_specified_type * x,
+                                const slang_fully_specified_type * y)
+{
+   slang_fully_specified_type z;
+
+   if (!slang_fully_specified_type_construct(&z))
+      return 0;
+   z.qualifier = y->qualifier;
+   z.precision = y->precision;
+   z.variant = y->variant;
+   z.centroid = y->centroid;
+   z.layout = y->layout;
+   z.array_len = y->array_len;
+   if (!slang_type_specifier_copy(&z.specifier, &y->specifier)) {
+      slang_fully_specified_type_destruct(&z);
+      return 0;
+   }
+   slang_fully_specified_type_destruct(x);
+   *x = z;
+   return 1;
+}
+
+
+/**
+ * Test if two fully specified types are compatible.  This is a bit
+ * looser than testing for equality.  We don't check the precision,
+ * variant, centroid, etc. information.
+ * XXX this may need some tweaking.
+ */
+GLboolean
+slang_fully_specified_types_compatible(const slang_fully_specified_type * x,
+                                       const slang_fully_specified_type * y)
+{
+   if (!slang_type_specifier_equal(&x->specifier, &y->specifier))
+      return GL_FALSE;
+
+   if (x->qualifier == SLANG_QUAL_FIXEDINPUT &&
+       y->qualifier == SLANG_QUAL_VARYING)
+      ; /* ok */
+   else if (x->qualifier != y->qualifier)
+      return GL_FALSE;
+
+   /* Note: don't compare precision, variant, centroid */
+
+   /* XXX array length? */
+
+   return GL_TRUE;
+}
+
+
+GLvoid
+slang_type_specifier_ctr(slang_type_specifier * self)
+{
+   self->type = SLANG_SPEC_VOID;
+   self->_struct = NULL;
+   self->_array = NULL;
+}
+
+GLvoid
+slang_type_specifier_dtr(slang_type_specifier * self)
+{
+   if (self->_struct != NULL) {
+      slang_struct_destruct(self->_struct);
+      _slang_free(self->_struct);
+   }
+   if (self->_array != NULL) {
+      slang_type_specifier_dtr(self->_array);
+      _slang_free(self->_array);
+   }
+}
+
+slang_type_specifier *
+slang_type_specifier_new(slang_type_specifier_type type,
+                         struct slang_struct_ *_struct,
+                         struct slang_type_specifier_ *_array)
+{
+   slang_type_specifier *spec =
+      (slang_type_specifier *) _slang_alloc(sizeof(slang_type_specifier));
+   if (spec) {
+      spec->type = type;
+      spec->_struct = _struct;
+      spec->_array = _array;
+   }
+   return spec;
+}
+
+GLboolean
+slang_type_specifier_copy(slang_type_specifier * x,
+                          const slang_type_specifier * y)
+{
+   slang_type_specifier z;
+
+   slang_type_specifier_ctr(&z);
+   z.type = y->type;
+   if (z.type == SLANG_SPEC_STRUCT) {
+      z._struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
+      if (z._struct == NULL) {
+         slang_type_specifier_dtr(&z);
+         return GL_FALSE;
+      }
+      if (!slang_struct_construct(z._struct)) {
+         _slang_free(z._struct);
+         slang_type_specifier_dtr(&z);
+         return GL_FALSE;
+      }
+      if (!slang_struct_copy(z._struct, y->_struct)) {
+         slang_type_specifier_dtr(&z);
+         return GL_FALSE;
+      }
+   }
+   else if (z.type == SLANG_SPEC_ARRAY) {
+      z._array = (slang_type_specifier *)
+         _slang_alloc(sizeof(slang_type_specifier));
+      if (z._array == NULL) {
+         slang_type_specifier_dtr(&z);
+         return GL_FALSE;
+      }
+      slang_type_specifier_ctr(z._array);
+      if (!slang_type_specifier_copy(z._array, y->_array)) {
+         slang_type_specifier_dtr(&z);
+         return GL_FALSE;
+      }
+   }
+   slang_type_specifier_dtr(x);
+   *x = z;
+   return GL_TRUE;
+}
+
+
+/**
+ * Test if two types are equal.
+ */
+GLboolean
+slang_type_specifier_equal(const slang_type_specifier * x,
+                           const slang_type_specifier * y)
+{
+   if (x->type != y->type)
+      return GL_FALSE;
+   if (x->type == SLANG_SPEC_STRUCT)
+      return slang_struct_equal(x->_struct, y->_struct);
+   if (x->type == SLANG_SPEC_ARRAY)
+      return slang_type_specifier_equal(x->_array, y->_array);
+   return GL_TRUE;
+}
+
+
+/**
+ * As above, but allow float/int casting.
+ */
+GLboolean
+slang_type_specifier_compatible(const slang_type_specifier * x,
+                                const slang_type_specifier * y)
+{
+   /* special case: float == int */
+   if (x->type == SLANG_SPEC_INT && y->type == SLANG_SPEC_FLOAT) {
+      return GL_TRUE;
+   }
+   /* XXX may need to add bool/int compatibility, etc */
+
+   if (x->type != y->type)
+      return GL_FALSE;
+   if (x->type == SLANG_SPEC_STRUCT)
+      return slang_struct_equal(x->_struct, y->_struct);
+   if (x->type == SLANG_SPEC_ARRAY)
+      return slang_type_specifier_compatible(x->_array, y->_array);
+   return GL_TRUE;
+}
+
+
+GLboolean
+slang_typeinfo_construct(slang_typeinfo * ti)
+{
+   memset(ti, 0, sizeof(*ti));
+   slang_type_specifier_ctr(&ti->spec);
+   ti->array_len = 0;
+   return GL_TRUE;
+}
+
+GLvoid
+slang_typeinfo_destruct(slang_typeinfo * ti)
+{
+   slang_type_specifier_dtr(&ti->spec);
+}
+
+
+
+/**
+ * Determine the return type of a function.
+ * \param a_name  the function name
+ * \param param  function parameters (overloading)
+ * \param num_params  number of parameters to function
+ * \param space  namespace to search
+ * \param spec  returns the type
+ * \param funFound  returns pointer to the function, or NULL if not found.
+ * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
+ */
+static GLboolean
+_slang_typeof_function(slang_atom a_name,
+                       slang_operation * params, GLuint num_params,
+                       const slang_name_space * space,
+                       slang_type_specifier * spec,
+                       slang_function **funFound,
+                       slang_atom_pool *atoms, slang_info_log *log)
+{
+   GLboolean error;
+
+   *funFound = _slang_function_locate(space->funcs, a_name, params,
+                                      num_params, space, atoms, log, &error);
+   if (error)
+      return GL_FALSE;
+
+   if (!*funFound)
+      return GL_TRUE;  /* yes, not false */
+
+   return slang_type_specifier_copy(spec, &(*funFound)->header.type.specifier);
+}
+
+
+/**
+ * Determine the type of a math function.
+ * \param name  name of the operator, one of +,-,*,/ or unary -
+ * \param params  array of function parameters
+ * \param num_params  number of parameters
+ * \param space  namespace to use
+ * \param spec  returns the function's type
+ * \param atoms  atom pool
+ * \return GL_TRUE for success, GL_FALSE if failure
+ */
+static GLboolean
+typeof_math_call(const char *name, slang_operation *call,
+                 const slang_name_space * space,
+                 slang_type_specifier * spec,
+                 slang_atom_pool * atoms,
+                 slang_info_log *log)
+{
+   if (call->fun) {
+      /* we've previously resolved this function call */
+      slang_type_specifier_copy(spec, &call->fun->header.type.specifier);
+      return GL_TRUE;
+   }
+   else {
+      slang_atom atom;
+      slang_function *fun;
+
+      /* number of params: */
+      assert(call->num_children == 1 || call->num_children == 2);
+
+      atom = slang_atom_pool_atom(atoms, name);
+      if (!_slang_typeof_function(atom, call->children, call->num_children,
+                                  space, spec, &fun, atoms, log))
+         return GL_FALSE;
+
+      if (fun) {
+         /* Save pointer to save time in future */
+         call->fun = fun;
+         return GL_TRUE;
+      }
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Determine the return type of an operation.
+ * \param op  the operation node
+ * \param space  the namespace to use
+ * \param ti  the returned type
+ * \param atoms  atom pool
+ * \return GL_TRUE for success, GL_FALSE if failure
+ */
+GLboolean
+_slang_typeof_operation(slang_operation * op,
+                         const slang_name_space * space,
+                         slang_typeinfo * ti,
+                         slang_atom_pool * atoms,
+                         slang_info_log *log)
+{
+   ti->can_be_referenced = GL_FALSE;
+   ti->is_swizzled = GL_FALSE;
+
+   switch (op->type) {
+   case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
+   case SLANG_OPER_BLOCK_NEW_SCOPE:
+   case SLANG_OPER_ASM:
+   case SLANG_OPER_BREAK:
+   case SLANG_OPER_CONTINUE:
+   case SLANG_OPER_DISCARD:
+   case SLANG_OPER_RETURN:
+   case SLANG_OPER_IF:
+   case SLANG_OPER_WHILE:
+   case SLANG_OPER_DO:
+   case SLANG_OPER_FOR:
+   case SLANG_OPER_VOID:
+      ti->spec.type = SLANG_SPEC_VOID;
+      break;
+   case SLANG_OPER_EXPRESSION:
+   case SLANG_OPER_ASSIGN:
+   case SLANG_OPER_ADDASSIGN:
+   case SLANG_OPER_SUBASSIGN:
+   case SLANG_OPER_MULASSIGN:
+   case SLANG_OPER_DIVASSIGN:
+   case SLANG_OPER_PREINCREMENT:
+   case SLANG_OPER_PREDECREMENT:
+      if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
+         return GL_FALSE;
+      break;
+   case SLANG_OPER_LITERAL_BOOL:
+      if (op->literal_size == 1)
+         ti->spec.type = SLANG_SPEC_BOOL;
+      else if (op->literal_size == 2)
+         ti->spec.type = SLANG_SPEC_BVEC2;
+      else if (op->literal_size == 3)
+         ti->spec.type = SLANG_SPEC_BVEC3;
+      else if (op->literal_size == 4)
+         ti->spec.type = SLANG_SPEC_BVEC4;
+      else {
+         _mesa_problem(NULL,
+               "Unexpected bool literal_size %d in _slang_typeof_operation()",
+               op->literal_size);
+         ti->spec.type = SLANG_SPEC_BOOL;
+      }
+      break;
+   case SLANG_OPER_LOGICALOR:
+   case SLANG_OPER_LOGICALXOR:
+   case SLANG_OPER_LOGICALAND:
+   case SLANG_OPER_EQUAL:
+   case SLANG_OPER_NOTEQUAL:
+   case SLANG_OPER_LESS:
+   case SLANG_OPER_GREATER:
+   case SLANG_OPER_LESSEQUAL:
+   case SLANG_OPER_GREATEREQUAL:
+   case SLANG_OPER_NOT:
+      ti->spec.type = SLANG_SPEC_BOOL;
+      break;
+   case SLANG_OPER_LITERAL_INT:
+      if (op->literal_size == 1)
+         ti->spec.type = SLANG_SPEC_INT;
+      else if (op->literal_size == 2)
+         ti->spec.type = SLANG_SPEC_IVEC2;
+      else if (op->literal_size == 3)
+         ti->spec.type = SLANG_SPEC_IVEC3;
+      else if (op->literal_size == 4)
+         ti->spec.type = SLANG_SPEC_IVEC4;
+      else {
+         _mesa_problem(NULL,
+               "Unexpected int literal_size %d in _slang_typeof_operation()",
+               op->literal_size);
+         ti->spec.type = SLANG_SPEC_INT;
+      }
+      break;
+   case SLANG_OPER_LITERAL_FLOAT:
+      if (op->literal_size == 1)
+         ti->spec.type = SLANG_SPEC_FLOAT;
+      else if (op->literal_size == 2)
+         ti->spec.type = SLANG_SPEC_VEC2;
+      else if (op->literal_size == 3)
+         ti->spec.type = SLANG_SPEC_VEC3;
+      else if (op->literal_size == 4)
+         ti->spec.type = SLANG_SPEC_VEC4;
+      else {
+         _mesa_problem(NULL,
+               "Unexpected float literal_size %d in _slang_typeof_operation()",
+               op->literal_size);
+         ti->spec.type = SLANG_SPEC_FLOAT;
+      }
+      break;
+   case SLANG_OPER_IDENTIFIER:
+   case SLANG_OPER_VARIABLE_DECL:
+      {
+         slang_variable *var;
+         var = _slang_variable_locate(op->locals, op->a_id, GL_TRUE);
+         if (!var) {
+            slang_info_log_error(log, "undefined variable '%s'",
+                                 (char *) op->a_id);
+            return GL_FALSE;
+         }
+         if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier)) {
+            slang_info_log_memory(log);
+            return GL_FALSE;
+         }
+         ti->can_be_referenced = GL_TRUE;
+         if (var->type.specifier.type == SLANG_SPEC_ARRAY &&
+             var->type.array_len >= 1) {
+            /* the datatype is an array, ex: float[3] x; */
+            ti->array_len = var->type.array_len;
+         }
+         else {
+            /* the variable is an array, ex: float x[3]; */
+            ti->array_len = var->array_len;
+         }
+      }
+      break;
+   case SLANG_OPER_SEQUENCE:
+      /* TODO: check [0] and [1] if they match */
+      if (!_slang_typeof_operation(&op->children[1], space, ti, atoms, log)) {
+         return GL_FALSE;
+      }
+      ti->can_be_referenced = GL_FALSE;
+      ti->is_swizzled = GL_FALSE;
+      break;
+      /*case SLANG_OPER_MODASSIGN: */
+      /*case SLANG_OPER_LSHASSIGN: */
+      /*case SLANG_OPER_RSHASSIGN: */
+      /*case SLANG_OPER_ORASSIGN: */
+      /*case SLANG_OPER_XORASSIGN: */
+      /*case SLANG_OPER_ANDASSIGN: */
+   case SLANG_OPER_SELECT:
+      /* TODO: check [1] and [2] if they match */
+      if (!_slang_typeof_operation(&op->children[1], space, ti, atoms, log)) {
+         return GL_FALSE;
+      }
+      ti->can_be_referenced = GL_FALSE;
+      ti->is_swizzled = GL_FALSE;
+      break;
+      /*case SLANG_OPER_BITOR: */
+      /*case SLANG_OPER_BITXOR: */
+      /*case SLANG_OPER_BITAND: */
+      /*case SLANG_OPER_LSHIFT: */
+      /*case SLANG_OPER_RSHIFT: */
+   case SLANG_OPER_ADD:
+      assert(op->num_children == 2);
+      if (!typeof_math_call("+", op, space, &ti->spec, atoms, log))
+         return GL_FALSE;
+      break;
+   case SLANG_OPER_SUBTRACT:
+      assert(op->num_children == 2);
+      if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
+         return GL_FALSE;
+      break;
+   case SLANG_OPER_MULTIPLY:
+      assert(op->num_children == 2);
+      if (!typeof_math_call("*", op, space, &ti->spec, atoms, log))
+         return GL_FALSE;
+      break;
+   case SLANG_OPER_DIVIDE:
+      assert(op->num_children == 2);
+      if (!typeof_math_call("/", op, space, &ti->spec, atoms, log))
+         return GL_FALSE;
+      break;
+   /*case SLANG_OPER_MODULUS: */
+   case SLANG_OPER_PLUS:
+      if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
+         return GL_FALSE;
+      ti->can_be_referenced = GL_FALSE;
+      ti->is_swizzled = GL_FALSE;
+      break;
+   case SLANG_OPER_MINUS:
+      assert(op->num_children == 1);
+      if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
+         return GL_FALSE;
+      break;
+      /*case SLANG_OPER_COMPLEMENT: */
+   case SLANG_OPER_SUBSCRIPT:
+      {
+         slang_typeinfo _ti;
+
+         if (!slang_typeinfo_construct(&_ti))
+            return GL_FALSE;
+         if (!_slang_typeof_operation(op->children, space, &_ti, atoms, log)) {
+            slang_typeinfo_destruct(&_ti);
+            return GL_FALSE;
+         }
+         ti->can_be_referenced = _ti.can_be_referenced;
+         if (_ti.spec.type == SLANG_SPEC_ARRAY) {
+            if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
+               slang_typeinfo_destruct(&_ti);
+               return GL_FALSE;
+            }
+         }
+         else {
+            if (!_slang_type_is_vector(_ti.spec.type)
+                && !_slang_type_is_matrix(_ti.spec.type)) {
+               slang_typeinfo_destruct(&_ti);
+               slang_info_log_error(log, "cannot index a non-array type");
+               return GL_FALSE;
+            }
+            ti->spec.type = _slang_type_base(_ti.spec.type);
+         }
+         slang_typeinfo_destruct(&_ti);
+      }
+      break;
+   case SLANG_OPER_CALL:
+      if (op->array_constructor) {
+         /* build array typeinfo */
+         ti->spec.type = SLANG_SPEC_ARRAY;
+         ti->spec._array = (slang_type_specifier *)
+            _slang_alloc(sizeof(slang_type_specifier));
+         slang_type_specifier_ctr(ti->spec._array);
+
+         ti->spec._array->type =
+            slang_type_specifier_type_from_string((char *) op->a_id);
+         ti->array_len = op->num_children;
+      }
+      else if (op->fun) {
+         /* we've resolved this call before */
+         slang_type_specifier_copy(&ti->spec, &op->fun->header.type.specifier);
+      }
+      else {
+         slang_function *fun;
+         if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
+                                     space, &ti->spec, &fun, atoms, log))
+            return GL_FALSE;
+         if (fun) {
+            /* save result for future use */
+            op->fun = fun;
+         }
+         else {
+            slang_struct *s =
+               slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
+            if (s) {
+               /* struct initializer */
+               ti->spec.type = SLANG_SPEC_STRUCT;
+               ti->spec._struct =
+                  (slang_struct *) _slang_alloc(sizeof(slang_struct));
+               if (ti->spec._struct == NULL)
+                  return GL_FALSE;
+               if (!slang_struct_construct(ti->spec._struct)) {
+                  _slang_free(ti->spec._struct);
+                  ti->spec._struct = NULL;
+                  return GL_FALSE;
+               }
+               if (!slang_struct_copy(ti->spec._struct, s))
+                  return GL_FALSE;
+            }
+            else {
+               /* float, int, vec4, mat3, etc. constructor? */
+               const char *name;
+               slang_type_specifier_type type;
+
+               name = slang_atom_pool_id(atoms, op->a_id);
+               type = slang_type_specifier_type_from_string(name);
+               if (type == SLANG_SPEC_VOID) {
+                  slang_info_log_error(log, "undefined function '%s'", name);
+                  return GL_FALSE;
+               }
+               ti->spec.type = type;
+            }
+         }
+      }
+      break;
+   case SLANG_OPER_METHOD:
+      /* at this time, GLSL 1.20 only has one method: array.length()
+       * which returns an integer.
+       */
+      ti->spec.type = SLANG_SPEC_INT;
+      break;
+   case SLANG_OPER_FIELD:
+      {
+         slang_typeinfo _ti;
+
+         if (!slang_typeinfo_construct(&_ti))
+            return GL_FALSE;
+         if (!_slang_typeof_operation(op->children, space, &_ti, atoms, log)) {
+            slang_typeinfo_destruct(&_ti);
+            return GL_FALSE;
+         }
+         if (_ti.spec.type == SLANG_SPEC_STRUCT) {
+            slang_variable *field;
+
+            field = _slang_variable_locate(_ti.spec._struct->fields, op->a_id,
+                                           GL_FALSE);
+            if (field == NULL) {
+               slang_typeinfo_destruct(&_ti);
+               return GL_FALSE;
+            }
+            if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
+               slang_typeinfo_destruct(&_ti);
+               return GL_FALSE;
+            }
+            ti->can_be_referenced = _ti.can_be_referenced;
+            ti->array_len = field->array_len;
+         }
+         else {
+            GLuint rows;
+            const char *swizzle;
+            slang_type_specifier_type base;
+
+            /* determine the swizzle of the field expression */
+            if (!_slang_type_is_vector(_ti.spec.type)) {
+               slang_typeinfo_destruct(&_ti);
+               slang_info_log_error(log, "Can't swizzle scalar expression");
+               return GL_FALSE;
+            }
+            rows = _slang_type_dim(_ti.spec.type);
+            swizzle = slang_atom_pool_id(atoms, op->a_id);
+            if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) {
+               slang_typeinfo_destruct(&_ti);
+               slang_info_log_error(log, "bad swizzle '%s'", swizzle);
+               return GL_FALSE;
+            }
+            ti->is_swizzled = GL_TRUE;
+            ti->can_be_referenced = _ti.can_be_referenced
+               && _slang_is_swizzle_mask(&ti->swz, rows);
+            if (_ti.is_swizzled) {
+               slang_swizzle swz;
+
+               /* swizzle the swizzle */
+               _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz);
+               ti->swz = swz;
+            }
+            base = _slang_type_base(_ti.spec.type);
+            switch (ti->swz.num_components) {
+            case 1:
+               ti->spec.type = base;
+               break;
+            case 2:
+               switch (base) {
+               case SLANG_SPEC_FLOAT:
+                  ti->spec.type = SLANG_SPEC_VEC2;
+                  break;
+               case SLANG_SPEC_INT:
+                  ti->spec.type = SLANG_SPEC_IVEC2;
+                  break;
+               case SLANG_SPEC_BOOL:
+                  ti->spec.type = SLANG_SPEC_BVEC2;
+                  break;
+               default:
+                  break;
+               }
+               break;
+            case 3:
+               switch (base) {
+               case SLANG_SPEC_FLOAT:
+                  ti->spec.type = SLANG_SPEC_VEC3;
+                  break;
+               case SLANG_SPEC_INT:
+                  ti->spec.type = SLANG_SPEC_IVEC3;
+                  break;
+               case SLANG_SPEC_BOOL:
+                  ti->spec.type = SLANG_SPEC_BVEC3;
+                  break;
+               default:
+                  break;
+               }
+               break;
+            case 4:
+               switch (base) {
+               case SLANG_SPEC_FLOAT:
+                  ti->spec.type = SLANG_SPEC_VEC4;
+                  break;
+               case SLANG_SPEC_INT:
+                  ti->spec.type = SLANG_SPEC_IVEC4;
+                  break;
+               case SLANG_SPEC_BOOL:
+                  ti->spec.type = SLANG_SPEC_BVEC4;
+                  break;
+               default:
+                  break;
+               }
+               break;
+            default:
+               break;
+            }
+         }
+         slang_typeinfo_destruct(&_ti);
+      }
+      break;
+   case SLANG_OPER_POSTINCREMENT:
+   case SLANG_OPER_POSTDECREMENT:
+      if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
+         return GL_FALSE;
+      ti->can_be_referenced = GL_FALSE;
+      ti->is_swizzled = GL_FALSE;
+      break;
+   default:
+      return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
+
+/**
+ * Determine if a type is a matrix.
+ * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
+ */
+GLboolean
+_slang_type_is_matrix(slang_type_specifier_type ty)
+{
+   switch (ty) {
+   case SLANG_SPEC_MAT2:
+   case SLANG_SPEC_MAT3:
+   case SLANG_SPEC_MAT4:
+   case SLANG_SPEC_MAT23:
+   case SLANG_SPEC_MAT32:
+   case SLANG_SPEC_MAT24:
+   case SLANG_SPEC_MAT42:
+   case SLANG_SPEC_MAT34:
+   case SLANG_SPEC_MAT43:
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Determine if a type is a vector.
+ * \return GL_TRUE if is a vector, GL_FALSE otherwise.
+ */
+GLboolean
+_slang_type_is_vector(slang_type_specifier_type ty)
+{
+   switch (ty) {
+   case SLANG_SPEC_VEC2:
+   case SLANG_SPEC_VEC3:
+   case SLANG_SPEC_VEC4:
+   case SLANG_SPEC_IVEC2:
+   case SLANG_SPEC_IVEC3:
+   case SLANG_SPEC_IVEC4:
+   case SLANG_SPEC_BVEC2:
+   case SLANG_SPEC_BVEC3:
+   case SLANG_SPEC_BVEC4:
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Determine if a type is a float, float vector or float matrix.
+ * \return GL_TRUE if so, GL_FALSE otherwise
+ */
+GLboolean
+_slang_type_is_float_vec_mat(slang_type_specifier_type ty)
+{
+   switch (ty) {
+   case SLANG_SPEC_FLOAT:
+   case SLANG_SPEC_VEC2:
+   case SLANG_SPEC_VEC3:
+   case SLANG_SPEC_VEC4:
+   case SLANG_SPEC_MAT2:
+   case SLANG_SPEC_MAT3:
+   case SLANG_SPEC_MAT4:
+   case SLANG_SPEC_MAT23:
+   case SLANG_SPEC_MAT32:
+   case SLANG_SPEC_MAT24:
+   case SLANG_SPEC_MAT42:
+   case SLANG_SPEC_MAT34:
+   case SLANG_SPEC_MAT43:
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Given a vector type, return the type of the vector's elements.
+ * For a matrix, return the type of the columns.
+ */
+slang_type_specifier_type
+_slang_type_base(slang_type_specifier_type ty)
+{
+   switch (ty) {
+   case SLANG_SPEC_FLOAT:
+   case SLANG_SPEC_VEC2:
+   case SLANG_SPEC_VEC3:
+   case SLANG_SPEC_VEC4:
+      return SLANG_SPEC_FLOAT;
+   case SLANG_SPEC_INT:
+   case SLANG_SPEC_IVEC2:
+   case SLANG_SPEC_IVEC3:
+   case SLANG_SPEC_IVEC4:
+      return SLANG_SPEC_INT;
+   case SLANG_SPEC_BOOL:
+   case SLANG_SPEC_BVEC2:
+   case SLANG_SPEC_BVEC3:
+   case SLANG_SPEC_BVEC4:
+      return SLANG_SPEC_BOOL;
+   case SLANG_SPEC_MAT2:
+      return SLANG_SPEC_VEC2;
+   case SLANG_SPEC_MAT3:
+      return SLANG_SPEC_VEC3;
+   case SLANG_SPEC_MAT4:
+      return SLANG_SPEC_VEC4;
+   case SLANG_SPEC_MAT23:
+      return SLANG_SPEC_VEC3;
+   case SLANG_SPEC_MAT32:
+      return SLANG_SPEC_VEC2;
+   case SLANG_SPEC_MAT24:
+      return SLANG_SPEC_VEC4;
+   case SLANG_SPEC_MAT42:
+      return SLANG_SPEC_VEC2;
+   case SLANG_SPEC_MAT34:
+      return SLANG_SPEC_VEC4;
+   case SLANG_SPEC_MAT43:
+      return SLANG_SPEC_VEC3;
+   default:
+      return SLANG_SPEC_VOID;
+   }
+}
+
+
+/**
+ * Return the dimensionality of a vector, or for a matrix, return number
+ * of columns.
+ */
+GLuint
+_slang_type_dim(slang_type_specifier_type ty)
+{
+   switch (ty) {
+   case SLANG_SPEC_FLOAT:
+   case SLANG_SPEC_INT:
+   case SLANG_SPEC_BOOL:
+      return 1;
+   case SLANG_SPEC_VEC2:
+   case SLANG_SPEC_IVEC2:
+   case SLANG_SPEC_BVEC2:
+   case SLANG_SPEC_MAT2:
+      return 2;
+   case SLANG_SPEC_VEC3:
+   case SLANG_SPEC_IVEC3:
+   case SLANG_SPEC_BVEC3:
+   case SLANG_SPEC_MAT3:
+      return 3;
+   case SLANG_SPEC_VEC4:
+   case SLANG_SPEC_IVEC4:
+   case SLANG_SPEC_BVEC4:
+   case SLANG_SPEC_MAT4:
+      return 4;
+
+   case SLANG_SPEC_MAT23:
+      return 2;
+   case SLANG_SPEC_MAT32:
+      return 3;
+   case SLANG_SPEC_MAT24:
+      return 2;
+   case SLANG_SPEC_MAT42:
+      return 4;
+   case SLANG_SPEC_MAT34:
+      return 3;
+   case SLANG_SPEC_MAT43:
+      return 4;
+
+   default:
+      return 0;
+   }
+}
+
+
+/**
+ * Return the GL_* type that corresponds to a SLANG_SPEC_* type.
+ */
+GLenum
+_slang_gltype_from_specifier(const slang_type_specifier *type)
+{
+   switch (type->type) {
+   case SLANG_SPEC_BOOL:
+      return GL_BOOL;
+   case SLANG_SPEC_BVEC2:
+      return GL_BOOL_VEC2;
+   case SLANG_SPEC_BVEC3:
+      return GL_BOOL_VEC3;
+   case SLANG_SPEC_BVEC4:
+      return GL_BOOL_VEC4;
+   case SLANG_SPEC_INT:
+      return GL_INT;
+   case SLANG_SPEC_IVEC2:
+      return GL_INT_VEC2;
+   case SLANG_SPEC_IVEC3:
+      return GL_INT_VEC3;
+   case SLANG_SPEC_IVEC4:
+      return GL_INT_VEC4;
+   case SLANG_SPEC_FLOAT:
+      return GL_FLOAT;
+   case SLANG_SPEC_VEC2:
+      return GL_FLOAT_VEC2;
+   case SLANG_SPEC_VEC3:
+      return GL_FLOAT_VEC3;
+   case SLANG_SPEC_VEC4:
+      return GL_FLOAT_VEC4;
+   case SLANG_SPEC_MAT2:
+      return GL_FLOAT_MAT2;
+   case SLANG_SPEC_MAT3:
+      return GL_FLOAT_MAT3;
+   case SLANG_SPEC_MAT4:
+      return GL_FLOAT_MAT4;
+   case SLANG_SPEC_MAT23:
+      return GL_FLOAT_MAT2x3;
+   case SLANG_SPEC_MAT32:
+      return GL_FLOAT_MAT3x2;
+   case SLANG_SPEC_MAT24:
+      return GL_FLOAT_MAT2x4;
+   case SLANG_SPEC_MAT42:
+      return GL_FLOAT_MAT4x2;
+   case SLANG_SPEC_MAT34:
+      return GL_FLOAT_MAT3x4;
+   case SLANG_SPEC_MAT43:
+      return GL_FLOAT_MAT4x3;
+   case SLANG_SPEC_SAMPLER_1D:
+      return GL_SAMPLER_1D;
+   case SLANG_SPEC_SAMPLER_2D:
+      return GL_SAMPLER_2D;
+   case SLANG_SPEC_SAMPLER_3D:
+      return GL_SAMPLER_3D;
+   case SLANG_SPEC_SAMPLER_CUBE:
+      return GL_SAMPLER_CUBE;
+   case SLANG_SPEC_SAMPLER_1D_SHADOW:
+      return GL_SAMPLER_1D_SHADOW;
+   case SLANG_SPEC_SAMPLER_2D_SHADOW:
+      return GL_SAMPLER_2D_SHADOW;
+   case SLANG_SPEC_SAMPLER_RECT:
+      return GL_SAMPLER_2D_RECT_ARB;
+   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
+      return GL_SAMPLER_2D_RECT_SHADOW_ARB;
+   case SLANG_SPEC_SAMPLER_1D_ARRAY:
+      return GL_SAMPLER_1D_ARRAY_EXT;
+   case SLANG_SPEC_SAMPLER_2D_ARRAY:
+      return GL_SAMPLER_2D_ARRAY_EXT;
+   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
+      return GL_SAMPLER_1D_ARRAY_SHADOW_EXT;
+   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
+      return GL_SAMPLER_2D_ARRAY_SHADOW_EXT;
+   case SLANG_SPEC_ARRAY:
+      return _slang_gltype_from_specifier(type->_array);
+   case SLANG_SPEC_STRUCT:
+      /* fall-through */
+   default:
+      return GL_NONE;
+   }
+}
+
diff --git a/src/mesa/slang/slang_typeinfo.h b/src/mesa/slang/slang_typeinfo.h
new file mode 100644 (file)
index 0000000..9a6407a
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SLANG_TYPEINFO_H
+#define SLANG_TYPEINFO_H 1
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "slang_log.h"
+#include "slang_utility.h"
+#include "slang_vartable.h"
+
+
+struct slang_operation_;
+
+struct slang_name_space_;
+
+
+
+/**
+ * Holds complete information about vector swizzle - the <swizzle>
+ * array contains vector component source indices, where 0 is "x", 1
+ * is "y", 2 is "z" and 3 is "w".
+ * Example: "xwz" --> { 3, { 0, 3, 2, not used } }.
+ */
+typedef struct slang_swizzle_
+{
+   GLuint num_components;
+   GLuint swizzle[4];
+} slang_swizzle;
+
+extern GLboolean
+_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle *swz);
+
+
+typedef enum slang_type_variant_
+{
+   SLANG_VARIANT,    /* the default */
+   SLANG_INVARIANT   /* indicates the "invariant" keyword */
+} slang_type_variant;
+
+
+typedef enum slang_type_centroid_
+{
+   SLANG_CENTER,    /* the default */
+   SLANG_CENTROID   /* indicates the "centroid" keyword */
+} slang_type_centroid;
+
+
+/**
+ * These only apply to gl_FragCoord, but other layout qualifiers may
+ * appear in the future.
+ */
+typedef enum slang_layout_qualifier_
+{
+   SLANG_LAYOUT_NONE                      = 0x0,
+   SLANG_LAYOUT_UPPER_LEFT_BIT            = 0x1,
+   SLANG_LAYOUT_PIXEL_CENTER_INTEGER_BIT  = 0x2
+} slang_layout_qualifier;
+
+
+typedef enum slang_type_qualifier_
+{
+   SLANG_QUAL_NONE,
+   SLANG_QUAL_CONST,
+   SLANG_QUAL_ATTRIBUTE,
+   SLANG_QUAL_VARYING,
+   SLANG_QUAL_UNIFORM,
+   SLANG_QUAL_OUT,
+   SLANG_QUAL_INOUT,
+   SLANG_QUAL_FIXEDOUTPUT,      /* internal */
+   SLANG_QUAL_FIXEDINPUT        /* internal */
+} slang_type_qualifier;
+
+
+typedef enum slang_type_precision_
+{
+   SLANG_PREC_DEFAULT,
+   SLANG_PREC_LOW,
+   SLANG_PREC_MEDIUM,
+   SLANG_PREC_HIGH
+} slang_type_precision;
+
+
+/**
+ * The basic shading language types (float, vec4, mat3, etc)
+ */
+typedef enum slang_type_specifier_type_
+{
+   SLANG_SPEC_VOID,
+   SLANG_SPEC_BOOL,
+   SLANG_SPEC_BVEC2,
+   SLANG_SPEC_BVEC3,
+   SLANG_SPEC_BVEC4,
+   SLANG_SPEC_INT,
+   SLANG_SPEC_IVEC2,
+   SLANG_SPEC_IVEC3,
+   SLANG_SPEC_IVEC4,
+   SLANG_SPEC_FLOAT,
+   SLANG_SPEC_VEC2,
+   SLANG_SPEC_VEC3,
+   SLANG_SPEC_VEC4,
+   SLANG_SPEC_MAT2,
+   SLANG_SPEC_MAT3,
+   SLANG_SPEC_MAT4,
+   SLANG_SPEC_MAT23,
+   SLANG_SPEC_MAT32,
+   SLANG_SPEC_MAT24,
+   SLANG_SPEC_MAT42,
+   SLANG_SPEC_MAT34,
+   SLANG_SPEC_MAT43,
+   SLANG_SPEC_SAMPLER_1D,
+   SLANG_SPEC_SAMPLER_2D,
+   SLANG_SPEC_SAMPLER_3D,
+   SLANG_SPEC_SAMPLER_CUBE,
+   SLANG_SPEC_SAMPLER_RECT,
+   SLANG_SPEC_SAMPLER_1D_SHADOW,
+   SLANG_SPEC_SAMPLER_2D_SHADOW,
+   SLANG_SPEC_SAMPLER_RECT_SHADOW,
+   SLANG_SPEC_SAMPLER_1D_ARRAY,
+   SLANG_SPEC_SAMPLER_2D_ARRAY,
+   SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW,
+   SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW,
+   SLANG_SPEC_STRUCT,
+   SLANG_SPEC_ARRAY
+} slang_type_specifier_type;
+
+
+extern slang_type_specifier_type
+slang_type_specifier_type_from_string(const char *);
+
+extern const char *
+slang_type_specifier_type_to_string(slang_type_specifier_type);
+
+
+/**
+ * Describes more sophisticated types, like structs and arrays.
+ */
+typedef struct slang_type_specifier_
+{
+   slang_type_specifier_type type;
+   struct slang_struct_ *_struct;         /**< if type == SLANG_SPEC_STRUCT */
+   struct slang_type_specifier_ *_array;  /**< if type == SLANG_SPEC_ARRAY */
+} slang_type_specifier;
+
+
+extern GLvoid
+slang_type_specifier_ctr(slang_type_specifier *);
+
+extern GLvoid
+slang_type_specifier_dtr(slang_type_specifier *);
+
+extern slang_type_specifier *
+slang_type_specifier_new(slang_type_specifier_type type,
+                         struct slang_struct_ *_struct,
+                         struct slang_type_specifier_ *_array);
+
+
+extern GLboolean
+slang_type_specifier_copy(slang_type_specifier *, const slang_type_specifier *);
+
+extern GLboolean
+slang_type_specifier_equal(const slang_type_specifier *,
+                           const slang_type_specifier *);
+
+
+extern GLboolean
+slang_type_specifier_compatible(const slang_type_specifier *x,
+                                const slang_type_specifier *y);
+
+
+typedef struct slang_fully_specified_type_
+{
+   slang_type_qualifier qualifier;
+   slang_type_specifier specifier;
+   slang_type_precision precision;
+   slang_type_variant variant;
+   slang_type_centroid centroid;
+   slang_layout_qualifier layout;
+   GLint array_len;           /**< -1 if not an array type */
+} slang_fully_specified_type;
+
+extern int
+slang_fully_specified_type_construct(slang_fully_specified_type *);
+
+extern void
+slang_fully_specified_type_destruct(slang_fully_specified_type *);
+
+extern int
+slang_fully_specified_type_copy(slang_fully_specified_type *,
+                               const slang_fully_specified_type *);
+
+GLboolean
+slang_fully_specified_types_compatible(const slang_fully_specified_type * x,
+                                       const slang_fully_specified_type * y);
+
+
+typedef struct slang_typeinfo_
+{
+   GLboolean can_be_referenced;
+   GLboolean is_swizzled;
+   slang_swizzle swz;
+   slang_type_specifier spec;
+   GLuint array_len;
+} slang_typeinfo;
+
+extern GLboolean
+slang_typeinfo_construct(slang_typeinfo *);
+
+extern GLvoid
+slang_typeinfo_destruct(slang_typeinfo *);
+
+
+extern GLboolean
+_slang_typeof_operation(struct slang_operation_ *,
+                         const struct slang_name_space_ *,
+                         slang_typeinfo *, slang_atom_pool *,
+                         slang_info_log *log);
+
+extern GLboolean
+_slang_type_is_matrix(slang_type_specifier_type);
+
+extern GLboolean
+_slang_type_is_vector(slang_type_specifier_type);
+
+extern GLboolean
+_slang_type_is_float_vec_mat(slang_type_specifier_type);
+
+extern slang_type_specifier_type
+_slang_type_base(slang_type_specifier_type);
+
+extern GLuint
+_slang_type_dim(slang_type_specifier_type);
+
+extern GLenum
+_slang_gltype_from_specifier(const slang_type_specifier *type);
+
+#endif
diff --git a/src/mesa/slang/slang_utility.c b/src/mesa/slang/slang_utility.c
new file mode 100644 (file)
index 0000000..c1d5740
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_utility.c
+ * slang utilities
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "slang_utility.h"
+#include "slang_mem.h"
+
+char *
+slang_string_concat (char *dst, const char *src)
+{
+   return strcpy (dst + strlen (dst), src);
+}
+
+
+/* slang_string */
+
+GLvoid
+slang_string_init (slang_string *self)
+{
+   self->data = NULL;
+   self->capacity = 0;
+   self->length = 0;
+   self->fail = GL_FALSE;
+}
+
+GLvoid
+slang_string_free (slang_string *self)
+{
+   if (self->data != NULL)
+      free(self->data);
+}
+
+GLvoid
+slang_string_reset (slang_string *self)
+{
+   self->length = 0;
+   self->fail = GL_FALSE;
+}
+
+static GLboolean
+grow (slang_string *self, GLuint size)
+{
+   if (self->fail)
+      return GL_FALSE;
+   if (size > self->capacity) {
+      /* do not overflow 32-bit range */
+      assert (size < 0x80000000);
+
+      self->data = (char *) (_mesa_realloc (self->data, self->capacity, size * 2));
+      self->capacity = size * 2;
+      if (self->data == NULL) {
+         self->capacity = 0;
+         self->fail = GL_TRUE;
+         return GL_FALSE;
+      }
+   }
+   return GL_TRUE;
+}
+
+GLvoid
+slang_string_push (slang_string *self, const slang_string *str)
+{
+   if (str->fail) {
+      self->fail = GL_TRUE;
+      return;
+   }
+   if (grow (self, self->length + str->length)) {
+      memcpy (&self->data[self->length], str->data, str->length);
+      self->length += str->length;
+   }
+}
+
+GLvoid
+slang_string_pushc (slang_string *self, const char c)
+{
+   if (grow (self, self->length + 1)) {
+      self->data[self->length] = c;
+      self->length++;
+   }
+}
+
+GLvoid
+slang_string_pushs (slang_string *self, const char *cstr, GLuint len)
+{
+   if (grow (self, self->length + len)) {
+      memcpy (&self->data[self->length], cstr, len);
+      self->length += len;
+   }
+}
+
+GLvoid
+slang_string_pushi (slang_string *self, GLint i)
+{
+   char buffer[12];
+
+   _mesa_snprintf (buffer, sizeof(buffer), "%d", i);
+   slang_string_pushs (self, buffer, strlen (buffer));
+}
+
+const char *
+slang_string_cstr (slang_string *self)
+{
+   if (grow (self, self->length + 1))
+      self->data[self->length] = '\0';
+   return self->data;
+}
+
+/* slang_atom_pool */
+
+void
+slang_atom_pool_construct(slang_atom_pool * pool)
+{
+   GLuint i;
+
+   for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++)
+      pool->entries[i] = NULL;
+}
+
+void
+slang_atom_pool_destruct (slang_atom_pool * pool)
+{
+   GLuint i;
+
+   for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++) {
+      slang_atom_entry * entry;
+               
+      entry = pool->entries[i];
+      while (entry != NULL) {
+         slang_atom_entry *next = entry->next;
+         _slang_free(entry->id);
+         _slang_free(entry);
+         entry = next;
+      }
+   }
+}
+
+/*
+ * Search the atom pool for an atom with a given name.
+ * If atom is not found, create and add it to the pool.
+ * Returns ATOM_NULL if the atom was not found and the function failed
+ * to create a new atom.
+ */
+slang_atom
+slang_atom_pool_atom(slang_atom_pool * pool, const char * id)
+{
+   GLuint hash;
+   const char * p = id;
+   slang_atom_entry ** entry;
+
+   /* Hash a given string to a number in the range [0, ATOM_POOL_SIZE). */
+   hash = 0;
+   while (*p != '\0') {
+      GLuint g;
+
+      hash = (hash << 4) + (GLuint) (*p++);
+      g = hash & 0xf0000000;
+      if (g != 0)
+         hash ^= g >> 24;
+      hash &= ~g;
+   }
+   hash %= SLANG_ATOM_POOL_SIZE;
+
+   /* Now the hash points to a linked list of atoms with names that
+    * have the same hash value.  Search the linked list for a given
+    * name.
+    */
+   entry = &pool->entries[hash];
+   while (*entry != NULL) {
+      /* If the same, return the associated atom. */
+      if (slang_string_compare((**entry).id, id) == 0)
+         return (slang_atom) (**entry).id;
+      /* Grab the next atom in the linked list. */
+      entry = &(**entry).next;
+   }
+
+   /* Okay, we have not found an atom. Create a new entry for it.
+    * Note that the <entry> points to the last entry's <next> field.
+    */
+   *entry = (slang_atom_entry *) _slang_alloc(sizeof(slang_atom_entry));
+   if (*entry == NULL)
+      return SLANG_ATOM_NULL;
+
+   /* Initialize a new entry. Because we'll need the actual name of
+    * the atom, we use the pointer to this string as an actual atom's
+    * value.
+    */
+   (**entry).next = NULL;
+   (**entry).id = _slang_strdup(id);
+   if ((**entry).id == NULL)
+      return SLANG_ATOM_NULL;
+   return (slang_atom) (**entry).id;
+}
+
+/**
+ * Return the name of a given atom.
+ */
+const char *
+slang_atom_pool_id(slang_atom_pool * pool, slang_atom atom)
+{
+   return (const char *) (atom);
+}
diff --git a/src/mesa/slang/slang_utility.h b/src/mesa/slang/slang_utility.h
new file mode 100644 (file)
index 0000000..2c0d0bc
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SLANG_UTILITY_H
+#define SLANG_UTILITY_H
+
+
+/* Compile-time assertions.  If the expression is zero, try to declare an
+ * array of size [-1] to cause compilation error.
+ */
+#define static_assert(expr) do { int _array[(expr) ? 1 : -1]; (void) _array[0]; } while (0)
+
+
+#define slang_string_compare(str1, str2) strcmp (str1, str2)
+#define slang_string_copy(dst, src) strcpy (dst, src)
+#define slang_string_length(str) strlen (str)
+
+char *slang_string_concat (char *, const char *);
+
+/* slang_string */
+
+typedef struct
+{
+   char *data;
+   GLuint length;
+   GLuint capacity;
+   GLboolean fail;
+} slang_string;
+
+GLvoid
+slang_string_init (slang_string *);
+
+GLvoid
+slang_string_free (slang_string *);
+
+GLvoid
+slang_string_reset (slang_string *);
+
+GLvoid
+slang_string_push (slang_string *, const slang_string *);
+
+GLvoid
+slang_string_pushc (slang_string *, const char);
+
+GLvoid
+slang_string_pushs (slang_string *, const char *, GLuint);
+
+GLvoid
+slang_string_pushi (slang_string *, GLint);
+
+const char *
+slang_string_cstr (slang_string *);
+
+/* slang_atom */
+
+typedef GLvoid *slang_atom;
+
+#define SLANG_ATOM_NULL ((slang_atom) 0)
+
+typedef struct slang_atom_entry_
+{
+       char *id;
+       struct slang_atom_entry_ *next;
+} slang_atom_entry;
+
+#define SLANG_ATOM_POOL_SIZE 1023
+
+typedef struct slang_atom_pool_
+{
+       slang_atom_entry *entries[SLANG_ATOM_POOL_SIZE];
+} slang_atom_pool;
+
+GLvoid slang_atom_pool_construct (slang_atom_pool *);
+GLvoid slang_atom_pool_destruct (slang_atom_pool *);
+slang_atom slang_atom_pool_atom (slang_atom_pool *, const char *);
+const char *slang_atom_pool_id (slang_atom_pool *, slang_atom);
+
+
+#endif
diff --git a/src/mesa/slang/slang_vartable.c b/src/mesa/slang/slang_vartable.c
new file mode 100644 (file)
index 0000000..e07e3a2
--- /dev/null
@@ -0,0 +1,362 @@
+
+#include "main/imports.h"
+#include "shader/program.h"
+#include "shader/prog_print.h"
+#include "slang_compile.h"
+#include "slang_compile_variable.h"
+#include "slang_emit.h"
+#include "slang_mem.h"
+#include "slang_vartable.h"
+#include "slang_ir.h"
+
+
+static int dbg = 0;
+
+
+typedef enum {
+   FREE,
+   VAR,
+   TEMP
+} TempState;
+
+
+/**
+ * Variable/register info for one variable scope.
+ */
+struct table
+{
+   int Level;
+   int NumVars;
+   slang_variable **Vars;  /* array [NumVars] */
+
+   TempState Temps[MAX_PROGRAM_TEMPS * 4];  /* per-component state */
+   int ValSize[MAX_PROGRAM_TEMPS * 4];     /**< For debug only */
+
+   struct table *Parent;  /** Parent scope table */
+};
+
+
+/**
+ * A variable table is a stack of tables, one per scope.
+ */
+struct slang_var_table_
+{
+   GLint CurLevel;
+   GLuint MaxRegisters;
+   struct table *Top;  /**< Table at top of stack */
+};
+
+
+
+slang_var_table *
+_slang_new_var_table(GLuint maxRegisters)
+{
+   slang_var_table *vt
+      = (slang_var_table *) _slang_alloc(sizeof(slang_var_table));
+   if (vt) {
+      vt->MaxRegisters = maxRegisters;
+   }
+   return vt;
+}
+
+
+void
+_slang_delete_var_table(slang_var_table *vt)
+{
+   if (vt->Top) {
+      _mesa_problem(NULL, "non-empty var table in _slang_delete_var_table()");
+      return;
+   }
+   _slang_free(vt);
+}
+
+
+
+/**
+ * Create new table on top of vartable stack.
+ * Used when we enter a {} block.
+ */
+void
+_slang_push_var_table(slang_var_table *vt)
+{
+   struct table *t = (struct table *) _slang_alloc(sizeof(struct table));
+   if (t) {
+      t->Level = vt->CurLevel++;
+      t->Parent = vt->Top;
+      if (t->Parent) {
+         /* copy the info indicating which temp regs are in use */
+         memcpy(t->Temps, t->Parent->Temps, sizeof(t->Temps));
+         memcpy(t->ValSize, t->Parent->ValSize, sizeof(t->ValSize));
+      }
+      vt->Top = t;
+      if (dbg) printf("Pushing level %d\n", t->Level);
+   }
+}
+
+
+/**
+ * Pop top entry from variable table.
+ * Used when we leave a {} block.
+ */
+void
+_slang_pop_var_table(slang_var_table *vt)
+{
+   struct table *t = vt->Top;
+   int i;
+
+   if (dbg) printf("Popping level %d\n", t->Level);
+
+   /* free the storage allocated for each variable */
+   for (i = 0; i < t->NumVars; i++) {
+      slang_ir_storage *store = t->Vars[i]->store;
+      GLint j;
+      GLuint comp;
+      if (dbg) printf("  Free var %s, size %d at %d.%s\n",
+                      (char*) t->Vars[i]->a_name, store->Size,
+                      store->Index,
+                      _mesa_swizzle_string(store->Swizzle, 0, 0));
+
+      if (store->File == PROGRAM_SAMPLER) {
+         /* samplers have no storage */
+         continue;
+      }
+
+      if (store->Size == 1)
+         comp = GET_SWZ(store->Swizzle, 0);
+      else
+         comp = 0;
+
+      /* store->Index may be -1 if we run out of registers */
+      if (store->Index >= 0) {
+         for (j = 0; j < store->Size; j++) {
+            assert(t->Temps[store->Index * 4 + j + comp] == VAR);
+            t->Temps[store->Index * 4 + j + comp] = FREE;
+         }
+      }
+      store->Index = -1;
+   }
+   if (t->Parent) {
+      /* just verify that any remaining allocations in this scope 
+       * were for temps
+       */
+      for (i = 0; i < (int) vt->MaxRegisters * 4; i++) {
+         if (t->Temps[i] != FREE && t->Parent->Temps[i] == FREE) {
+            if (dbg) printf("  Free reg %d\n", i/4);
+            assert(t->Temps[i] == TEMP);
+         }
+      }
+   }
+
+   if (t->Vars) {
+      _slang_free(t->Vars);
+      t->Vars = NULL;
+   }
+
+   vt->Top = t->Parent;
+   _slang_free(t);
+   vt->CurLevel--;
+}
+
+
+/**
+ * Add a new variable to the given var/symbol table.
+ */
+void
+_slang_add_variable(slang_var_table *vt, slang_variable *v)
+{
+   struct table *t;
+   assert(vt);
+   t = vt->Top;
+   assert(t);
+   if (dbg) printf("Adding var %s, store %p\n", (char *) v->a_name, (void *) v->store);
+   t->Vars = (slang_variable **)
+      _slang_realloc(t->Vars,
+                     t->NumVars * sizeof(slang_variable *),
+                     (t->NumVars + 1) * sizeof(slang_variable *));
+   t->Vars[t->NumVars] = v;
+   t->NumVars++;
+}
+
+
+/**
+ * Look for variable by name in given table.
+ * If not found, Parent table will be searched.
+ */
+slang_variable *
+_slang_find_variable(const slang_var_table *vt, slang_atom name)
+{
+   struct table *t = vt->Top;
+   while (1) {
+      int i;
+      for (i = 0; i < t->NumVars; i++) {
+         if (t->Vars[i]->a_name == name)
+            return t->Vars[i];
+      }
+      if (t->Parent)
+         t = t->Parent;
+      else
+         return NULL;
+   }
+}
+
+
+/**
+ * Allocation helper.
+ * \param size  var size in floats
+ * \return  position for var, measured in floats
+ */
+static GLint
+alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
+{
+   struct table *t = vt->Top;
+   /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
+   const GLuint step = (size == 1) ? 1 : 4;
+   GLuint i, j;
+   assert(size > 0); /* number of floats */
+
+   for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) {
+      GLuint found = 0;
+      for (j = 0; j < (GLuint) size; j++) {
+         assert(i + j < 4 * MAX_PROGRAM_TEMPS);
+         if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) {
+            found++;
+         }
+         else {
+            break;
+         }
+      }
+      if (found == size) {
+         /* found block of size free regs */
+         if (size > 1)
+            assert(i % 4 == 0);
+         for (j = 0; j < (GLuint) size; j++) {
+            assert(i + j < 4 * MAX_PROGRAM_TEMPS);
+            t->Temps[i + j] = isTemp ? TEMP : VAR;
+         }
+         assert(i < MAX_PROGRAM_TEMPS * 4);
+         t->ValSize[i] = size;
+         return i;
+      }
+   }
+
+   /* if we get here, we ran out of registers */
+   return -1;
+}
+
+
+/**
+ * Allocate temp register(s) for storing a variable.
+ * \param size  size needed, in floats
+ * \param swizzle  returns swizzle mask for accessing var in register
+ * \return  register allocated, or -1
+ */
+GLboolean
+_slang_alloc_var(slang_var_table *vt, slang_ir_storage *store)
+{
+   struct table *t = vt->Top;
+   int i;
+
+   if (store->File == PROGRAM_SAMPLER) {
+      /* don't really allocate storage */
+      store->Index = 0;
+      return GL_TRUE;
+   }
+
+   i = alloc_reg(vt, store->Size, GL_FALSE);
+   if (i < 0)
+      return GL_FALSE;
+
+   store->Index = i / 4;
+   store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
+
+   if (dbg)
+      printf("Alloc var storage sz %d at %d.%s (level %d) store %p\n",
+             store->Size, store->Index,
+             _mesa_swizzle_string(store->Swizzle, 0, 0),
+             t->Level,
+             (void*) store);
+
+   return GL_TRUE;
+}
+
+
+
+/**
+ * Allocate temp register(s) for storing an unnamed intermediate value.
+ */
+GLboolean
+_slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store)
+{
+   struct table *t = vt->Top;
+   const int i = alloc_reg(vt, store->Size, GL_TRUE);
+   if (i < 0)
+      return GL_FALSE;
+
+   assert(store->Index < 0);
+
+   store->Index = i / 4;
+   store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
+
+   if (dbg) printf("Alloc temp sz %d at %d.%s (level %d) store %p\n",
+                   store->Size, store->Index,
+                   _mesa_swizzle_string(store->Swizzle, 0, 0), t->Level,
+                   (void *) store);
+
+   return GL_TRUE;
+}
+
+
+void
+_slang_free_temp(slang_var_table *vt, slang_ir_storage *store)
+{
+   struct table *t = vt->Top;
+   GLuint i;
+   GLint r = store->Index;
+   assert(store->Size > 0);
+   assert(r >= 0);
+   assert((GLuint)r + store->Size <= vt->MaxRegisters * 4);
+   if (dbg) printf("Free temp sz %d at %d.%s (level %d) store %p\n",
+                   store->Size, r,
+                   _mesa_swizzle_string(store->Swizzle, 0, 0),
+                   t->Level, (void *) store);
+   if (store->Size == 1) {
+      const GLuint comp = GET_SWZ(store->Swizzle, 0);
+      /* we can actually fail some of these assertions because of the
+       * troublesome IR_SWIZZLE handling.
+       */
+#if 0
+      assert(store->Swizzle == MAKE_SWIZZLE4(comp, comp, comp, comp));
+      assert(comp < 4);
+      assert(t->ValSize[r * 4 + comp] == 1);
+#endif
+      assert(t->Temps[r * 4 + comp] == TEMP);
+      t->Temps[r * 4 + comp] = FREE;
+   }
+   else {
+      /*assert(store->Swizzle == SWIZZLE_NOOP);*/
+      assert(t->ValSize[r*4] == store->Size);
+      for (i = 0; i < (GLuint) store->Size; i++) {
+         assert(t->Temps[r * 4 + i] == TEMP);
+         t->Temps[r * 4 + i] = FREE;
+      }
+   }
+}
+
+
+GLboolean
+_slang_is_temp(const slang_var_table *vt, const slang_ir_storage *store)
+{
+   struct table *t = vt->Top;
+   GLuint comp;
+   assert(store->Index >= 0);
+   assert(store->Index < (int) vt->MaxRegisters);
+   if (store->Swizzle == SWIZZLE_NOOP)
+      comp = 0;
+   else
+      comp = GET_SWZ(store->Swizzle, 0);
+
+   if (t->Temps[store->Index * 4 + comp] == TEMP)
+      return GL_TRUE;
+   else
+      return GL_FALSE;
+}
diff --git a/src/mesa/slang/slang_vartable.h b/src/mesa/slang/slang_vartable.h
new file mode 100644 (file)
index 0000000..94bcd63
--- /dev/null
@@ -0,0 +1,42 @@
+
+#ifndef SLANG_VARTABLE_H
+#define SLANG_VARTABLE_H
+
+struct slang_ir_storage_;
+
+typedef struct slang_var_table_ slang_var_table;
+
+struct slang_variable_;
+
+extern slang_var_table *
+_slang_new_var_table(GLuint maxRegisters);
+
+extern void
+_slang_delete_var_table(slang_var_table *vt);
+
+extern void
+_slang_push_var_table(slang_var_table *parent);
+
+extern void
+_slang_pop_var_table(slang_var_table *t);
+
+extern void
+_slang_add_variable(slang_var_table *t, struct slang_variable_ *v);
+
+extern struct slang_variable_ *
+_slang_find_variable(const slang_var_table *t, slang_atom name);
+
+extern GLboolean
+_slang_alloc_var(slang_var_table *t, struct slang_ir_storage_ *store);
+
+extern GLboolean
+_slang_alloc_temp(slang_var_table *t, struct slang_ir_storage_ *store);
+
+extern void
+_slang_free_temp(slang_var_table *t, struct slang_ir_storage_ *store);
+
+extern GLboolean
+_slang_is_temp(const slang_var_table *t, const struct slang_ir_storage_ *store);
+
+
+#endif /* SLANG_VARTABLE_H */
index 38b781cb4cef9221e452913c165429cc4dbf9f9b..236baf5e2f8a808016f3fcf001a6e1921ea96760 100644 (file)
@@ -251,25 +251,25 @@ SHADER_SOURCES = \
        shader/symbol_table.c
 
 SLANG_SOURCES =        \
-       shader/slang/slang_builtin.c    \
-       shader/slang/slang_codegen.c    \
-       shader/slang/slang_compile.c    \
-       shader/slang/slang_compile_function.c   \
-       shader/slang/slang_compile_operation.c  \
-       shader/slang/slang_compile_struct.c     \
-       shader/slang/slang_compile_variable.c   \
-       shader/slang/slang_emit.c       \
-       shader/slang/slang_ir.c \
-       shader/slang/slang_label.c      \
-       shader/slang/slang_link.c       \
-       shader/slang/slang_log.c        \
-       shader/slang/slang_mem.c        \
-       shader/slang/slang_print.c      \
-       shader/slang/slang_simplify.c   \
-       shader/slang/slang_storage.c    \
-       shader/slang/slang_typeinfo.c   \
-       shader/slang/slang_vartable.c   \
-       shader/slang/slang_utility.c
+       slang/slang_builtin.c   \
+       slang/slang_codegen.c   \
+       slang/slang_compile.c   \
+       slang/slang_compile_function.c  \
+       slang/slang_compile_operation.c \
+       slang/slang_compile_struct.c    \
+       slang/slang_compile_variable.c  \
+       slang/slang_emit.c      \
+       slang/slang_ir.c        \
+       slang/slang_label.c     \
+       slang/slang_link.c      \
+       slang/slang_log.c       \
+       slang/slang_mem.c       \
+       slang/slang_print.c     \
+       slang/slang_simplify.c  \
+       slang/slang_storage.c   \
+       slang/slang_typeinfo.c  \
+       slang/slang_vartable.c  \
+       slang/slang_utility.c
 
 ASM_C_SOURCES =        \
        x86/common_x86.c \