From a0af473a8bedbff4df6152bc6732ed6548a96150 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Wed, 12 Dec 2012 21:15:54 +0000 Subject: [PATCH] Create a base GLSL front-end from the 3Dlabs glslang front-end from 20-Sep-2005. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@19944 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- BuildLinux.sh | 13 + OGLCompilersDLL/InitializeDll.cpp | 149 ++ OGLCompilersDLL/InitializeDll.h | 47 + OGLCompilersDLL/Makefile | 53 + README.txt | 337 +++ StandAlone.sln | 28 + StandAlone.vcproj | 145 ++ StandAlone/Makefile | 40 + StandAlone/StandAlone.cpp | 366 ++++ StandAlone/sample.frag | 40 + StandAlone/sample.frag.out | 15 + StandAlone/sample.vert | 42 + StandAlone/sample.vert.out | 20 + glslang.vcproj | 436 ++++ glslang/GenericCodeGen/CodeGen.cpp | 75 + glslang/GenericCodeGen/Link.cpp | 91 + glslang/GenericCodeGen/Makefile | 34 + glslang/Include/BaseTypes.h | 137 ++ glslang/Include/Common.h | 192 ++ glslang/Include/ConstantUnion.h | 315 +++ glslang/Include/InfoSink.h | 137 ++ glslang/Include/InitializeGlobals.h | 43 + glslang/Include/InitializeParseContext.h | 45 + glslang/Include/PoolAlloc.h | 349 +++ glslang/Include/ResourceLimits.h | 52 + glslang/Include/ShHandle.h | 169 ++ glslang/Include/Types.h | 322 +++ glslang/Include/intermediate.h | 522 +++++ glslang/MachineIndependent/InfoSink.cpp | 107 + glslang/MachineIndependent/Initialize.cpp | 962 ++++++++ glslang/MachineIndependent/Initialize.h | 63 + glslang/MachineIndependent/IntermTraverse.cpp | 243 ++ glslang/MachineIndependent/Intermediate.cpp | 1514 +++++++++++++ glslang/MachineIndependent/MMap.h | 84 + glslang/MachineIndependent/Makefile | 161 ++ glslang/MachineIndependent/ParseHelper.cpp | 1494 +++++++++++++ glslang/MachineIndependent/ParseHelper.h | 150 ++ glslang/MachineIndependent/PoolAlloc.cpp | 342 +++ glslang/MachineIndependent/QualifierAlive.cpp | 91 + glslang/MachineIndependent/QualifierAlive.h | 35 + glslang/MachineIndependent/RemoveTree.cpp | 98 + glslang/MachineIndependent/RemoveTree.h | 35 + glslang/MachineIndependent/ShaderLang.cpp | 586 +++++ glslang/MachineIndependent/SymbolTable.cpp | 245 +++ glslang/MachineIndependent/SymbolTable.h | 318 +++ glslang/MachineIndependent/glslang.l | 637 ++++++ glslang/MachineIndependent/glslang.y | 2317 ++++++++++++++++++++ glslang/MachineIndependent/intermOut.cpp | 491 +++++ glslang/MachineIndependent/localintermediate.h | 86 + glslang/MachineIndependent/parseConst.cpp | 266 +++ glslang/MachineIndependent/preprocessor/Makefile | 38 + glslang/MachineIndependent/preprocessor/atom.c | 768 +++++++ glslang/MachineIndependent/preprocessor/atom.h | 96 + glslang/MachineIndependent/preprocessor/compile.h | 132 ++ glslang/MachineIndependent/preprocessor/cpp.c | 1037 +++++++++ glslang/MachineIndependent/preprocessor/cpp.h | 119 + .../MachineIndependent/preprocessor/cppstruct.c | 185 ++ glslang/MachineIndependent/preprocessor/memory.c | 191 ++ glslang/MachineIndependent/preprocessor/memory.h | 89 + glslang/MachineIndependent/preprocessor/parser.h | 126 ++ .../MachineIndependent/preprocessor/preprocess.h | 84 + glslang/MachineIndependent/preprocessor/scanner.c | 794 +++++++ glslang/MachineIndependent/preprocessor/scanner.h | 118 + .../MachineIndependent/preprocessor/slglobals.h | 115 + glslang/MachineIndependent/preprocessor/symbols.c | 318 +++ glslang/MachineIndependent/preprocessor/symbols.h | 145 ++ glslang/MachineIndependent/preprocessor/tokens.c | 472 ++++ glslang/MachineIndependent/preprocessor/tokens.h | 122 ++ glslang/MachineIndependent/unistd.h | 1 + glslang/OSDependent/Linux/Makefile | 62 + glslang/OSDependent/Linux/osinclude.h | 78 + glslang/OSDependent/Linux/ossource.cpp | 141 ++ glslang/OSDependent/Windows/main.cpp | 69 + glslang/OSDependent/Windows/osinclude.h | 69 + glslang/OSDependent/Windows/ossource.cpp | 85 + glslang/Public/ShaderLang.h | 212 ++ tools/bison.exe | Bin 0 -> 196096 bytes tools/bison.hairy | 334 +++ tools/bison.simple | 699 ++++++ tools/flex.exe | Bin 0 -> 181248 bytes 80 files changed, 21238 insertions(+) create mode 100755 BuildLinux.sh create mode 100644 OGLCompilersDLL/InitializeDll.cpp create mode 100644 OGLCompilersDLL/InitializeDll.h create mode 100644 OGLCompilersDLL/Makefile create mode 100644 README.txt create mode 100644 StandAlone.sln create mode 100644 StandAlone.vcproj create mode 100644 StandAlone/Makefile create mode 100644 StandAlone/StandAlone.cpp create mode 100644 StandAlone/sample.frag create mode 100644 StandAlone/sample.frag.out create mode 100644 StandAlone/sample.vert create mode 100644 StandAlone/sample.vert.out create mode 100644 glslang.vcproj create mode 100644 glslang/GenericCodeGen/CodeGen.cpp create mode 100644 glslang/GenericCodeGen/Link.cpp create mode 100644 glslang/GenericCodeGen/Makefile create mode 100644 glslang/Include/BaseTypes.h create mode 100644 glslang/Include/Common.h create mode 100644 glslang/Include/ConstantUnion.h create mode 100644 glslang/Include/InfoSink.h create mode 100644 glslang/Include/InitializeGlobals.h create mode 100644 glslang/Include/InitializeParseContext.h create mode 100644 glslang/Include/PoolAlloc.h create mode 100644 glslang/Include/ResourceLimits.h create mode 100644 glslang/Include/ShHandle.h create mode 100644 glslang/Include/Types.h create mode 100644 glslang/Include/intermediate.h create mode 100644 glslang/MachineIndependent/InfoSink.cpp create mode 100644 glslang/MachineIndependent/Initialize.cpp create mode 100644 glslang/MachineIndependent/Initialize.h create mode 100644 glslang/MachineIndependent/IntermTraverse.cpp create mode 100644 glslang/MachineIndependent/Intermediate.cpp create mode 100644 glslang/MachineIndependent/MMap.h create mode 100644 glslang/MachineIndependent/Makefile create mode 100644 glslang/MachineIndependent/ParseHelper.cpp create mode 100644 glslang/MachineIndependent/ParseHelper.h create mode 100644 glslang/MachineIndependent/PoolAlloc.cpp create mode 100644 glslang/MachineIndependent/QualifierAlive.cpp create mode 100644 glslang/MachineIndependent/QualifierAlive.h create mode 100644 glslang/MachineIndependent/RemoveTree.cpp create mode 100644 glslang/MachineIndependent/RemoveTree.h create mode 100644 glslang/MachineIndependent/ShaderLang.cpp create mode 100644 glslang/MachineIndependent/SymbolTable.cpp create mode 100644 glslang/MachineIndependent/SymbolTable.h create mode 100644 glslang/MachineIndependent/glslang.l create mode 100644 glslang/MachineIndependent/glslang.y create mode 100644 glslang/MachineIndependent/intermOut.cpp create mode 100644 glslang/MachineIndependent/localintermediate.h create mode 100644 glslang/MachineIndependent/parseConst.cpp create mode 100644 glslang/MachineIndependent/preprocessor/Makefile create mode 100644 glslang/MachineIndependent/preprocessor/atom.c create mode 100644 glslang/MachineIndependent/preprocessor/atom.h create mode 100644 glslang/MachineIndependent/preprocessor/compile.h create mode 100644 glslang/MachineIndependent/preprocessor/cpp.c create mode 100644 glslang/MachineIndependent/preprocessor/cpp.h create mode 100644 glslang/MachineIndependent/preprocessor/cppstruct.c create mode 100644 glslang/MachineIndependent/preprocessor/memory.c create mode 100644 glslang/MachineIndependent/preprocessor/memory.h create mode 100644 glslang/MachineIndependent/preprocessor/parser.h create mode 100644 glslang/MachineIndependent/preprocessor/preprocess.h create mode 100644 glslang/MachineIndependent/preprocessor/scanner.c create mode 100644 glslang/MachineIndependent/preprocessor/scanner.h create mode 100644 glslang/MachineIndependent/preprocessor/slglobals.h create mode 100644 glslang/MachineIndependent/preprocessor/symbols.c create mode 100644 glslang/MachineIndependent/preprocessor/symbols.h create mode 100644 glslang/MachineIndependent/preprocessor/tokens.c create mode 100644 glslang/MachineIndependent/preprocessor/tokens.h create mode 100644 glslang/MachineIndependent/unistd.h create mode 100644 glslang/OSDependent/Linux/Makefile create mode 100644 glslang/OSDependent/Linux/osinclude.h create mode 100644 glslang/OSDependent/Linux/ossource.cpp create mode 100644 glslang/OSDependent/Windows/main.cpp create mode 100644 glslang/OSDependent/Windows/osinclude.h create mode 100644 glslang/OSDependent/Windows/ossource.cpp create mode 100644 glslang/Public/ShaderLang.h create mode 100644 tools/bison.exe create mode 100644 tools/bison.hairy create mode 100644 tools/bison.simple create mode 100644 tools/flex.exe diff --git a/BuildLinux.sh b/BuildLinux.sh new file mode 100755 index 0000000..1abd9c5 --- /dev/null +++ b/BuildLinux.sh @@ -0,0 +1,13 @@ +#! /bin/bash + +# build the StandAlone app and all it's dependencies +make -C StandAlone + +# so we can find the shared library +LD_LIBRARY_PATH=`pwd`/glslang/MachineIndependent/lib:${LD_LIBRARY_PATH} +export LD_LIBRARY_PATH + +# run using test data +cd StandAlone +./StandAlone -i sample.vert sample.frag + diff --git a/OGLCompilersDLL/InitializeDll.cpp b/OGLCompilersDLL/InitializeDll.cpp new file mode 100644 index 0000000..8804ae8 --- /dev/null +++ b/OGLCompilersDLL/InitializeDll.cpp @@ -0,0 +1,149 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#define SH_EXPORTING + +#include "InitializeDll.h" +#include "Include/InitializeGlobals.h" +#include "Include/InitializeParseContext.h" + +#include "Public/ShaderLang.h" + +OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX; + +bool InitProcess() +{ + if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) { + // + // Function is re-entrant. + // + return true; + } + + ThreadInitializeIndex = OS_AllocTLSIndex(); + + if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "InitProcess(): Failed to allocate TLS area for init flag"); + return false; + } + + + if (!InitializePoolIndex()) { + assert(0 && "InitProcess(): Failed to initalize global pool"); + return false; + } + + if (!InitializeParseContextIndex()) { + assert(0 && "InitProcess(): Failed to initalize parse context"); + return false; + } + + InitThread(); + return true; +} + + +bool InitThread() +{ + // + // This function is re-entrant + // + if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "InitThread(): Process hasn't been initalised."); + return false; + } + + if (OS_GetTLSValue(ThreadInitializeIndex) != 0) + return true; + + InitializeGlobalPools(); + + if (!InitializeGlobalParseContext()) + return false; + + if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) { + assert(0 && "InitThread(): Unable to set init flag."); + return false; + } + + return true; +} + + +bool DetachThread() +{ + bool success = true; + + if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) + return true; + + // + // Function is re-entrant and this thread may not have been initalised. + // + if (OS_GetTLSValue(ThreadInitializeIndex) != 0) { + if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) { + assert(0 && "DetachThread(): Unable to clear init flag."); + success = false; + } + + FreeGlobalPools(); + + if (!FreeParseContext()) + success = false; + } + + return success; +} + +bool DetachProcess() +{ + bool success = true; + + if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) + return true; + + ShFinalize(); + + success = DetachThread(); + + FreePoolIndex(); + + if (!FreeParseContextIndex()) + success = false; + + OS_FreeTLSIndex(ThreadInitializeIndex); + ThreadInitializeIndex = OS_INVALID_TLS_INDEX; + + return success; +} diff --git a/OGLCompilersDLL/InitializeDll.h b/OGLCompilersDLL/InitializeDll.h new file mode 100644 index 0000000..f1ea567 --- /dev/null +++ b/OGLCompilersDLL/InitializeDll.h @@ -0,0 +1,47 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +#ifndef __INITIALIZEDLL_H +#define __INITIALIZEDLL_H + + +#include "osinclude.h" + + +bool InitProcess(); +bool InitThread(); +bool DetachThread(); +bool DetachProcess(); + +#endif // __INITIALIZEDLL_H + diff --git a/OGLCompilersDLL/Makefile b/OGLCompilersDLL/Makefile new file mode 100644 index 0000000..f45495b --- /dev/null +++ b/OGLCompilersDLL/Makefile @@ -0,0 +1,53 @@ +INCLUDE = -I. -I../glslang -I../glslang/Include -I../glslang/OSDependent/Linux -I../glslang/MachineIndependent +WARNINGS = -Wall -Wwrite-strings -Wpointer-arith -Wcast-align -Wstrict-prototypes \ + -Wnested-externs +DEFINE = -Dlinux -D__i386__ + +CPP = g++ +CPPOPTIONS = -O3 -Wno-deprecated -D_ALT_NS=1 +CPPOPTIONS = -g -Wno-deprecated -D_ALT_NS=1 +CPPFLAGS = $(CPPOPTIONS) $(DEFINE) $(INCLUDE) + +# +# Linking related +# +AR = ar +STATIC_OPTION = rcs + +# +# Misc +# +export PERL = perl +export RM = rm -f +export MV = mv -f +export DEPEND = g++ -M + +# +# Object file variables are defined here. +# +OSSRCS = InitializeDll.cpp +OSOBJS = InitializeDll.o + +LIBNAME = libInitializeDll.a + +all : $(LIBNAME) + +$(LIBNAME) : $(OSOBJS) + $(AR) $(STATIC_OPTION) $(LIBNAME) $(OSOBJS) + +%.o : %.cpp + $(CPP) $(CPPFLAGS) -c $< + +# +# Dependency +# +depend : $(OSSRCS) + $(DEPEND) $(CPPFLAGS) $(OSSRCS) > depend +include depend + +# +# Cleanup +# +.PHONY : clean +clean : + $(RM) *.o *.a diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..b7ab72f --- /dev/null +++ b/README.txt @@ -0,0 +1,337 @@ +OpenGL Shading Language source readme for Window and Linux + +Version: Sept 20, 2005 + + +Source Copyright +---------------- + + +Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + Neither the name of 3Dlabs Inc. Ltd. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +Changes since June 2005 Release +------------------------------- +- Some infrastructure is simplified, improved, and cleaned up. Details follow. + +- TPublicType is easier to setup and extend. + +- Constant values know their own types. Methods are added to set the +constant values as the data members are now protected instead of public. +Lots of code was cleaned up because of that. + +- Added support for an array object extension. Array constructors are +allowed. Constant arrays can be declared and parse time constant folding +and propagation is done through array objects. Extension GL_3DL_array_objects +must be enabled to use the array objects. + +- Arrays and structures are handled more uniformly. Sizing is simplified and improved. + +- Changed the implementation of the way constants values were stored in +the parse tree. Constants are now always flattened out. Constructors with +constant values are represented with constant values directly. Example mat2(1) +is stored as a constant node with values 1.0, 0.0, 0.0, 1.0. Earlier this +was stored as an aggregate node with correct operator and a single constant +value 1.0. This change caused a lot of code to be cleaned up and simplified. + +- Renamed ARB texture rectangle functions to match the final version of the specification. + + +Changes since Feb 2005 Release +------------------------------ +- Source now compiles on gcc 3.4.4. +- Fixed constant folding for ternary operator. +- Non-dereferenced arrays not allowed in constructors. Other semantic +error checking on arrays such as ++array, array1 = array2. +- Max allowed index for gl_TexCoord is gl_MaxTextureCoords - 1. +- Raise an error when one of the string passed to the parser is a NULL +pointer. +- Parser code tested to be portable on STLport stl. +- Detect error when preprocessor directives does not begin at the start +of the line. + +Please feel free to submit any fixes to the parser code. + + +Changes since Jan 2005 Release +------------------------------ +- Relaxed grammar rules for ?: (ternary operator) to allow assignment +expressions after the ':'. +- Fixed the correct parsing of empty shader source string. +- No longer raise an error when gl_Position is not written in a vertex +shader. This is link time functionality. +- Added some basic support for MSVC++6.0 to the extent that C++ standards +are not violated. + + +Changes since Sept 2004 Release +------------------------------- +- Memory usage by builtIn symbol table level is reduced to 1/4th of what +was used earlier. +- Built In symbol table level is split into two, the first level contains +symbols that do not change and the second level is constructed per compile, +based on the resource values specified by the driver. This required ShCompile +method to take in a pointer to the resource values. +- Correct handling of pragmas. +- Fixed defects such as comma operator folding, swizzling allowed only with +offsets from same set, texture look up functions appropriately split between +vertex and fragment shaders, ternary operator type checking, preprocessor +directives etc. +- Linux build now use flex version 2.5.4 that comes with Redhat 9.0 + + +Changes since July 2004 Release +------------------------------- +- Structures when initialized both as a constant and a non constant were broken. + + +Changes Since Apr 2004 Release +------------------------------- +- Added support for #extension and #version preprocessor directives. +- Removed printf statements and instead dump messages on InfoSink. +- Most of the source code is now thread safe except for some of the +preprocessor code. Also For Linux, the per thread data clean up is yet to be +implemented as it is not exactly known when the thread exits. +- Fixed comma operator when used with constant initializer. +- Added folding when constructors are called with constant values. +- Correctly updated builtIn names for texture functions from +texture{1|2}DShadow[Proj][Lod] to shadow{1|2}D[Proj][Lod]. +- Updated the built-in constant names as per latest GL2 specs. +- Portable across more platforms. + + +Changes Since Oct 2003 Release +------------------------------- +- Added new reserved keywords. Also reserved %=. +- Fixed some bugs and memory leaks in the preprocessor. +- Fixed name mangling for function names. Names also now include array sizes. +- Fixed implementation of unsized arrays. +- Constructors: Disallow matrices constructed from matrices, and unused +arguments. + Also fixed some cases like float(vec2) that were not working right. +- TILDA -> TILDE. +- Fixed structure qualifier semantics: they apply to variables declared, +not the structure definition. + + +Changes since May 2003 Release +------------------------------- + +- Corrected some bugs in preprocessor. +- Keeping track of maximum size of the array used in the source code. +- Parameter passing during function call and keeping track of inout and out +parameters. +- Added some more built in functions. +- Portability to Linux + + +Changes Since April 2002 Release +-------------------------------- + +* Semantic changes to bring the implementation and spec closer together, + and support issue resolution. + +* Some minor functionality completeness. + + - User function calls are more complete, + - added the ^^ operator (logical exclusive or) + - fixed variable scoping in if-else + - no declarations in if-conditions + - improved typing of field selectors + - removed suffixes from literal constants + - many smaller semantic changes to be in line with the current spec + - added preprocessor + - added non-scalar constants + - added structures + + +Changes since July 2002 Release +------------------------------- + +Brought up to date with version 1.051 of the OpenGL Shading Language +Specification. It is now almost complete. The list of detailed +changes would be long, as the specification has changed extensively, +and all missing functionality has been added. + + +Procedure to Build on Windows +----------------------------- + +Put this project in a path name without spaces. + +procedure To build using MS visual studio .Net. + +It has two projects. +The glslang project must be compiled first, followed by the +StandAlone project. + +1. The solution is StandAlone.sln. The two necessary +projects are glslang.vcproj and StandAlone.vcproj, +which devstudio will automatically open. + +2. You may have a missing header file, unistd.h. Create an empty one in +some standard devstudio or SDK system include directory. (Bison/flex +generate a #include , this makes them happy.) + +3. Build the glslang project (in devstudio, right click the glslang project +and build). This creates the glslang.dll and glslang.lib files needed to +make the StandAlone compiler run. It leaves them in the StandAlone +directory. + +4. Build the StandAlone project if you want to run the tests or run the +compiler stand-alone. + + +Running Stand Alone on Windows +------------------------------ + +The build process should create glslang.dll and StandAlone.exe. glslang.dll +has an interface suitable for integration with an ICD. StandAlone.exe uses +this interface to create a version of the compiler that can run outside +the ICD environment. + +The stand-alone compiler is a Win32 console application, best executed +from a command prompt. + +“cd” into the StandAlone directory, or a directory you've installed +StandAlone.exe, the OglBuiltIns subdirectory, and glslang.dll into. + +The normal case will be to compile and link a pair of shaders like this: + + StandAlone -i .vert .frag + + where the following command line options are possible for StandAlone: + i - dump parse tree + m - dump linker output (nothing dumped in the source code provided) + a - dump assembly code (nothing dumped in the source code provided) + +The applied compilation-language is based on the file extension. +Give the full name of the files containing the shader source code. +The output from running this will contain compile and link errors, as +well as a textual version of the intermediate representation. + + +Procedure to build and run on Linux +----------------------------------- + +A simple bash script "BuildLinux.sh" is provided to do the build and run the test +cases, or you may run the steps manually as described below: + +"cd" into StandAlone directory and run make. It will build all the dependency +directories also. You can also go to the specific directories and do a make for each +directory individually. Make sure that there exists a lib directory at the given +path: glslang/MachineIndependent/lib where libglslang.so is stored. + +To compile glslang.l, flex version 2.5.31 is required. An executable of flex is +provided in tools directory. To compile glslang.y, bison version 1.35 or higher is +required. Most versions of Red Hat comes with bison 1.35. + +Once the executable is generated, it needs to be dynamically linked with the +shared object created in lib directory. To achieve that, we need to "cd" to +StandAlone directory to update the LD_LIBRARY_PATH as follows + +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./../glslang/MachineIndependent/lib + +You can also update LD_LIBRARY_PATH in the .cshrc or .bashrc file, depending on +the shell you are using. You will need to give the complete path of "lib" directory +in .cshrc or .bashrc files. + +The normal case will be to compile and link a pair of shaders like this: + + ./StandAlone -i .vert .frag + + where the following command line options are possible for StandAlone: + i - dump parse tree + m - dump linker output (nothing dumped in the source code provided) + a - dump assembly code (nothing dumped in the source code provided) + +The applied compilation-language is based on the file extension. +Give the full name of the files containing the shader source code. +The output from running this will contain compile and link errors, as +well as a textual version of the intermediate representation. + +To generate the dependencies, you can run "make depend". +This step has already been done and need not be done again by the user. + +To clean the ".o"s, ".a"s and ".so" generated by make, you can use "make clean". + + +Notes for Understanding/Modifying the Code +------------------------------------------ + +* This is completely machine independent code. We have a working + back-end card-specific compiler that is not present. Instead, a trivial + back-end compiler is in the directory GenericCodeGen. + +* The main directory for parsing and intermediate representation is + MachineIndependent. + +* Header files shared between machine independent parsing and the + machine dependent compiling and linking are in include. + +* Header files shared between the compiler and an ICD are in public. + +* Merging with future updates will be easiest if initially you confine + your changes to the GenericCodeGen directory. + +* To write a back-end compiler, see the next section on Basic Design. + + +Basic Design +------------ + +1. Code is parsed by flex/bison, with the aid of a symbol table and an + intermediate representation. The symbol table is not passed on to + the back-end; the intermediate representation stands on its own. + +2. The intermediate representation is very high-level, and represented + as an in-memory tree. This serves to lose no information from the + original program, and to have efficient transfer of the result from + parsing to the back-end. In the intermediate representation, + constants are propogated and folded, and some dead code is eliminated. + +3. The primary algorithm of the back-end compiler is to traverse the + tree (high-level intermediate representation), and create an internal + object code representation. There is a query in the compiler interface + to the ICD for retrieval of this object code. + +4. Reduction of the tree to a linear byte-code style low-level intermediate + representation is likely a good way to generate fully optimized code. + There is some possibility of standardizing such a byte code. + +See these files to get started: + +* IntermOut.cpp: this shows traversing the tree to generate output. +* CodeGen.cpp: this shows the basic interface to the back-end compiler. +* Link.cpp: this shows the basic interface to the linker. +* Intermediate.h: to see the data structures backing the tree. + diff --git a/StandAlone.sln b/StandAlone.sln new file mode 100644 index 0000000..b2f325a --- /dev/null +++ b/StandAlone.sln @@ -0,0 +1,28 @@ +Microsoft Visual Studio Solution File, Format Version 7.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tests - StandAlone", "StandAlone.vcproj", "{660D0A05-69A9-4F09-9664-02FBEB08FAE2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Targets - glslang (generic)", "glslang.vcproj", "{3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}" +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = UserM_Debug + ConfigName.1 = UserM_Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + {660D0A05-69A9-4F09-9664-02FBEB08FAE2}.0 = {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3} + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {660D0A05-69A9-4F09-9664-02FBEB08FAE2}.UserM_Debug.ActiveCfg = UserM_Debug|Win32 + {660D0A05-69A9-4F09-9664-02FBEB08FAE2}.UserM_Debug.Build.0 = UserM_Debug|Win32 + {660D0A05-69A9-4F09-9664-02FBEB08FAE2}.UserM_Release.ActiveCfg = UserM_Release|Win32 + {660D0A05-69A9-4F09-9664-02FBEB08FAE2}.UserM_Release.Build.0 = UserM_Release|Win32 + {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.UserM_Debug.ActiveCfg = UserM_Debug|Win32 + {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.UserM_Debug.Build.0 = UserM_Debug|Win32 + {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.UserM_Release.ActiveCfg = UserM_Release|Win32 + {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.UserM_Release.Build.0 = UserM_Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/StandAlone.vcproj b/StandAlone.vcproj new file mode 100644 index 0000000..411a83c --- /dev/null +++ b/StandAlone.vcproj @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/StandAlone/Makefile b/StandAlone/Makefile new file mode 100644 index 0000000..80023b1 --- /dev/null +++ b/StandAlone/Makefile @@ -0,0 +1,40 @@ +CC=g++ +OBJECTPATH=./../glslang/MachineIndependent +LIBPATH=./../glslang/MachineIndependent/lib +SRCS=StandAlone.cpp + +TARGETOBJECT=StandAlone.o + +default: all + +all: StandAlone + +StandAlone: $(TARGETOBJECT) SHAREDOBJECT + $(CC) -g -o $@ $(TARGETOBJECT) -L $(LIBPATH) -lglslang -lpthread \ + -lm -lstdc++ + +SHAREDOBJECT: + cd $(OBJECTPATH); make all + +%.o : %.cpp + $(CC) -c $< + +# +# Cleanup +# +.PHONY : clean +clean : + $(RM) *.o StandAlone + cd $(OBJECTPATH); make clean + +depend: + cd $(OBJECTPATH); make depend + makedepend -Y -- $(SRCS) +# DO NOT DELETE + +StandAlone.o: ./../glslang/Include/ShHandle.h +StandAlone.o: ./../glslang/Public/ShaderLang.h +StandAlone.o: ./../glslang/Include/InfoSink.h ./../glslang/Include/Common.h +StandAlone.o: ./../glslang/Include/PoolAlloc.h +StandAlone.o: ./../glslang/Public/ShaderLang.h + diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp new file mode 100644 index 0000000..e970185 --- /dev/null +++ b/StandAlone/StandAlone.cpp @@ -0,0 +1,366 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +#include "./../glslang/Include/ShHandle.h" +#include "./../glslang/Public/ShaderLang.h" +#include +#include + +#ifdef _WIN32 + #include + #include +#endif + +extern "C" { + SH_IMPORT_EXPORT void ShOutputHtml(); +} + +//#define MEASURE_MEMORY + +// +// Return codes from main. +// +enum TFailCode { + ESuccess = 0, + EFailUsage, + EFailCompile, + EFailLink, + EFailCompilerCreate, + EFailLinkerCreate +}; + +// +// Just placeholders for testing purposes. The stand-alone environment +// can't actually do a full link without something specifying real +// attribute bindings. +// +ShBinding FixedAttributeBindings[] = { + { "gl_Vertex", 15 }, + { "gl_Color", 10 }, + { "gl_Normal", 7 }, +}; + +ShBindingTable FixedAttributeTable = { 3, FixedAttributeBindings }; + +static EShLanguage FindLanguage(char *lang); +bool CompileFile(char *fileName, ShHandle, int, const TBuiltInResource*); +void usage(); +void FreeFileData(char **data); +char** ReadFileData(char *fileName); +void InfoLogMsg(char* msg, const char* name, const int num); +int ShOutputMultipleStrings(char ** ); +//Added to accomodate the multiple strings. +int OutputMultipleStrings = 1; + +// +// Set up the per compile resources +// +void GenerateResources(TBuiltInResource& resources) +{ + resources.maxLights = 32; + resources.maxClipPlanes = 6; + resources.maxTextureUnits = 32; + resources.maxTextureCoords = 32; + resources.maxVertexAttribs = 64; + resources.maxVertexUniformComponents = 4096; + resources.maxVaryingFloats = 64; + resources.maxVertexTextureImageUnits = 32; + resources.maxCombinedTextureImageUnits = 32; + resources.maxTextureImageUnits = 32; + resources.maxFragmentUniformComponents = 4096; + resources.maxDrawBuffers = 32; +} + +int C_DECL main(int argc, char* argv[]) +{ + bool delay = false; + int numCompilers = 0; + bool compileFailed = false; + bool linkFailed = false; + int debugOptions = 0; + int i; + + ShHandle linker = 0; + ShHandle uniformMap = 0; + ShHandle compilers[EShLangCount]; + + ShInitialize(); + +#ifdef _WIN32 + __try { +#endif + argc--; + argv++; + for (; argc >= 1; argc--, argv++) { + if (argv[0][0] == '-' || argv[0][0] == '/') { + switch (argv[0][1]) { + case 'd': delay = true; break; + +#ifdef MEASURE_MEMORY + case 'i': break; + case 'a': break; + case 'h': break; +#else + case 'i': debugOptions |= EDebugOpIntermediate; break; + case 'a': debugOptions |= EDebugOpAssembly; break; +#endif + case 'c': if(!ShOutputMultipleStrings(++argv)) + return EFailUsage; + --argc; break; + case 'm': debugOptions |= EDebugOpLinkMaps; break; + default: usage(); return EFailUsage; + } + } else { + compilers[numCompilers] = ShConstructCompiler(FindLanguage(argv[0]), debugOptions); + if (compilers[numCompilers] == 0) + return EFailCompilerCreate; + ++numCompilers; + + TBuiltInResource resources; + GenerateResources(resources); + if (! CompileFile(argv[0], compilers[numCompilers-1], debugOptions, &resources)) + compileFailed = true; + } + } + + if (!numCompilers) { + usage(); + return EFailUsage; + } + + linker = ShConstructLinker(EShExVertexFragment, debugOptions); + if (linker == 0) + return EFailLinkerCreate; + + uniformMap = ShConstructUniformMap(); + if (uniformMap == 0) + return EFailLinkerCreate; + + if (numCompilers > 0) { + ShSetFixedAttributeBindings(linker, &FixedAttributeTable); + if (! ShLink(linker, compilers, numCompilers, uniformMap, 0, 0)) + linkFailed = true; + } + + for (i = 0; i < numCompilers; ++i) { + InfoLogMsg("BEGIN", "COMPILER", i); + puts(ShGetInfoLog(compilers[i])); + InfoLogMsg("END", "COMPILER", i); + } + + InfoLogMsg("BEGIN", "LINKER", -1); + puts(ShGetInfoLog(linker)); + InfoLogMsg("END", "LINKER", -1); + +#ifdef _WIN32 + } __finally { +#endif + for (i = 0; i < numCompilers; ++i) + ShDestruct(compilers[i]); + + ShDestruct(linker); + ShDestruct(uniformMap); + +#ifdef _WIN32 + if (delay) + Sleep(1000000); + + } +#endif + + if (compileFailed) + return EFailCompile; + if (linkFailed) + return EFailLink; + + return 0; +} + +// +// Deduce the language from the filename. Files must end in one of the +// following extensions: +// +// .frag* = fragment programs +// .vert* = vertex programs +// .pack* = pack programs +// .unpa* = unpack pragrams +// +static EShLanguage FindLanguage(char *name) +{ + if (!name) + return EShLangFragment; + + char *ext = strrchr(name, '.'); + + if (ext && strcmp(ext, ".sl") == 0) + for (; ext > name && ext[0] != '.'; ext--); + + if (ext = strrchr(name, '.')) { + if (strncmp(ext, ".frag", 4) == 0) return EShLangFragment; + if (strncmp(ext, ".vert", 4) == 0) return EShLangVertex; + if (strncmp(ext, ".pack", 4) == 0) return EShLangPack; + if (strncmp(ext, ".unpa", 4) == 0) return EShLangUnpack; + } + + return EShLangFragment; +} + + +// +// Read a file's data into a string, and compile it using ShCompile +// +bool CompileFile(char *fileName, ShHandle compiler, int debugOptions, const TBuiltInResource *resources) +{ + int ret; + char **data = ReadFileData(fileName); + +#ifdef MEASURE_MEMORY + PROCESS_MEMORY_COUNTERS counters; +#endif + + if (!data) + return false; + +#ifdef MEASURE_MEMORY + for (int i = 0; i < 1000; ++i) { + for (int j = 0; j < 100; ++j) +#endif + ret = ShCompile(compiler, data, OutputMultipleStrings, EShOptNone, resources, debugOptions); +#ifdef MEASURE_MEMORY + + GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)); + } +#endif + + FreeFileData(data); + + return ret ? true : false; +} + + +// +// print usage to stdout +// +void usage() +{ + printf("Usage: standalone [-i -a -c -m -d -h] file1 file2 ...\n" + "Where: filename = filename ending in .frag* or .vert*\n"); +} + + +// +// Malloc a string of sufficient size and read a string into it. +// +# define MAX_SOURCE_STRINGS 5 +char** ReadFileData(char *fileName) +{ + FILE *in = fopen(fileName, "r"); + char *fdata; + int count = 0; + char**return_data=(char**)malloc(MAX_SOURCE_STRINGS+1); + + //return_data[MAX_SOURCE_STRINGS]=NULL; + if (!in) { + printf("Error: unable to open input file: %s\n", fileName); + return 0; + } + + while (fgetc(in) != EOF) + count++; + + fseek(in, 0, SEEK_SET); + + + if (!(fdata = (char *)malloc(count+2))) { + printf("Error allocating memory\n"); + return 0; + } + if (fread(fdata,1,count, in)!=count) { + printf("Error reading input file: %s\n", fileName); + return 0; + } + fdata[count] = '\0'; + fclose(in); + if(count==0){ + return_data[0]=(char*)malloc(count+2); + return_data[0][0]='\0'; + OutputMultipleStrings=0; + return return_data; + } + + int len = (int)(ceil)((float)count/(float)OutputMultipleStrings); + int ptr_len=0,i=0; + while(count>0){ + return_data[i]=(char*)malloc(len+2); + memcpy(return_data[i],fdata+ptr_len,len); + return_data[i][len]='\0'; + count-=(len); + ptr_len+=(len); + if(count= 0 ? "#### %s %s %d INFO LOG ####\n" : + "#### %s %s INFO LOG ####\n", msg, name, num); +} + +int ShOutputMultipleStrings(char **argv) +{ + if(!(abs(OutputMultipleStrings = atoi(*argv)))||((OutputMultipleStrings >5 || OutputMultipleStrings < 1)? 1:0)){ + printf("Invalid Command Line Argument after -c option.\n" + "Usage: -c where integer =[1,5]\n" + "This option must be specified before the input file path\n"); + return 0; + } + return 1; +} diff --git a/StandAlone/sample.frag b/StandAlone/sample.frag new file mode 100644 index 0000000..0d11cb2 --- /dev/null +++ b/StandAlone/sample.frag @@ -0,0 +1,40 @@ +// +//Copyright (C) 2002-2004 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +varying vec3 color; + +void main() +{ + gl_FragColor = vec4(color, 1.0); +} diff --git a/StandAlone/sample.frag.out b/StandAlone/sample.frag.out new file mode 100644 index 0000000..5af223e --- /dev/null +++ b/StandAlone/sample.frag.out @@ -0,0 +1,15 @@ +#### BEGIN COMPILER 0 INFO LOG #### +0:? Sequence +0:37 Function Definition: main( (void) +0:37 Function Parameters: +0:39 Sequence +0:39 move second child to first child (4-component vector of float) +0:39 'gl_FragColor' (FragColor 4-component vector of float) +0:39 Construct vec4 (4-component vector of float) +0:39 'color' (varying 3-component vector of float) +0:39 1.000000 (const float) + +#### END COMPILER 0 INFO LOG #### +#### BEGIN LINKER INFO LOG #### + +#### END LINKER INFO LOG #### diff --git a/StandAlone/sample.vert b/StandAlone/sample.vert new file mode 100644 index 0000000..0ecaf2c --- /dev/null +++ b/StandAlone/sample.vert @@ -0,0 +1,42 @@ +// +//Copyright (C) 2002-2004 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +varying vec3 color; + +void main() +{ + color = vec3(1.0, 1.0, 1.0); + + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; +} diff --git a/StandAlone/sample.vert.out b/StandAlone/sample.vert.out new file mode 100644 index 0000000..2d50a82 --- /dev/null +++ b/StandAlone/sample.vert.out @@ -0,0 +1,20 @@ +#### BEGIN COMPILER 0 INFO LOG #### +0:? Sequence +0:37 Function Definition: main( (void) +0:37 Function Parameters: +0:39 Sequence +0:39 move second child to first child (3-component vector of float) +0:39 'color' (varying 3-component vector of float) +0:39 1.000000 (const float) +0:39 1.000000 (const float) +0:39 1.000000 (const float) +0:41 move second child to first child (4-component vector of float) +0:41 'gl_Position' (Position 4-component vector of float) +0:41 matrix-times-vector (4-component vector of float) +0:41 'gl_ModelViewProjectionMatrix' (uniform 4X4 matrix of float) +0:41 'gl_Vertex' (attribute 4-component vector of float) + +#### END COMPILER 0 INFO LOG #### +#### BEGIN LINKER INFO LOG #### + +#### END LINKER INFO LOG #### diff --git a/glslang.vcproj b/glslang.vcproj new file mode 100644 index 0000000..a1fdc9a --- /dev/null +++ b/glslang.vcproj @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/glslang/GenericCodeGen/CodeGen.cpp b/glslang/GenericCodeGen/CodeGen.cpp new file mode 100644 index 0000000..89394ba --- /dev/null +++ b/glslang/GenericCodeGen/CodeGen.cpp @@ -0,0 +1,75 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#include "../Include/Common.h" +#include "../Include/ShHandle.h" + +// +// Here is where real machine specific high-level data would be defined. +// +class TGenericCompiler : public TCompiler { +public: + TGenericCompiler(EShLanguage l, int dOptions) : TCompiler(l, infoSink), debugOptions(dOptions) { } + virtual bool compile(TIntermNode* root); + TInfoSink infoSink; + int debugOptions; +}; + +// +// This function must be provided to create the actual +// compile object used by higher level code. It returns +// a subclass of TCompiler. +// +TCompiler* ConstructCompiler(EShLanguage language, int debugOptions) +{ + return new TGenericCompiler(language, debugOptions); +} + +// +// Delete the compiler made by ConstructCompiler +// +void DeleteCompiler(TCompiler* compiler) +{ + delete compiler; +} + +// +// Generate code from the given parse tree +// +bool TGenericCompiler::compile(TIntermNode *root) +{ + haveValidObjectCode = true; + + return haveValidObjectCode; +} diff --git a/glslang/GenericCodeGen/Link.cpp b/glslang/GenericCodeGen/Link.cpp new file mode 100644 index 0000000..60762d8 --- /dev/null +++ b/glslang/GenericCodeGen/Link.cpp @@ -0,0 +1,91 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +// +// The top level algorithms for linking multiple +// shaders together. +// +#include "../Include/Common.h" +#include "../Include/ShHandle.h" + +// +// Actual link object, derived from the shader handle base classes. +// +class TGenericLinker : public TLinker { +public: + TGenericLinker(EShExecutable e, int dOptions) : TLinker(e, infoSink), debugOptions(dOptions) { } + bool link(TCompilerList&, TUniformMap*) { return true; } + void getAttributeBindings(ShBindingTable const **t) const { } + TInfoSink infoSink; + int debugOptions; +}; + +// +// The internal view of a uniform/float object exchanged with the driver. +// +class TUniformLinkedMap : public TUniformMap { +public: + TUniformLinkedMap() { } + virtual int getLocation(const char* name) { return 0; } +}; + +TShHandleBase* ConstructLinker(EShExecutable executable, int debugOptions) +{ + return new TGenericLinker(executable, debugOptions); +} + +void DeleteLinker(TShHandleBase* linker) +{ + delete linker; +} + +TUniformMap* ConstructUniformMap() +{ + return new TUniformLinkedMap(); +} + +void DeleteUniformMap(TUniformMap* map) +{ + delete map; +} + +TShHandleBase* ConstructBindings() +{ + return 0; +} + +void DeleteBindingList(TShHandleBase* bindingList) +{ + delete bindingList; +} diff --git a/glslang/GenericCodeGen/Makefile b/glslang/GenericCodeGen/Makefile new file mode 100644 index 0000000..2a2f62a --- /dev/null +++ b/glslang/GenericCodeGen/Makefile @@ -0,0 +1,34 @@ +CC = g++ + +OBJECTS = CodeGen.o Link.o +AR=ar + +SRCS=CodeGen.cpp Link.cpp + +default : all +all : libCodeGen.a + +libCodeGen.a : $(OBJECTS) + $(AR) rvu $@ $(OBJECTS) + ranlib $@ + +%.o : %.cpp + $(CC) -c $< + +# +# Cleanup +# +.PHONY : clean +clean : + $(RM) *.o *.a + +depend: + makedepend -- $(CFLAGS) -- $(SRCS) +# DO NOT DELETE + +CodeGen.o: ../Include/Common.h ../Include/PoolAlloc.h ../Include/ShHandle.h +CodeGen.o: ../Public/ShaderLang.h +CodeGen.o: ../Include/InfoSink.h +Link.o: ../Include/Common.h ../Include/PoolAlloc.h ../Include/ShHandle.h +Link.o: ../Public/ShaderLang.h +Link.o: ../Include/InfoSink.h diff --git a/glslang/Include/BaseTypes.h b/glslang/Include/BaseTypes.h new file mode 100644 index 0000000..1249cde --- /dev/null +++ b/glslang/Include/BaseTypes.h @@ -0,0 +1,137 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _BASICTYPES_INCLUDED_ +#define _BASICTYPES_INCLUDED_ + +// +// Basic type. Arrays, vectors, etc., are orthogonal to this. +// +enum TBasicType { + EbtVoid, + EbtFloat, + EbtInt, + EbtBool, + EbtGuardSamplerBegin, // non type: see implementation of IsSampler() + EbtSampler1D, + EbtSampler2D, + EbtSampler3D, + EbtSamplerCube, + EbtSampler1DShadow, + EbtSampler2DShadow, + EbtSamplerRect, // ARB_texture_rectangle + EbtSamplerRectShadow, // ARB_texture_rectangle + EbtGuardSamplerEnd, // non type: see implementation of IsSampler() + EbtStruct, + EbtAddress, // should be deprecated?? +}; + +__inline bool IsSampler(TBasicType type) +{ + return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd; +} + +// +// Qualifiers and built-ins. These are mainly used to see what can be read +// or written, and by the machine dependent translator to know which registers +// to allocate variables in. Since built-ins tend to go to different registers +// than varying or uniform, it makes sense they are peers, not sub-classes. +// +enum TQualifier { + EvqTemporary, // For temporaries (within a function), read/write + EvqGlobal, // For globals read/write + EvqConst, // User defined constants and non-output parameters in functions + EvqAttribute, // Readonly + EvqVaryingIn, // readonly, fragment shaders only + EvqVaryingOut, // vertex shaders only read/write + EvqUniform, // Readonly, vertex and fragment + + // pack/unpack input and output + EvqInput, + EvqOutput, + + // parameters + EvqIn, + EvqOut, + EvqInOut, + EvqConstReadOnly, + + // built-ins written by vertex shader + EvqPosition, + EvqPointSize, + EvqClipVertex, + + // built-ins read by fragment shader + EvqFace, + EvqFragCoord, + + // built-ins written by fragment shader + EvqFragColor, + EvqFragDepth, + + // end of list + EvqLast, +}; + +// +// This is just for debug print out, carried along with the definitions above. +// +__inline const char* getQualifierString(TQualifier q) +{ + switch (q) { + case EvqTemporary: return "Temporary"; break; + case EvqGlobal: return "Global"; break; + case EvqConst: return "const"; break; + case EvqConstReadOnly: return "const"; break; + case EvqAttribute: return "attribute"; break; + case EvqVaryingIn: return "varying"; break; + case EvqVaryingOut: return "varying"; break; + case EvqUniform: return "uniform"; break; + case EvqIn: return "in"; break; + case EvqOut: return "out"; break; + case EvqInOut: return "inout"; break; + case EvqInput: return "input"; break; + case EvqOutput: return "output"; break; + case EvqPosition: return "Position"; break; + case EvqPointSize: return "PointSize"; break; + case EvqClipVertex: return "ClipVertex"; break; + case EvqFace: return "Face"; break; + case EvqFragCoord: return "FragCoord"; break; + case EvqFragColor: return "FragColor"; break; + case EvqFragDepth: return "FragDepth"; break; + default: return "unknown qualifier"; + } +} + +#endif // _BASICTYPES_INCLUDED_ diff --git a/glslang/Include/Common.h b/glslang/Include/Common.h new file mode 100644 index 0000000..9f20ed2 --- /dev/null +++ b/glslang/Include/Common.h @@ -0,0 +1,192 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _COMMON_INCLUDED_ +#define _COMMON_INCLUDED_ + +#ifdef _WIN32 + #include +#elif defined (solaris) + #include + #define UINT_PTR uintptr_t +#else + #include + #define UINT_PTR uintptr_t +#endif + +/* windows only pragma */ +#ifdef _MSC_VER + #pragma warning(disable : 4786) // Don't warn about too long identifiers + #pragma warning(disable : 4514) // unused inline method + #pragma warning(disable : 4201) // nameless union +#endif + +// +// Doing the push and pop below for warnings does not leave the warning state +// the way it was. This seems like a defect in the compiler. We would like +// to do this, but since it does not work correctly right now, it is turned +// off. +// +//??#pragma warning(push, 3) + + #include + #include + #include + #include + #include + #include + +//??#pragma warning(pop) + +typedef int TSourceLoc; + + #include + +#include "PoolAlloc.h" + +// +// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. +// +#define POOL_ALLOCATOR_NEW_DELETE(A) \ + void* operator new(size_t s) { return (A).allocate(s); } \ + void* operator new(size_t, void *_Where) { return (_Where); } \ + void operator delete(void*) { } \ + void operator delete(void *, void *) { } \ + void* operator new[](size_t s) { return (A).allocate(s); } \ + void* operator new[](size_t, void *_Where) { return (_Where); } \ + void operator delete[](void*) { } \ + void operator delete[](void *, void *) { } + +#define TBaseMap std::map +#define TBaseList std::list +#define TBaseSet std::set + +// +// Pool version of string. +// +typedef pool_allocator TStringAllocator; +typedef std::basic_string , TStringAllocator > TString; +inline TString* NewPoolTString(const char* s) +{ + void* memory = GlobalPoolAllocator.allocate(sizeof(TString)); + return new(memory) TString(s); +} + +// +// Pool allocator versions of vectors, lists, and maps +// +template class TVector : public std::vector > { +public: + typedef typename std::vector >::size_type size_type; + TVector() : std::vector >() {} + TVector(const pool_allocator& a) : std::vector >(a) {} + TVector(size_type i): std::vector >(i) {} +}; + +template class TList : public TBaseList > { +public: + typedef typename TBaseList >::size_type size_type; + TList() : TBaseList >() {} + TList(const pool_allocator& a) : TBaseList >(a) {} + TList(size_type i): TBaseList >(i) {} +}; + +// This is called TStlSet, because TSet is taken by an existing compiler class. +template class TStlSet : public std::set > { + // No pool allocator versions of constructors in std::set. +}; + + +template > +class TMap : public TBaseMap > > { +public: + typedef pool_allocator > tAllocator; + + TMap() : TBaseMap() {} + // use correct two-stage name lookup supported in gcc 3.4 and above + TMap(const tAllocator& a) : TBaseMap(TBaseMap::key_compare(), a) {} +}; + +// +// Persistent string memory. Should only be used for strings that survive +// across compiles/links. +// +typedef std::basic_string TPersistString; + +// +// templatized min and max functions. +// +template T Min(const T a, const T b) { return a < b ? a : b; } +template T Max(const T a, const T b) { return a > b ? a : b; } + +// +// Create a TString object from an integer. +// +inline const TString String(const int i, const int base = 10) +{ + char text[16]; // 32 bit ints are at most 10 digits in base 10 + + #ifdef _WIN32 + itoa(i, text, base); + #else + // we assume base 10 for all cases + sprintf(text, "%d", i); + #endif + + return text; +} + +const unsigned int SourceLocLineMask = 0xffff; +const unsigned int SourceLocStringShift = 16; + +__inline TPersistString FormatSourceLoc(const TSourceLoc loc) +{ + char locText[64]; + + int string = loc >> SourceLocStringShift; + int line = loc & SourceLocLineMask; + + if (line) + sprintf(locText, "%d:%d", string, line); + else + sprintf(locText, "%d:? ", string); + + return TPersistString(locText); +} + + +typedef TMap TPragmaTable; +typedef TMap::tAllocator TPragmaTableAllocator; + +#endif // _COMMON_INCLUDED_ diff --git a/glslang/Include/ConstantUnion.h b/glslang/Include/ConstantUnion.h new file mode 100644 index 0000000..3116796 --- /dev/null +++ b/glslang/Include/ConstantUnion.h @@ -0,0 +1,315 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _CONSTANT_UNION_INCLUDED_ +#define _CONSTANT_UNION_INCLUDED_ + + +class constUnion { +public: + + POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + void setIConst(int i) {iConst = i; type = EbtInt; } + void setFConst(float f) {fConst = f; type = EbtFloat; } + void setBConst(bool b) {bConst = b; type = EbtBool; } + + int getIConst() { return iConst; } + float getFConst() { return fConst; } + bool getBConst() { return bConst; } + int getIConst() const { return iConst; } + float getFConst() const { return fConst; } + bool getBConst() const { return bConst; } + + bool operator==(const int i) const + { + if (i == iConst) + return true; + + return false; + } + + bool operator==(const float f) const + { + if (f == fConst) + return true; + + return false; + } + + bool operator==(const bool b) const + { + if (b == bConst) + return true; + + return false; + } + + bool operator==(const constUnion& constant) const + { + if (constant.type != type) + return false; + + switch (type) { + case EbtInt: + if (constant.iConst == iConst) + return true; + + break; + case EbtFloat: + if (constant.fConst == fConst) + return true; + + break; + case EbtBool: + if (constant.bConst == bConst) + return true; + + break; + } + + return false; + } + + bool operator!=(const int i) const + { + return !operator==(i); + } + + bool operator!=(const float f) const + { + return !operator==(f); + } + + bool operator!=(const bool b) const + { + return !operator==(b); + } + + bool operator!=(const constUnion& constant) const + { + return !operator==(constant); + } + + bool operator>(const constUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + if (iConst > constant.iConst) + return true; + + return false; + case EbtFloat: + if (fConst > constant.fConst) + return true; + + return false; + default: + assert(false && "Default missing"); + return false; + } + + return false; + } + + bool operator<(const constUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + if (iConst < constant.iConst) + return true; + + return false; + case EbtFloat: + if (fConst < constant.fConst) + return true; + + return false; + default: + assert(false && "Default missing"); + return false; + } + + return false; + } + + constUnion operator+(const constUnion& constant) const + { + constUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; + case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + constUnion operator-(const constUnion& constant) const + { + constUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; + case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + constUnion operator*(const constUnion& constant) const + { + constUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; + case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + constUnion operator%(const constUnion& constant) const + { + constUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + constUnion operator>>(const constUnion& constant) const + { + constUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + constUnion operator<<(const constUnion& constant) const + { + constUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + constUnion operator&(const constUnion& constant) const + { + constUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + constUnion operator|(const constUnion& constant) const + { + constUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + constUnion operator^(const constUnion& constant) const + { + constUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + constUnion operator&&(const constUnion& constant) const + { + constUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + constUnion operator||(const constUnion& constant) const + { + constUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TBasicType getType() { return type; } +private: + + union { + int iConst; // used for ivec, scalar ints + bool bConst; // used for bvec, scalar bools + float fConst; // used for vec, mat, scalar floats + } ; + + TBasicType type; +}; + +#endif // _CONSTANT_UNION_INCLUDED_ diff --git a/glslang/Include/InfoSink.h b/glslang/Include/InfoSink.h new file mode 100644 index 0000000..debe9bb --- /dev/null +++ b/glslang/Include/InfoSink.h @@ -0,0 +1,137 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _INFOSINK_INCLUDED_ +#define _INFOSINK_INCLUDED_ + +#include "../Include/Common.h" +#include + +// +// TPrefixType is used to centralize how info log messages start. +// See below. +// +enum TPrefixType { + EPrefixNone, + EPrefixWarning, + EPrefixError, + EPrefixInternalError, + EPrefixUnimplemented, + EPrefixNote +}; + +enum TOutputStream { + ENull = 0, + EDebugger = 0x01, + EStdOut = 0x02, + EString = 0x04, +}; +// +// Encapsulate info logs for all objects that have them. +// +// The methods are a general set of tools for getting a variety of +// messages and types inserted into the log. +// +class TInfoSinkBase { +public: + TInfoSinkBase() : outputStream(4) {} + void erase() { sink.erase(); } + TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; } + TInfoSinkBase& operator<<(char c) { append(1, c); return *this; } + TInfoSinkBase& operator<<(const char* s) { append(s); return *this; } + TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; } + TInfoSinkBase& operator<<(const unsigned int n) { append(String(n)); return *this; } + TInfoSinkBase& operator<<(float n) { char buf[40]; + sprintf(buf, (fabs(n) > 1e-8 && fabs(n) < 1e8) || n == 0.0f ? + "%f" : "%g", n); + append(buf); + return *this; } + TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; } + TInfoSinkBase& operator+(const TString& t) { append(t); return *this; } + TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; } + TInfoSinkBase& operator+(const char* s) { append(s); return *this; } + const char* c_str() const { return sink.c_str(); } + void prefix(TPrefixType message) { + switch(message) { + case EPrefixNone: break; + case EPrefixWarning: append("WARNING: "); break; + case EPrefixError: append("ERROR: "); break; + case EPrefixInternalError: append("INTERNAL ERROR: "); break; + case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break; + case EPrefixNote: append("NOTE: "); break; + default: append("UNKOWN ERROR: "); break; + } + } + void location(TSourceLoc loc) { + append(FormatSourceLoc(loc).c_str()); + append(": "); + } + void message(TPrefixType message, const char* s) { + prefix(message); + append(s); + append("\n"); + } + void message(TPrefixType message, const char* s, TSourceLoc loc) { + prefix(message); + location(loc); + append(s); + append("\n"); + } + + void setOutputStream(int output = 4) + { + outputStream = output; + } + +protected: + void append(const char *s); + + void append(int count, char c); + void append(const TPersistString& t); + void append(const TString& t); + + void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2) + sink.reserve(sink.capacity() + sink.capacity() / 2); } + void appendToStream(const char* s); + TPersistString sink; + int outputStream; +}; + +class TInfoSink { +public: + TInfoSinkBase info; + TInfoSinkBase debug; +}; + +#endif // _INFOSINK_INCLUDED_ diff --git a/glslang/Include/InitializeGlobals.h b/glslang/Include/InitializeGlobals.h new file mode 100644 index 0000000..dc1ef91 --- /dev/null +++ b/glslang/Include/InitializeGlobals.h @@ -0,0 +1,43 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef __INITIALIZE_GLOBALS_INCLUDED_ +#define __INITIALIZE_GLOBALS_INCLUDED_ + +void InitializeGlobalPools(); +void FreeGlobalPools(); +bool InitializePoolIndex(); +void FreePoolIndex(); + +#endif // __INITIALIZE_GLOBALS_INCLUDED_ diff --git a/glslang/Include/InitializeParseContext.h b/glslang/Include/InitializeParseContext.h new file mode 100644 index 0000000..4d369e8 --- /dev/null +++ b/glslang/Include/InitializeParseContext.h @@ -0,0 +1,45 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_ +#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_ +#include "osinclude.h" + +bool InitializeParseContextIndex(); +bool InitializeGlobalParseContext(); +bool FreeParseContext(); +bool FreeParseContextIndex(); + + +#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_ diff --git a/glslang/Include/PoolAlloc.h b/glslang/Include/PoolAlloc.h new file mode 100644 index 0000000..14c5985 --- /dev/null +++ b/glslang/Include/PoolAlloc.h @@ -0,0 +1,349 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _POOLALLOC_INCLUDED_ +#define _POOLALLOC_INCLUDED_ + +#ifdef _DEBUG +# define GUARD_BLOCKS // define to enable guard block sanity checking +#endif + +// +// This header defines an allocator that can be used to efficiently +// allocate a large number of small requests for heap memory, with the +// intention that they are not individually deallocated, but rather +// collectively deallocated at one time. +// +// This simultaneously +// +// * Makes each individual allocation much more efficient; the +// typical allocation is trivial. +// * Completely avoids the cost of doing individual deallocation. +// * Saves the trouble of tracking down and plugging a large class of leaks. +// +// Individual classes can use this allocator by supplying their own +// new and delete methods. +// +// STL containers can use this allocator by using the pool_allocator +// class as the allocator (second) template argument. +// + +#include +#include + +// If we are using guard blocks, we must track each indivual +// allocation. If we aren't using guard blocks, these +// never get instantiated, so won't have any impact. +// + +class TAllocation { +public: + TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) : + size(size), mem(mem), prevAlloc(prev) { + // Allocations are bracketed: + // [allocationHeader][initialGuardBlock][userData][finalGuardBlock] + // This would be cleaner with if (guardBlockSize)..., but that + // makes the compiler print warnings about 0 length memsets, + // even with the if() protecting them. +# ifdef GUARD_BLOCKS + memset(preGuard(), guardBlockBeginVal, guardBlockSize); + memset(data(), userDataFill, size); + memset(postGuard(), guardBlockEndVal, guardBlockSize); +# endif + } + + void check() const { + checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); + checkGuardBlock(postGuard(), guardBlockEndVal, "after"); + } + + void checkAllocList() const; + + // Return total size needed to accomodate user buffer of 'size', + // plus our tracking data. + inline static size_t allocationSize(size_t size) { + return size + 2 * guardBlockSize + headerSize(); + } + + // Offset from surrounding buffer to get to user data buffer. + inline static unsigned char* offsetAllocation(unsigned char* m) { + return m + guardBlockSize + headerSize(); + } + +private: + void checkGuardBlock(unsigned char* blockMem, unsigned char val, char* locText) const; + + // Find offsets to pre and post guard blocks, and user data buffer + unsigned char* preGuard() const { return mem + headerSize(); } + unsigned char* data() const { return preGuard() + guardBlockSize; } + unsigned char* postGuard() const { return data() + size; } + + size_t size; // size of the user data area + unsigned char* mem; // beginning of our allocation (pts to header) + TAllocation* prevAlloc; // prior allocation in the chain + + // Support MSVC++ 6.0 + const static unsigned char guardBlockBeginVal; + const static unsigned char guardBlockEndVal; + const static unsigned char userDataFill; + + const static size_t guardBlockSize; +# ifdef GUARD_BLOCKS + inline static size_t headerSize() { return sizeof(TAllocation); } +# else + inline static size_t headerSize() { return 0; } +# endif +}; + +// +// There are several stacks. One is to track the pushing and popping +// of the user, and not yet implemented. The others are simply a +// repositories of free pages or used pages. +// +// Page stacks are linked together with a simple header at the beginning +// of each allocation obtained from the underlying OS. Multi-page allocations +// are returned to the OS. Individual page allocations are kept for future +// re-use. +// +// The "page size" used is not, nor must it match, the underlying OS +// page size. But, having it be about that size or equal to a set of +// pages is likely most optimal. +// +class TPoolAllocator { +public: + TPoolAllocator(bool global = false, int growthIncrement = 8*1024, int allocationAlignment = 16); + + // + // Don't call the destructor just to free up the memory, call pop() + // + ~TPoolAllocator(); + + // + // Call push() to establish a new place to pop memory too. Does not + // have to be called to get things started. + // + void push(); + + // + // Call pop() to free all memory allocated since the last call to push(), + // or if no last call to push, frees all memory since first allocation. + // + void pop(); + + // + // Call popAll() to free all memory allocated. + // + void popAll(); + + // + // Call allocate() to actually acquire memory. Returns 0 if no memory + // available, otherwise a properly aligned pointer to 'numBytes' of memory. + // + void* allocate(size_t numBytes); + + // + // There is no deallocate. The point of this class is that + // deallocation can be skipped by the user of it, as the model + // of use is to simultaneously deallocate everything at once + // by calling pop(), and to not have to solve memory leak problems. + // + +protected: + friend struct tHeader; + + struct tHeader { + tHeader(tHeader* nextPage, size_t pageCount) : +#ifdef GUARD_BLOCKS + lastAllocation(0), +#endif + nextPage(nextPage), pageCount(pageCount) { } + + ~tHeader() { +#ifdef GUARD_BLOCKS + if (lastAllocation) + lastAllocation->checkAllocList(); +#endif + } + + tHeader* nextPage; + size_t pageCount; +#ifdef GUARD_BLOCKS + TAllocation* lastAllocation; +#endif + }; + + struct tAllocState { + size_t offset; + tHeader* page; + }; + typedef std::vector tAllocStack; + + // Track allocations if and only if we're using guard blocks + void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) { +# ifdef GUARD_BLOCKS + new(memory) TAllocation(numBytes, memory, block->lastAllocation); + block->lastAllocation = reinterpret_cast(memory); +# endif + + // This is optimized entirely away if GUARD_BLOCKS is not defined. + return TAllocation::offsetAllocation(memory); + } + + bool global; // should be true if this object is globally scoped + size_t pageSize; // granularity of allocation from the OS + size_t alignment; // all returned allocations will be aligned at + // this granularity, which will be a power of 2 + size_t alignmentMask; + size_t headerSkip; // amount of memory to skip to make room for the + // header (basically, size of header, rounded + // up to make it aligned + size_t currentPageOffset; // next offset in top of inUseList to allocate from + tHeader* freeList; // list of popped memory + tHeader* inUseList; // list of all memory currently being used + tAllocStack stack; // stack of where to allocate from, to partition pool + + int numCalls; // just an interesting statistic + size_t totalBytes; // just an interesting statistic +private: + TPoolAllocator& operator=(const TPoolAllocator&); // dont allow assignment operator + TPoolAllocator(const TPoolAllocator&); // dont allow default copy constructor +}; + + +// +// There could potentially be many pools with pops happening at +// different times. But a simple use is to have a global pop +// with everyone using the same global allocator. +// +typedef TPoolAllocator* PoolAllocatorPointer; +extern TPoolAllocator& GetGlobalPoolAllocator(); +#define GlobalPoolAllocator GetGlobalPoolAllocator() + + +struct TThreadGlobalPools +{ + TPoolAllocator* globalPoolAllocator; +}; + +void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator); + +// +// This STL compatible allocator is intended to be used as the allocator +// parameter to templatized STL containers, like vector and map. +// +// It will use the pools for allocation, and not +// do any deallocation, but will still do destruction. +// +template +class pool_allocator { +public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T *pointer; + typedef const T *const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + template + struct rebind { + typedef pool_allocator other; + }; + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + +#ifdef USING_SGI_STL + pool_allocator() { } +#else + pool_allocator() : allocator(GlobalPoolAllocator) { } + pool_allocator(TPoolAllocator& a) : allocator(a) { } + pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1300 + template +#ifdef USING_SGI_STL + pool_allocator(const pool_allocator& p) /*: allocator(p.getAllocator())*/ { } +#else + pool_allocator(const pool_allocator& p) : allocator(p.getAllocator()) { } +#endif +#endif + +#ifndef _WIN32 + template + pool_allocator(const pool_allocator& p) : allocator(p.getAllocator()) { } +#endif + +#ifdef USING_SGI_STL + static pointer allocate(size_type n) { + return reinterpret_cast(getAllocator().allocate(n)); } + pointer allocate(size_type n, const void*) { + return reinterpret_cast(getAllocator().allocate(n)); } + + static void deallocate(void*, size_type) { } + static void deallocate(pointer, size_type) { } +#else + pointer allocate(size_type n) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } + pointer allocate(size_type n, const void*) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } + + void deallocate(void*, size_type) { } + void deallocate(pointer, size_type) { } +#endif + + pointer _Charalloc(size_t n) { + return reinterpret_cast(getAllocator().allocate(n)); } + + void construct(pointer p, const T& val) { new ((void *)p) T(val); } + void destroy(pointer p) { p->T::~T(); } + + bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); } + bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); } + + size_type max_size() const { return static_cast(-1) / sizeof(T); } + size_type max_size(int size) const { return static_cast(-1) / size; } + +#ifdef USING_SGI_STL + //void setAllocator(TPoolAllocator* a) { allocator = a; } + static TPoolAllocator& getAllocator() { return GlobalPoolAllocator; } +#else + void setAllocator(TPoolAllocator* a) { allocator = *a; } + TPoolAllocator& getAllocator() const { return allocator; } + +protected: + TPoolAllocator& allocator; +#endif +}; + +#endif // _POOLALLOC_INCLUDED_ diff --git a/glslang/Include/ResourceLimits.h b/glslang/Include/ResourceLimits.h new file mode 100644 index 0000000..f3d1a53 --- /dev/null +++ b/glslang/Include/ResourceLimits.h @@ -0,0 +1,52 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _RESOURCE_LIMITS_INCLUDED_ +#define _RESOURCE_LIMITS_INCLUDED_ + +struct TBuiltInResource { + int maxLights; + int maxClipPlanes; + int maxTextureUnits; + int maxTextureCoords; + int maxVertexAttribs; + int maxVertexUniformComponents; + int maxVaryingFloats; + int maxVertexTextureImageUnits; + int maxCombinedTextureImageUnits; + int maxTextureImageUnits; + int maxFragmentUniformComponents; + int maxDrawBuffers; +}; +#endif // _RESOURCE_LIMITS_INCLUDED_ diff --git a/glslang/Include/ShHandle.h b/glslang/Include/ShHandle.h new file mode 100644 index 0000000..0bde67b --- /dev/null +++ b/glslang/Include/ShHandle.h @@ -0,0 +1,169 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _SHHANDLE_INCLUDED_ +#define _SHHANDLE_INCLUDED_ + +// +// Machine independent part of the compiler private objects +// sent as ShHandle to the driver. +// +// This should not be included by driver code. +// + + +#define SH_EXPORTING +#include "../Public/ShaderLang.h" + +#include "InfoSink.h" + +class TCompiler; +class TLinker; +class TUniformMap; + + +// +// The base class used to back handles returned to the driver. +// +class TShHandleBase { +public: + TShHandleBase() { } + virtual ~TShHandleBase() { } + virtual TCompiler* getAsCompiler() { return 0; } + virtual TLinker* getAsLinker() { return 0; } + virtual TUniformMap* getAsUniformMap() { return 0; } +}; + +// +// The base class for the machine dependent linker to derive from +// for managing where uniforms live. +// +class TUniformMap : public TShHandleBase { +public: + TUniformMap() { } + virtual ~TUniformMap() { } + virtual TUniformMap* getAsUniformMap() { return this; } + virtual int getLocation(const char* name) = 0; + virtual TInfoSink& getInfoSink() { return infoSink; } + TInfoSink infoSink; +}; +class TIntermNode; + +// +// The base class for the machine dependent compiler to derive from +// for managing object code from the compile. +// +class TCompiler : public TShHandleBase { +public: + TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { } + virtual ~TCompiler() { } + EShLanguage getLanguage() { return language; } + virtual TInfoSink& getInfoSink() { return infoSink; } + + virtual bool compile(TIntermNode* root) = 0; + + virtual TCompiler* getAsCompiler() { return this; } + virtual bool linkable() { return haveValidObjectCode; } + + TInfoSink& infoSink; +protected: + EShLanguage language; + bool haveValidObjectCode; +}; + +// +// Link operations are base on a list of compile results... +// +typedef TVector TCompilerList; +typedef TVector THandleList; + +// +// The base class for the machine dependent linker to derive from +// to manage the resulting executable. +// + +class TLinker : public TShHandleBase { +public: + TLinker(EShExecutable e, TInfoSink& iSink) : + infoSink(iSink), + executable(e), + haveReturnableObjectCode(false), + appAttributeBindings(0), + fixedAttributeBindings(0), + excludedAttributes(0), + excludedCount(0), + uniformBindings(0) { } + virtual TLinker* getAsLinker() { return this; } + virtual ~TLinker() { } + virtual bool link(TCompilerList&, TUniformMap*) = 0; + virtual bool link(THandleList&) { return false; } + virtual void setAppAttributeBindings(const ShBindingTable* t) { appAttributeBindings = t; } + virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; } + virtual void getAttributeBindings(ShBindingTable const **t) const = 0; + virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; } + virtual ShBindingTable* getUniformBindings() const { return uniformBindings; } + virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here + virtual TInfoSink& getInfoSink() { return infoSink; } + TInfoSink& infoSink; +protected: + EShExecutable executable; + bool haveReturnableObjectCode; // true when objectCode is acceptable to send to driver + + const ShBindingTable* appAttributeBindings; + const ShBindingTable* fixedAttributeBindings; + const int* excludedAttributes; + int excludedCount; + ShBindingTable* uniformBindings; // created by the linker +}; + +// +// This is the interface between the machine independent code +// and the machine dependent code. +// +// The machine dependent code should derive from the classes +// above. Then Construct*() and Delete*() will create and +// destroy the machine dependent objects, which contain the +// above machine independent information. +// +TCompiler* ConstructCompiler(EShLanguage, int); + +TShHandleBase* ConstructLinker(EShExecutable, int); +void DeleteLinker(TShHandleBase*); + +TUniformMap* ConstructUniformMap(); +void DeleteCompiler(TCompiler*); + +void DeleteUniformMap(TUniformMap*); + +#endif // _SHHANDLE_INCLUDED_ diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h new file mode 100644 index 0000000..3db8d3a --- /dev/null +++ b/glslang/Include/Types.h @@ -0,0 +1,322 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _TYPES_INCLUDED +#define _TYPES_INCLUDED + +#include "../Include/Common.h" +#include "../Include/BaseTypes.h" + +// +// Need to have association of line numbers to types in a list for building structs. +// +class TType; +struct TTypeLine { + TType* type; + int line; +}; +typedef TVector TTypeList; + +inline TTypeList* NewPoolTTypeList() +{ + void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList)); + return new(memory) TTypeList; +} + +// +// This is a workaround for a problem with the yacc stack, It can't have +// types that it thinks have non-trivial constructors. It should +// just be used while recognizing the grammar, not anything else. Pointers +// could be used, but also trying to avoid lots of memory management overhead. +// +// Not as bad as it looks, there is no actual assumption that the fields +// match up or are name the same or anything like that. +// +class TPublicType { +public: + TBasicType type; + TQualifier qualifier; + int size; // size of vector or matrix, not size of array + bool matrix; + bool array; + int arraySize; + TType* userDef; + int line; + + void setBasic(TBasicType bt, TQualifier q, int ln = 0) + { + type = bt; + qualifier = q; + size = 1; + matrix = false; + array = false; + arraySize = 0; + userDef = 0; + line = ln; + } + + void setAggregate(int s, bool m = false) + { + size = s; + matrix = m; + } + + void setArray(bool a, int s = 0) + { + array = a; + arraySize = s; + } +}; + +typedef std::map TStructureMap; +typedef std::map::iterator TStructureMapIterator; +// +// Base class for things that have a type. +// +class TType { +public: + POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + explicit TType(TBasicType t, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) : + type(t), qualifier(q), size(s), matrix(m), array(a), arraySize(0), + structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0) + { } + explicit TType(const TPublicType &p) : + type(p.type), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), + structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0) + { + if (p.userDef) { + structure = p.userDef->getStruct(); + typeName = NewPoolTString(p.userDef->getTypeName().c_str()); + } + } + explicit TType(TTypeList* userDef, const TString& n) : + type(EbtStruct), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), + structure(userDef), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0) { + typeName = NewPoolTString(n.c_str()); + } + explicit TType() {} + virtual ~TType() {} + + TType(const TType& type) { *this = type; } + + void copyType(const TType& copyOf, TStructureMap& remapper) + { + type = copyOf.type; + qualifier = copyOf.qualifier; + size = copyOf.size; + matrix = copyOf.matrix; + array = copyOf.array; + arraySize = copyOf.arraySize; + + TStructureMapIterator iter; + if (copyOf.structure) { + if ((iter = remapper.find(structure)) == remapper.end()) { + // create the new structure here + structure = NewPoolTTypeList(); + for (unsigned int i = 0; i < copyOf.structure->size(); ++i) { + TTypeLine typeLine; + typeLine.line = (*copyOf.structure)[i].line; + typeLine.type = (*copyOf.structure)[i].type->clone(remapper); + structure->push_back(typeLine); + } + } else { + structure = iter->second; + } + } else + structure = 0; + + fieldName = 0; + if (copyOf.fieldName) + fieldName = NewPoolTString(copyOf.fieldName->c_str()); + typeName = 0; + if (copyOf.typeName) + typeName = NewPoolTString(copyOf.typeName->c_str()); + + mangled = 0; + if (copyOf.mangled) + mangled = NewPoolTString(copyOf.mangled->c_str()); + + structureSize = copyOf.structureSize; + maxArraySize = copyOf.maxArraySize; + assert(copyOf.arrayInformationType == 0); + arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level + } + + TType* clone(TStructureMap& remapper) + { + TType *newType = new TType(); + newType->copyType(*this, remapper); + + return newType; + } + + virtual void setType(TBasicType t, int s, bool m, bool a, int aS = 0) + { type = t; size = s; matrix = m; array = a; arraySize = aS; } + virtual void setType(TBasicType t, int s, bool m, TType* userDef = 0) + { type = t; + size = s; + matrix = m; + if (userDef) + structure = userDef->getStruct(); + // leave array information intact. + } + virtual void setTypeName(const TString& n) { typeName = NewPoolTString(n.c_str()); } + virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); } + virtual const TString& getTypeName() const + { + assert(typeName); + return *typeName; + } + + virtual const TString& getFieldName() const + { + assert(fieldName); + return *fieldName; + } + + virtual TBasicType getBasicType() const { return type; } + virtual TQualifier getQualifier() const { return qualifier; } + virtual void changeQualifier(TQualifier q) { qualifier = q; } + + // One-dimensional size of single instance type + virtual int getNominalSize() const { return size; } + + // Full-dimensional size of single instance of type + virtual int getInstanceSize() const + { + if (matrix) + return size * size; + else + return size; + } + + virtual bool isMatrix() const { return matrix ? true : false; } + virtual bool isArray() const { return array ? true : false; } + int getArraySize() const { return arraySize; } + void setArraySize(int s) { array = true; arraySize = s; } + void setMaxArraySize (int s) { maxArraySize = s; } + int getMaxArraySize () const { return maxArraySize; } + void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; } + void setArrayInformationType(TType* t) { arrayInformationType = t; } + TType* getArrayInformationType() { return arrayInformationType; } + virtual bool isVector() const { return size > 1 && !matrix; } + static char* getBasicString(TBasicType t) { + switch (t) { + case EbtVoid: return "void"; break; + case EbtFloat: return "float"; break; + case EbtInt: return "int"; break; + case EbtBool: return "bool"; break; + case EbtSampler1D: return "sampler1D"; break; + case EbtSampler2D: return "sampler2D"; break; + case EbtSampler3D: return "sampler3D"; break; + case EbtSamplerCube: return "samplerCube"; break; + case EbtSampler1DShadow: return "sampler1DShadow"; break; + case EbtSampler2DShadow: return "sampler2DShadow"; break; + case EbtSamplerRect: return "samplerRect"; break; // ARB_texture_rectangle + case EbtSamplerRectShadow: return "samplerRectShadow"; break; // ARB_texture_rectangle + case EbtStruct: return "structure"; break; + default: return "unknown type"; + } + } + const char* getBasicString() const { return TType::getBasicString(type); } + const char* getQualifierString() const { return ::getQualifierString(qualifier); } + TTypeList* getStruct() { return structure; } + + int getObjectSize() const + { + int totalSize; + + if (getBasicType() == EbtStruct) + totalSize = getStructSize(); + else if (matrix) + totalSize = size * size; + else + totalSize = size; + + if (isArray()) + totalSize *= Max(getArraySize(), getMaxArraySize()); + + return totalSize; + } + + TTypeList* getStruct() const { return structure; } + TString& getMangledName() { + if (!mangled) { + mangled = NewPoolTString(""); + buildMangledName(*mangled); + *mangled += ';' ; + } + + return *mangled; + } + bool sameElementType(const TType& right) const { + return type == right.type && + size == right.size && + matrix == right.matrix && + structure == right.structure; + } + bool operator==(const TType& right) const { + return type == right.type && + size == right.size && + matrix == right.matrix && + array == right.array && (!array || arraySize == right.arraySize) && + structure == right.structure; + // don't check the qualifier, it's not ever what's being sought after + } + bool operator!=(const TType& right) const { + return !operator==(right); + } + TString getCompleteString() const; + +protected: + void buildMangledName(TString&); + int getStructSize() const; + + TBasicType type : 6; + TQualifier qualifier : 7; + int size : 8; // size of vector or matrix, not size of array + unsigned int matrix : 1; + unsigned int array : 1; + int arraySize; + + TTypeList* structure; // 0 unless this is a struct + mutable int structureSize; + int maxArraySize; + TType* arrayInformationType; + TString *fieldName; // for structure field names + TString *mangled; + TString *typeName; // for structure field type name +}; + +#endif // _TYPES_INCLUDED_ diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h new file mode 100644 index 0000000..336e43c --- /dev/null +++ b/glslang/Include/intermediate.h @@ -0,0 +1,522 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +// +// Definition of the in-memory high-level intermediate representation +// of shaders. This is a tree that parser creates. +// +// Nodes in the tree are defined as a hierarchy of classes derived from +// TIntermNode. Each is a node in a tree. There is no preset branching factor; +// each node can have it's own type of list of children. +// + +#ifndef __INTERMEDIATE_H +#define __INTERMEDIATE_H + +#include "../Include/Common.h" +#include "../Include/Types.h" +#include "../Include/ConstantUnion.h" + +// +// Operators used by the high-level (parse tree) representation. +// +enum TOperator { + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpFunctionCall, + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + // + // Unary operators + // + + EOpNegative, + EOpLogicalNot, + EOpVectorLogicalNot, + EOpBitwiseNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + EOpConvIntToBool, + EOpConvFloatToBool, + EOpConvBoolToFloat, + EOpConvIntToFloat, + EOpConvFloatToInt, + EOpConvBoolToInt, + + // + // binary operations + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpMod, + EOpRightShift, + EOpLeftShift, + EOpAnd, + EOpInclusiveOr, + EOpExclusiveOr, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + + EOpVectorSwizzle, + + // + // Built-in functions potentially mapped to operators + // + + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, + + EOpAbs, + EOpSign, + EOpFloor, + EOpCeil, + EOpFract, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + + EOpLength, + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, + EOpFaceForward, + EOpReflect, + EOpRefract, + + EOpDPdx, // Fragment only + EOpDPdy, // Fragment only + EOpFwidth, // Fragment only + + EOpMatrixTimesMatrix, + + EOpAny, + EOpAll, + + EOpItof, // pack/unpack only + EOpFtoi, // pack/unpack only + EOpSkipPixels, // pack/unpack only + EOpReadInput, // unpack only + EOpWritePixel, // unpack only + EOpBitmapLsb, // unpack only + EOpBitmapMsb, // unpack only + EOpWriteOutput, // pack only + EOpReadPixel, // pack only + + // + // Branch + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + + // + // Constructors + // + + EOpConstructInt, + EOpConstructBool, + EOpConstructFloat, + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructMat2, + EOpConstructMat3, + EOpConstructMat4, + EOpConstructStruct, + + // + // moves + // + + EOpAssign, + EOpAddAssign, + EOpSubAssign, + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + EOpDivAssign, + EOpModAssign, + EOpAndAssign, + EOpInclusiveOrAssign, + EOpExclusiveOrAssign, + EOpLeftShiftAssign, + EOpRightShiftAssign, + + // + // Array operators + // + + EOpArrayLength, +}; + +class TIntermTraverser; +class TIntermAggregate; +class TIntermBinary; +class TIntermConstantUnion; +class TIntermSelection; +class TIntermTyped; +class TIntermSymbol; +class TInfoSink; + +// +// Base class for the tree nodes +// +class TIntermNode { +public: + POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + + TIntermNode() : line(0) {} + virtual TSourceLoc getLine() const { return line; } + virtual void setLine(TSourceLoc l) { line = l; } + virtual void traverse(TIntermTraverser*) = 0; + virtual TIntermTyped* getAsTyped() { return 0; } + virtual TIntermConstantUnion* getAsConstantUnion() { return 0; } + virtual TIntermAggregate* getAsAggregate() { return 0; } + virtual TIntermBinary* getAsBinaryNode() { return 0; } + virtual TIntermSelection* getAsSelectionNode() { return 0; } + virtual TIntermSymbol* getAsSymbolNode() { return 0; } + virtual ~TIntermNode() { } +protected: + TSourceLoc line; +}; + +// +// This is just to help yacc. +// +struct TIntermNodePair { + TIntermNode* node1; + TIntermNode* node2; +}; + +class TIntermSymbol; +class TIntermBinary; + +// +// Intermediate class for nodes that have a type. +// +class TIntermTyped : public TIntermNode { +public: + TIntermTyped(const TType& t) : type(t) { } + virtual TIntermTyped* getAsTyped() { return this; } + virtual void setType(const TType& t) { type = t; } + virtual TType getType() const { return type; } + virtual TType* getTypePointer() { return &type; } + + virtual TBasicType getBasicType() const { return type.getBasicType(); } + virtual TQualifier getQualifier() const { return type.getQualifier(); } + virtual int getNominalSize() const { return type.getNominalSize(); } + virtual int getSize() const { return type.getInstanceSize(); } + virtual bool isMatrix() const { return type.isMatrix(); } + virtual bool isArray() const { return type.isArray(); } + virtual bool isVector() const { return type.isVector(); } + const char* getBasicString() const { return type.getBasicString(); } + const char* getQualifierString() const { return type.getQualifierString(); } + TString getCompleteString() const { return type.getCompleteString(); } + +protected: + TType type; +}; + +// +// Handle for, do-while, and while loops. +// +class TIntermLoop : public TIntermNode { +public: + TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : + body(aBody), + test(aTest), + terminal(aTerminal), + first(testFirst) { } + virtual void traverse(TIntermTraverser*); + TIntermNode* getBody() { return body; } + TIntermTyped* getTest() { return test; } + TIntermTyped* getTerminal() { return terminal; } + bool testFirst() { return first; } +protected: + TIntermNode* body; // code to loop over + TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops + TIntermTyped* terminal; // exists for for-loops + bool first; // true for while and for, not for do-while +}; + +// +// Handle break, continue, return, and kill. +// +class TIntermBranch : public TIntermNode { +public: + TIntermBranch(TOperator op, TIntermTyped* e) : + flowOp(op), + expression(e) { } + virtual void traverse(TIntermTraverser*); + TOperator getFlowOp() { return flowOp; } + TIntermTyped* getExpression() { return expression; } +protected: + TOperator flowOp; + TIntermTyped* expression; // non-zero except for "return exp;" statements +}; + +// +// Nodes that correspond to symbols or constants in the source code. +// +class TIntermSymbol : public TIntermTyped { +public: + // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from + // per process globalpoolallocator, then it causes increased memory usage per compile + // it is essential to use "symbol = sym" to assign to symbol + TIntermSymbol(int i, const TString& sym, const TType& t) : + TIntermTyped(t), id(i) { symbol = sym;} + virtual int getId() const { return id; } + virtual const TString& getSymbol() const { return symbol; } + virtual void traverse(TIntermTraverser*); + virtual TIntermSymbol* getAsSymbolNode() { return this; } +protected: + int id; + TString symbol; +}; + +class TIntermConstantUnion : public TIntermTyped { +public: + TIntermConstantUnion(constUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { } + constUnion* getUnionArrayPointer() const { return unionArrayPointer; } + void setUnionArrayPointer(constUnion *c) { unionArrayPointer = c; } + virtual TIntermConstantUnion* getAsConstantUnion() { return this; } + virtual void traverse(TIntermTraverser* ); + virtual TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&); +protected: + constUnion *unionArrayPointer; +}; + +// +// Intermediate class for node types that hold operators. +// +class TIntermOperator : public TIntermTyped { +public: + TOperator getOp() { return op; } + bool modifiesState() const; + bool isConstructor() const; + virtual bool promote(TInfoSink&) { return true; } +protected: + TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat)), op(o) {} + TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {} + TOperator op; +}; + +// +// Nodes for all the basic binary math operators. +// +class TIntermBinary : public TIntermOperator { +public: + TIntermBinary(TOperator o) : TIntermOperator(o) {} + virtual void traverse(TIntermTraverser*); + virtual void setLeft(TIntermTyped* n) { left = n; } + virtual void setRight(TIntermTyped* n) { right = n; } + virtual TIntermTyped* getLeft() const { return left; } + virtual TIntermTyped* getRight() const { return right; } + virtual TIntermBinary* getAsBinaryNode() { return this; } + virtual bool promote(TInfoSink&); +protected: + TIntermTyped* left; + TIntermTyped* right; +}; + +// +// Nodes for unary math operators. +// +class TIntermUnary : public TIntermOperator { +public: + TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {} + TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {} + virtual void traverse(TIntermTraverser*); + virtual void setOperand(TIntermTyped* o) { operand = o; } + virtual TIntermTyped* getOperand() { return operand; } + virtual bool promote(TInfoSink&); +protected: + TIntermTyped* operand; +}; + +typedef TVector TIntermSequence; +typedef TVector TQualifierList; +// +// Nodes that operate on an arbitrary sized set of children. +// +class TIntermAggregate : public TIntermOperator { +public: + TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { } + TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { } + ~TIntermAggregate() { delete pragmaTable; } + virtual TIntermAggregate* getAsAggregate() { return this; } + virtual void setOperator(TOperator o) { op = o; } + virtual TIntermSequence& getSequence() { return sequence; } + virtual void setName(const TString& n) { name = n; } + virtual const TString& getName() const { return name; } + virtual void traverse(TIntermTraverser*); + virtual void setUserDefined() { userDefined = true; } + virtual bool isUserDefined() { return userDefined; } + virtual TQualifierList& getQualifier() { return qualifier; } + void setOptimize(bool o) { optimize = o; } + void setDebug(bool d) { debug = d; } + bool getOptimize() { return optimize; } + bool getDebug() { return debug; } + void addToPragmaTable(const TPragmaTable& pTable); + const TPragmaTable& getPragmaTable() const { return *pragmaTable; } +protected: + TIntermAggregate(const TIntermAggregate&); // disallow copy constructor + TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator + TIntermSequence sequence; + TQualifierList qualifier; + TString name; + bool userDefined; // used for user defined function names + bool optimize; + bool debug; + TPragmaTable *pragmaTable; +}; + +// +// For if tests. Simplified since there is no switch statement. +// +class TIntermSelection : public TIntermTyped { +public: + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : + TIntermTyped(TType(EbtVoid)), condition(cond), trueBlock(trueB), falseBlock(falseB) {} + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : + TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {} + virtual void traverse(TIntermTraverser*); + virtual TIntermNode* getCondition() const { return condition; } + virtual TIntermNode* getTrueBlock() const { return trueBlock; } + virtual TIntermNode* getFalseBlock() const { return falseBlock; } + virtual TIntermSelection* getAsSelectionNode() { return this; } +protected: + TIntermTyped* condition; + TIntermNode* trueBlock; + TIntermNode* falseBlock; +}; + +// +// For traversing the tree. User should derive from this, +// put their traversal specific data in it, and then pass +// it to a Traverse method. +// +// When using this, just fill in the methods for nodes you want visited. +// Return false from a pre-visit to skip visiting that node's subtree. +// +class TIntermTraverser { +public: + POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + + TIntermTraverser() : + visitSymbol(0), + visitConstantUnion(0), + visitBinary(0), + visitUnary(0), + visitSelection(0), + visitAggregate(0), + visitLoop(0), + visitBranch(0), + depth(0), + preVisit(true), + postVisit(false), + rightToLeft(false) {} + + void (*visitSymbol)(TIntermSymbol*, TIntermTraverser*); + void (*visitConstantUnion)(TIntermConstantUnion*, TIntermTraverser*); + bool (*visitBinary)(bool preVisit, TIntermBinary*, TIntermTraverser*); + bool (*visitUnary)(bool preVisit, TIntermUnary*, TIntermTraverser*); + bool (*visitSelection)(bool preVisit, TIntermSelection*, TIntermTraverser*); + bool (*visitAggregate)(bool preVisit, TIntermAggregate*, TIntermTraverser*); + bool (*visitLoop)(bool preVisit, TIntermLoop*, TIntermTraverser*); + bool (*visitBranch)(bool preVisit, TIntermBranch*, TIntermTraverser*); + + int depth; + bool preVisit; + bool postVisit; + bool rightToLeft; +}; + +#endif // __INTERMEDIATE_H diff --git a/glslang/MachineIndependent/InfoSink.cpp b/glslang/MachineIndependent/InfoSink.cpp new file mode 100644 index 0000000..b8c1f5f --- /dev/null +++ b/glslang/MachineIndependent/InfoSink.cpp @@ -0,0 +1,107 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#include "Include/InfoSink.h" + +#ifdef _WIN32 + #include +#endif + +void TInfoSinkBase::append(const char *s) +{ + if (outputStream & EString) { + checkMem(strlen(s)); + sink.append(s); + } + +#ifdef _WIN32 + if (outputStream & EDebugger) + OutputDebugString(s); +#endif + + if (outputStream & EStdOut) + fprintf(stdout, "%s", s); +} + +void TInfoSinkBase::append(int count, char c) +{ + if (outputStream & EString) { + checkMem(count); + sink.append(count, c); + } + +#ifdef _WIN32 + if (outputStream & EDebugger) { + char str[2]; + str[0] = c; + str[1] = '\0'; + OutputDebugString(str); + } +#endif + + if (outputStream & EStdOut) + fprintf(stdout, "%c", c); +} + +void TInfoSinkBase::append(const TPersistString& t) +{ + if (outputStream & EString) { + checkMem(t.size()); + sink.append(t); + } + +#ifdef _WIN32 + if (outputStream & EDebugger) + OutputDebugString(t.c_str()); +#endif + + if (outputStream & EStdOut) + fprintf(stdout, "%s", t.c_str()); +} + +void TInfoSinkBase::append(const TString& t) +{ + if (outputStream & EString) { + checkMem(t.size()); + sink.append(t.c_str()); + } + +#ifdef _WIN32 + if (outputStream & EDebugger) + OutputDebugString(t.c_str()); +#endif + + if (outputStream & EStdOut) + fprintf(stdout, "%s", t.c_str()); +} diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp new file mode 100644 index 0000000..3bb8a0c --- /dev/null +++ b/glslang/MachineIndependent/Initialize.cpp @@ -0,0 +1,962 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +// +// Create strings that declare built-in definitions, add built-ins that +// cannot be expressed in the files, and establish mappings between +// built-in functions and operators. +// + +#include "../Include/intermediate.h" +#include "Initialize.h" + +void TBuiltIns::initialize() +{ + // + // Initialize all the built-in strings for parsing. + // + TString BuiltInFunctions; + TString BuiltInFunctionsVertex; + TString BuiltInFunctionsFragment; + TString StandardVertexVaryings; + TString StandardFragmentVaryings; + TString StandardVertexAttributes; + TString StandardUniforms; + + { + //============================================================================ + // + // Prototypes for built-in functions seen by both vertex and fragment shaders. + // + //============================================================================ + + TString& s = BuiltInFunctions; + + // + // Angle and Trigonometric Functions. + // + s.append(TString("float radians(float degrees);")); + s.append(TString("vec2 radians(vec2 degrees);")); + s.append(TString("vec3 radians(vec3 degrees);")); + s.append(TString("vec4 radians(vec4 degrees);")); + + s.append(TString("float degrees(float radians);")); + s.append(TString("vec2 degrees(vec2 radians);")); + s.append(TString("vec3 degrees(vec3 radians);")); + s.append(TString("vec4 degrees(vec4 radians);")); + + s.append(TString("float sin(float angle);")); + s.append(TString("vec2 sin(vec2 angle);")); + s.append(TString("vec3 sin(vec3 angle);")); + s.append(TString("vec4 sin(vec4 angle);")); + + s.append(TString("float cos(float angle);")); + s.append(TString("vec2 cos(vec2 angle);")); + s.append(TString("vec3 cos(vec3 angle);")); + s.append(TString("vec4 cos(vec4 angle);")); + + s.append(TString("float tan(float angle);")); + s.append(TString("vec2 tan(vec2 angle);")); + s.append(TString("vec3 tan(vec3 angle);")); + s.append(TString("vec4 tan(vec4 angle);")); + + s.append(TString("float asin(float x);")); + s.append(TString("vec2 asin(vec2 x);")); + s.append(TString("vec3 asin(vec3 x);")); + s.append(TString("vec4 asin(vec4 x);")); + + s.append(TString("float acos(float x);")); + s.append(TString("vec2 acos(vec2 x);")); + s.append(TString("vec3 acos(vec3 x);")); + s.append(TString("vec4 acos(vec4 x);")); + + s.append(TString("float atan(float y, float x);")); + s.append(TString("vec2 atan(vec2 y, vec2 x);")); + s.append(TString("vec3 atan(vec3 y, vec3 x);")); + s.append(TString("vec4 atan(vec4 y, vec4 x);")); + + s.append(TString("float atan(float y_over_x);")); + s.append(TString("vec2 atan(vec2 y_over_x);")); + s.append(TString("vec3 atan(vec3 y_over_x);")); + s.append(TString("vec4 atan(vec4 y_over_x);")); + + // + // Exponential Functions. + // + s.append(TString("float pow(float x, float y);")); + s.append(TString("vec2 pow(vec2 x, vec2 y);")); + s.append(TString("vec3 pow(vec3 x, vec3 y);")); + s.append(TString("vec4 pow(vec4 x, vec4 y);")); + + s.append(TString("float exp(float x);")); + s.append(TString("vec2 exp(vec2 x);")); + s.append(TString("vec3 exp(vec3 x);")); + s.append(TString("vec4 exp(vec4 x);")); + + s.append(TString("float log(float x);")); + s.append(TString("vec2 log(vec2 x);")); + s.append(TString("vec3 log(vec3 x);")); + s.append(TString("vec4 log(vec4 x);")); + + s.append(TString("float exp2(float x);")); + s.append(TString("vec2 exp2(vec2 x);")); + s.append(TString("vec3 exp2(vec3 x);")); + s.append(TString("vec4 exp2(vec4 x);")); + + s.append(TString("float log2(float x);")); + s.append(TString("vec2 log2(vec2 x);")); + s.append(TString("vec3 log2(vec3 x);")); + s.append(TString("vec4 log2(vec4 x);")); + + s.append(TString("float sqrt(float x);")); + s.append(TString("vec2 sqrt(vec2 x);")); + s.append(TString("vec3 sqrt(vec3 x);")); + s.append(TString("vec4 sqrt(vec4 x);")); + + s.append(TString("float inversesqrt(float x);")); + s.append(TString("vec2 inversesqrt(vec2 x);")); + s.append(TString("vec3 inversesqrt(vec3 x);")); + s.append(TString("vec4 inversesqrt(vec4 x);")); + + // + // Common Functions. + // + s.append(TString("float abs(float x);")); + s.append(TString("vec2 abs(vec2 x);")); + s.append(TString("vec3 abs(vec3 x);")); + s.append(TString("vec4 abs(vec4 x);")); + + s.append(TString("float sign(float x);")); + s.append(TString("vec2 sign(vec2 x);")); + s.append(TString("vec3 sign(vec3 x);")); + s.append(TString("vec4 sign(vec4 x);")); + + s.append(TString("float floor(float x);")); + s.append(TString("vec2 floor(vec2 x);")); + s.append(TString("vec3 floor(vec3 x);")); + s.append(TString("vec4 floor(vec4 x);")); + + s.append(TString("float ceil(float x);")); + s.append(TString("vec2 ceil(vec2 x);")); + s.append(TString("vec3 ceil(vec3 x);")); + s.append(TString("vec4 ceil(vec4 x);")); + + s.append(TString("float fract(float x);")); + s.append(TString("vec2 fract(vec2 x);")); + s.append(TString("vec3 fract(vec3 x);")); + s.append(TString("vec4 fract(vec4 x);")); + + s.append(TString("float mod(float x, float y);")); + s.append(TString("vec2 mod(vec2 x, float y);")); + s.append(TString("vec3 mod(vec3 x, float y);")); + s.append(TString("vec4 mod(vec4 x, float y);")); + s.append(TString("vec2 mod(vec2 x, vec2 y);")); + s.append(TString("vec3 mod(vec3 x, vec3 y);")); + s.append(TString("vec4 mod(vec4 x, vec4 y);")); + + s.append(TString("float min(float x, float y);")); + s.append(TString("vec2 min(vec2 x, float y);")); + s.append(TString("vec3 min(vec3 x, float y);")); + s.append(TString("vec4 min(vec4 x, float y);")); + s.append(TString("vec2 min(vec2 x, vec2 y);")); + s.append(TString("vec3 min(vec3 x, vec3 y);")); + s.append(TString("vec4 min(vec4 x, vec4 y);")); + + s.append(TString("float max(float x, float y);")); + s.append(TString("vec2 max(vec2 x, float y);")); + s.append(TString("vec3 max(vec3 x, float y);")); + s.append(TString("vec4 max(vec4 x, float y);")); + s.append(TString("vec2 max(vec2 x, vec2 y);")); + s.append(TString("vec3 max(vec3 x, vec3 y);")); + s.append(TString("vec4 max(vec4 x, vec4 y);")); + + s.append(TString("float clamp(float x, float minVal, float maxVal);")); + s.append(TString("vec2 clamp(vec2 x, float minVal, float maxVal);")); + s.append(TString("vec3 clamp(vec3 x, float minVal, float maxVal);")); + s.append(TString("vec4 clamp(vec4 x, float minVal, float maxVal);")); + s.append(TString("vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);")); + s.append(TString("vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);")); + s.append(TString("vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);")); + + s.append(TString("float mix(float x, float y, float a);")); + s.append(TString("vec2 mix(vec2 x, vec2 y, float a);")); + s.append(TString("vec3 mix(vec3 x, vec3 y, float a);")); + s.append(TString("vec4 mix(vec4 x, vec4 y, float a);")); + s.append(TString("vec2 mix(vec2 x, vec2 y, vec2 a);")); + s.append(TString("vec3 mix(vec3 x, vec3 y, vec3 a);")); + s.append(TString("vec4 mix(vec4 x, vec4 y, vec4 a);")); + + s.append(TString("float step(float edge, float x);")); + s.append(TString("vec2 step(vec2 edge, vec2 x);")); + s.append(TString("vec3 step(vec3 edge, vec3 x);")); + s.append(TString("vec4 step(vec4 edge, vec4 x);")); + s.append(TString("vec2 step(float edge, vec2 x);")); + s.append(TString("vec3 step(float edge, vec3 x);")); + s.append(TString("vec4 step(float edge, vec4 x);")); + + s.append(TString("float smoothstep(float edge0, float edge1, float x);")); + s.append(TString("vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);")); + s.append(TString("vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);")); + s.append(TString("vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);")); + s.append(TString("vec2 smoothstep(float edge0, float edge1, vec2 x);")); + s.append(TString("vec3 smoothstep(float edge0, float edge1, vec3 x);")); + s.append(TString("vec4 smoothstep(float edge0, float edge1, vec4 x);")); + + // + // Geometric Functions. + // + s.append(TString("float length(float x);")); + s.append(TString("float length(vec2 x);")); + s.append(TString("float length(vec3 x);")); + s.append(TString("float length(vec4 x);")); + + s.append(TString("float distance(float p0, float p1);")); + s.append(TString("float distance(vec2 p0, vec2 p1);")); + s.append(TString("float distance(vec3 p0, vec3 p1);")); + s.append(TString("float distance(vec4 p0, vec4 p1);")); + + s.append(TString("float dot(float x, float y);")); + s.append(TString("float dot(vec2 x, vec2 y);")); + s.append(TString("float dot(vec3 x, vec3 y);")); + s.append(TString("float dot(vec4 x, vec4 y);")); + + s.append(TString("vec3 cross(vec3 x, vec3 y);")); + s.append(TString("float normalize(float x);")); + s.append(TString("vec2 normalize(vec2 x);")); + s.append(TString("vec3 normalize(vec3 x);")); + s.append(TString("vec4 normalize(vec4 x);")); + + s.append(TString("float faceforward(float N, float I, float Nref);")); + s.append(TString("vec2 faceforward(vec2 N, vec2 I, vec2 Nref);")); + s.append(TString("vec3 faceforward(vec3 N, vec3 I, vec3 Nref);")); + s.append(TString("vec4 faceforward(vec4 N, vec4 I, vec4 Nref);")); + + s.append(TString("float reflect(float I, float N);")); + s.append(TString("vec2 reflect(vec2 I, vec2 N);")); + s.append(TString("vec3 reflect(vec3 I, vec3 N);")); + s.append(TString("vec4 reflect(vec4 I, vec4 N);")); + + s.append(TString("float refract(float I, float N, float eta);")); + s.append(TString("vec2 refract(vec2 I, vec2 N, float eta);")); + s.append(TString("vec3 refract(vec3 I, vec3 N, float eta);")); + s.append(TString("vec4 refract(vec4 I, vec4 N, float eta);")); + + // + // Matrix Functions. + // + s.append(TString("mat2 matrixCompMult(mat2 x, mat2 y);")); + s.append(TString("mat3 matrixCompMult(mat3 x, mat3 y);")); + s.append(TString("mat4 matrixCompMult(mat4 x, mat4 y);")); + + // + // Vector relational functions. + // + s.append(TString("bvec2 lessThan(vec2 x, vec2 y);")); + s.append(TString("bvec3 lessThan(vec3 x, vec3 y);")); + s.append(TString("bvec4 lessThan(vec4 x, vec4 y);")); + + s.append(TString("bvec2 lessThan(ivec2 x, ivec2 y);")); + s.append(TString("bvec3 lessThan(ivec3 x, ivec3 y);")); + s.append(TString("bvec4 lessThan(ivec4 x, ivec4 y);")); + + s.append(TString("bvec2 lessThanEqual(vec2 x, vec2 y);")); + s.append(TString("bvec3 lessThanEqual(vec3 x, vec3 y);")); + s.append(TString("bvec4 lessThanEqual(vec4 x, vec4 y);")); + + s.append(TString("bvec2 lessThanEqual(ivec2 x, ivec2 y);")); + s.append(TString("bvec3 lessThanEqual(ivec3 x, ivec3 y);")); + s.append(TString("bvec4 lessThanEqual(ivec4 x, ivec4 y);")); + + s.append(TString("bvec2 greaterThan(vec2 x, vec2 y);")); + s.append(TString("bvec3 greaterThan(vec3 x, vec3 y);")); + s.append(TString("bvec4 greaterThan(vec4 x, vec4 y);")); + + s.append(TString("bvec2 greaterThan(ivec2 x, ivec2 y);")); + s.append(TString("bvec3 greaterThan(ivec3 x, ivec3 y);")); + s.append(TString("bvec4 greaterThan(ivec4 x, ivec4 y);")); + + s.append(TString("bvec2 greaterThanEqual(vec2 x, vec2 y);")); + s.append(TString("bvec3 greaterThanEqual(vec3 x, vec3 y);")); + s.append(TString("bvec4 greaterThanEqual(vec4 x, vec4 y);")); + + s.append(TString("bvec2 greaterThanEqual(ivec2 x, ivec2 y);")); + s.append(TString("bvec3 greaterThanEqual(ivec3 x, ivec3 y);")); + s.append(TString("bvec4 greaterThanEqual(ivec4 x, ivec4 y);")); + + s.append(TString("bvec2 equal(vec2 x, vec2 y);")); + s.append(TString("bvec3 equal(vec3 x, vec3 y);")); + s.append(TString("bvec4 equal(vec4 x, vec4 y);")); + + s.append(TString("bvec2 equal(ivec2 x, ivec2 y);")); + s.append(TString("bvec3 equal(ivec3 x, ivec3 y);")); + s.append(TString("bvec4 equal(ivec4 x, ivec4 y);")); + + s.append(TString("bvec2 equal(bvec2 x, bvec2 y);")); + s.append(TString("bvec3 equal(bvec3 x, bvec3 y);")); + s.append(TString("bvec4 equal(bvec4 x, bvec4 y);")); + + s.append(TString("bvec2 notEqual(vec2 x, vec2 y);")); + s.append(TString("bvec3 notEqual(vec3 x, vec3 y);")); + s.append(TString("bvec4 notEqual(vec4 x, vec4 y);")); + + s.append(TString("bvec2 notEqual(ivec2 x, ivec2 y);")); + s.append(TString("bvec3 notEqual(ivec3 x, ivec3 y);")); + s.append(TString("bvec4 notEqual(ivec4 x, ivec4 y);")); + + s.append(TString("bvec2 notEqual(bvec2 x, bvec2 y);")); + s.append(TString("bvec3 notEqual(bvec3 x, bvec3 y);")); + s.append(TString("bvec4 notEqual(bvec4 x, bvec4 y);")); + + s.append(TString("bool any(bvec2 x);")); + s.append(TString("bool any(bvec3 x);")); + s.append(TString("bool any(bvec4 x);")); + + s.append(TString("bool all(bvec2 x);")); + s.append(TString("bool all(bvec3 x);")); + s.append(TString("bool all(bvec4 x);")); + + s.append(TString("bvec2 not(bvec2 x);")); + s.append(TString("bvec3 not(bvec3 x);")); + s.append(TString("bvec4 not(bvec4 x);")); + + // + // Texture Functions. + // + s.append(TString("vec4 texture1D(sampler1D sampler, float coord);")); + s.append(TString("vec4 texture1DProj(sampler1D sampler, vec2 coord);")); + s.append(TString("vec4 texture1DProj(sampler1D sampler, vec4 coord);")); + + s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);")); + s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord);")); + s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord);")); + + s.append(TString("vec4 texture3D(sampler3D sampler, vec3 coord);")); + s.append(TString("vec4 texture3DProj(sampler3D sampler, vec4 coord);")); + + s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);")); + + s.append(TString("vec4 shadow1D(sampler1DShadow sampler, vec3 coord);")); + + s.append(TString("vec4 shadow2D(sampler2DShadow sampler, vec3 coord);")); + + s.append(TString("vec4 shadow1DProj(sampler1DShadow sampler, vec4 coord);")); + + s.append(TString("vec4 shadow2DProj(sampler2DShadow sampler, vec4 coord);")); + + // ARB_texture_rectangle + s.append(TString("vec4 texture2DRect(sampler2DRect sampler, vec2 coord);")); + s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec3 coord);")); + s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec4 coord);")); + s.append(TString("vec4 shadow2DRect(sampler2DRectShadow sampler, vec3 coord);")); + s.append(TString("vec4 shadow2DRectProj(sampler2DRectShadow sampler, vec4 coord);")); + + // + // Noise functions. + // + s.append(TString("float noise1(float x);")); + s.append(TString("float noise1(vec2 x);")); + s.append(TString("float noise1(vec3 x);")); + s.append(TString("float noise1(vec4 x);")); + + s.append(TString("vec2 noise2(float x);")); + s.append(TString("vec2 noise2(vec2 x);")); + s.append(TString("vec2 noise2(vec3 x);")); + s.append(TString("vec2 noise2(vec4 x);")); + + s.append(TString("vec3 noise3(float x);")); + s.append(TString("vec3 noise3(vec2 x);")); + s.append(TString("vec3 noise3(vec3 x);")); + s.append(TString("vec3 noise3(vec4 x);")); + + s.append(TString("vec4 noise4(float x);")); + s.append(TString("vec4 noise4(vec2 x);")); + s.append(TString("vec4 noise4(vec3 x);")); + s.append(TString("vec4 noise4(vec4 x);")); + + s.append(TString("\n")); + } + { + //============================================================================ + // + // Prototypes for built-in functions seen by vertex shaders only. + // + //============================================================================ + + TString& s = BuiltInFunctionsVertex; + + // + // Geometric Functions. + // + s.append(TString("vec4 ftransform();")); + + // + // Texture Functions. + // + s.append(TString("vec4 texture1DLod(sampler1D sampler, float coord, float lod);")); + s.append(TString("vec4 texture1DProjLod(sampler1D sampler, vec2 coord, float lod);")); + s.append(TString("vec4 texture1DProjLod(sampler1D sampler, vec4 coord, float lod);")); + + s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);")); + s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);")); + s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);")); + + s.append(TString("vec4 texture3DLod(sampler3D sampler, vec3 coord, float lod);")); + s.append(TString("vec4 texture3DProjLod(sampler3D sampler, vec4 coord, float lod);")); + s.append(TString("vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);")); + + s.append(TString("vec4 shadow1DLod(sampler1DShadow sampler, vec3 coord, float lod);")); + s.append(TString("vec4 shadow2DLod(sampler2DShadow sampler, vec3 coord, float lod);")); + s.append(TString("vec4 shadow1DProjLod(sampler1DShadow sampler, vec4 coord, float lod);")); + s.append(TString("vec4 shadow2DProjLod(sampler2DShadow sampler, vec4 coord, float lod);")); + + s.append(TString("\n")); + } + { + //============================================================================ + // + // Prototypes for built-in functions seen by fragment shaders only. + // + //============================================================================ + + TString& s = BuiltInFunctionsFragment; + + // + // Texture Functions. + // + s.append(TString("vec4 texture1D(sampler1D sampler, float coord, float bias);")); + s.append(TString("vec4 texture1DProj(sampler1D sampler, vec2 coord, float bias);")); + s.append(TString("vec4 texture1DProj(sampler1D sampler, vec4 coord, float bias);")); + + s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord, float bias);")); + s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);")); + s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);")); + + s.append(TString("vec4 texture3D(sampler3D sampler, vec3 coord, float bias);")); + s.append(TString("vec4 texture3DProj(sampler3D sampler, vec4 coord, float bias);")); + s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord, float bias);")); + + s.append(TString("vec4 shadow1D(sampler1DShadow sampler, vec3 coord, float bias);")); + s.append(TString("vec4 shadow2D(sampler2DShadow sampler, vec3 coord, float bias);")); + s.append(TString("vec4 shadow1DProj(sampler1DShadow sampler, vec4 coord, float bias);")); + s.append(TString("vec4 shadow2DProj(sampler2DShadow sampler, vec4 coord, float bias);")); + + s.append(TString("float dFdx(float p);")); + s.append(TString("vec2 dFdx(vec2 p);")); + s.append(TString("vec3 dFdx(vec3 p);")); + s.append(TString("vec4 dFdx(vec4 p);")); + + s.append(TString("float dFdy(float p);")); + s.append(TString("vec2 dFdy(vec2 p);")); + s.append(TString("vec3 dFdy(vec3 p);")); + s.append(TString("vec4 dFdy(vec4 p);")); + + s.append(TString("float fwidth(float p);")); + s.append(TString("vec2 fwidth(vec2 p);")); + s.append(TString("vec3 fwidth(vec3 p);")); + s.append(TString("vec4 fwidth(vec4 p);")); + + s.append(TString("\n")); + } + { + //============================================================================ + // + // Standard Uniforms + // + //============================================================================ + + TString& s = StandardUniforms; + + + // + // OpenGL'uniform' state. Page numbers are in reference to version + // 1.4 of the OpenGL specification. + // + + // + // Matrix state. p. 31, 32, 37, 39, 40. + // + s.append(TString("uniform mat4 gl_ModelViewMatrix;")); + s.append(TString("uniform mat4 gl_ProjectionMatrix;")); + s.append(TString("uniform mat4 gl_ModelViewProjectionMatrix;")); + + // + // Derived matrix state that provides inverse and transposed versions + // of the matrices above. + // + s.append(TString("uniform mat3 gl_NormalMatrix;")); + + s.append(TString("uniform mat4 gl_ModelViewMatrixInverse;")); + s.append(TString("uniform mat4 gl_ProjectionMatrixInverse;")); + s.append(TString("uniform mat4 gl_ModelViewProjectionMatrixInverse;")); + + s.append(TString("uniform mat4 gl_ModelViewMatrixTranspose;")); + s.append(TString("uniform mat4 gl_ProjectionMatrixTranspose;")); + s.append(TString("uniform mat4 gl_ModelViewProjectionMatrixTranspose;")); + + s.append(TString("uniform mat4 gl_ModelViewMatrixInverseTranspose;")); + s.append(TString("uniform mat4 gl_ProjectionMatrixInverseTranspose;")); + s.append(TString("uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;")); + + // + // Normal scaling p. 39. + // + s.append(TString("uniform float gl_NormalScale;")); + + // + // Depth range in window coordinates, p. 33 + // + s.append(TString("struct gl_DepthRangeParameters {")); + s.append(TString(" float near;")); // n + s.append(TString(" float far;")); // f + s.append(TString(" float diff;")); // f - n + s.append(TString("};")); + s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;")); + + + // + // Point Size, p. 66, 67. + // + s.append(TString("struct gl_PointParameters {")); + s.append(TString(" float size;")); + s.append(TString(" float sizeMin;")); + s.append(TString(" float sizeMax;")); + s.append(TString(" float fadeThresholdSize;")); + s.append(TString(" float distanceConstantAttenuation;")); + s.append(TString(" float distanceLinearAttenuation;")); + s.append(TString(" float distanceQuadraticAttenuation;")); + s.append(TString("};")); + + s.append(TString("uniform gl_PointParameters gl_Point;")); + + // + // Material State p. 50, 55. + // + s.append(TString("struct gl_MaterialParameters {")); + s.append(TString(" vec4 emission;")); // Ecm + s.append(TString(" vec4 ambient;")); // Acm + s.append(TString(" vec4 diffuse;")); // Dcm + s.append(TString(" vec4 specular;")); // Scm + s.append(TString(" float shininess;")); // Srm + s.append(TString("};")); + s.append(TString("uniform gl_MaterialParameters gl_FrontMaterial;")); + s.append(TString("uniform gl_MaterialParameters gl_BackMaterial;")); + + // + // Light State p 50, 53, 55. + // + + s.append(TString("struct gl_LightSourceParameters {")); + s.append(TString(" vec4 ambient;")); // Acli + s.append(TString(" vec4 diffuse;")); // Dcli + s.append(TString(" vec4 specular;")); // Scli + s.append(TString(" vec4 position;")); // Ppli + s.append(TString(" vec4 halfVector;")); // Derived: Hi + s.append(TString(" vec3 spotDirection;")); // Sdli + s.append(TString(" float spotExponent;")); // Srli + s.append(TString(" float spotCutoff;")); // Crli + // (range: [0.0,90.0], 180.0) + s.append(TString(" float spotCosCutoff;")); // Derived: cos(Crli) + // (range: [1.0,0.0],-1.0) + s.append(TString(" float constantAttenuation;")); // K0 + s.append(TString(" float linearAttenuation;")); // K1 + s.append(TString(" float quadraticAttenuation;"));// K2 + s.append(TString("};")); + + + s.append(TString("struct gl_LightModelParameters {")); + s.append(TString(" vec4 ambient;")); // Acs + s.append(TString("};")); + + s.append(TString("uniform gl_LightModelParameters gl_LightModel;")); + + // + // Derived state from products of light and material. + // + + s.append(TString("struct gl_LightModelProducts {")); + s.append(TString(" vec4 sceneColor;")); // Derived. Ecm + Acm * Acs + s.append(TString("};")); + + s.append(TString("uniform gl_LightModelProducts gl_FrontLightModelProduct;")); + s.append(TString("uniform gl_LightModelProducts gl_BackLightModelProduct;")); + + s.append(TString("struct gl_LightProducts {")); + s.append(TString(" vec4 ambient;")); // Acm * Acli + s.append(TString(" vec4 diffuse;")); // Dcm * Dcli + s.append(TString(" vec4 specular;")); // Scm * Scli + s.append(TString("};")); + + + + + // + // Fog p. 161 + // + s.append(TString("struct gl_FogParameters {")); + s.append(TString(" vec4 color;")); + s.append(TString(" float density;")); + s.append(TString(" float start;")); + s.append(TString(" float end;")); + s.append(TString(" float scale;")); // 1 / (gl_FogEnd - gl_FogStart) + s.append(TString("};")); + + s.append(TString("uniform gl_FogParameters gl_Fog;")); + + s.append(TString("\n")); + } + { + //============================================================================ + // + // Vertex attributes, p. 19. + // + //============================================================================ + + TString& s = StandardVertexAttributes; + + s.append(TString("attribute vec4 gl_Color;")); + s.append(TString("attribute vec4 gl_SecondaryColor;")); + s.append(TString("attribute vec3 gl_Normal;")); + s.append(TString("attribute vec4 gl_Vertex;")); + s.append(TString("attribute vec4 gl_MultiTexCoord0;")); + s.append(TString("attribute vec4 gl_MultiTexCoord1;")); + s.append(TString("attribute vec4 gl_MultiTexCoord2;")); + s.append(TString("attribute vec4 gl_MultiTexCoord3;")); + s.append(TString("attribute vec4 gl_MultiTexCoord4;")); + s.append(TString("attribute vec4 gl_MultiTexCoord5;")); + s.append(TString("attribute vec4 gl_MultiTexCoord6;")); + s.append(TString("attribute vec4 gl_MultiTexCoord7;")); + s.append(TString("attribute float gl_FogCoord;")); + + s.append(TString("\n")); + } + { + //============================================================================ + // + // Define the output varying interface from the vertex shader. + // + //============================================================================ + + TString& s = StandardVertexVaryings; + + s.append(TString("varying vec4 gl_FrontColor;")); + s.append(TString("varying vec4 gl_BackColor;")); + s.append(TString("varying vec4 gl_FrontSecondaryColor;")); + s.append(TString("varying vec4 gl_BackSecondaryColor;")); + s.append(TString("varying vec4 gl_TexCoord[];")); + s.append(TString("varying float gl_FogFragCoord;")); + + s.append(TString("\n")); + } + { + //============================================================================ + // + // Define the input varying interface to the fragment shader. + // + //============================================================================ + + TString& s = StandardFragmentVaryings; + + s.append(TString("varying vec4 gl_Color;")); + s.append(TString("varying vec4 gl_SecondaryColor;")); + s.append(TString("varying vec4 gl_TexCoord[];")); + s.append(TString("varying float gl_FogFragCoord;")); + + s.append(TString("\n")); + } + + builtInStrings[EShLangFragment].push_back(BuiltInFunctions.c_str()); + builtInStrings[EShLangFragment].push_back(BuiltInFunctionsFragment); + builtInStrings[EShLangFragment].push_back(StandardUniforms); + builtInStrings[EShLangFragment].push_back(StandardFragmentVaryings); + + builtInStrings[EShLangVertex].push_back(BuiltInFunctions); + builtInStrings[EShLangVertex].push_back(BuiltInFunctionsVertex); + builtInStrings[EShLangVertex].push_back(StandardVertexVaryings); + builtInStrings[EShLangVertex].push_back(StandardVertexAttributes); + builtInStrings[EShLangVertex].push_back(StandardUniforms); +} + + +void TBuiltIns::initialize(const TBuiltInResource &resources) +{ + // + // Initialize all the built-in strings for parsing. + // + TString StandardUniforms; + + { + //============================================================================ + // + // Standard Uniforms + // + //============================================================================ + + TString& s = StandardUniforms; + + // + // Implementation dependent constants. The example values below + // are the minimum values allowed for these maximums. + // + char builtInConstant[80]; + sprintf(builtInConstant, "const int gl_MaxLights = %d;", resources.maxLights); // GL 1.0 + s.append(TString(builtInConstant)); + + sprintf(builtInConstant, "const int gl_MaxClipPlanes = %d;", resources.maxClipPlanes); // GL 1.0 + s.append(TString(builtInConstant)); + + sprintf(builtInConstant, "const int gl_MaxTextureUnits = %d;", resources.maxTextureUnits); // GL 1.2 + s.append(TString(builtInConstant)); + + sprintf(builtInConstant, "const int gl_MaxTextureCoords = %d;", resources.maxTextureCoords); // ARB_fragment_program + s.append(TString(builtInConstant)); + + sprintf(builtInConstant, "const int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs); // ARB_vertex_shader + s.append(TString(builtInConstant)); + + sprintf(builtInConstant, "const int gl_MaxVertexUniformComponents = %d;", resources.maxVertexUniformComponents); // ARB_vertex_shader + s.append(TString(builtInConstant)); + + sprintf(builtInConstant, "const int gl_MaxVaryingFloats = %d;", resources.maxVaryingFloats); // ARB_vertex_shader + s.append(TString(builtInConstant)); + + sprintf(builtInConstant, "const int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits); // ARB_vertex_shader + s.append(TString(builtInConstant)); + + sprintf(builtInConstant, "const int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits); // ARB_vertex_shader + s.append(TString(builtInConstant)); + + sprintf(builtInConstant, "const int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits); // ARB_fragment_shader + s.append(TString(builtInConstant)); + + sprintf(builtInConstant, "const int gl_MaxFragmentUniformComponents = %d;", resources.maxFragmentUniformComponents); // ARB_fragment_shader + s.append(TString(builtInConstant)); + + sprintf(builtInConstant, "const int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers); // proposed ARB_draw_buffers + s.append(TString(builtInConstant)); + + // + // OpenGL'uniform' state. Page numbers are in reference to version + // 1.4 of the OpenGL specification. + // + + // + // Matrix state. p. 31, 32, 37, 39, 40. + // + s.append(TString("uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];")); + + // + // Derived matrix state that provides inverse and transposed versions + // of the matrices above. + // + s.append(TString("uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];")); + + s.append(TString("uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];")); + + s.append(TString("uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];")); + + // + // Clip planes p. 42. + // + s.append(TString("uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];")); + + // + // Light State p 50, 53, 55. + // + s.append(TString("uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];")); + + // + // Derived state from products of light. + // + s.append(TString("uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];")); + s.append(TString("uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];")); + + // + // Textureg Environment and Generation, p. 152, p. 40-42. + // + s.append(TString("uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];")); + s.append(TString("uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];")); + s.append(TString("uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];")); + + s.append(TString("\n")); + } + + builtInStrings[EShLangFragment].push_back(StandardUniforms); + builtInStrings[EShLangVertex].push_back(StandardUniforms); +} + +void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable) +{ + // + // First, insert some special built-in variables that are not in + // the built-in header files. + // + switch(language) { + + case EShLangFragment: { + symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EvqFace, 1))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EvqFragCoord, 4))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EvqFragColor, 4))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepth"), TType(EbtFloat, EvqFragDepth, 1))); + + } + break; + + case EShLangVertex: + symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EvqPosition, 4))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EvqPointSize, 1))); + symbolTable.insert(*new TVariable(NewPoolTString("gl_ClipVertex"), TType(EbtFloat, EvqClipVertex, 4))); + break; + default: break; + } + + // + // Next, identify which built-ins from the already loaded headers have + // a mapping to an operator. Those that are not identified as such are + // expected to be resolved through a library of functions, versus as + // operations. + // + symbolTable.relateToOperator("not", EOpVectorLogicalNot); + + symbolTable.relateToOperator("matrixCompMult", EOpMul); + symbolTable.relateToOperator("mod", EOpMod); + + symbolTable.relateToOperator("equal", EOpVectorEqual); + symbolTable.relateToOperator("notEqual", EOpVectorNotEqual); + symbolTable.relateToOperator("lessThan", EOpLessThan); + symbolTable.relateToOperator("greaterThan", EOpGreaterThan); + symbolTable.relateToOperator("lessThanEqual", EOpLessThanEqual); + symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual); + + symbolTable.relateToOperator("radians", EOpRadians); + symbolTable.relateToOperator("degrees", EOpDegrees); + symbolTable.relateToOperator("sin", EOpSin); + symbolTable.relateToOperator("cos", EOpCos); + symbolTable.relateToOperator("tan", EOpTan); + symbolTable.relateToOperator("asin", EOpAsin); + symbolTable.relateToOperator("acos", EOpAcos); + symbolTable.relateToOperator("atan", EOpAtan); + + symbolTable.relateToOperator("pow", EOpPow); + symbolTable.relateToOperator("exp2", EOpExp2); + symbolTable.relateToOperator("log", EOpLog); + symbolTable.relateToOperator("exp", EOpExp); + symbolTable.relateToOperator("log2", EOpLog2); + symbolTable.relateToOperator("sqrt", EOpSqrt); + symbolTable.relateToOperator("inversesqrt", EOpInverseSqrt); + + symbolTable.relateToOperator("abs", EOpAbs); + symbolTable.relateToOperator("sign", EOpSign); + symbolTable.relateToOperator("floor", EOpFloor); + symbolTable.relateToOperator("ceil", EOpCeil); + symbolTable.relateToOperator("fract", EOpFract); + symbolTable.relateToOperator("min", EOpMin); + symbolTable.relateToOperator("max", EOpMax); + symbolTable.relateToOperator("clamp", EOpClamp); + symbolTable.relateToOperator("mix", EOpMix); + symbolTable.relateToOperator("step", EOpStep); + symbolTable.relateToOperator("smoothstep", EOpSmoothStep); + + symbolTable.relateToOperator("length", EOpLength); + symbolTable.relateToOperator("distance", EOpDistance); + symbolTable.relateToOperator("dot", EOpDot); + symbolTable.relateToOperator("cross", EOpCross); + symbolTable.relateToOperator("normalize", EOpNormalize); + symbolTable.relateToOperator("forward", EOpFaceForward); + symbolTable.relateToOperator("reflect", EOpReflect); + symbolTable.relateToOperator("refract", EOpRefract); + + symbolTable.relateToOperator("any", EOpAny); + symbolTable.relateToOperator("all", EOpAll); + + switch(language) { + + case EShLangVertex: + break; + + case EShLangFragment: + symbolTable.relateToOperator("dFdx", EOpDPdx); + symbolTable.relateToOperator("dFdy", EOpDPdy); + symbolTable.relateToOperator("fwidth", EOpFwidth); + + break; + + case EShLangPack: + case EShLangUnpack: + symbolTable.relateToOperator("itof", EOpItof); + symbolTable.relateToOperator("ftoi", EOpFtoi); + symbolTable.relateToOperator("skipPixels", EOpSkipPixels); + symbolTable.relateToOperator("readInput", EOpReadInput); + symbolTable.relateToOperator("writePixel", EOpWritePixel); + symbolTable.relateToOperator("bitmapLSB", EOpBitmapLsb); + symbolTable.relateToOperator("bitmapMSB", EOpBitmapMsb); + symbolTable.relateToOperator("writeOutput", EOpWriteOutput); + symbolTable.relateToOperator("readPixel", EOpReadPixel); + break; + default: assert(false && "Language not supported"); + } +} + +void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) +{ + // + // First, insert some special built-in variables that are not in + // the built-in header files. + // + switch(language) { + + case EShLangFragment: { + // Set up gl_FragData. The array size. + TType fragData(EbtFloat, EvqFragColor, 4, false, true); + fragData.setArraySize(resources.maxDrawBuffers); + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData)); + } + break; + + default: break; + } +} + +char* GetPreprocessorBuiltinString() +{ + static char *PreprocessorBuiltinString = "#define GL_ARB_texture_rectangle 1\n" + "#define GL_3DL_array_objects 1\n"; + + return PreprocessorBuiltinString; +} diff --git a/glslang/MachineIndependent/Initialize.h b/glslang/MachineIndependent/Initialize.h new file mode 100644 index 0000000..b4f4a03 --- /dev/null +++ b/glslang/MachineIndependent/Initialize.h @@ -0,0 +1,63 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _INITIALIZE_INCLUDED_ +#define _INITIALIZE_INCLUDED_ + +#include "Include/ResourceLimits.h" +#include "../Include/Common.h" +#include "../Include/ShHandle.h" +#include "SymbolTable.h" + +typedef TVector TBuiltInStrings; + +class TBuiltIns { +public: + POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + void initialize(); + void initialize(const TBuiltInResource& resources); + TBuiltInStrings* getBuiltInStrings() { return builtInStrings; } +protected: + TBuiltInStrings builtInStrings[EShLangCount]; +}; + +void IdentifyBuiltIns(EShLanguage, TSymbolTable&); +void IdentifyBuiltIns(EShLanguage, TSymbolTable&, const TBuiltInResource &resources); +bool GenerateBuiltInSymbolTable(const TBuiltInResource* resources, TInfoSink&, TSymbolTable*, EShLanguage language = EShLangCount); +bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language, TInfoSink& infoSink, const TBuiltInResource *resources, TSymbolTable*); +char* GetPreprocessorBuiltinString(); +extern "C" int InitPreprocessor(void); +extern "C" int FinalizePreprocessor(void); + +#endif // _INITIALIZE_INCLUDED_ diff --git a/glslang/MachineIndependent/IntermTraverse.cpp b/glslang/MachineIndependent/IntermTraverse.cpp new file mode 100644 index 0000000..8b379db --- /dev/null +++ b/glslang/MachineIndependent/IntermTraverse.cpp @@ -0,0 +1,243 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#include "../Include/intermediate.h" + +// +// Traverse the intermediate representation tree, and +// call a node type specific function for each node. +// Done recursively through the member function Traverse(). +// Node types can be skipped if their function to call is 0, +// but their subtree will still be traversed. +// Nodes with children can have their whole subtree skipped +// if preVisit is turned on and the type specific function +// returns false. +// +// preVisit, postVisit, and rightToLeft control what order +// nodes are visited in. +// + +// +// Traversal functions for terminals are straighforward.... +// +void TIntermSymbol::traverse(TIntermTraverser* it) +{ + if (it->visitSymbol) + it->visitSymbol(this, it); +} + +void TIntermConstantUnion::traverse(TIntermTraverser* it) +{ + if (it->visitConstantUnion) + it->visitConstantUnion(this, it); +} + +// +// Traverse a binary node. +// +void TIntermBinary::traverse(TIntermTraverser* it) +{ + bool visit = true; + + // + // visit the node before children if pre-visiting. + // + if (it->preVisit && it->visitBinary) + visit = it->visitBinary(true, this, it); + + // + // Visit the children, in the right order. + // + if (visit) { + ++it->depth; + if (it->rightToLeft) { + if (right) + right->traverse(it); + if (left) + left->traverse(it); + } else { + if (left) + left->traverse(it); + if (right) + right->traverse(it); + } + --it->depth; + } + + // + // Visit the node after the children, if requested and the traversal + // hasn't been cancelled yet. + // + if (visit && it->postVisit && it->visitBinary) + it->visitBinary(false, this, it); +} + +// +// Traverse a unary node. Same comments in binary node apply here. +// +void TIntermUnary::traverse(TIntermTraverser* it) +{ + bool visit = true; + + if (it->preVisit && it->visitUnary) + visit = it->visitUnary(true, this, it); + + if (visit) { + ++it->depth; + operand->traverse(it); + --it->depth; + } + + if (visit && it->postVisit && it->visitUnary) + it->visitUnary(false, this, it); +} + +// +// Traverse an aggregate node. Same comments in binary node apply here. +// +void TIntermAggregate::traverse(TIntermTraverser* it) +{ + bool visit = true; + + if (it->preVisit && it->visitAggregate) + visit = it->visitAggregate(true, this, it); + + if (visit) { + ++it->depth; + + TIntermSequence::iterator sit; + if (it->rightToLeft) { + sit = sequence.end(); + while (sit != sequence.begin()) { + --sit; + (*sit)->traverse(it); + } + } else { + for (sit = sequence.begin(); sit != sequence.end(); ++sit) + (*sit)->traverse(it); + } + + --it->depth; + } + + if (visit && it->postVisit && it->visitAggregate) + it->visitAggregate(false, this, it); +} + +// +// Traverse a selection node. Same comments in binary node apply here. +// +void TIntermSelection::traverse(TIntermTraverser* it) +{ + bool visit = true; + + if (it->preVisit && it->visitSelection) + visit = it->visitSelection(true, this, it); + + if (visit) { + ++it->depth; + if (it->rightToLeft) { + if (falseBlock) + falseBlock->traverse(it); + if (trueBlock) + trueBlock->traverse(it); + condition->traverse(it); + } else { + condition->traverse(it); + if (trueBlock) + trueBlock->traverse(it); + if (falseBlock) + falseBlock->traverse(it); + } + --it->depth; + } + + if (visit && it->postVisit && it->visitSelection) + it->visitSelection(false, this, it); +} + +// +// Traverse a loop node. Same comments in binary node apply here. +// +void TIntermLoop::traverse(TIntermTraverser* it) +{ + bool visit = true; + + if (it->preVisit && it->visitLoop) + visit = it->visitLoop(true, this, it); + + if (visit) { + ++it->depth; + if (it->rightToLeft) { + if (terminal) + terminal->traverse(it); + if (body) + body->traverse(it); + if (test) + test->traverse(it); + } else { + if (test) + test->traverse(it); + if (body) + body->traverse(it); + if (terminal) + terminal->traverse(it); + } + --it->depth; + } + + if (visit && it->postVisit && it->visitLoop) + it->visitLoop(false, this, it); +} + +// +// Traverse a branch node. Same comments in binary node apply here. +// +void TIntermBranch::traverse(TIntermTraverser* it) +{ + bool visit = true; + + if (it->preVisit && it->visitBranch) + visit = it->visitBranch(true, this, it); + + if (visit && expression) { + ++it->depth; + expression->traverse(it); + --it->depth; + } + + if (visit && it->postVisit && it->visitBranch) + it->visitBranch(false, this, it); +} + diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp new file mode 100644 index 0000000..96c9074 --- /dev/null +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -0,0 +1,1514 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +// +// Build the intermediate representation. +// + +#include "localintermediate.h" +#include "QualifierAlive.h" +#include "RemoveTree.h" +#include + +bool CompareStructure(const TType& leftNodeType, constUnion* rightUnionArray, constUnion* leftUnionArray); + +//////////////////////////////////////////////////////////////////////////// +// +// First set of functions are to help build the intermediate representation. +// These functions are not member functions of the nodes. +// They are called from parser productions. +// +///////////////////////////////////////////////////////////////////////////// + +// +// Add a terminal node for an identifier in an expression. +// +// Returns the added node. +// +TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line) +{ + TIntermSymbol* node = new TIntermSymbol(id, name, type); + node->setLine(line); + + return node; +} + +// +// Connect two nodes with a new parent that does a binary operation on the nodes. +// +// Returns the added node. +// +TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable) +{ + switch (op) { + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if (left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector() || left->getType().getBasicType() == EbtStruct) { + return 0; + } + break; + case EOpLogicalOr: + case EOpLogicalXor: + case EOpLogicalAnd: + if (left->getType().getBasicType() != EbtBool || left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector()) { + return 0; + } + break; + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpMul: + if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool) + return 0; + default: break; + } + + // + // First try converting the children to compatible types. + // + + if (!(left->getType().getStruct() && right->getType().getStruct())) { + TIntermTyped* child = addConversion(op, left->getType(), right); + if (child) + right = child; + else { + child = addConversion(op, right->getType(), left); + if (child) + left = child; + else + return 0; + } + } else { + if (left->getType() != right->getType()) + return 0; + } + + + // + // Need a new node holding things together then. Make + // one and promote it to the right type. + // + TIntermBinary* node = new TIntermBinary(op); + if (line == 0) + line = right->getLine(); + node->setLine(line); + + node->setLeft(left); + node->setRight(right); + if (! node->promote(infoSink)) + return 0; + + TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); + TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); + + if (leftTempConstant) + leftTempConstant = left->getAsConstantUnion(); + + if (rightTempConstant) + rightTempConstant = right->getAsConstantUnion(); + + // + // See if we can fold constants. + // + + TIntermTyped* typedReturnNode = 0; + if ( leftTempConstant && rightTempConstant) { + typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink); + + if (typedReturnNode) + return typedReturnNode; + } + + return node; +} + +// +// Connect two nodes through an assignment. +// +// Returns the added node. +// +TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line) +{ + // + // Like adding binary math, except the conversion can only go + // from right to left. + // + TIntermBinary* node = new TIntermBinary(op); + if (line == 0) + line = left->getLine(); + node->setLine(line); + + TIntermTyped* child = addConversion(op, left->getType(), right); + if (child == 0) + return 0; + + node->setLeft(left); + node->setRight(child); + if (! node->promote(infoSink)) + return 0; + + return node; +} + +// +// Connect two nodes through an index operator, where the left node is the base +// of an array or struct, and the right node is a direct or indirect offset. +// +// Returns the added node. +// The caller should set the type of the returned node. +// +TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line) +{ + TIntermBinary* node = new TIntermBinary(op); + if (line == 0) + line = index->getLine(); + node->setLine(line); + node->setLeft(base); + node->setRight(index); + + // caller should set the type + + return node; +} + +// +// Add one node as the parent of another that it operates on. +// +// Returns the added node. +// +TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable) +{ + TIntermUnary* node; + TIntermTyped* child = childNode->getAsTyped(); + + if (child == 0) { + infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line); + return 0; + } + + switch (op) { + case EOpLogicalNot: + if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { + return 0; + } + break; + + case EOpPostIncrement: + case EOpPreIncrement: + case EOpPostDecrement: + case EOpPreDecrement: + case EOpNegative: + if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) + return 0; + default: break; + } + + // + // Do we need to promote the operand? + // + // Note: Implicit promotions were removed from the language. + // + TBasicType newType = EbtVoid; + switch (op) { + case EOpConstructInt: newType = EbtInt; break; + case EOpConstructBool: newType = EbtBool; break; + case EOpConstructFloat: newType = EbtFloat; break; + default: break; + } + + if (newType != EbtVoid) { + child = addConversion(op, TType(newType, EvqTemporary, child->getNominalSize(), + child->isMatrix(), + child->isArray()), + child); + if (child == 0) + return 0; + } + + // + // For constructors, we are now done, it's all in the conversion. + // + switch (op) { + case EOpConstructInt: + case EOpConstructBool: + case EOpConstructFloat: + return child; + default: break; + } + + TIntermConstantUnion *childTempConstant = 0; + if (child->getAsConstantUnion()) + childTempConstant = child->getAsConstantUnion(); + + // + // Make a new node for the operator. + // + node = new TIntermUnary(op); + if (line == 0) + line = child->getLine(); + node->setLine(line); + node->setOperand(child); + + if (! node->promote(infoSink)) + return 0; + + if (childTempConstant) { + TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink); + + if (newChild) + return newChild; + } + + return node; +} + +// +// This is the safe way to change the operator on an aggregate, as it +// does lots of error checking and fixing. Especially for establishing +// a function call's operation on it's set of parameters. Sequences +// of instructions are also aggregates, but they just direnctly set +// their operator to EOpSequence. +// +// Returns an aggregate node, which could be the one passed in if +// it was already an aggregate. +// +TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line) +{ + TIntermAggregate* aggNode; + + // + // Make sure we have an aggregate. If not turn it into one. + // + if (node) { + aggNode = node->getAsAggregate(); + if (aggNode == 0 || aggNode->getOp() != EOpNull) { + // + // Make an aggregate containing this node. + // + aggNode = new TIntermAggregate(); + aggNode->getSequence().push_back(node); + if (line == 0) + line = node->getLine(); + } + } else + aggNode = new TIntermAggregate(); + + // + // Set the operator. + // + aggNode->setOperator(op); + if (line != 0) + aggNode->setLine(line); + + return aggNode; +} + +// +// Convert one type to another. +// +// Returns the node representing the conversion, which could be the same +// node passed in if no conversion was needed. +// +// Return 0 if a conversion can't be done. +// +TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) +{ + // + // Does the base type allow operation? + // + switch (node->getBasicType()) { + case EbtVoid: + case EbtSampler1D: + case EbtSampler2D: + case EbtSampler3D: + case EbtSamplerCube: + case EbtSampler1DShadow: + case EbtSampler2DShadow: + case EbtSamplerRect: // ARB_texture_rectangle + case EbtSamplerRectShadow: // ARB_texture_rectangle + return 0; + default: break; + } + + // + // Otherwise, if types are identical, no problem + // + if (type == node->getType()) + return node; + + // + // If one's a structure, then no conversions. + // + if (type.getStruct() || node->getType().getStruct()) + return 0; + + // + // If one's an array, then no conversions. + // + if (type.isArray() || node->getType().isArray()) + return 0; + + TBasicType promoteTo; + + switch (op) { + // + // Explicit conversions + // + case EOpConstructBool: + promoteTo = EbtBool; + break; + case EOpConstructFloat: + promoteTo = EbtFloat; + break; + case EOpConstructInt: + promoteTo = EbtInt; + break; + default: + // + // implicit conversions were removed from the language. + // + if (type.getBasicType() != node->getType().getBasicType()) + return 0; + // + // Size and structure could still differ, but that's + // handled by operator promotion. + // + return node; + } + + if (node->getAsConstantUnion()) { + + return (promoteConstantUnion(promoteTo, node->getAsConstantUnion())); + } else { + + // + // Add a new newNode for the conversion. + // + TIntermUnary* newNode = 0; + + TOperator newOp = EOpNull; + switch (promoteTo) { + case EbtFloat: + switch (node->getBasicType()) { + case EbtInt: newOp = EOpConvIntToFloat; break; + case EbtBool: newOp = EOpConvBoolToFloat; break; + default: + infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); + return 0; + } + break; + case EbtBool: + switch (node->getBasicType()) { + case EbtInt: newOp = EOpConvIntToBool; break; + case EbtFloat: newOp = EOpConvFloatToBool; break; + default: + infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); + return 0; + } + break; + case EbtInt: + switch (node->getBasicType()) { + case EbtBool: newOp = EOpConvBoolToInt; break; + case EbtFloat: newOp = EOpConvFloatToInt; break; + default: + infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); + return 0; + } + break; + default: + infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine()); + return 0; + } + + TType type(promoteTo, EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray()); + newNode = new TIntermUnary(newOp, type); + newNode->setLine(node->getLine()); + newNode->setOperand(node); + + return newNode; + } +} + +// +// Safe way to combine two nodes into an aggregate. Works with null pointers, +// a node that's not a aggregate yet, etc. +// +// Returns the resulting aggregate, unless 0 was passed in for +// both existing nodes. +// +TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line) +{ + if (left == 0 && right == 0) + return 0; + + TIntermAggregate* aggNode = 0; + if (left) + aggNode = left->getAsAggregate(); + if (!aggNode || aggNode->getOp() != EOpNull) { + aggNode = new TIntermAggregate; + if (left) + aggNode->getSequence().push_back(left); + } + + if (right) + aggNode->getSequence().push_back(right); + + if (line != 0) + aggNode->setLine(line); + + return aggNode; +} + +// +// Turn an existing node into an aggregate. +// +// Returns an aggregate, unless 0 was passed in for the existing node. +// +TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line) +{ + if (node == 0) + return 0; + + TIntermAggregate* aggNode = new TIntermAggregate; + aggNode->getSequence().push_back(node); + + if (line != 0) + aggNode->setLine(line); + else + aggNode->setLine(node->getLine()); + + return aggNode; +} + +// +// For "if" test nodes. There are three children; a condition, +// a true path, and a false path. The two paths are in the +// nodePair. +// +// Returns the selection node created. +// +TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line) +{ + // + // For compile time constant selections, prune the code and + // test now. + // + + if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) { + if (cond->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getBConst()) + return nodePair.node1; + else + return nodePair.node2; + } + + TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2); + node->setLine(line); + + return node; +} + + +TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line) +{ + if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) { + return right; + } else { + TIntermTyped *commaAggregate = growAggregate(left, right, line); + commaAggregate->getAsAggregate()->setOperator(EOpComma); + commaAggregate->setType(right->getType()); + commaAggregate->getTypePointer()->changeQualifier(EvqTemporary); + return commaAggregate; + } +} + +// +// For "?:" test nodes. There are three children; a condition, +// a true path, and a false path. The two paths are specified +// as separate parameters. +// +// Returns the selection node created, or 0 if one could not be. +// +TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line) +{ + // + // Get compatible types. + // + TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock); + if (child) + falseBlock = child; + else { + child = addConversion(EOpSequence, falseBlock->getType(), trueBlock); + if (child) + trueBlock = child; + else + return 0; + } + + // + // See if all the operands are constant, then fold it otherwise not. + // + + if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) { + if (cond->getAsConstantUnion()->getUnionArrayPointer()->getBConst()) + return trueBlock; + else + return falseBlock; + } + + // + // Make a selection node. + // + TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); + node->setLine(line); + + return node; +} + +// +// Constant terminal nodes. Has a union that contains bool, float or int constants +// +// Returns the constant union node created. +// + +TIntermConstantUnion* TIntermediate::addConstantUnion(constUnion* unionArrayPointer, const TType& t, TSourceLoc line) +{ + TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t); + node->setLine(line); + + return node; +} + +TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line) +{ + + TIntermAggregate* node = new TIntermAggregate(EOpSequence); + + node->setLine(line); + TIntermConstantUnion* constIntNode; + TIntermSequence &sequenceVector = node->getSequence(); + constUnion* unionArray; + + for (int i = 0; i < fields.num; i++) { + unionArray = new constUnion[1]; + unionArray->setIConst(fields.offsets[i]); + constIntNode = addConstantUnion(unionArray, TType(EbtInt, EvqConst), line); + sequenceVector.push_back(constIntNode); + } + + return node; +} + +// +// Create loop nodes. +// +TIntermNode* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc line) +{ + TIntermNode* node = new TIntermLoop(body, test, terminal, testFirst); + node->setLine(line); + + return node; +} + +// +// Add branches. +// +TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line) +{ + return addBranch(branchOp, 0, line); +} + +TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line) +{ + TIntermBranch* node = new TIntermBranch(branchOp, expression); + node->setLine(line); + + return node; +} + +// +// This is to be executed once the final root is put on top by the parsing +// process. +// +bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language) +{ + if (root == 0) + return true; + + // + // First, finish off the top level sequence, if any + // + TIntermAggregate* aggRoot = root->getAsAggregate(); + if (aggRoot && aggRoot->getOp() == EOpNull) + aggRoot->setOperator(EOpSequence); + + return true; +} + +// +// This deletes the tree. +// +void TIntermediate::remove(TIntermNode* root) +{ + if (root) + RemoveAllTreeNodes(root); +} + +//////////////////////////////////////////////////////////////// +// +// Member functions of the nodes used for building the tree. +// +//////////////////////////////////////////////////////////////// + +// +// Say whether or not an operation node changes the value of a variable. +// +// Returns true if state is modified. +// +bool TIntermOperator::modifiesState() const +{ + switch (op) { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + case EOpAssign: + case EOpAddAssign: + case EOpSubAssign: + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + case EOpDivAssign: + case EOpModAssign: + case EOpAndAssign: + case EOpInclusiveOrAssign: + case EOpExclusiveOrAssign: + case EOpLeftShiftAssign: + case EOpRightShiftAssign: + return true; + default: + return false; + } +} + +// +// returns true if the operator is for one of the constructors +// +bool TIntermOperator::isConstructor() const +{ + switch (op) { + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + case EOpConstructFloat: + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + case EOpConstructInt: + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructBool: + case EOpConstructStruct: + return true; + default: + return false; + } +} +// +// Make sure the type of a unary operator is appropriate for its +// combination of operation and operand type. +// +// Returns false in nothing makes sense. +// +bool TIntermUnary::promote(TInfoSink&) +{ + switch (op) { + case EOpLogicalNot: + if (operand->getBasicType() != EbtBool) + return false; + break; + case EOpBitwiseNot: + if (operand->getBasicType() != EbtInt) + return false; + break; + case EOpNegative: + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + if (operand->getBasicType() == EbtBool) + return false; + break; + + // operators for built-ins are already type checked against their prototype + case EOpAny: + case EOpAll: + case EOpVectorLogicalNot: + return true; + + default: + if (operand->getBasicType() != EbtFloat) + return false; + } + + setType(operand->getType()); + + return true; +} + +// +// Establishes the type of the resultant operation, as well as +// makes the operator the correct one for the operands. +// +// Returns false if operator can't work on operands. +// +bool TIntermBinary::promote(TInfoSink& infoSink) +{ + int size = left->getNominalSize(); + if (right->getNominalSize() > size) + size = right->getNominalSize(); + + TBasicType type = left->getBasicType(); + + // + // Arrays have to be exact matches. + // + if ((left->isArray() || right->isArray()) && (left->getType() != right->getType())) + return false; + + // + // Base assumption: just make the type the same as the left + // operand. Then only deviations from this need be coded. + // + setType(TType(type, EvqTemporary, left->getNominalSize(), left->isMatrix())); + + // + // Array operations. + // + if (left->isArray()) { + + switch (op) { + + // + // Promote to conditional + // + case EOpEqual: + case EOpNotEqual: + setType(TType(EbtBool)); + break; + + // + // Set array information. + // + case EOpAssign: + getType().setArraySize(left->getType().getArraySize()); + getType().setArrayInformationType(left->getType().getArrayInformationType()); + break; + + default: + return false; + } + + return true; + } + + // + // All scalars. Code after this test assumes this case is removed! + // + if (size == 1) { + + switch (op) { + + // + // Promote to conditional + // + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + setType(TType(EbtBool)); + break; + + // + // And and Or operate on conditionals + // + case EOpLogicalAnd: + case EOpLogicalOr: + if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool) + return false; + setType(TType(EbtBool)); + break; + + // + // Check for integer only operands. + // + case EOpMod: + case EOpRightShift: + case EOpLeftShift: + case EOpAnd: + case EOpInclusiveOr: + case EOpExclusiveOr: + if (left->getBasicType() != EbtInt || right->getBasicType() != EbtInt) + return false; + break; + case EOpModAssign: + case EOpAndAssign: + case EOpInclusiveOrAssign: + case EOpExclusiveOrAssign: + case EOpLeftShiftAssign: + case EOpRightShiftAssign: + if (left->getBasicType() != EbtInt || right->getBasicType() != EbtInt) + return false; + // fall through + + // + // Everything else should have matching types + // + default: + if (left->getBasicType() != right->getBasicType() || + left->isMatrix() != right->isMatrix()) + return false; + } + + return true; + } + + // + // Are the sizes compatible? + // + if ( left->getNominalSize() != size && left->getNominalSize() != 1 || + right->getNominalSize() != size && right->getNominalSize() != 1) + return false; + + // + // Can these two operands be combined? + // + switch (op) { + case EOpMul: + if (!left->isMatrix() && right->isMatrix()) { + if (left->isVector()) + op = EOpVectorTimesMatrix; + else { + op = EOpMatrixTimesScalar; + setType(TType(type, EvqTemporary, size, true)); + } + } else if (left->isMatrix() && !right->isMatrix()) { + if (right->isVector()) { + op = EOpMatrixTimesVector; + setType(TType(type, EvqTemporary, size, false)); + } else { + op = EOpMatrixTimesScalar; + } + } else if (left->isMatrix() && right->isMatrix()) { + op = EOpMatrixTimesMatrix; + } else if (!left->isMatrix() && !right->isMatrix()) { + if (left->isVector() && right->isVector()) { + // leave as component product + } else if (left->isVector() || right->isVector()) { + op = EOpVectorTimesScalar; + setType(TType(type, EvqTemporary, size, false)); + } + } else { + infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); + return false; + } + break; + case EOpMulAssign: + if (!left->isMatrix() && right->isMatrix()) { + if (left->isVector()) + op = EOpVectorTimesMatrixAssign; + else { + return false; + } + } else if (left->isMatrix() && !right->isMatrix()) { + if (right->isVector()) { + return false; + } else { + op = EOpMatrixTimesScalarAssign; + } + } else if (left->isMatrix() && right->isMatrix()) { + op = EOpMatrixTimesMatrixAssign; + } else if (!left->isMatrix() && !right->isMatrix()) { + if (left->isVector() && right->isVector()) { + // leave as component product + } else if (left->isVector() || right->isVector()) { + if (! left->isVector()) + return false; + op = EOpVectorTimesScalarAssign; + setType(TType(type, EvqTemporary, size, false)); + } + } else { + infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); + return false; + } + break; + case EOpAssign: + if (left->getNominalSize() != right->getNominalSize()) + return false; + // fall through + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpMod: + case EOpAddAssign: + case EOpSubAssign: + case EOpDivAssign: + case EOpModAssign: + if (left->isMatrix() && right->isVector() || + left->isVector() && right->isMatrix() || + left->getBasicType() != right->getBasicType()) + return false; + setType(TType(type, EvqTemporary, size, left->isMatrix() || right->isMatrix())); + break; + + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if (left->isMatrix() && right->isVector() || + left->isVector() && right->isMatrix() || + left->getBasicType() != right->getBasicType()) + return false; + setType(TType(EbtBool)); + break; + +default: + return false; + } + + // + // One more check for assignment. The Resulting type has to match the left operand. + // + switch (op) { + case EOpAssign: + case EOpAddAssign: + case EOpSubAssign: + case EOpMulAssign: + case EOpDivAssign: + case EOpModAssign: + case EOpAndAssign: + case EOpInclusiveOrAssign: + case EOpExclusiveOrAssign: + case EOpLeftShiftAssign: + case EOpRightShiftAssign: + if (getType() != left->getType()) + return false; + break; + default: + break; + } + + return true; +} + +bool CompareStruct(const TType& leftNodeType, constUnion* rightUnionArray, constUnion* leftUnionArray) +{ + TTypeList* fields = leftNodeType.getStruct(); + + size_t structSize = fields->size(); + int index = 0; + + for (size_t j = 0; j < structSize; j++) { + int size = (*fields)[j].type->getObjectSize(); + for (int i = 0; i < size; i++) { + if ((*fields)[j].type->getBasicType() == EbtStruct) { + if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index])) + return false; + } else { + if (leftUnionArray[index] != rightUnionArray[index]) + return false; + index++; + } + + } + } + return true; +} + +bool CompareStructure(const TType& leftNodeType, constUnion* rightUnionArray, constUnion* leftUnionArray) +{ + if (leftNodeType.isArray()) { + TType typeWithoutArrayness = leftNodeType; + typeWithoutArrayness.clearArrayness(); + + int arraySize = leftNodeType.getArraySize(); + + for (int i = 0; i < arraySize; ++i) { + int offset = typeWithoutArrayness.getObjectSize() * i; + if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset])) + return false; + } + } else + return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); + + return true; +} + +// +// The fold functions see if an operation on a constant can be done in place, +// without generating run-time code. +// +// Returns the node to keep using, which may or may not be the node passed in. +// + +TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink) +{ + constUnion *unionArray = getUnionArrayPointer(); + int objectSize = getType().getObjectSize(); + + if (constantNode) { // binary operations + TIntermConstantUnion *node = constantNode->getAsConstantUnion(); + constUnion *rightUnionArray = node->getUnionArrayPointer(); + TType returnType = getType(); + + // for a case like float f = 1.2 + vec4(2,3,4,5); + if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) { + rightUnionArray = new constUnion[objectSize]; + for (int i = 0; i < objectSize; ++i) + rightUnionArray[i] = *node->getUnionArrayPointer(); + returnType = getType(); + } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) { + // for a case like float f = vec4(2,3,4,5) + 1.2; + unionArray = new constUnion[constantNode->getType().getObjectSize()]; + for (int i = 0; i < constantNode->getType().getObjectSize(); ++i) + unionArray[i] = *getUnionArrayPointer(); + returnType = node->getType(); + objectSize = constantNode->getType().getObjectSize(); + } + + constUnion* tempConstArray = 0; + TIntermConstantUnion *tempNode; + int index = 0; + bool boolNodeFlag = false; + switch(op) { + case EOpAdd: + tempConstArray = new constUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] + rightUnionArray[i]; + } + break; + case EOpSub: + tempConstArray = new constUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] - rightUnionArray[i]; + } + break; + + case EOpMul: + case EOpVectorTimesScalar: + case EOpMatrixTimesScalar: + tempConstArray = new constUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] * rightUnionArray[i]; + } + break; + case EOpMatrixTimesMatrix: + if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) { + infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine()); + return 0; + } + {// support MSVC++6.0 + int size = getNominalSize(); + tempConstArray = new constUnion[size*size]; + for (int row = 0; row < size; row++) { + for (int column = 0; column < size; column++) { + tempConstArray[size * column + row].setFConst(0.0f); + for (int i = 0; i < size; i++) { + tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst())); + } + } + } + } + break; + case EOpDiv: + tempConstArray = new constUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) { + switch (getType().getBasicType()) { + case EbtFloat: + if (rightUnionArray[i] == 0.0f) { + infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine()); + tempConstArray[i].setFConst(FLT_MAX); + } else + tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst()); + break; + + case EbtInt: + if (rightUnionArray[i] == 0) { + infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine()); + tempConstArray[i].setIConst(INT_MAX); + } else + tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst()); + break; + default: + infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine()); + return 0; + } + } + } + break; + + case EOpMatrixTimesVector: + if (node->getBasicType() != EbtFloat) { + infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine()); + return 0; + } + tempConstArray = new constUnion[getNominalSize()]; + + {// support MSVC++6.0 + for (int size = getNominalSize(), i = 0; i < size; i++) { + tempConstArray[i].setFConst(0.0f); + for (int j = 0; j < size; j++) { + tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst())); + } + } + } + + tempNode = new TIntermConstantUnion(tempConstArray, node->getType()); + tempNode->setLine(getLine()); + + return tempNode; + + case EOpVectorTimesMatrix: + if (getType().getBasicType() != EbtFloat) { + infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine()); + return 0; + } + + tempConstArray = new constUnion[getNominalSize()]; + {// support MSVC++6.0 + for (int size = getNominalSize(), i = 0; i < size; i++) { + tempConstArray[i].setFConst(0.0f); + for (int j = 0; j < size; j++) { + tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst())); + } + } + } + break; + + case EOpMod: + tempConstArray = new constUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] % rightUnionArray[i]; + } + break; + + case EOpRightShift: + tempConstArray = new constUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] >> rightUnionArray[i]; + } + break; + + case EOpLeftShift: + tempConstArray = new constUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] << rightUnionArray[i]; + } + break; + + case EOpAnd: + tempConstArray = new constUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] & rightUnionArray[i]; + } + break; + case EOpInclusiveOr: + tempConstArray = new constUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] | rightUnionArray[i]; + } + break; + case EOpExclusiveOr: + tempConstArray = new constUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] ^ rightUnionArray[i]; + } + break; + + case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently + tempConstArray = new constUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] && rightUnionArray[i]; + } + break; + + case EOpLogicalOr: // this code is written for possible future use, will not get executed currently + tempConstArray = new constUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] || rightUnionArray[i]; + } + break; + + case EOpLogicalXor: + tempConstArray = new constUnion[objectSize]; + {// support MSVC++6.0 + for (int i = 0; i < objectSize; i++) + switch (getType().getBasicType()) { + case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break; + default: assert(false && "Default missing"); + } + } + break; + + case EOpLessThan: + assert(objectSize == 1); + tempConstArray = new constUnion[1]; + tempConstArray->setBConst(*unionArray < *rightUnionArray); + returnType = TType(EbtBool, EvqConst); + break; + case EOpGreaterThan: + assert(objectSize == 1); + tempConstArray = new constUnion[1]; + tempConstArray->setBConst(*unionArray > *rightUnionArray); + returnType = TType(EbtBool, EvqConst); + break; + case EOpLessThanEqual: + { + assert(objectSize == 1); + constUnion constant; + constant.setBConst(*unionArray > *rightUnionArray); + tempConstArray = new constUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EvqConst); + break; + } + case EOpGreaterThanEqual: + { + assert(objectSize == 1); + constUnion constant; + constant.setBConst(*unionArray < *rightUnionArray); + tempConstArray = new constUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EvqConst); + break; + } + + case EOpEqual: + if (getType().getBasicType() == EbtStruct) { + if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) + boolNodeFlag = true; + } else { + for (int i = 0; i < objectSize; i++) { + if (unionArray[i] != rightUnionArray[i]) { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new constUnion[1]; + if (!boolNodeFlag) { + tempConstArray->setBConst(true); + } + else { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + case EOpNotEqual: + if (getType().getBasicType() == EbtStruct) { + if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) + boolNodeFlag = true; + } else { + for (int i = 0; i < objectSize; i++) { + if (unionArray[i] == rightUnionArray[i]) { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new constUnion[1]; + if (!boolNodeFlag) { + tempConstArray->setBConst(true); + } + else { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + default: + infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine()); + return 0; + } + tempNode = new TIntermConstantUnion(tempConstArray, returnType); + tempNode->setLine(getLine()); + + return tempNode; + } else { + // + // Do unary operations + // + TIntermConstantUnion *newNode = 0; + constUnion* tempConstArray = new constUnion[objectSize]; + for (int i = 0; i < objectSize; i++) { + switch(op) { + case EOpNegative: + switch (getType().getBasicType()) { + case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break; + case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break; + default: + infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine()); + return 0; + } + break; + case EOpLogicalNot: // this code is written for possible future use, will not get executed currently + switch (getType().getBasicType()) { + case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break; + default: + infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine()); + return 0; + } + break; + default: + return 0; + } + } + newNode = new TIntermConstantUnion(tempConstArray, getType()); + newNode->setLine(getLine()); + return newNode; + } + + return this; +} + +TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) +{ + constUnion *rightUnionArray = node->getUnionArrayPointer(); + int size = node->getType().getObjectSize(); + + constUnion *leftUnionArray = new constUnion[size]; + + for (int i=0; i < size; i++) { + + switch (promoteTo) { + case EbtFloat: + switch (node->getType().getBasicType()) { + case EbtInt: + leftUnionArray[i].setFConst(static_cast(rightUnionArray[i].getIConst())); + break; + case EbtBool: + leftUnionArray[i].setFConst(static_cast(rightUnionArray[i].getBConst())); + break; + case EbtFloat: + leftUnionArray[i] = rightUnionArray[i]; + break; + default: + infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + return 0; + } + break; + case EbtInt: + switch (node->getType().getBasicType()) { + case EbtInt: + leftUnionArray[i] = rightUnionArray[i]; + break; + case EbtBool: + leftUnionArray[i].setIConst(static_cast(rightUnionArray[i].getBConst())); + break; + case EbtFloat: + leftUnionArray[i].setIConst(static_cast(rightUnionArray[i].getFConst())); + break; + default: + infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + return 0; + } + break; + case EbtBool: + switch (node->getType().getBasicType()) { + case EbtInt: + leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0); + break; + case EbtBool: + leftUnionArray[i] = rightUnionArray[i]; + break; + case EbtFloat: + leftUnionArray[i].setBConst(rightUnionArray[i].getFConst() != 0.0f); + break; + default: + infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + return 0; + } + + break; + default: + infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine()); + return 0; + } + + } + + const TType& t = node->getType(); + + return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine()); +} + +void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable) +{ + assert(!pragmaTable); + pragmaTable = new TPragmaTable(); + *pragmaTable = pTable; +} + diff --git a/glslang/MachineIndependent/MMap.h b/glslang/MachineIndependent/MMap.h new file mode 100644 index 0000000..82254f0 --- /dev/null +++ b/glslang/MachineIndependent/MMap.h @@ -0,0 +1,84 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _MMAP_INCLUDED_ +#define _MMAP_INCLUDED_ + +// +// Encapsulate memory mapped files +// + +class TMMap { +public: + TMMap(const char* fileName) : + fSize(-1), // -1 is the error value returned by GetFileSize() + fp(NULL), + fBuff(0) // 0 is the error value returned by MapViewOfFile() + { + if ((fp = fopen(fileName, "r")) == NULL) + return; + char c = getc(fp); + fSize = 0; + while (c != EOF) { + fSize++; + c = getc(fp); + } + if (c == EOF) + fSize++; + rewind(fp); + fBuff = (char*)malloc(sizeof(char) * fSize); + int count = 0; + c = getc(fp); + while (c != EOF) { + fBuff[count++] = c; + c = getc(fp); + } + fBuff[count++] = c; + } + + char* getData() { return fBuff; } + int getSize() { return fSize; } + + ~TMMap() { + if (fp != NULL) + fclose(fp); + } + +private: + int fSize; // size of file to map in + FILE *fp; + char* fBuff; // the actual data; +}; + +#endif // _MMAP_INCLUDED_ diff --git a/glslang/MachineIndependent/Makefile b/glslang/MachineIndependent/Makefile new file mode 100644 index 0000000..9704c80 --- /dev/null +++ b/glslang/MachineIndependent/Makefile @@ -0,0 +1,161 @@ +INCLUDE = -I. -I.. -I../.. -I../Include -I../Public -I../OSDependent/Linux -I../../OGLCompilersDLL +CC=g++ +INCPREPROCESSOR=./preprocessor +INCCODEGEN=./../GenericCodeGen +INCOSDEPENDENT=./../OSDependent/Linux/ +INCINITIALISATION=./../../OGLCompilersDLL/ +LIBPREPROCESSOR=./preprocessor/libPreprocessor.a +LIBOSDEPENDENT=./../OSDependent/Linux/libOssource.a +LIBINITIALISATION=./../../OGLCompilersDLL/libInitializeDll.a +LIBCODEGEN=./../GenericCodeGen/libCodeGen.a +OBJECTS= Initialize.o IntermTraverse.o \ + Intermediate.o ParseHelper.o PoolAlloc.o QualifierAlive.o \ + RemoveTree.o ShaderLang.o intermOut.o parseConst.o SymbolTable.o \ + InfoSink.o + +SRCS= Gen_glslang.cpp Gen_glslang_tab.cpp Initialize.cpp IntermTraverse.cpp \ + Intermediate.cpp ParseHelper.cpp PoolAlloc.cp QualifierAlive.cpp \ + RemoveTree.cpp ShaderLang.cpp SymbolTable.cpp intermOut.cpp \ + parseConst.cpp InfoSink.cpp +CPPFLAGS=$(DEFINE) $(INCLUDE) +SHAREDOBJECT=./lib/libglslang.so + +default: all + +all: $(SHAREDOBJECT) + +$(SHAREDOBJECT): Gen_glslang.o Gen_glslang_tab.o $(OBJECTS) \ + $(LIBPREPROCESSOR) $(LIBCODEGEN) $(LIBOSDEPENDENT) $(LIBINITIALISATION) + $(CC) -fPIC -shared -lc -o $@ $(OBJECTS) $(LIBPREPROCESSOR) $(LIBCODEGEN) $(LIBOSDEPENDENT) $(LIBINITIALISATION) Gen_glslang.o Gen_glslang_tab.o + +Gen_glslang.o : Gen_glslang.cpp glslang_tab.h + $(CC) -c $(INCLUDE) Gen_glslang.cpp -o $@ + +Gen_glslang_tab.o : Gen_glslang_tab.cpp + $(CC) -c $(INCLUDE) Gen_glslang_tab.cpp -o $@ + +Gen_glslang.cpp: glslang.l + @echo Generating Gen_glslang.cpp + @dos2unix glslang.l + flex glslang.l + +Gen_glslang_tab.cpp glslang_tab.h: glslang.y + @echo Generating Gen_glslang_tab.cpp + @dos2unix glslang.y + bison -t -v -d glslang.y + mv glslang.tab.c Gen_glslang_tab.cpp + mv glslang.tab.h glslang_tab.h + +%.o : %.cpp + $(CC) $(CPPFLAGS) -c $< + +$(LIBPREPROCESSOR): + cd $(INCPREPROCESSOR); make + +$(LIBCODEGEN): + cd $(INCCODEGEN); make + +$(LIBINITIALISATION): + cd $(INCINITIALISATION); make + +$(LIBOSDEPENDENT): + cd $(INCOSDEPENDENT); make + +depend: + cd $(INCPREPROCESSOR); make depend + cd $(INCCODEGEN); make depend + cd $(INCINITIALISATION); make depend + cd $(INCOSDEPENDENT); make depend + makedepend -Y -- $(CPPFLAGS) -- $(SRCS) +# +# Cleanup +# +.PHONY : clean +clean : + $(RM) *.o *.a Gen_glslang_tab.cpp Gen_glslang.cpp glslang_tab.h glslang.output + $(RM) ./lib/*.so + cd $(INCPREPROCESSOR); make clean + cd $(INCCODEGEN); make clean + cd $(INCINITIALISATION); make clean + cd $(INCOSDEPENDENT); make clean + +# DO NOT DELETE + +Gen_glslang.o: ParseHelper.h ../Include/ShHandle.h +Gen_glslang.o: ../Public/ShaderLang.h ../Include/InfoSink.h +Gen_glslang.o: ../Include/Common.h ../Include/PoolAlloc.h SymbolTable.h +Gen_glslang.o: ../Include/Common.h ../Include/intermediate.h +Gen_glslang.o: ../Include/Types.h ../Include/BaseTypes.h +Gen_glslang.o: ../Include/ConstantUnion.h ../Include/InfoSink.h +Gen_glslang.o: localintermediate.h ../Include/intermediate.h +Gen_glslang.o: ../Public/ShaderLang.h glslang_tab.h ./unistd.h +Gen_glslang.o: ./preprocessor/preprocess.h ./preprocessor/slglobals.h +Gen_glslang.o: ./preprocessor/memory.h ./preprocessor/atom.h +Gen_glslang.o: ./preprocessor/scanner.h ./preprocessor/parser.h +Gen_glslang.o: ./preprocessor/cpp.h ./preprocessor/tokens.h +Gen_glslang.o: ./preprocessor/symbols.h ./preprocessor/compile.h +Gen_glslang_tab.o: SymbolTable.h ../Include/Common.h +Gen_glslang_tab.o: ../Include/intermediate.h ../Include/Common.h +Gen_glslang_tab.o: ../Include/PoolAlloc.h ../Include/Types.h +Gen_glslang_tab.o: ../Include/BaseTypes.h ../Include/ConstantUnion.h +Gen_glslang_tab.o: ../Include/InfoSink.h ParseHelper.h ../Include/ShHandle.h +Gen_glslang_tab.o: ../Public/ShaderLang.h +Gen_glslang_tab.o: ../Include/InfoSink.h localintermediate.h +Gen_glslang_tab.o: ../Include/intermediate.h ../Public/ShaderLang.h +Initialize.o: ../Include/intermediate.h Initialize.h +Initialize.o: ../Include/ResourceLimits.h ../Include/Common.h +Initialize.o: ../Include/PoolAlloc.h ../Include/ShHandle.h +Initialize.o: ../Public/ShaderLang.h +Initialize.o: ../Include/InfoSink.h SymbolTable.h ../Include/Common.h +Initialize.o: ../Include/intermediate.h ../Include/Types.h +Initialize.o: ../Include/BaseTypes.h ../Include/ConstantUnion.h +Initialize.o: ../Include/InfoSink.h +IntermTraverse.o: ../Include/intermediate.h +Intermediate.o: ../Include/ShHandle.h +Intermediate.o: ../Public/ShaderLang.h ../Include/InfoSink.h +Intermediate.o: ../Include/Common.h ../Include/PoolAlloc.h +Intermediate.o: localintermediate.h ../Include/intermediate.h +Intermediate.o: ../Public/ShaderLang.h SymbolTable.h ../Include/Common.h +Intermediate.o: ../Include/intermediate.h ../Include/Types.h +Intermediate.o: ../Include/BaseTypes.h ../Include/ConstantUnion.h +Intermediate.o: ../Include/InfoSink.h QualifierAlive.h RemoveTree.h +ParseHelper.o: ParseHelper.h ../Include/ShHandle.h +ParseHelper.o: ../Public/ShaderLang.h ../Include/InfoSink.h +ParseHelper.o: ../Include/Common.h ../Include/PoolAlloc.h SymbolTable.h +ParseHelper.o: ../Include/Common.h ../Include/intermediate.h +ParseHelper.o: ../Include/Types.h ../Include/BaseTypes.h +ParseHelper.o: ../Include/ConstantUnion.h ../Include/InfoSink.h +ParseHelper.o: localintermediate.h ../Include/intermediate.h +ParseHelper.o: ../Public/ShaderLang.h ../Include/InitializeParseContext.h +ParseHelper.o: ../OSDependent/Linux/osinclude.h +ParseHelper.o: ../Include/InitializeGlobals.h ../Include/PoolAlloc.h +QualifierAlive.o: ../Include/intermediate.h +RemoveTree.o: ../Include/intermediate.h RemoveTree.h +ShaderLang.o: SymbolTable.h ../Include/Common.h ../Include/intermediate.h +ShaderLang.o: ../Include/Common.h ../Include/PoolAlloc.h ../Include/Types.h +ShaderLang.o: ../Include/BaseTypes.h ../Include/ConstantUnion.h +ShaderLang.o: ../Include/InfoSink.h ParseHelper.h ../Include/ShHandle.h +ShaderLang.o: ../Public/ShaderLang.h +ShaderLang.o: ../Include/InfoSink.h localintermediate.h +ShaderLang.o: ../Include/intermediate.h ../Public/ShaderLang.h +ShaderLang.o: ../Include/ResourceLimits.h Initialize.h +SymbolTable.o: SymbolTable.h ../Include/Common.h ../Include/intermediate.h +SymbolTable.o: ../Include/Common.h ../Include/PoolAlloc.h ../Include/Types.h +SymbolTable.o: ../Include/BaseTypes.h ../Include/ConstantUnion.h +SymbolTable.o: ../Include/InfoSink.h +intermOut.o: localintermediate.h ../Include/intermediate.h +intermOut.o: ../Public/ShaderLang.h SymbolTable.h ../Include/Common.h +intermOut.o: ../Include/intermediate.h ../Include/Common.h +intermOut.o: ../Include/PoolAlloc.h ../Include/Types.h ../Include/BaseTypes.h +intermOut.o: ../Include/ConstantUnion.h ../Include/InfoSink.h +intermOut.o: ../Include/ShHandle.h +intermOut.o: ../Public/ShaderLang.h ../Include/InfoSink.h +parseConst.o: ParseHelper.h ../Include/ShHandle.h +parseConst.o: ../Public/ShaderLang.h ../Include/InfoSink.h +parseConst.o: ../Include/Common.h ../Include/PoolAlloc.h SymbolTable.h +parseConst.o: ../Include/Common.h ../Include/intermediate.h +parseConst.o: ../Include/Types.h ../Include/BaseTypes.h +parseConst.o: ../Include/ConstantUnion.h ../Include/InfoSink.h +parseConst.o: localintermediate.h ../Include/intermediate.h +parseConst.o: ../Public/ShaderLang.h +InfoSink.o: ../Include/InfoSink.h diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp new file mode 100644 index 0000000..6088bdf --- /dev/null +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -0,0 +1,1494 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#include "ParseHelper.h" +#include "Include/InitializeParseContext.h" +#include "osinclude.h" +#include +/////////////////////////////////////////////////////////////////////// +// +// Sub- vector and matrix fields +// +//////////////////////////////////////////////////////////////////////// + +// +// Look at a '.' field selector string and change it into offsets +// for a vector. +// +bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line) +{ + fields.num = (int) compString.size(); + if (fields.num > 4) { + error(line, "illegal vector field selection", compString.c_str(), ""); + return false; + } + + enum { + exyzw, + ergba, + estpq, + } fieldSet[4]; + + for (int i = 0; i < fields.num; ++i) { + switch (compString[i]) { + case 'x': + fields.offsets[i] = 0; + fieldSet[i] = exyzw; + break; + case 'r': + fields.offsets[i] = 0; + fieldSet[i] = ergba; + break; + case 's': + fields.offsets[i] = 0; + fieldSet[i] = estpq; + break; + case 'y': + fields.offsets[i] = 1; + fieldSet[i] = exyzw; + break; + case 'g': + fields.offsets[i] = 1; + fieldSet[i] = ergba; + break; + case 't': + fields.offsets[i] = 1; + fieldSet[i] = estpq; + break; + case 'z': + fields.offsets[i] = 2; + fieldSet[i] = exyzw; + break; + case 'b': + fields.offsets[i] = 2; + fieldSet[i] = ergba; + break; + case 'p': + fields.offsets[i] = 2; + fieldSet[i] = estpq; + break; + + case 'w': + fields.offsets[i] = 3; + fieldSet[i] = exyzw; + break; + case 'a': + fields.offsets[i] = 3; + fieldSet[i] = ergba; + break; + case 'q': + fields.offsets[i] = 3; + fieldSet[i] = estpq; + break; + default: + error(line, "illegal vector field selection", compString.c_str(), ""); + return false; + } + } + + for (int i = 0; i < fields.num; ++i) { + if (fields.offsets[i] >= vecSize) { + error(line, "vector field selection out of range", compString.c_str(), ""); + return false; + } + + if (i > 0) { + if (fieldSet[i] != fieldSet[i-1]) { + error(line, "illegal - vector component fields not from the same set", compString.c_str(), ""); + return false; + } + } + } + + return true; +} + + +// +// Look at a '.' field selector string and change it into offsets +// for a matrix. +// +bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line) +{ + fields.wholeRow = false; + fields.wholeCol = false; + fields.row = -1; + fields.col = -1; + + if (compString.size() != 2) { + error(line, "illegal length of matrix field selection", compString.c_str(), ""); + return false; + } + + if (compString[0] == '_') { + if (compString[1] < '0' || compString[1] > '3') { + error(line, "illegal matrix field selection", compString.c_str(), ""); + return false; + } + fields.wholeCol = true; + fields.col = compString[1] - '0'; + } else if (compString[1] == '_') { + if (compString[0] < '0' || compString[0] > '3') { + error(line, "illegal matrix field selection", compString.c_str(), ""); + return false; + } + fields.wholeRow = true; + fields.row = compString[0] - '0'; + } else { + if (compString[0] < '0' || compString[0] > '3' || + compString[1] < '0' || compString[1] > '3') { + error(line, "illegal matrix field selection", compString.c_str(), ""); + return false; + } + fields.row = compString[0] - '0'; + fields.col = compString[1] - '0'; + } + + if (fields.row >= matSize || fields.col >= matSize) { + error(line, "matrix field selection out of range", compString.c_str(), ""); + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////// +// +// Errors +// +//////////////////////////////////////////////////////////////////////// + +// +// Track whether errors have occurred. +// +void TParseContext::recover() +{ + recoveredFromError = true; +} + +// +// Used by flex/bison to output all syntax and parsing errors. +// +void C_DECL TParseContext::error(TSourceLoc nLine, const char *szReason, const char *szToken, + const char *szExtraInfoFormat, ...) +{ + char szExtraInfo[400]; + va_list marker; + + va_start(marker, szExtraInfoFormat); + + _vsnprintf(szExtraInfo, sizeof(szExtraInfo), szExtraInfoFormat, marker); + + /* VC++ format: file(linenum) : error #: 'token' : extrainfo */ + infoSink.info.prefix(EPrefixError); + infoSink.info.location(nLine); + infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n"; + + va_end(marker); + + ++numErrors; +} + +// +// Same error message for all places assignments don't work. +// +void TParseContext::assignError(int line, const char* op, TString left, TString right) +{ + error(line, "", op, "cannot convert from '%s' to '%s'", + right.c_str(), left.c_str()); +} + +// +// Same error message for all places unary operations don't work. +// +void TParseContext::unaryOpError(int line, char* op, TString operand) +{ + error(line, " wrong operand type", op, + "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)", + op, operand.c_str()); +} + +// +// Same error message for all binary operations don't work. +// +void TParseContext::binaryOpError(int line, char* op, TString left, TString right) +{ + error(line, " wrong operand types ", op, + "no operation '%s' exists that takes a left-hand operand of type '%s' and " + "a right operand of type '%s' (or there is no acceptable conversion)", + op, left.c_str(), right.c_str()); +} + +// +// Both test and if necessary, spit out an error, to see if the node is really +// an l-value that can be operated on this way. +// +// Returns true if the was an error. +// +bool TParseContext::lValueErrorCheck(int line, char* op, TIntermTyped* node) +{ + TIntermSymbol* symNode = node->getAsSymbolNode(); + TIntermBinary* binaryNode = node->getAsBinaryNode(); + + if (binaryNode) { + bool errorReturn; + + switch(binaryNode->getOp()) { + case EOpIndexDirect: + case EOpIndexIndirect: + case EOpIndexDirectStruct: + return lValueErrorCheck(line, op, binaryNode->getLeft()); + case EOpVectorSwizzle: + errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft()); + if (!errorReturn) { + int offset[4] = {0,0,0,0}; + + TIntermTyped* rightNode = binaryNode->getRight(); + TIntermAggregate *aggrNode = rightNode->getAsAggregate(); + + for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); + p != aggrNode->getSequence().end(); p++) { + int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); + offset[value]++; + if (offset[value] > 1) { + error(line, " l-value of swizzle cannot have duplicate components", op, "", ""); + + return true; + } + } + } + + return errorReturn; + default: + break; + } + error(line, " l-value required", op, "", ""); + + return true; + } + + + const char* symbol = 0; + if (symNode != 0) + symbol = symNode->getSymbol().c_str(); + + char* message = 0; + switch (node->getQualifier()) { + case EvqConst: message = "can't modify a const"; break; + case EvqConstReadOnly: message = "can't modify a const"; break; + case EvqAttribute: message = "can't modify an attribute"; break; + case EvqUniform: message = "can't modify a uniform"; break; + case EvqVaryingIn: message = "can't modify a varying"; break; + case EvqInput: message = "can't modify an input"; break; + case EvqFace: message = "can't modify gl_FrontFace"; break; + case EvqFragCoord: message = "can't modify gl_FragCoord"; break; + default: + + // + // Type that can't be written to? + // + switch (node->getBasicType()) { + case EbtSampler1D: + case EbtSampler2D: + case EbtSampler3D: + case EbtSamplerCube: + case EbtSampler1DShadow: + case EbtSampler2DShadow: + case EbtSamplerRect: // ARB_texture_rectangle + case EbtSamplerRectShadow: // ARB_texture_rectangle + message = "can't modify a sampler"; + break; + case EbtVoid: + message = "can't modify void"; + break; + default: + break; + } + } + + if (message == 0 && binaryNode == 0 && symNode == 0) { + error(line, " l-value required", op, "", ""); + + return true; + } + + + // + // Everything else is okay, no error. + // + if (message == 0) + return false; + + // + // If we get here, we have an error and a message. + // + if (symNode) + error(line, " l-value required", op, "\"%s\" (%s)", symbol, message); + else + error(line, " l-value required", op, "(%s)", message); + + return true; +} + +// +// Both test, and if necessary spit out an error, to see if the node is really +// a constant. +// +// Returns true if the was an error. +// +bool TParseContext::constErrorCheck(TIntermTyped* node) +{ + if (node->getQualifier() == EvqConst) + return false; + + error(node->getLine(), "constant expression required", "", ""); + + return true; +} + +// +// Both test, and if necessary spit out an error, to see if the node is really +// an integer. +// +// Returns true if the was an error. +// +bool TParseContext::integerErrorCheck(TIntermTyped* node, char* token) +{ + if (node->getBasicType() == EbtInt && node->getNominalSize() == 1) + return false; + + error(node->getLine(), "integer expression required", token, ""); + + return true; +} + +// +// Both test, and if necessary spit out an error, to see if we are currently +// globally scoped. +// +// Returns true if the was an error. +// +bool TParseContext::globalErrorCheck(int line, bool global, char* token) +{ + if (global) + return false; + + error(line, "only allowed at global scope", token, ""); + + return true; +} + +// +// For now, keep it simple: if it starts "gl_", it's reserved, independent +// of scope. Except, if the symbol table is at the built-in push-level, +// which is when we are parsing built-ins. +// +// Returns true if there was an error. +// +bool TParseContext::reservedErrorCheck(int line, const TString& identifier) +{ + if (!symbolTable.atBuiltInLevel()) { + if (identifier.substr(0, 3) == TString("gl_")) { + error(line, "reserved built-in name", "gl_", ""); + return true; + } + if (identifier.find("__") != TString::npos) { + //error(line, "Two consecutive underscores are reserved for future use.", identifier.c_str(), "", ""); + //return true; + infoSink.info.message(EPrefixWarning, "Two consecutive underscores are reserved for future use.", line); + return false; + } + } + + return false; +} + +// +// Make sure there is enough data provided to the constructor to build +// something of the type of the constructor. Also returns the type of +// the constructor. +// +// Returns true if there was an error in construction. +// +bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type) +{ + *type = function.getReturnType(); + + bool constructingMatrix = false; + switch(op) { + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + constructingMatrix = true; + break; + default: + break; + } + + // + // Note: It's okay to have too many components available, but not okay to have unused + // arguments. 'full' will go to true when enough args have been seen. If we loop + // again, there is an extra argument, so 'overfull' will become true. + // + + int size = 0; + bool constType = true; + bool full = false; + bool overFull = false; + bool matrixInMatrix = false; + bool arrayArg = false; + for (int i = 0; i < function.getParamCount(); ++i) { + size += function[i].type->getObjectSize(); + + if (constructingMatrix && function[i].type->isMatrix()) + matrixInMatrix = true; + if (full) + overFull = true; + if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize()) + full = true; + if (function[i].type->getQualifier() != EvqConst) + constType = false; + if (function[i].type->isArray()) + arrayArg = true; + } + + if (constType) + type->changeQualifier(EvqConst); + + if (type->isArray() && type->getArraySize() != function.getParamCount()) { + error(line, "array constructor needs one argument per array element", "constructor", ""); + return true; + } + + if (arrayArg && op != EOpConstructStruct) { + error(line, "constructing from a non-dereferenced array", "constructor", ""); + return true; + } + + if (matrixInMatrix && !type->isArray()) { + error(line, "constructing matrix from matrix", "constructor", "(reserved)"); + return true; + } + + if (overFull) { + error(line, "too many arguments", "constructor", ""); + return true; + } + + if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->size() != function.getParamCount()) { + error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", ""); + return true; + } + + if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) || + (op == EOpConstructStruct && size < type->getObjectSize())) { + error(line, "not enough data provided for construction", "constructor", ""); + return true; + } + + TIntermTyped* typed = node->getAsTyped(); + if (typed == 0) { + error(line, "constructor argument does not have a type", "constructor", ""); + return true; + } + if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) { + error(line, "cannot convert a sampler", "constructor", ""); + return true; + } + if (typed->getBasicType() == EbtVoid) { + error(line, "cannot convert a void", "constructor", ""); + return true; + } + + return false; +} + +// This function checks to see if a void variable has been declared and raise an error message for such a case +// +// returns true in case of an error +// +bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType) +{ + if (pubType.type == EbtVoid) { + error(line, "illegal use of type 'void'", identifier.c_str(), ""); + return true; + } + + return false; +} + +// This function checks to see if the node (for the expression) contains a scalar boolean expression or not +// +// returns true in case of an error +// +bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type) +{ + if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) { + error(line, "boolean expression expected", "", ""); + return true; + } + + return false; +} + +// This function checks to see if the node (for the expression) contains a scalar boolean expression or not +// +// returns true in case of an error +// +bool TParseContext::boolErrorCheck(int line, const TPublicType& pType) +{ + if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) { + error(line, "boolean expression expected", "", ""); + return true; + } + + return false; +} + +bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason) +{ + if (pType.type == EbtStruct) { + if (containsSampler(*pType.userDef)) { + error(line, reason, TType::getBasicString(pType.type), "(structure contains a sampler)"); + + return true; + } + + return false; + } else if (IsSampler(pType.type)) { + error(line, reason, TType::getBasicString(pType.type), ""); + + return true; + } + + return false; +} + +bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType) +{ + if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) && + pType.type == EbtStruct) { + error(line, "cannot be used with a structure", getQualifierString(pType.qualifier), ""); + + return true; + } + + if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform")) + return true; + + return false; +} + +bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type) +{ + if ((qualifier == EvqOut || qualifier == EvqInOut) && + type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) { + error(line, "samplers cannot be output parameters", type.getBasicString(), ""); + return true; + } + + return false; +} + +bool TParseContext::containsSampler(TType& type) +{ + if (IsSampler(type.getBasicType())) + return true; + + if (type.getBasicType() == EbtStruct) { + TTypeList& structure = *type.getStruct(); + for (unsigned int i = 0; i < structure.size(); ++i) { + if (containsSampler(*structure[i].type)) + return true; + } + } + + return false; +} + +bool TParseContext::insertBuiltInArrayAtGlobalLevel() +{ + TString *name = NewPoolTString("gl_TexCoord"); + TSymbol* symbol = symbolTable.find(*name); + if (!symbol) { + error(0, "INTERNAL ERROR finding symbol", name->c_str(), ""); + return true; + } + TVariable* variable = static_cast(symbol); + + TVariable* newVariable = new TVariable(name, variable->getType()); + + if (! symbolTable.insert(*newVariable)) { + delete newVariable; + error(0, "INTERNAL ERROR inserting new symbol", name->c_str(), ""); + return true; + } + + return false; +} + + + +// +// Do size checking for an array type's size. +// +// Returns true if there was an error. +// +bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) +{ + TIntermConstantUnion* constant = expr->getAsConstantUnion(); + if (constant == 0 || constant->getBasicType() != EbtInt) { + error(line, "array size must be a constant integer expression", "", ""); + return true; + } + + size = constant->getUnionArrayPointer()->getIConst(); + + if (size <= 0) { + error(line, "array size must be a positive integer", "", ""); + size = 1; + return true; + } + + return false; +} + +// +// See if this qualifier can be an array. +// +// Returns true if there is an error. +// +bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type) +{ + if (type.qualifier == EvqAttribute) { + error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), ""); + return true; + } + + if (type.qualifier == EvqConst && extensionErrorCheck(line, "GL_3DL_array_objects")) + return true; + + return false; +} + +// +// See if this type can be an array. +// +// Returns true if there is an error. +// +bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type) +{ + // + // Can the type be an array? + // + if (type.array) { + error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str(), ""); + return true; + } + + return false; +} + +// +// Do all the semantic checking for declaring an array, with and +// without a size, and make the right changes to the symbol table. +// +// size == 0 means no specified size. +// +// Returns true if there was an error. +// +bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable) +{ + // + // Don't check for reserved word use until after we know it's not in the symbol table, + // because reserved arrays can be redeclared. + // + + bool builtIn = false; + bool sameScope = false; + TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope); + if (symbol == 0 || !sameScope) { + if (reservedErrorCheck(line, identifier)) + return true; + + variable = new TVariable(&identifier, TType(type)); + + if (type.arraySize) + variable->getType().setArraySize(type.arraySize); + + if (! symbolTable.insert(*variable)) { + delete variable; + error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), ""); + return true; + } + } else { + if (! symbol->isVariable()) { + error(line, "variable expected", identifier.c_str(), ""); + return true; + } + + variable = static_cast(symbol); + if (! variable->getType().isArray()) { + error(line, "redeclaring non-array as array", identifier.c_str(), ""); + return true; + } + if (variable->getType().getArraySize() > 0) { + error(line, "redeclaration of array with size", identifier.c_str(), ""); + return true; + } + + if (! variable->getType().sameElementType(TType(type))) { + error(line, "redeclaration of array with a different type", identifier.c_str(), ""); + return true; + } + + TType* t = variable->getArrayInformationType(); + while (t != 0) { + if (t->getMaxArraySize() > type.arraySize) { + error(line, "higher index value already used for the array", identifier.c_str(), ""); + return true; + } + t->setArraySize(type.arraySize); + t = t->getArrayInformationType(); + } + + if (type.arraySize) + variable->getType().setArraySize(type.arraySize); + } + + if (voidErrorCheck(line, identifier, type)) + return true; + + return false; +} + +bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line) +{ + bool builtIn = false; + TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn); + if (symbol == 0) { + error(line, " undeclared identifier", node->getSymbol().c_str(), ""); + return true; + } + TVariable* variable = static_cast(symbol); + + type->setArrayInformationType(variable->getArrayInformationType()); + variable->updateArrayInformationType(type); + + // special casing to test index value of gl_TexCoord. If the accessed index is >= gl_MaxTextureCoords + // its an error + if (node->getSymbol() == "gl_TexCoord") { + TSymbol* texCoord = symbolTable.find("gl_MaxTextureCoords", &builtIn); + if (texCoord == 0) { + infoSink.info.message(EPrefixInternalError, "gl_MaxTextureCoords not defined", line); + return true; + } + + int texCoordValue = static_cast(texCoord)->getConstPointer()[0].getIConst(); + if (texCoordValue <= size) { + error(line, "", "[", "gl_TexCoord can only have a max array size of up to gl_MaxTextureCoords", ""); + return true; + } + } + + // we dont want to update the maxArraySize when this flag is not set, we just want to include this + // node type in the chain of node types so that its updated when a higher maxArraySize comes in. + if (!updateFlag) + return false; + + size++; + variable->getType().setMaxArraySize(size); + type->setMaxArraySize(size); + TType* tt = type; + + while(tt->getArrayInformationType() != 0) { + tt = tt->getArrayInformationType(); + tt->setMaxArraySize(size); + } + + return false; +} + +// +// Enforce non-initializer type/qualifier rules. +// +// Returns true if there was an error. +// +bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type) +{ + // + // Make the qualifier make sense. + // + if (type.qualifier == EvqConst) { + type.qualifier = EvqTemporary; + error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), ""); + return true; + } + + return false; +} + +// +// Do semantic checking for a variable declaration that has no initializer, +// and update the symbol table. +// +// Returns true if there was an error. +// +bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type) +{ + if (reservedErrorCheck(line, identifier)) + recover(); + + TVariable* variable = new TVariable(&identifier, TType(type)); + + if (! symbolTable.insert(*variable)) { + error(line, "redefinition", variable->getName().c_str(), ""); + delete variable; + return true; + } + + if (voidErrorCheck(line, identifier, type)) + return true; + + return false; +} + +bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type) +{ + if (qualifier != EvqConst && qualifier != EvqTemporary) { + error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier), ""); + return true; + } + if (qualifier == EvqConst && paramQualifier != EvqIn) { + error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier)); + return true; + } + + if (qualifier == EvqConst) + type->changeQualifier(EvqConstReadOnly); + else + type->changeQualifier(paramQualifier); + + return false; +} + +bool TParseContext::extensionErrorCheck(int line, const char* extension) +{ + if (extensionBehavior[extension] == EBhWarn) { + infoSink.info.message(EPrefixWarning, ("extension " + TString(extension) + " is being used").c_str(), line); + return false; + } + if (extensionBehavior[extension] == EBhDisable) { + error(line, "extension", extension, "is disabled"); + return true; + } + + return false; +} + +///////////////////////////////////////////////////////////////////////////////// +// +// Non-Errors. +// +///////////////////////////////////////////////////////////////////////////////// + +// +// Look up a function name in the symbol table, and make sure it is a function. +// +// Return the function symbol if found, otherwise 0. +// +const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn) +{ + const TSymbol* symbol = symbolTable.find(call->getMangledName(), builtIn); + + if (symbol == 0) { + error(line, "no matching overloaded function found", call->getName().c_str(), ""); + return 0; + } + + if (! symbol->isFunction()) { + error(line, "function name expected", call->getName().c_str(), ""); + return 0; + } + + const TFunction* function = static_cast(symbol); + + return function; +} + +// +// Initializers show up in several places in the grammar. Have one set of +// code to handle them here. +// +bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, + TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) +{ + TType type = TType(pType); + + if (variable == 0) { + if (reservedErrorCheck(line, identifier)) + return true; + + if (voidErrorCheck(line, identifier, pType)) + return true; + + // + // add variable to symbol table + // + variable = new TVariable(&identifier, type); + if (! symbolTable.insert(*variable)) { + error(line, "redefinition", variable->getName().c_str(), ""); + return true; + // don't delete variable, it's used by error recovery, and the pool + // pop will take care of the memory + } + } + + // + // identifier must be of type constant, a global, or a temporary + // + TQualifier qualifier = variable->getType().getQualifier(); + if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) { + error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString(), ""); + return true; + } + // + // test for and propagate constant + // + + if (qualifier == EvqConst) { + if (qualifier != initializer->getType().getQualifier()) { + error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str()); + variable->getType().changeQualifier(EvqTemporary); + return true; + } + if (type != initializer->getType()) { + error(line, " non-matching types for const initializer ", + variable->getType().getQualifierString(), ""); + variable->getType().changeQualifier(EvqTemporary); + return true; + } + if (initializer->getAsConstantUnion()) { + constUnion* unionArray = variable->getConstPointer(); + + if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) { + *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0]; + } else { + variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); + } + } else if (initializer->getAsSymbolNode()) { + const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol()); + const TVariable* tVar = static_cast(symbol); + + constUnion* constArray = tVar->getConstPointer(); + variable->shareConstPointer(constArray); + } else { + error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str()); + variable->getType().changeQualifier(EvqTemporary); + return true; + } + } + + if (qualifier != EvqConst) { + TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line); + intermNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, line); + if (intermNode == 0) { + assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); + return true; + } + } else + intermNode = 0; + + return false; +} + +bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) +{ + if (!aggrNode->isConstructor()) + return false; + + bool allConstant = true; + + // check if all the child nodes are constants so that they can be inserted into + // the parent node + if (aggrNode) { + TIntermSequence &childSequenceVector = aggrNode->getSequence() ; + for (TIntermSequence::iterator p = childSequenceVector.begin(); + p != childSequenceVector.end(); p++) { + if (!(*p)->getAsTyped()->getAsConstantUnion()) + return false; + } + } + + return allConstant; +} + +// This function is used to test for the correctness of the parameters passed to various constructor functions +// and also convert them to the right datatype if it is allowed and required. +// +// Returns 0 for an error or the constructed node (aggregate or typed) for no error. +// +TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line) +{ + if (node == 0) + return 0; + + TIntermAggregate* aggrNode = node->getAsAggregate(); + + TTypeList::iterator memberTypes; + if (op == EOpConstructStruct) + memberTypes = type->getStruct()->begin(); + + TType elementType = *type; + if (type->isArray()) + elementType.clearArrayness(); + + bool singleArg; + if (aggrNode) { + if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1) + singleArg = true; + else + singleArg = false; + } else + singleArg = true; + + TIntermTyped *newNode; + if (singleArg) { + // If structure constructor or array constructor is being called + // for only one parameter inside the structure, we need to call constructStruct function once. + if (type->isArray()) + newNode = constructStruct(node, &elementType, 1, node->getLine(), false); + else if (op == EOpConstructStruct) + newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false); + else + newNode = constructBuiltIn(type, op, node, node->getLine(), false); + + if (newNode && newNode->getAsAggregate()) { + TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type); + if (constConstructor) + return constConstructor; + } + + return newNode; + } + + // + // Handle list of arguments. + // + TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor + // if the structure constructor contains more than one parameter, then construct + // each parameter + + int paramCount = 0; // keeps a track of the constructor parameter number being checked + + // for each parameter to the constructor call, check to see if the right type is passed or convert them + // to the right type if possible (and allowed). + // for structure constructors, just check if the right type is passed, no conversion is allowed. + + for (TIntermSequence::iterator p = sequenceVector.begin(); + p != sequenceVector.end(); p++, paramCount++) { + if (type->isArray()) + newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true); + else if (op == EOpConstructStruct) + newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true); + else + newNode = constructBuiltIn(type, op, *p, node->getLine(), true); + + if (newNode) { + sequenceVector.erase(p); + sequenceVector.insert(p, newNode); + } + } + + TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line); + TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); + if (constConstructor) + return constConstructor; + + return constructor; +} + +TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type) +{ + bool canBeFolded = areAllChildConst(aggrNode); + aggrNode->setType(type); + if (canBeFolded) { + bool returnVal = false; + constUnion* unionArray = new constUnion[type.getObjectSize()]; + if (aggrNode->getSequence().size() == 1) { + returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type, true); + } + else { + returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type); + } + if (returnVal) + return 0; + + return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine()); + } + + return 0; +} + +// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value +// for the parameter to the constructor (passed to this function). Essentially, it converts +// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a +// float, then float is converted to int. +// +// Returns 0 for an error or the constructed node. +// +TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset) +{ + TIntermTyped* newNode; + TOperator basicOp; + + // + // First, convert types as needed. + // + switch (op) { + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + case EOpConstructFloat: + basicOp = EOpConstructFloat; + break; + + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + case EOpConstructInt: + basicOp = EOpConstructInt; + break; + + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructBool: + basicOp = EOpConstructBool; + break; + + default: + error(line, "unsupported construction", "", ""); + recover(); + + return 0; + } + newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable); + if (newNode == 0) { + error(line, "can't convert", "constructor", ""); + return 0; + } + + // + // Now, if there still isn't an operation to do the construction, and we need one, add one. + // + + // Otherwise, skip out early. + if (subset || newNode != node && newNode->getType() == *type) + return newNode; + + // setAggregateOperator will insert a new node for the constructor, as needed. + return intermediate.setAggregateOperator(newNode, op, line); +} + +// This function tests for the type of the parameters to the structures constructors. Raises +// an error message if the expected type does not match the parameter passed to the constructor. +// +// Returns 0 for an error or the input node itself if the expected and the given parameter types match. +// +TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset) +{ + if (*type == node->getAsTyped()->getType()) { + if (subset) + return node->getAsTyped(); + else + return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line); + } else { + error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount, + node->getAsTyped()->getType().getBasicString(), type->getBasicString()); + recover(); + } + + return 0; +} + +// +// This function returns the tree representation for the vector field(s) being accessed from contant vector. +// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is +// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol +// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of +// a constant matrix. +// +TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line) +{ + TIntermTyped* typedNode; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + + constUnion *unionArray; + if (tempConstantNode) { + unionArray = tempConstantNode->getUnionArrayPointer(); + + if (!unionArray) { // this error message should never be raised + infoSink.info.message(EPrefixInternalError, "constUnion not initialized in addConstVectorNode function", line); + recover(); + + return node; + } + } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error + error(line, "Cannot offset into the vector", "Error", ""); + recover(); + + return 0; + } + + constUnion* constArray = new constUnion[fields.num]; + + for (int i = 0; i < fields.num; i++) { + if (fields.offsets[i] >= node->getType().getObjectSize()) { + error(line, "", "[", "vector field selection out of range '%d'", fields.offsets[i]); + recover(); + fields.offsets[i] = 0; + } + + constArray[i] = unionArray[fields.offsets[i]]; + + } + typedNode = intermediate.addConstantUnion(constArray, node->getType(), line); + return typedNode; +} + +// +// This function returns the column being accessed from a constant matrix. The values are retrieved from +// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input +// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a +// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) +// +TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line) +{ + TIntermTyped* typedNode; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + + if (index >= node->getType().getNominalSize()) { + error(line, "", "[", "matrix field selection out of range '%d'", index); + recover(); + index = 0; + } + + if (tempConstantNode) { + constUnion* unionArray = tempConstantNode->getUnionArrayPointer(); + int size = tempConstantNode->getType().getNominalSize(); + typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line); + } else { + error(line, "Cannot offset into the matrix", "Error", ""); + recover(); + + return 0; + } + + return typedNode; +} + + +// +// This function returns an element of an array accessed from a constant array. The values are retrieved from +// the symbol table and parse-tree is built for the type of the element. The input +// to the function could either be a symbol node (a[0] where a is a constant array)that represents a +// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure) +// +TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line) +{ + TIntermTyped* typedNode; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + int arraySize = node->getType().getArraySize(); + TType arrayElementType = node->getType(); + arrayElementType.clearArrayness(); + + if (index >= node->getType().getArraySize()) { + error(line, "", "[", "array field selection out of range '%d'", index); + recover(); + index = 0; + } + + int arrayElementSize = arrayElementType.getObjectSize(); + + if (tempConstantNode) { + constUnion* unionArray = tempConstantNode->getUnionArrayPointer(); + typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); + } else { + error(line, "Cannot offset into the array", "Error", ""); + recover(); + + return 0; + } + + return typedNode; +} + + +// +// This function returns the value of a particular field inside a constant structure from the symbol table. +// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr +// function and returns the parse-tree with the values of the embedded/nested struct. +// +TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line) +{ + TTypeList* fields = node->getType().getStruct(); + TIntermTyped *typedNode; + int instanceSize = 0; + unsigned int index = 0; + TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion(); + + for ( index = 0; index < fields->size(); ++index) { + if ((*fields)[index].type->getFieldName() == identifier) { + break; + } else { + instanceSize += (*fields)[index].type->getObjectSize(); + } + } + + if (tempConstantNode) { + constUnion* constArray = tempConstantNode->getUnionArrayPointer(); + + typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function + } else { + error(line, "Cannot offset into the structure", "Error", ""); + recover(); + + return 0; + } + + return typedNode; +} + +// +// Initialize all supported extensions to disable +// +void TParseContext::initializeExtensionBehavior() +{ + // + // example code: extensionBehavior["test"] = EBhDisable; // where "test" is the name of + // supported extension + // + extensionBehavior["GL_ARB_texture_rectangle"] = EBhRequire; + extensionBehavior["GL_3DL_array_objects"] = EBhDisable; +} + +OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX; + +bool InitializeParseContextIndex() +{ + if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) { + assert(0 && "InitializeParseContextIndex(): Parse Context already initalised"); + return false; + } + + // + // Allocate a TLS index. + // + GlobalParseContextIndex = OS_AllocTLSIndex(); + + if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "InitializeParseContextIndex(): Parse Context already initalised"); + return false; + } + + return true; +} + +bool InitializeGlobalParseContext() +{ + if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalised"); + return false; + } + + TThreadParseContext *lpParseContext = static_cast(OS_GetTLSValue(GlobalParseContextIndex)); + if (lpParseContext != 0) { + assert(0 && "InitializeParseContextIndex(): Parse Context already initalised"); + return false; + } + + TThreadParseContext *lpThreadData = new TThreadParseContext(); + if (lpThreadData == 0) { + assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context"); + return false; + } + + lpThreadData->lpGlobalParseContext = 0; + OS_SetTLSValue(GlobalParseContextIndex, lpThreadData); + + return true; +} + +TParseContextPointer& GetGlobalParseContext() +{ + // + // Minimal error checking for speed + // + + TThreadParseContext *lpParseContext = static_cast(OS_GetTLSValue(GlobalParseContextIndex)); + + return lpParseContext->lpGlobalParseContext; +} + +bool FreeParseContext() +{ + if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "FreeParseContext(): Parse Context index not initalised"); + return false; + } + + TThreadParseContext *lpParseContext = static_cast(OS_GetTLSValue(GlobalParseContextIndex)); + if (lpParseContext) + delete lpParseContext; + + return true; +} + +bool FreeParseContextIndex() +{ + OS_TLSIndex tlsiIndex = GlobalParseContextIndex; + + if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "FreeParseContextIndex(): Parse Context index not initalised"); + return false; + } + + GlobalParseContextIndex = OS_INVALID_TLS_INDEX; + + return OS_FreeTLSIndex(tlsiIndex); +} diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h new file mode 100644 index 0000000..ca153ae --- /dev/null +++ b/glslang/MachineIndependent/ParseHelper.h @@ -0,0 +1,150 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _PARSER_HELPER_INCLUDED_ +#define _PARSER_HELPER_INCLUDED_ + +#include "../Include/ShHandle.h" +#include "SymbolTable.h" +#include "localintermediate.h" + +struct TMatrixFields { + bool wholeRow; + bool wholeCol; + int row; + int col; +}; + +typedef enum { + EBhRequire, + EBhEnable, + EBhWarn, + EBhDisable +} TBehavior; + +struct TPragma { + TPragma(bool o, bool d) : optimize(o), debug(d) { } + bool optimize; + bool debug; + TPragmaTable pragmaTable; +}; + +// +// The following are extra variables needed during parsing, grouped together so +// they can be passed to the parser without needing a global. +// +struct TParseContext { + TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is) : + intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0), + recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0), + inTypeParen(false), contextPragma(true, false) { } + TIntermediate& intermediate; // to hold and build a parse tree + TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed + TInfoSink& infoSink; + EShLanguage language; // vertex or fragment language (future: pack or unpack) + TIntermNode* treeRoot; // root of parse tree being created + bool recoveredFromError; // true if a parse error has occurred, but we continue to parse + int numErrors; + bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier + int loopNestingLevel; // 0 if outside all loops + bool inTypeParen; // true if in parentheses, looking only for an identifier + const TType* currentFunctionType; // the return type of the function that's currently being parsed + bool functionReturnsValue; // true if a non-void function has a return + TMap extensionBehavior; + void initializeExtensionBehavior(); + + void C_DECL error(TSourceLoc, const char *szReason, const char *szToken, + const char *szExtraInfoFormat, ...); + bool reservedErrorCheck(int line, const TString& identifier); + void recover(); + + bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line); + bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line); + void assignError(int line, const char* op, TString left, TString right); + void unaryOpError(int line, char* op, TString operand); + void binaryOpError(int line, char* op, TString left, TString right); + bool lValueErrorCheck(int line, char* op, TIntermTyped*); + bool constErrorCheck(TIntermTyped* node); + bool integerErrorCheck(TIntermTyped* node, char* token); + bool globalErrorCheck(int line, bool global, char* token); + bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*); + bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size); + bool arrayQualifierErrorCheck(int line, TPublicType type); + bool arrayTypeErrorCheck(int line, TPublicType type); + bool arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable); + bool insertBuiltInArrayAtGlobalLevel(); + bool voidErrorCheck(int, const TString&, const TPublicType&); + bool boolErrorCheck(int, const TIntermTyped*); + bool boolErrorCheck(int, const TPublicType&); + bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason); + bool structQualifierErrorCheck(int line, const TPublicType& pType); + bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type); + bool containsSampler(TType& type); + bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type); + bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type); + bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type); + bool extensionErrorCheck(int line, const char*); + const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0); + bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, + TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0); + bool areAllChildConst(TIntermAggregate* aggrNode); + TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc); + TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type); + TIntermTyped* constructStruct(TIntermNode*, TType*, int, TSourceLoc, bool subset); + TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, TSourceLoc, bool subset); + TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc); + TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc); + TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line); + TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc); + bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc); + struct TPragma contextPragma; + TString HashErrMsg; + bool AfterEOF; +}; + +int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext&); +void PaReservedWord(); +int PaIdentOrType(TString& id, TParseContext&, TSymbol*&); +int PaParseComment(int &lineno, TParseContext&); +void setInitialState(); + +typedef TParseContext* TParseContextPointer; +extern TParseContextPointer& GetGlobalParseContext(); +#define GlobalParseContext GetGlobalParseContext() + +typedef struct TThreadParseContextRec +{ + TParseContext *lpGlobalParseContext; +} TThreadParseContext; + +#endif // _PARSER_HELPER_INCLUDED_ diff --git a/glslang/MachineIndependent/PoolAlloc.cpp b/glslang/MachineIndependent/PoolAlloc.cpp new file mode 100644 index 0000000..9034bb3 --- /dev/null +++ b/glslang/MachineIndependent/PoolAlloc.cpp @@ -0,0 +1,342 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#include "../Include/PoolAlloc.h" +#include "../Include/Common.h" + +#include "Include/InitializeGlobals.h" +#include "osinclude.h" + +OS_TLSIndex PoolIndex; + +void InitializeGlobalPools() +{ + TThreadGlobalPools* globalPools= static_cast(OS_GetTLSValue(PoolIndex)); + if (globalPools) + return; + + TPoolAllocator *globalPoolAllocator = new TPoolAllocator(true); + + TThreadGlobalPools* threadData = new TThreadGlobalPools(); + + threadData->globalPoolAllocator = globalPoolAllocator; + + OS_SetTLSValue(PoolIndex, threadData); + globalPoolAllocator->push(); +} + +void FreeGlobalPools() +{ + // Release the allocated memory for this thread. + TThreadGlobalPools* globalPools= static_cast(OS_GetTLSValue(PoolIndex)); + if (!globalPools) + return; + + GlobalPoolAllocator.popAll(); + delete &GlobalPoolAllocator; + delete globalPools; +} + +bool InitializePoolIndex() +{ + // Allocate a TLS index. + if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX) + return false; + + return true; +} + +void FreePoolIndex() +{ + // Release the TLS index. + OS_FreeTLSIndex(PoolIndex); +} + +TPoolAllocator& GetGlobalPoolAllocator() +{ + TThreadGlobalPools* threadData = static_cast(OS_GetTLSValue(PoolIndex)); + + return *threadData->globalPoolAllocator; +} + +void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator) +{ + TThreadGlobalPools* threadData = static_cast(OS_GetTLSValue(PoolIndex)); + + threadData->globalPoolAllocator = poolAllocator; +} + +// +// Implement the functionality of the TPoolAllocator class, which +// is documented in PoolAlloc.h. +// +TPoolAllocator::TPoolAllocator(bool g, int growthIncrement, int allocationAlignment) : + global(g), + pageSize(growthIncrement), + alignment(allocationAlignment), + freeList(0), + inUseList(0), + numCalls(0) +{ + // + // Don't allow page sizes we know are smaller than all common + // OS page sizes. + // + if (pageSize < 4*1024) + pageSize = 4*1024; + + // + // A large currentPageOffset indicates a new page needs to + // be obtained to allocate memory. + // + currentPageOffset = pageSize; + + // + // Adjust alignment to be at least pointer aligned and + // power of 2. + // + size_t minAlign = sizeof(void*); + alignment &= ~(minAlign - 1); + if (alignment < minAlign) + alignment = minAlign; + size_t a = 1; + while (a < alignment) + a <<= 1; + alignment = a; + alignmentMask = a - 1; + + // + // Align header skip + // + headerSkip = minAlign; + if (headerSkip < sizeof(tHeader)) { + headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask; + } +} + +TPoolAllocator::~TPoolAllocator() +{ + if (!global) { + // + // Then we know that this object is not being + // allocated after other, globally scoped objects + // that depend on it. So we can delete the "in use" memory. + // + while (inUseList) { + tHeader* next = inUseList->nextPage; + inUseList->~tHeader(); + delete [] reinterpret_cast(inUseList); + inUseList = next; + } + } + + // + // Always delete the free list memory - it can't be being + // (correctly) referenced, whether the pool allocator was + // global or not. We should not check the guard blocks + // here, because we did it already when the block was + // placed into the free list. + // + while (freeList) { + tHeader* next = freeList->nextPage; + delete [] reinterpret_cast(freeList); + freeList = next; + } +} + +// Support MSVC++ 6.0 +const unsigned char TAllocation::guardBlockBeginVal = 0xfb; +const unsigned char TAllocation::guardBlockEndVal = 0xfe; +const unsigned char TAllocation::userDataFill = 0xcd; + +# ifdef GUARD_BLOCKS + const size_t TAllocation::guardBlockSize = 16; +# else + const size_t TAllocation::guardBlockSize = 0; +# endif + +// +// Check a single guard block for damage +// +void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, char* locText) const +{ + for (int x = 0; x < guardBlockSize; x++) { + if (blockMem[x] != val) { + char assertMsg[80]; + + // We don't print the assert message. It's here just to be helpful. + sprintf(assertMsg, "PoolAlloc: Damage %s %lu byte allocation at 0x%p\n", + locText, size, data()); + assert(0 && "PoolAlloc: Damage in guard block"); + } + } +} + + +void TPoolAllocator::push() +{ + tAllocState state = { currentPageOffset, inUseList }; + + stack.push_back(state); + + // + // Indicate there is no current page to allocate from. + // + currentPageOffset = pageSize; +} + +// +// Do a mass-deallocation of all the individual allocations +// that have occurred since the last push(), or since the +// last pop(), or since the object's creation. +// +// The deallocated pages are saved for future allocations. +// +void TPoolAllocator::pop() +{ + if (stack.size() < 1) + return; + + tHeader* page = stack.back().page; + currentPageOffset = stack.back().offset; + + while (inUseList != page) { + // invoke destructor to free allocation list + inUseList->~tHeader(); + + tHeader* nextInUse = inUseList->nextPage; + if (inUseList->pageCount > 1) + delete [] reinterpret_cast(inUseList); + else { + inUseList->nextPage = freeList; + freeList = inUseList; + } + inUseList = nextInUse; + } + + stack.pop_back(); +} + +// +// Do a mass-deallocation of all the individual allocations +// that have occurred. +// +void TPoolAllocator::popAll() +{ + while (stack.size() > 0) + pop(); +} + +void* TPoolAllocator::allocate(size_t numBytes) +{ + // If we are using guard blocks, all allocations are bracketed by + // them: [guardblock][allocation][guardblock]. numBytes is how + // much memory the caller asked for. allocationSize is the total + // size including guard blocks. In release build, + // guardBlockSize=0 and this all gets optimized away. + size_t allocationSize = TAllocation::allocationSize(numBytes); + + // + // Just keep some interesting statistics. + // + ++numCalls; + totalBytes += numBytes; + + // + // Do the allocation, most likely case first, for efficiency. + // This step could be moved to be inline sometime. + // + if (currentPageOffset + allocationSize <= pageSize) { + // + // Safe to allocate from currentPageOffset. + // + unsigned char* memory = reinterpret_cast(inUseList) + currentPageOffset; + currentPageOffset += allocationSize; + currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask; + + return initializeAllocation(inUseList, memory, numBytes); + } + + if (allocationSize + headerSkip > pageSize) { + // + // Do a multi-page allocation. Don't mix these with the others. + // The OS is efficient and allocating and free-ing multiple pages. + // + size_t numBytesToAlloc = allocationSize + headerSkip; + tHeader* memory = reinterpret_cast(::new char[numBytesToAlloc]); + if (memory == 0) + return 0; + + // Use placement-new to initialize header + new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize); + inUseList = memory; + + currentPageOffset = pageSize; // make next allocation come from a new page + + // No guard blocks for multi-page allocations (yet) + return reinterpret_cast(reinterpret_cast(memory) + headerSkip); + } + + // + // Need a simple page to allocate from. + // + tHeader* memory; + if (freeList) { + memory = freeList; + freeList = freeList->nextPage; + } else { + memory = reinterpret_cast(::new char[pageSize]); + if (memory == 0) + return 0; + } + + // Use placement-new to initialize header + new(memory) tHeader(inUseList, 1); + inUseList = memory; + + unsigned char* ret = reinterpret_cast(inUseList) + headerSkip; + currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask; + + return initializeAllocation(inUseList, ret, numBytes); +} + + +// +// Check all allocations in a list for damage by calling check on each. +// +void TAllocation::checkAllocList() const +{ + for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc) + alloc->check(); +} diff --git a/glslang/MachineIndependent/QualifierAlive.cpp b/glslang/MachineIndependent/QualifierAlive.cpp new file mode 100644 index 0000000..a88fd43 --- /dev/null +++ b/glslang/MachineIndependent/QualifierAlive.cpp @@ -0,0 +1,91 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#include "../Include/intermediate.h" + +class TAliveTraverser : public TIntermTraverser { +public: + TAliveTraverser(TQualifier q) : TIntermTraverser(), found(false), qualifier(q) + { + visitSymbol = AliveSymbol; + visitSelection = AliveSelection; + rightToLeft = true; + } + bool wasFound() { return found; } +protected: + bool found; + TQualifier qualifier; + + friend void AliveSymbol(TIntermSymbol*, TIntermTraverser*); + friend bool AliveSelection(bool, TIntermSelection*, TIntermTraverser*); +}; + +// +// Report whether or not a variable of the given qualifier type +// is guaranteed written. Not always possible to determine if +// it is written conditionally. +// +// ?? It does not do this well yet, this is just a place holder +// that simply determines if it was reference at all, anywhere. +// +bool QualifierWritten(TIntermNode* node, TQualifier qualifier) +{ + TAliveTraverser it(qualifier); + + if (node) + node->traverse(&it); + + return it.wasFound(); +} + +void AliveSymbol(TIntermSymbol* node, TIntermTraverser* it) +{ + TAliveTraverser* lit = static_cast(it); + + // + // If it's what we're looking for, record it. + // + if (node->getQualifier() == lit->qualifier) + lit->found = true; +} + +bool AliveSelection(bool preVisit, TIntermSelection* node, TIntermTraverser* it) +{ + TAliveTraverser* lit = static_cast(it); + + if (lit->wasFound()) + return false; + + return true; +} diff --git a/glslang/MachineIndependent/QualifierAlive.h b/glslang/MachineIndependent/QualifierAlive.h new file mode 100644 index 0000000..60dfa50 --- /dev/null +++ b/glslang/MachineIndependent/QualifierAlive.h @@ -0,0 +1,35 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +bool QualifierWritten(TIntermNode* root, TQualifier); diff --git a/glslang/MachineIndependent/RemoveTree.cpp b/glslang/MachineIndependent/RemoveTree.cpp new file mode 100644 index 0000000..196279e --- /dev/null +++ b/glslang/MachineIndependent/RemoveTree.cpp @@ -0,0 +1,98 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#include "../Include/intermediate.h" +#include "RemoveTree.h" +// +// Code to recursively delete the intermediate tree. +// + +void RemoveSymbol(TIntermSymbol* node, TIntermTraverser* it) +{ + delete node; +} + +bool RemoveBinary(bool /*preVisit*/ , TIntermBinary* node, TIntermTraverser*) +{ + delete node; + + return true; +} + +bool RemoveUnary(bool /*preVisit */, TIntermUnary* node, TIntermTraverser*) +{ + delete node; + + return true; +} + +bool RemoveAggregate(bool /*preVisit*/ , TIntermAggregate* node, TIntermTraverser*) +{ + delete node; + + return true; +} + +bool RemoveSelection(bool /*preVisit*/ , TIntermSelection* node, TIntermTraverser*) +{ + delete node; + + return true; +} + +void RemoveConstantUnion(TIntermConstantUnion* node, TIntermTraverser*) +{ + delete node; +} + +// +// Entry point. +// +void RemoveAllTreeNodes(TIntermNode* root) +{ + TIntermTraverser it; + + it.visitAggregate = RemoveAggregate; + it.visitBinary = RemoveBinary; + it.visitConstantUnion = RemoveConstantUnion; + it.visitSelection = RemoveSelection; + it.visitSymbol = RemoveSymbol; + it.visitUnary = RemoveUnary; + + it.preVisit = false; + it.postVisit = true; + + root->traverse(&it); +} + diff --git a/glslang/MachineIndependent/RemoveTree.h b/glslang/MachineIndependent/RemoveTree.h new file mode 100644 index 0000000..a6d70b4 --- /dev/null +++ b/glslang/MachineIndependent/RemoveTree.h @@ -0,0 +1,35 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +void RemoveAllTreeNodes(TIntermNode*); diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp new file mode 100644 index 0000000..5d932d1 --- /dev/null +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -0,0 +1,586 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +// +// Implement the top-level of interface to the compiler/linker, +// as defined in ShaderLang.h +// +#include "SymbolTable.h" +#include "ParseHelper.h" + +#include "../Include/ShHandle.h" +#include "InitializeDll.h" + +#define SH_EXPORTING +#include "../Public/ShaderLang.h" +#include "Initialize.h" +// +// A symbol table for each language. Each has a different +// set of built-ins, and we want to preserve that from +// compile to compile. +// +TSymbolTable SymbolTables[EShLangCount]; + + +TPoolAllocator* PerProcessGPA = 0; +// +// This is the platform independent interface between an OGL driver +// and the shading language compiler/linker. +// + +// +// Driver must call this first, once, before doing any other +// compiler/linker operations. +// +int ShInitialize() +{ + TInfoSink infoSink; + bool ret = true; + + if (!InitProcess()) + return 0; + + // This method should be called once per process. If its called by multiple threads, then + // we need to have thread synchronization code around the initialization of per process + // global pool allocator + if (!PerProcessGPA) { + TPoolAllocator *builtInPoolAllocator = new TPoolAllocator(true); + builtInPoolAllocator->push(); + TPoolAllocator* gPoolAllocator = &GlobalPoolAllocator; + SetGlobalPoolAllocatorPtr(builtInPoolAllocator); + + TSymbolTable symTables[EShLangCount]; + GenerateBuiltInSymbolTable(0, infoSink, symTables); + + PerProcessGPA = new TPoolAllocator(true); + PerProcessGPA->push(); + SetGlobalPoolAllocatorPtr(PerProcessGPA); + + SymbolTables[EShLangVertex].copyTable(symTables[EShLangVertex]); + SymbolTables[EShLangFragment].copyTable(symTables[EShLangFragment]); + + SetGlobalPoolAllocatorPtr(gPoolAllocator); + + symTables[EShLangVertex].pop(); + symTables[EShLangFragment].pop(); + + builtInPoolAllocator->popAll(); + delete builtInPoolAllocator; + + } + + return ret ? 1 : 0; +} + +// +// Driver calls these to create and destroy compiler/linker +// objects. +// + +ShHandle ShConstructCompiler(const EShLanguage language, int debugOptions) +{ + if (!InitThread()) + return 0; + + TShHandleBase* base = static_cast(ConstructCompiler(language, debugOptions)); + + return reinterpret_cast(base); +} + +ShHandle ShConstructLinker(const EShExecutable executable, int debugOptions) +{ + if (!InitThread()) + return 0; + + TShHandleBase* base = static_cast(ConstructLinker(executable, debugOptions)); + + return reinterpret_cast(base); +} + +ShHandle ShConstructUniformMap() +{ + if (!InitThread()) + return 0; + + TShHandleBase* base = static_cast(ConstructUniformMap()); + + return reinterpret_cast(base); +} + +void ShDestruct(ShHandle handle) +{ + if (handle == 0) + return; + + TShHandleBase* base = static_cast(handle); + + if (base->getAsCompiler()) + DeleteCompiler(base->getAsCompiler()); + else if (base->getAsLinker()) + DeleteLinker(base->getAsLinker()); + else if (base->getAsUniformMap()) + DeleteUniformMap(base->getAsUniformMap()); +} + +// +// Cleanup symbol tables +// +int __fastcall ShFinalize() +{ + if (PerProcessGPA) { + PerProcessGPA->popAll(); + delete PerProcessGPA; + } + return 1; +} + +bool GenerateBuiltInSymbolTable(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable* symbolTables, EShLanguage language) +{ + TBuiltIns builtIns; + + if (resources) { + builtIns.initialize(*resources); + InitializeSymbolTable(builtIns.getBuiltInStrings(), language, infoSink, resources, symbolTables); + } else { + builtIns.initialize(); + InitializeSymbolTable(builtIns.getBuiltInStrings(), EShLangVertex, infoSink, resources, symbolTables); + InitializeSymbolTable(builtIns.getBuiltInStrings(), EShLangFragment, infoSink, resources, symbolTables); + } + + return true; +} + +bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language, TInfoSink& infoSink, const TBuiltInResource* resources, TSymbolTable* symbolTables) +{ + TIntermediate intermediate(infoSink); + TSymbolTable* symbolTable; + + if (resources) + symbolTable = symbolTables; + else + symbolTable = &symbolTables[language]; + + TParseContext parseContext(*symbolTable, intermediate, language, infoSink); + + GlobalParseContext = &parseContext; + + setInitialState(); + + assert(symbolTable->isEmpty() || symbolTable->atSharedBuiltInLevel()); + + // + // Parse the built-ins. This should only happen once per + // language symbol table. + // + // Push the symbol table to give it an initial scope. This + // push should not have a corresponding pop, so that built-ins + // are preserved, and the test for an empty table fails. + // + + symbolTable->push(); + + //Initialize the Preprocessor + int ret = InitPreprocessor(); + if (ret) { + infoSink.info.message(EPrefixInternalError, "Unable to intialize the Preprocessor"); + return false; + } + + for (TBuiltInStrings::iterator i = BuiltInStrings[parseContext.language].begin(); + i != BuiltInStrings[parseContext.language].end(); + ++i) { + const char* builtInShaders[1]; + int builtInLengths[1]; + + builtInShaders[0] = (*i).c_str(); + builtInLengths[0] = (int) (*i).size(); + + if (PaParseStrings(const_cast(builtInShaders), builtInLengths, 1, parseContext) != 0) { + infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins"); + return false; + } + } + + if (resources) { + IdentifyBuiltIns(parseContext.language, *symbolTable, *resources); + } else { + IdentifyBuiltIns(parseContext.language, *symbolTable); + } + + FinalizePreprocessor(); + + return true; +} + +// +// Do an actual compile on the given strings. The result is left +// in the given compile object. +// +// Return: The return value of ShCompile is really boolean, indicating +// success or failure. +// +int ShCompile( + const ShHandle handle, + const char* const shaderStrings[], + const int numStrings, + const EShOptimizationLevel optLevel, + const TBuiltInResource* resources, + int debugOptions + ) +{ + if (!InitThread()) + return 0; + + if (handle == 0) + return 0; + + TShHandleBase* base = reinterpret_cast(handle); + TCompiler* compiler = base->getAsCompiler(); + if (compiler == 0) + return 0; + + GlobalPoolAllocator.push(); + compiler->infoSink.info.erase(); + compiler->infoSink.debug.erase(); + + if (numStrings == 0) + return 1; + + TIntermediate intermediate(compiler->infoSink); + TSymbolTable symbolTable(SymbolTables[compiler->getLanguage()]); + + GenerateBuiltInSymbolTable(resources, compiler->infoSink, &symbolTable, compiler->getLanguage()); + + TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->infoSink); + parseContext.initializeExtensionBehavior(); + + GlobalParseContext = &parseContext; + + setInitialState(); + + InitPreprocessor(); + // + // Parse the application's shaders. All the following symbol table + // work will be throw-away, so push a new allocation scope that can + // be thrown away, then push a scope for the current shader's globals. + // + bool success = true; + + symbolTable.push(); + if (!symbolTable.atGlobalLevel()) + parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level"); + + if (parseContext.insertBuiltInArrayAtGlobalLevel()) + success = false; + + int ret = PaParseStrings(const_cast(shaderStrings), 0, numStrings, parseContext); + if (ret) + success = false; + + if (success && parseContext.treeRoot) { + if (optLevel == EShOptNoGeneration) + parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested."); + else { + success = intermediate.postProcess(parseContext.treeRoot, parseContext.language); + + if (success) { + + if (debugOptions & EDebugOpIntermediate) + intermediate.outputTree(parseContext.treeRoot); + + // + // Call the machine dependent compiler + // + if (! compiler->compile(parseContext.treeRoot)) + success = false; + } + } + } else if (!success) { + parseContext.infoSink.info.prefix(EPrefixError); + parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n"; + success = false; + if (debugOptions & EDebugOpIntermediate) + intermediate.outputTree(parseContext.treeRoot); + } + + intermediate.remove(parseContext.treeRoot); + + // + // Ensure symbol table is returned to the built-in level, + // throwing away all but the built-ins. + // + while (! symbolTable.atSharedBuiltInLevel()) + symbolTable.pop(); + + FinalizePreprocessor(); + // + // Throw away all the temporary memory used by the compilation process. + // + GlobalPoolAllocator.pop(); + + return success ? 1 : 0; +} + +// +// Do an actual link on the given compile objects. +// +// Return: The return value of is really boolean, indicating +// success or failure. +// +int ShLink( + const ShHandle linkHandle, + const ShHandle compHandles[], + const int numHandles, + ShHandle uniformMapHandle, + short int** uniformsAccessed, + int* numUniformsAccessed) + +{ + if (!InitThread()) + return 0; + + TShHandleBase* base = reinterpret_cast(linkHandle); + TLinker* linker = static_cast(base->getAsLinker()); + if (linker == 0) + return 0; + + int returnValue; + GlobalPoolAllocator.push(); + returnValue = ShLinkExt(linkHandle, compHandles, numHandles); + GlobalPoolAllocator.pop(); + + if (returnValue) + return 1; + + return 0; +} +// +// This link method will be eventually used once the ICD supports the new linker interface +// +int ShLinkExt( + const ShHandle linkHandle, + const ShHandle compHandles[], + const int numHandles) +{ + if (linkHandle == 0 || numHandles == 0) + return 0; + + THandleList cObjects; + + {// support MSVC++6.0 + for (int i = 0; i < numHandles; ++i) { + if (compHandles[i] == 0) + return 0; + TShHandleBase* base = reinterpret_cast(compHandles[i]); + if (base->getAsLinker()) { + cObjects.push_back(base->getAsLinker()); + } + if (base->getAsCompiler()) + cObjects.push_back(base->getAsCompiler()); + + + if (cObjects[i] == 0) + return 0; + } + } + + TShHandleBase* base = reinterpret_cast(linkHandle); + TLinker* linker = static_cast(base->getAsLinker()); + + if (linker == 0) + return 0; + + linker->infoSink.info.erase(); + + {// support MSVC++6.0 + for (int i = 0; i < numHandles; ++i) { + if (cObjects[i]->getAsCompiler()) { + if (! cObjects[i]->getAsCompiler()->linkable()) { + linker->infoSink.info.message(EPrefixError, "Not all shaders have valid object code."); + return 0; + } + } + } + } + + bool ret = linker->link(cObjects); + + return ret ? 1 : 0; +} + +// +// ShSetEncrpytionMethod is a place-holder for specifying +// how source code is encrypted. +// +void ShSetEncryptionMethod(ShHandle handle) +{ + if (handle == 0) + return; +} + +// +// Return any compiler/linker/uniformmap log of messages for the application. +// +const char* ShGetInfoLog(const ShHandle handle) +{ + if (!InitThread()) + return 0; + + if (handle == 0) + return 0; + + TShHandleBase* base = static_cast(handle); + TInfoSink* infoSink; + + if (base->getAsCompiler()) + infoSink = &(base->getAsCompiler()->getInfoSink()); + else if (base->getAsLinker()) + infoSink = &(base->getAsLinker()->getInfoSink()); + + infoSink->info << infoSink->debug.c_str(); + return infoSink->info.c_str(); +} + +// +// Return the resulting binary code from the link process. Structure +// is machine dependent. +// +const void* ShGetExecutable(const ShHandle handle) +{ + if (!InitThread()) + return 0; + + if (handle == 0) + return 0; + + TShHandleBase* base = reinterpret_cast(handle); + + TLinker* linker = static_cast(base->getAsLinker()); + if (linker == 0) + return 0; + + return linker->getObjectCode(); +} + +// +// Let the linker know where the application said it's attributes are bound. +// The linker does not use these values, they are remapped by the ICD or +// hardware. It just needs them to know what's aliased. +// +// Return: The return value of is really boolean, indicating +// success or failure. +// +int ShSetVirtualAttributeBindings(const ShHandle handle, const ShBindingTable* table) +{ + if (!InitThread()) + return 0; + + if (handle == 0) + return 0; + + TShHandleBase* base = reinterpret_cast(handle); + TLinker* linker = static_cast(base->getAsLinker()); + + if (linker == 0) + return 0; + + linker->setAppAttributeBindings(table); + + return 1; +} + +// +// Let the linker know where the predefined attributes have to live. +// +int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* table) +{ + if (!InitThread()) + return 0; + + if (handle == 0) + return 0; + + TShHandleBase* base = reinterpret_cast(handle); + TLinker* linker = static_cast(base->getAsLinker()); + + if (linker == 0) + return 0; + + linker->setFixedAttributeBindings(table); + return 1; +} + +// +// Some attribute locations are off-limits to the linker... +// +int ShExcludeAttributes(const ShHandle handle, int *attributes, int count) +{ + if (!InitThread()) + return 0; + + if (handle == 0) + return 0; + + TShHandleBase* base = reinterpret_cast(handle); + TLinker* linker = static_cast(base->getAsLinker()); + if (linker == 0) + return 0; + + linker->setExcludedAttributes(attributes, count); + + return 1; +} + +// +// Return the index for OpenGL to use for knowing where a uniform lives. +// +// Return: The return value of is really boolean, indicating +// success or failure. +// +int ShGetUniformLocation(const ShHandle handle, const char* name) +{ + if (!InitThread()) + return 0; + + if (handle == 0) + return -1; + + TShHandleBase* base = reinterpret_cast(handle); + TUniformMap* uniformMap= base->getAsUniformMap(); + if (uniformMap == 0) + return -1; + + return uniformMap->getLocation(name); +} + diff --git a/glslang/MachineIndependent/SymbolTable.cpp b/glslang/MachineIndependent/SymbolTable.cpp new file mode 100644 index 0000000..ea89950 --- /dev/null +++ b/glslang/MachineIndependent/SymbolTable.cpp @@ -0,0 +1,245 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +// +// Symbol table for parsing. Most functionaliy and main ideas +// are documented in the header file. +// + +#include "SymbolTable.h" + +// +// TType helper function needs a place to live. +// + +// +// Recursively generate mangled names. +// +void TType::buildMangledName(TString& mangledName) +{ + if (isMatrix()) + mangledName += 'm'; + else if (isVector()) + mangledName += 'v'; + + switch (type) { + case EbtFloat: mangledName += 'f'; break; + case EbtInt: mangledName += 'i'; break; + case EbtBool: mangledName += 'b'; break; + case EbtSampler1D: mangledName += "s1"; break; + case EbtSampler2D: mangledName += "s2"; break; + case EbtSampler3D: mangledName += "s3"; break; + case EbtSamplerCube: mangledName += "sC"; break; + case EbtSampler1DShadow: mangledName += "sS1"; break; + case EbtSampler2DShadow: mangledName += "sS2"; break; + case EbtSamplerRect: mangledName += "sR2"; break; // ARB_texture_rectangle + case EbtSamplerRectShadow: mangledName += "sSR2"; break; // ARB_texture_rectangle + case EbtStruct: + mangledName += "struct-"; + if (typeName) + mangledName += *typeName; + {// support MSVC++6.0 + for (unsigned int i = 0; i < structure->size(); ++i) { + mangledName += '-'; + (*structure)[i].type->buildMangledName(mangledName); + } + } + default: + break; + } + + mangledName += static_cast('0' + getNominalSize()); + if (isArray()) { + char buf[10]; + sprintf(buf, "%d", arraySize); + mangledName += '['; + mangledName += buf; + mangledName += ']'; + } +} + +int TType::getStructSize() const +{ + if (!getStruct()) { + assert(false && "Not a struct"); + return 0; + } + + if (structureSize == 0) + for (TTypeList::iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) + structureSize += ((*tl).type)->getObjectSize(); + + return structureSize; +} + +// +// Dump functions. +// + +void TVariable::dump(TInfoSink& infoSink) const +{ + infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getBasicString(); + if (type.isArray()) { + infoSink.debug << "[0]"; + } + infoSink.debug << "\n"; +} + +void TFunction::dump(TInfoSink &infoSink) const +{ + infoSink.debug << getName().c_str() << ": " << returnType.getBasicString() << " " << getMangledName().c_str() << "\n"; +} + +void TSymbolTableLevel::dump(TInfoSink &infoSink) const +{ + tLevel::const_iterator it; + for (it = level.begin(); it != level.end(); ++it) + (*it).second->dump(infoSink); +} + +void TSymbolTable::dump(TInfoSink &infoSink) const +{ + for (int level = currentLevel(); level >= 0; --level) { + infoSink.debug << "LEVEL " << level << "\n"; + table[level]->dump(infoSink); + } +} + +// +// Functions have buried pointers to delete. +// +TFunction::~TFunction() +{ + for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) + delete (*i).type; +} + +// +// Symbol table levels are a map of pointers to symbols that have to be deleted. +// +TSymbolTableLevel::~TSymbolTableLevel() +{ + for (tLevel::iterator it = level.begin(); it != level.end(); ++it) + delete (*it).second; +} + +// +// Change all function entries in the table with the non-mangled name +// to be related to the provided built-in operation. This is a low +// performance operation, and only intended for symbol tables that +// live across a large number of compiles. +// +void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) +{ + tLevel::iterator it; + for (it = level.begin(); it != level.end(); ++it) { + if ((*it).second->isFunction()) { + TFunction* function = static_cast((*it).second); + if (function->getName() == name) + function->relateToOperator(op); + } + } +} + + +TSymbol::TSymbol(const TSymbol& copyOf) +{ + name = NewPoolTString(copyOf.name->c_str()); + uniqueId = copyOf.uniqueId; +} + +TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf) +{ + type.copyType(copyOf.type, remapper); + userType = copyOf.userType; + // for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL + assert(copyOf.arrayInformationType == 0); + arrayInformationType = 0; + + if (copyOf.unionArray) { + assert(!copyOf.type.getStruct()); + assert(copyOf.type.getObjectSize() == 1); + unionArray = new constUnion[1]; + unionArray[0] = copyOf.unionArray[0]; + } else + unionArray = 0; +} + +TVariable* TVariable::clone(TStructureMap& remapper) +{ + TVariable *variable = new TVariable(*this, remapper); + + return variable; +} + +TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf) +{ + for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) { + TParameter param; + parameters.push_back(param); + parameters.back().copyParam(copyOf.parameters[i], remapper); + } + + returnType.copyType(copyOf.returnType, remapper); + mangledName = copyOf.mangledName; + op = copyOf.op; + defined = copyOf.defined; +} + +TFunction* TFunction::clone(TStructureMap& remapper) +{ + TFunction *function = new TFunction(*this, remapper); + + return function; +} + +TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper) +{ + TSymbolTableLevel *symTableLevel = new TSymbolTableLevel(); + tLevel::iterator iter; + for (iter = level.begin(); iter != level.end(); ++iter) { + symTableLevel->insert(*iter->second->clone(remapper)); + } + + return symTableLevel; +} + +void TSymbolTable::copyTable(const TSymbolTable& copyOf) +{ + TStructureMap remapper; + uniqueId = copyOf.uniqueId; + for (unsigned int i = 0; i < copyOf.table.size(); ++i) { + table.push_back(copyOf.table[i]->clone(remapper)); + } +} diff --git a/glslang/MachineIndependent/SymbolTable.h b/glslang/MachineIndependent/SymbolTable.h new file mode 100644 index 0000000..719c0c8 --- /dev/null +++ b/glslang/MachineIndependent/SymbolTable.h @@ -0,0 +1,318 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _SYMBOL_TABLE_INCLUDED_ +#define _SYMBOL_TABLE_INCLUDED_ + +// +// Symbol table for parsing. Has these design characteristics: +// +// * Same symbol table can be used to compile many shaders, to preserve +// effort of creating and loading with the large numbers of built-in +// symbols. +// +// * Name mangling will be used to give each function a unique name +// so that symbol table lookups are never ambiguous. This allows +// a simpler symbol table structure. +// +// * Pushing and popping of scope, so symbol table will really be a stack +// of symbol tables. Searched from the top, with new inserts going into +// the top. +// +// * Constants: Compile time constant symbols will keep their values +// in the symbol table. The parser can substitute constants at parse +// time, including doing constant folding and constant propagation. +// +// * No temporaries: Temporaries made from operations (+, --, .xy, etc.) +// are tracked in the intermediate representation, not the symbol table. +// + +#include "Include/Common.h" +#include "Include/intermediate.h" +#include "Include/InfoSink.h" + +// +// Symbol base class. (Can build functions or variables out of these...) +// +class TSymbol { +public: + POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + TSymbol(const TString *n) : name(n) { } + virtual ~TSymbol() { /* don't delete name, it's from the pool */ } + const TString& getName() const { return *name; } + virtual const TString& getMangledName() const { return getName(); } + virtual bool isFunction() const { return false; } + virtual bool isVariable() const { return false; } + void setUniqueId(int id) { uniqueId = id; } + int getUniqueId() const { return uniqueId; } + virtual void dump(TInfoSink &infoSink) const = 0; + TSymbol(const TSymbol&); + virtual TSymbol* clone(TStructureMap& remapper) = 0; + +protected: + const TString *name; + unsigned int uniqueId; // For real comparing during code generation +}; + +// +// Variable class, meaning a symbol that's not a function. +// +// There could be a separate class heirarchy for Constant variables; +// Only one of int, bool, or float, (or none) is correct for +// any particular use, but it's easy to do this way, and doesn't +// seem worth having separate classes, and "getConst" can't simply return +// different values for different types polymorphically, so this is +// just simple and pragmatic. +// +class TVariable : public TSymbol { +public: + TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { } + virtual ~TVariable() { } + virtual bool isVariable() const { return true; } + TType& getType() { return type; } + const TType& getType() const { return type; } + bool isUserType() const { return userType; } + void changeQualifier(TQualifier qualifier) { type.changeQualifier(qualifier); } + void updateArrayInformationType(TType *t) { arrayInformationType = t; } + TType* getArrayInformationType() { return arrayInformationType; } + + virtual void dump(TInfoSink &infoSink) const; + + constUnion* getConstPointer() { + if (!unionArray) + unionArray = new constUnion[type.getObjectSize()]; + + return unionArray; + } + + constUnion* getConstPointer() const { return unionArray; } + + void shareConstPointer( constUnion *constArray) + { + delete unionArray; + unionArray = constArray; + } + TVariable(const TVariable&, TStructureMap& remapper); // copy constructor + virtual TVariable* clone(TStructureMap& remapper); + +protected: + TType type; + bool userType; + // we are assuming that Pool Allocator will free the memory allocated to unionArray + // when this object is destroyed + constUnion *unionArray; + TType *arrayInformationType; // this is used for updating maxArraySize in all the references to a given symbol +}; + +// +// The function sub-class of symbols and the parser will need to +// share this definition of a function parameter. +// +struct TParameter { + TString *name; + TType* type; + void copyParam(const TParameter& param, TStructureMap& remapper) { + name = NewPoolTString(param.name->c_str()); + type = param.type->clone(remapper); + } +}; + +// +// The function sub-class of a symbol. +// +class TFunction : public TSymbol { +public: + TFunction(TOperator o) : + TSymbol(0), + returnType(TType(EbtVoid)), + op(o), + defined(false) { } + TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : + TSymbol(name), + returnType(retType), + mangledName(*name + '('), + op(tOp), + defined(false) { } + virtual ~TFunction(); + virtual bool isFunction() const { return true; } + + void addParameter(TParameter& p) + { + parameters.push_back(p); + mangledName = mangledName + p.type->getMangledName(); + } + + const TString& getMangledName() const { return mangledName; } + const TType& getReturnType() const { return returnType; } + void relateToOperator(TOperator o) { op = o; } + TOperator getBuiltInOp() const { return op; } + void setDefined() { defined = true; } + bool isDefined() { return defined; } + + int getParamCount() const { return static_cast(parameters.size()); } + TParameter& operator [](int i) { return parameters[i]; } + const TParameter& operator [](int i) const { return parameters[i]; } + + virtual void dump(TInfoSink &infoSink) const; + TFunction(const TFunction&, TStructureMap& remapper); + virtual TFunction* clone(TStructureMap& remapper); + +protected: + typedef TVector TParamList; + TParamList parameters; + TType returnType; + TString mangledName; + TOperator op; + bool defined; +}; + + +class TSymbolTableLevel { +public: + POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + TSymbolTableLevel() { } + ~TSymbolTableLevel(); + + bool insert(TSymbol& symbol) + { + // + // returning true means symbol was added to the table + // + tInsertResult result; + result = level.insert(tLevelPair(symbol.getMangledName(), &symbol)); + + return result.second; + } + + TSymbol* find(const TString& name) const + { + tLevel::const_iterator it = level.find(name); + if (it == level.end()) + return 0; + else + return (*it).second; + } + + + void relateToOperator(const char* name, TOperator op); + void dump(TInfoSink &infoSink) const; + TSymbolTableLevel* clone(TStructureMap& remapper); + +protected: + typedef std::map, pool_allocator > > tLevel; + typedef const tLevel::value_type tLevelPair; + typedef std::pair tInsertResult; + + tLevel level; +}; + +class TSymbolTable { +public: + TSymbolTable() : uniqueId(0) + { + // + // The symbol table cannot be used until push() is called, but + // the lack of an initial call to push() can be used to detect + // that the symbol table has not been preloaded with built-ins. + // + } + + TSymbolTable(TSymbolTable& symTable) + { + table.push_back(symTable.table[0]); + uniqueId = symTable.uniqueId; + } + + ~TSymbolTable() + { + // level 0 is always built In symbols, so we never pop that out + while (table.size() > 1) + pop(); + } + + // + // When the symbol table is initialized with the built-ins, there should + // 'push' calls, so that built-ins are at level 0 and the shader + // globals are at level 1. + // + bool isEmpty() { return table.size() == 0; } + bool atBuiltInLevel() { return atSharedBuiltInLevel() || atDynamicBuiltInLevel(); } + bool atSharedBuiltInLevel() { return table.size() == 1; } + bool atGlobalLevel() { return table.size() <= 3; } + void push() { + table.push_back(new TSymbolTableLevel); + } + + void pop() { + delete table[currentLevel()]; + table.pop_back(); + } + + bool insert(TSymbol& symbol) + { + symbol.setUniqueId(++uniqueId); + return table[currentLevel()]->insert(symbol); + } + + TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0) + { + int level = currentLevel(); + TSymbol* symbol; + do { + symbol = table[level]->find(name); + --level; + } while (symbol == 0 && level >= 0); + level++; + if (builtIn) + *builtIn = level == 0; + if (sameScope) + *sameScope = level == currentLevel(); + return symbol; + } + + TSymbolTableLevel* getGlobalLevel() { assert(table.size() >= 3); return table[2]; } + void relateToOperator(const char* name, TOperator op) { table[0]->relateToOperator(name, op); } + int getMaxSymbolId() { return uniqueId; } + void dump(TInfoSink &infoSink) const; + void copyTable(const TSymbolTable& copyOf); + +protected: + int currentLevel() const { return static_cast(table.size()) - 1; } + bool atDynamicBuiltInLevel() { return table.size() == 2; } + + std::vector table; + int uniqueId; // for unique identification in code generation +}; + +#endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/glslang/MachineIndependent/glslang.l b/glslang/MachineIndependent/glslang.l new file mode 100644 index 0000000..094933e --- /dev/null +++ b/glslang/MachineIndependent/glslang.l @@ -0,0 +1,637 @@ +/* +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +*/ +/* Based on +ANSI C grammar, Lex specification + +In 1985, Jeff Lee published this Lex specification together with a Yacc +grammar for the April 30, 1985 ANSI C draft. Tom Stockfisch reposted +both to net.sources in 1987; that original, as mentioned in the answer +to question 17.25 of the comp.lang.c FAQ, can be ftp'ed from ftp.uu.net, +file usenet/net.sources/ansi.c.grammar.Z. + +I intend to keep this version as close to the current C Standard grammar +as possible; please let me know if you discover discrepancies. + +Jutta Degener, 1995 +*/ + +D [0-9] +L [a-zA-Z_] +H [a-fA-F0-9] +E [Ee][+-]?{D}+ +O [0-7] + +%option nounput +%{ +#include +#include +#include "ParseHelper.h" +#include "glslang_tab.h" + +/* windows only pragma */ +#ifdef _MSC_VER +#pragma warning(disable : 4102) +#endif + +int yy_input(char* buf, int max_size); +TSourceLoc yylineno; + +#ifdef _WIN32 + extern int yyparse(TParseContext&); + #define YY_DECL int yylex(YYSTYPE* pyylval, TParseContext& parseContext) +#else + extern int yyparse(void*); + #define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal) + #define parseContext (*((TParseContext*)(parseContextLocal))) +#endif + +#define YY_INPUT(buf,result,max_size) (result = yy_input(buf, max_size)) + +%} + +%option noyywrap +%option never-interactive +%option outfile="Gen_glslang.cpp" +%x FIELDS + + +%% +<*>"//"[^\n]*"\n" { /* ?? carriage and/or line-feed? */ }; + +"attribute" { pyylval->lex.line = yylineno; return(ATTRIBUTE); } +"const" { pyylval->lex.line = yylineno; return(CONST_QUAL); } +"uniform" { pyylval->lex.line = yylineno; return(UNIFORM); } +"varying" { pyylval->lex.line = yylineno; return(VARYING); } + +"break" { pyylval->lex.line = yylineno; return(BREAK); } +"continue" { pyylval->lex.line = yylineno; return(CONTINUE); } +"do" { pyylval->lex.line = yylineno; return(DO); } +"for" { pyylval->lex.line = yylineno; return(FOR); } +"while" { pyylval->lex.line = yylineno; return(WHILE); } + +"if" { pyylval->lex.line = yylineno; return(IF); } +"else" { pyylval->lex.line = yylineno; return(ELSE); } + +"in" { pyylval->lex.line = yylineno; return(IN_QUAL); } +"out" { pyylval->lex.line = yylineno; return(OUT_QUAL); } +"inout" { pyylval->lex.line = yylineno; return(INOUT_QUAL); } + +"float" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(FLOAT_TYPE); } +"int" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(INT_TYPE); } +"void" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(VOID_TYPE); } +"bool" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(BOOL_TYPE); } +"true" { pyylval->lex.line = yylineno; pyylval->lex.b = true; return(BOOLCONSTANT); } +"false" { pyylval->lex.line = yylineno; pyylval->lex.b = false; return(BOOLCONSTANT); } + +"discard" { pyylval->lex.line = yylineno; return(DISCARD); } +"return" { pyylval->lex.line = yylineno; return(RETURN); } + +"mat2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX2); } +"mat3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX3); } +"mat4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX4); } + +"vec2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC2); } +"vec3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC3); } +"vec4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC4); } +"ivec2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC2); } +"ivec3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC3); } +"ivec4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC4); } +"bvec2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC2); } +"bvec3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC3); } +"bvec4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC4); } + +"sampler1D" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER1D; } +"sampler2D" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER2D; } +"sampler3D" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER3D; } +"samplerCube" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLERCUBE; } +"sampler1DShadow" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER1DSHADOW; } +"sampler2DShadow" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER2DSHADOW; } + +"sampler2DRect" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLERRECTARB; /* ARB_texture_rectangle */ } +"sampler2DRectShadow" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLERRECTSHADOWARB; /* ARB_texture_rectangle */ } + +"struct" { pyylval->lex.line = yylineno; return(STRUCT); } + +"asm" { PaReservedWord(); return 0; } + +"class" { PaReservedWord(); return 0; } +"union" { PaReservedWord(); return 0; } +"enum" { PaReservedWord(); return 0; } +"typedef" { PaReservedWord(); return 0; } +"template" { PaReservedWord(); return 0; } +"this" { PaReservedWord(); return 0; } +"packed" { PaReservedWord(); return 0; } + +"goto" { PaReservedWord(); return 0; } +"switch" { PaReservedWord(); return 0; } +"default" { PaReservedWord(); return 0; } + +"inline" { PaReservedWord(); return 0; } +"noinline" { PaReservedWord(); return 0; } +"volatile" { PaReservedWord(); return 0; } +"public" { PaReservedWord(); return 0; } +"static" { PaReservedWord(); return 0; } +"extern" { PaReservedWord(); return 0; } +"external" { PaReservedWord(); return 0; } +"interface" { PaReservedWord(); return 0; } + +"long" { PaReservedWord(); return 0; } +"short" { PaReservedWord(); return 0; } +"double" { PaReservedWord(); return 0; } +"half" { PaReservedWord(); return 0; } +"fixed" { PaReservedWord(); return 0; } +"unsigned" { PaReservedWord(); return 0; } + +"input" { PaReservedWord(); return 0; } +"output" { PaReservedWord(); return 0; } + +"hvec2" { PaReservedWord(); return 0; } +"hvec3" { PaReservedWord(); return 0; } +"hvec4" { PaReservedWord(); return 0; } +"fvec2" { PaReservedWord(); return 0; } +"fvec3" { PaReservedWord(); return 0; } +"fvec4" { PaReservedWord(); return 0; } +"dvec2" { PaReservedWord(); return 0; } +"dvec3" { PaReservedWord(); return 0; } +"dvec4" { PaReservedWord(); return 0; } + +"sampler3DRect" { PaReservedWord(); return 0; } + +"sizeof" { PaReservedWord(); return 0; } +"cast" { PaReservedWord(); return 0; } + +"namespace" { PaReservedWord(); return 0; } +"using" { PaReservedWord(); return 0; } + +{L}({L}|{D})* { + pyylval->lex.line = yylineno; + pyylval->lex.string = NewPoolTString(yytext); + return PaIdentOrType(*pyylval->lex.string, parseContext, pyylval->lex.symbol); +} + +0[xX]{H}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } +0{O}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } +0{D}+ { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;} +{D}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } + +{D}+{E} { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast(atof(yytext)); return(FLOATCONSTANT); } +{D}+"."{D}*({E})? { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast(atof(yytext)); return(FLOATCONSTANT); } +"."{D}+({E})? { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast(atof(yytext)); return(FLOATCONSTANT); } + +"/*" { int ret = PaParseComment(pyylval->lex.line, parseContext); if (!ret) return ret; } + +"+=" { pyylval->lex.line = yylineno; return(ADD_ASSIGN); } +"-=" { pyylval->lex.line = yylineno; return(SUB_ASSIGN); } +"*=" { pyylval->lex.line = yylineno; return(MUL_ASSIGN); } +"/=" { pyylval->lex.line = yylineno; return(DIV_ASSIGN); } +"%=" { pyylval->lex.line = yylineno; return(MOD_ASSIGN); } +"<<=" { pyylval->lex.line = yylineno; return(LEFT_ASSIGN); } +">>=" { pyylval->lex.line = yylineno; return(RIGHT_ASSIGN); } +"&=" { pyylval->lex.line = yylineno; return(AND_ASSIGN); } +"^=" { pyylval->lex.line = yylineno; return(XOR_ASSIGN); } +"|=" { pyylval->lex.line = yylineno; return(OR_ASSIGN); } + +"++" { pyylval->lex.line = yylineno; return(INC_OP); } +"--" { pyylval->lex.line = yylineno; return(DEC_OP); } +"&&" { pyylval->lex.line = yylineno; return(AND_OP); } +"||" { pyylval->lex.line = yylineno; return(OR_OP); } +"^^" { pyylval->lex.line = yylineno; return(XOR_OP); } +"<=" { pyylval->lex.line = yylineno; return(LE_OP); } +">=" { pyylval->lex.line = yylineno; return(GE_OP); } +"==" { pyylval->lex.line = yylineno; return(EQ_OP); } +"!=" { pyylval->lex.line = yylineno; return(NE_OP); } +"<<" { pyylval->lex.line = yylineno; return(LEFT_OP); } +">>" { pyylval->lex.line = yylineno; return(RIGHT_OP); } +";" { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(SEMICOLON); } +("{"|"<%") { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(LEFT_BRACE); } +("}"|"%>") { pyylval->lex.line = yylineno; return(RIGHT_BRACE); } +"," { pyylval->lex.line = yylineno; if (parseContext.inTypeParen) parseContext.lexAfterType = false; return(COMMA); } +":" { pyylval->lex.line = yylineno; return(COLON); } +"=" { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(EQUAL); } +"(" { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; parseContext.inTypeParen = true; return(LEFT_PAREN); } +")" { pyylval->lex.line = yylineno; parseContext.inTypeParen = false; return(RIGHT_PAREN); } +("["|"<:") { pyylval->lex.line = yylineno; return(LEFT_BRACKET); } +("]"|":>") { pyylval->lex.line = yylineno; return(RIGHT_BRACKET); } +"." { BEGIN(FIELDS); return(DOT); } +"!" { pyylval->lex.line = yylineno; return(BANG); } +"-" { pyylval->lex.line = yylineno; return(DASH); } +"~" { pyylval->lex.line = yylineno; return(TILDE); } +"+" { pyylval->lex.line = yylineno; return(PLUS); } +"*" { pyylval->lex.line = yylineno; return(STAR); } +"/" { pyylval->lex.line = yylineno; return(SLASH); } +"%" { pyylval->lex.line = yylineno; return(PERCENT); } +"<" { pyylval->lex.line = yylineno; return(LEFT_ANGLE); } +">" { pyylval->lex.line = yylineno; return(RIGHT_ANGLE); } +"|" { pyylval->lex.line = yylineno; return(VERTICAL_BAR); } +"^" { pyylval->lex.line = yylineno; return(CARET); } +"&" { pyylval->lex.line = yylineno; return(AMPERSAND); } +"?" { pyylval->lex.line = yylineno; return(QUESTION); } + +{L}({L}|{D})* { +BEGIN(INITIAL); + pyylval->lex.line = yylineno; + pyylval->lex.string = NewPoolTString(yytext); + return FIELD_SELECTION; } +[ \t\v\f\r] {} + +[ \t\v\n\f\r] { } +<*><> { (&parseContext)->AfterEOF = true; yy_delete_buffer(YY_CURRENT_BUFFER); yyterminate();} +<*>. { parseContext.infoSink.info << "FLEX: Unknown char " << yytext << "\n"; + return 0; } + +%% + + +//Including Pre-processor. +extern "C" { + #include "./preprocessor/preprocess.h" +} + +// +// The YY_INPUT macro just calls this. Maybe this could be just put into +// the macro directly. +// + +int yy_input(char* buf, int max_size) +{ + char *char_token =NULL; + int len; + + if ((len = yylex_CPP(buf, max_size)) == 0) + return 0; + if (len >= max_size) + YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); + + buf[len] = ' '; + return len+1; +} + + +// +// Parse an array of strings using yyparse. We set up globals used by +// yywrap. +// +// Returns 0 for success, as per yyparse(). +// +int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseContextLocal) +{ + int argv0len; + + ScanFromString(argv[0]); + + //Storing the Current Compiler Parse context into the cpp structure. + cpp->pC = (void*)&parseContextLocal; + + if (!argv || argc == 0) + return 1; + + for (int i = 0; i < argc; ++i) { + if (!argv[i]) { + parseContextLocal.error(0, "Null shader source string", "", ""); + parseContextLocal.recover(); + return 1; + } + } + + if (!strLen) { + argv0len = (int) strlen(argv[0]); + strLen = &argv0len; + } + yyrestart(0); + (&parseContextLocal)->AfterEOF = false; + cpp->PaWhichStr = 0; + cpp->PaArgv = argv; + cpp->PaArgc = argc; + cpp->PaStrLen = strLen; + cpp->notAVersionToken = 0; + yylineno = 1; + + if (*cpp->PaStrLen >= 0) { + int ret; + #ifdef _WIN32 + ret = yyparse(parseContextLocal); + #else + ret = yyparse((void*)(&parseContextLocal)); + #endif + if (cpp->CompileError == 1 || parseContextLocal.recoveredFromError || parseContextLocal.numErrors > 0) + return 1; + else + return 0; + } + else + return 0; +} + +void yyerror(char *s) +{ + if (((TParseContext *)cpp->pC)->AfterEOF) { + if (cpp->tokensBeforeEOF == 1) { + GlobalParseContext->error(yylineno, "syntax error", "pre-mature EOF", s, ""); + GlobalParseContext->recover(); + } + } else { + GlobalParseContext->error(yylineno, "syntax error", yytext, s, ""); + GlobalParseContext->recover(); + } +} + +void PaReservedWord() +{ + GlobalParseContext->error(yylineno, "Reserved word.", yytext, "", ""); + GlobalParseContext->recover(); +} + +int PaIdentOrType(TString& id, TParseContext& parseContextLocal, TSymbol*& symbol) +{ + symbol = parseContextLocal.symbolTable.find(id); + if (parseContextLocal.lexAfterType == false && symbol && symbol->isVariable()) { + TVariable* variable = static_cast(symbol); + if (variable->isUserType()) { + parseContextLocal.lexAfterType = true; + return TYPE_NAME; + } + } + + return IDENTIFIER; +} + +int PaParseComment(int &lineno, TParseContext& parseContextLocal) +{ + int transitionFlag = 0; + int nextChar; + + while (transitionFlag != 2) { + nextChar = yyinput(); + if (nextChar == '\n') + lineno++; + switch (nextChar) { + case '*' : + transitionFlag = 1; + break; + case '/' : /* if star is the previous character, then it is the end of comment */ + if (transitionFlag == 1) { + return 1 ; + } + break; + case EOF : + /* Raise error message here */ + parseContextLocal.error(yylineno, "End of shader found before end of comment.", "", "", ""); + GlobalParseContext->recover(); + return YY_NULL; + default : /* Any other character will be a part of the comment */ + transitionFlag = 0; + } + } + return 1; +} + +extern "C" { + +void CPPDebugLogMsg(const char *msg) +{ + ((TParseContext *)cpp->pC)->infoSink.debug.message(EPrefixNone, msg); +} + +void CPPWarningToInfoLog(const char *msg) +{ + ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg, yylineno); +} + +void CPPShInfoLogMsg(const char *msg) +{ + ((TParseContext *)cpp->pC)->error(yylineno,"", "",msg,""); + GlobalParseContext->recover(); +} + +void CPPErrorToInfoLog(char *msg) +{ + ((TParseContext *)cpp->pC)->error(yylineno,"syntax error", "",msg,""); + GlobalParseContext->recover(); +} + +void SetLineNumber(int line) +{ + yylineno &= ~SourceLocLineMask; + yylineno |= line; +} + +void SetStringNumber(int string) +{ + yylineno = (string << SourceLocStringShift) | (yylineno & SourceLocLineMask); +} + +int GetStringNumber(void) +{ + return yylineno >> 16; +} + +int GetLineNumber(void) +{ + return yylineno & SourceLocLineMask; +} + +void IncLineNumber(void) +{ + if ((yylineno & SourceLocLineMask) <= SourceLocLineMask) + ++yylineno; +} + +void DecLineNumber(void) +{ + if ((yylineno & SourceLocLineMask) > 0) + --yylineno; +} + +void HandlePragma(const char **tokens, int numTokens) +{ + if (!strcmp(tokens[0], "optimize")) { + if (numTokens != 4) { + CPPShInfoLogMsg("optimize pragma syntax is incorrect"); + return; + } + + if (strcmp(tokens[1], "(")) { + CPPShInfoLogMsg("\"(\" expected after 'optimize' keyword"); + return; + } + + if (!strcmp(tokens[2], "on")) + ((TParseContext *)cpp->pC)->contextPragma.optimize = true; + else if (!strcmp(tokens[2], "off")) + ((TParseContext *)cpp->pC)->contextPragma.optimize = false; + else { + CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'optimize' pragma"); + return; + } + + if (strcmp(tokens[3], ")")) { + CPPShInfoLogMsg("\")\" expected to end 'optimize' pragma"); + return; + } + } else if (!strcmp(tokens[0], "debug")) { + if (numTokens != 4) { + CPPShInfoLogMsg("debug pragma syntax is incorrect"); + return; + } + + if (strcmp(tokens[1], "(")) { + CPPShInfoLogMsg("\"(\" expected after 'debug' keyword"); + return; + } + + if (!strcmp(tokens[2], "on")) + ((TParseContext *)cpp->pC)->contextPragma.debug = true; + else if (!strcmp(tokens[2], "off")) + ((TParseContext *)cpp->pC)->contextPragma.debug = false; + else { + CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'debug' pragma"); + return; + } + + if (strcmp(tokens[3], ")")) { + CPPShInfoLogMsg("\")\" expected to end 'debug' pragma"); + return; + } + } else { + +#ifdef PRAGMA_TABLE + // + // implementation specific pragma + // use ((TParseContext *)cpp->pC)->contextPragma.pragmaTable to store the information about pragma + // For now, just ignore the pragma that the implementation cannot recognize + // An Example of one such implementation for a pragma that has a syntax like + // #pragma pragmaname(pragmavalue) + // This implementation stores the current pragmavalue against the pragma name in pragmaTable. + // + if (numTokens == 4 && !strcmp(tokens[1], "(") && !strcmp(tokens[3], ")")) { + TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable; + TPragmaTable::iterator iter; + iter = pragmaTable.find(TString(tokens[0])); + if (iter != pragmaTable.end()) { + iter->second = tokens[2]; + } else { + pragmaTable[tokens[0]] = tokens[2]; + } + } else if (numTokens >= 2) { + TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable; + TPragmaTable::iterator iter; + iter = pragmaTable.find(TString(tokens[0])); + if (iter != pragmaTable.end()) { + iter->second = tokens[1]; + } else { + pragmaTable[tokens[0]] = tokens[1]; + } + } +#endif // PRAGMA_TABLE + } +} + +void StoreStr(char *string) +{ + TString strSrc; + strSrc = TString(string); + + ((TParseContext *)cpp->pC)->HashErrMsg = ((TParseContext *)cpp->pC)->HashErrMsg + " " + strSrc; +} + +const char* GetStrfromTStr(void) +{ + cpp->ErrMsg = (((TParseContext *)cpp->pC)->HashErrMsg).c_str(); + return cpp->ErrMsg; +} + +void ResetTString(void) +{ + ((TParseContext *)cpp->pC)->HashErrMsg = ""; +} + +TBehavior GetBehavior(const char* behavior) +{ + if (!strcmp("require", behavior)) + return EBhRequire; + else if (!strcmp("enable", behavior)) + return EBhEnable; + else if (!strcmp("disable", behavior)) + return EBhDisable; + else if (!strcmp("warn", behavior)) + return EBhWarn; + else { + CPPShInfoLogMsg((TString("behavior '") + behavior + "' is not supported").c_str()); + return EBhDisable; + } +} + +void updateExtensionBehavior(const char* extName, const char* behavior) +{ + TBehavior behaviorVal = GetBehavior(behavior); + TMap:: iterator iter; + TString msg; + + // special cased for all extension + if (!strcmp(extName, "all")) { + if (behaviorVal == EBhRequire || behaviorVal == EBhEnable) { + CPPShInfoLogMsg("extension 'all' cannot have 'require' or 'enable' behavior"); + return; + } else { + for (iter = ((TParseContext *)cpp->pC)->extensionBehavior.begin(); iter != ((TParseContext *)cpp->pC)->extensionBehavior.end(); ++iter) + iter->second = behaviorVal; + } + } else { + iter = ((TParseContext *)cpp->pC)->extensionBehavior.find(TString(extName)); + if (iter == ((TParseContext *)cpp->pC)->extensionBehavior.end()) { + switch (behaviorVal) { + case EBhRequire: + CPPShInfoLogMsg((TString("extension '") + extName + "' is not supported").c_str()); + break; + case EBhEnable: + case EBhWarn: + case EBhDisable: + msg = TString("extension '") + extName + "' is not supported"; + ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno); + break; + } + return; + } else + iter->second = behaviorVal; + } +} + +} // extern "C" + +void setInitialState() +{ + yy_start = 1; +} diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y new file mode 100644 index 0000000..c3fe427 --- /dev/null +++ b/glslang/MachineIndependent/glslang.y @@ -0,0 +1,2317 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +/** + * This is bison grammar and production code for parsing the OpenGL 2.0 shading + * languages. + */ +%{ + +/* Based on: +ANSI C Yacc grammar + +In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a +matching Lex specification) for the April 30, 1985 draft version of the +ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that +original, as mentioned in the answer to question 17.25 of the comp.lang.c +FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z. + +I intend to keep this version as close to the current C Standard grammar as +possible; please let me know if you discover discrepancies. + +Jutta Degener, 1995 +*/ + +#include "SymbolTable.h" +#include "ParseHelper.h" +#include "../Public/ShaderLang.h" + +#ifdef _WIN32 + #define YYPARSE_PARAM parseContext + #define YYPARSE_PARAM_DECL TParseContext& + #define YY_DECL int yylex(YYSTYPE* pyylval, TParseContext& parseContext) + #define YYLEX_PARAM parseContext +#else + #define YYPARSE_PARAM parseContextLocal + #define parseContext (*((TParseContext*)(parseContextLocal))) + #define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal) + #define YYLEX_PARAM (void*)(parseContextLocal) + extern void yyerror(char*); +#endif + +#define FRAG_VERT_ONLY(S, L) { \ + if (parseContext.language != EShLangFragment && \ + parseContext.language != EShLangVertex) { \ + parseContext.error(L, " supported in vertex/fragment shaders only ", S, "", ""); \ + parseContext.recover(); \ + } \ +} + +#define VERTEX_ONLY(S, L) { \ + if (parseContext.language != EShLangVertex) { \ + parseContext.error(L, " supported in vertex shaders only ", S, "", ""); \ + parseContext.recover(); \ + } \ +} + +#define FRAG_ONLY(S, L) { \ + if (parseContext.language != EShLangFragment) { \ + parseContext.error(L, " supported in fragment shaders only ", S, "", ""); \ + parseContext.recover(); \ + } \ +} + +#define PACK_ONLY(S, L) { \ + if (parseContext.language != EShLangPack) { \ + parseContext.error(L, " supported in pack shaders only ", S, "", ""); \ + parseContext.recover(); \ + } \ +} + +#define UNPACK_ONLY(S, L) { \ + if (parseContext.language != EShLangUnpack) { \ + parseContext.error(L, " supported in unpack shaders only ", S, "", ""); \ + parseContext.recover(); \ + } \ +} + +#define PACK_UNPACK_ONLY(S, L) { \ + if (parseContext.language != EShLangUnpack && \ + parseContext.language != EShLangPack) { \ + parseContext.error(L, " supported in pack/unpack shaders only ", S, "", ""); \ + parseContext.recover(); \ + } \ +} +%} +%union { + struct { + TSourceLoc line; + union { + TString *string; + float f; + int i; + bool b; + }; + TSymbol* symbol; + } lex; + struct { + TSourceLoc line; + TOperator op; + union { + TIntermNode* intermNode; + TIntermNodePair nodePair; + TIntermTyped* intermTypedNode; + TIntermAggregate* intermAggregate; + }; + union { + TPublicType type; + TQualifier qualifier; + TFunction* function; + TParameter param; + TTypeLine typeLine; + TTypeList* typeList; + }; + } interm; +} + +%{ +#ifndef _WIN32 + extern int yylex(YYSTYPE*, void*); +#endif +%} + +%pure_parser /* Just in case is called from multiple threads */ +%expect 1 /* One shift reduce conflict because of if | else */ +%token ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE +%token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN +%token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 +%token MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING +%token STRUCT VOID_TYPE WHILE +%token SAMPLER1D SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER1DSHADOW SAMPLER2DSHADOW + +%token SAMPLERRECTARB SAMPLERRECTSHADOWARB // ARB_texture_rectangle + +%token IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT +%token FIELD_SELECTION +%token LEFT_OP RIGHT_OP +%token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP +%token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN +%token MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN +%token SUB_ASSIGN + +%token LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT +%token COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT +%token LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION + +%type assignment_operator unary_operator +%type variable_identifier primary_expression postfix_expression +%type expression integer_expression assignment_expression +%type unary_expression multiplicative_expression additive_expression +%type relational_expression equality_expression +%type conditional_expression constant_expression +%type logical_or_expression logical_xor_expression logical_and_expression +%type shift_expression and_expression exclusive_or_expression inclusive_or_expression +%type function_call initializer condition conditionopt + +%type translation_unit function_definition +%type statement simple_statement +%type statement_list compound_statement +%type declaration_statement selection_statement expression_statement +%type declaration external_declaration +%type for_init_statement compound_statement_no_new_scope +%type selection_rest_statement for_rest_statement +%type iteration_statement jump_statement statement_no_new_scope +%type single_declaration init_declarator_list + +%type parameter_declaration parameter_declarator parameter_type_specifier +%type parameter_qualifier + +%type type_qualifier fully_specified_type type_specifier +%type type_specifier_nonarray +%type struct_specifier +%type struct_declarator +%type struct_declarator_list struct_declaration struct_declaration_list +%type function_header function_declarator function_identifier +%type function_header_with_parameters function_call_header +%type function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype +%type function_call_or_method + +%start translation_unit +%% + +variable_identifier + : IDENTIFIER { + // The symbol table search was done in the lexical phase + const TSymbol* symbol = $1.symbol; + const TVariable* variable; + if (symbol == 0) { + parseContext.error($1.line, "undeclared identifier", $1.string->c_str(), ""); + parseContext.recover(); + TType type(EbtFloat); + TVariable* fakeVariable = new TVariable($1.string, type); + parseContext.symbolTable.insert(*fakeVariable); + variable = fakeVariable; + } else { + // This identifier can only be a variable type symbol + if (! symbol->isVariable()) { + parseContext.error($1.line, "variable expected", $1.string->c_str(), ""); + parseContext.recover(); + } + variable = static_cast(symbol); + } + + // don't delete $1.string, it's used by error recovery, and the pool + // pop will reclaim the memory + + if (variable->getType().getQualifier() == EvqConst ) { + constUnion* constArray = variable->getConstPointer(); + TType t(variable->getType()); + $$ = parseContext.intermediate.addConstantUnion(constArray, t, $1.line); + } else + $$ = parseContext.intermediate.addSymbol(variable->getUniqueId(), + variable->getName(), + variable->getType(), $1.line); + } + ; + +primary_expression + : variable_identifier { + $$ = $1; + } + | INTCONSTANT { + // + // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders, + // check for overflow for constants + // + if (abs($1.i) >= (1 << 16)) { + parseContext.error($1.line, " integer constant overflow", "", ""); + parseContext.recover(); + } + constUnion *unionArray = new constUnion[1]; + unionArray->setIConst($1.i); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.line); + } + | FLOATCONSTANT { + constUnion *unionArray = new constUnion[1]; + unionArray->setFConst($1.f); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line); + } + | BOOLCONSTANT { + constUnion *unionArray = new constUnion[1]; + unionArray->setBConst($1.b); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $1.line); + } + | LEFT_PAREN expression RIGHT_PAREN { + $$ = $2; + } + ; + +postfix_expression + : primary_expression { + $$ = $1; + } + | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { + if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) { + if ($1->getAsSymbolNode()) + parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), ""); + else + parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", ""); + parseContext.recover(); + } + if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) { + if ($1->isArray()) { // constant folding for arrays + $$ = parseContext.addConstArrayNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line); + } else if ($1->isVector()) { // constant folding for vectors + TVectorFields fields; + fields.num = 1; + fields.offsets[0] = $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); // need to do it this way because v.xy sends fields integer array + $$ = parseContext.addConstVectorNode(fields, $1, $2.line); + } else if ($1->isMatrix()) { // constant folding for matrices + $$ = parseContext.addConstMatrixNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line); + } + } else { + if ($3->getQualifier() == EvqConst) { + if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() && !$1->isArray() ) { + parseContext.error($2.line, "", "[", "field selection out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()); + parseContext.recover(); + } else { + if ($1->isArray()) { + if ($1->getType().getArraySize() == 0) { + if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) { + if (parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line)) + parseContext.recover(); + } else { + if (parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line)) + parseContext.recover(); + } + } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize()) { + parseContext.error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()); + parseContext.recover(); + } + } + $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line); + } + } else { + if ($1->isArray() && $1->getType().getArraySize() == 0) { + parseContext.error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable"); + parseContext.recover(); + } + + $$ = parseContext.intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line); + } + } + if ($$ == 0) { + constUnion *unionArray = new constUnion[1]; + unionArray->setFConst(0.0f); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $2.line); + } else if ($1->isArray()) { + if ($1->getType().getStruct()) + $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName())); + else + $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize(), $1->isMatrix())); + + if ($1->getType().getQualifier() == EvqConst) + $$->getTypePointer()->changeQualifier(EvqConst); + } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst) + $$->setType(TType($1->getBasicType(), EvqConst, $1->getNominalSize())); + else if ($1->isMatrix()) + $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize())); + else if ($1->isVector() && $1->getType().getQualifier() == EvqConst) + $$->setType(TType($1->getBasicType(), EvqConst)); + else if ($1->isVector()) + $$->setType(TType($1->getBasicType(), EvqTemporary)); + else + $$->setType($1->getType()); + } + | function_call { + $$ = $1; + } + | postfix_expression DOT FIELD_SELECTION { + if ($1->isArray()) { + parseContext.error($3.line, "cannot apply dot operator to an array", ".", ""); + parseContext.recover(); + } + + if ($1->isVector()) { + TVectorFields fields; + if (! parseContext.parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { + fields.num = 1; + fields.offsets[0] = 0; + parseContext.recover(); + } + + if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields + $$ = parseContext.addConstVectorNode(fields, $1, $3.line); + if ($$ == 0) { + parseContext.recover(); + $$ = $1; + } + else + $$->setType(TType($1->getBasicType(), EvqConst, (int) (*$3.string).size())); + } else { + if (fields.num == 1) { + constUnion *unionArray = new constUnion[1]; + unionArray->setIConst(fields.offsets[0]); + TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line); + $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + $$->setType(TType($1->getBasicType())); + } else { + TString vectorString = *$3.string; + TIntermTyped* index = parseContext.intermediate.addSwizzle(fields, $3.line); + $$ = parseContext.intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line); + $$->setType(TType($1->getBasicType(),EvqTemporary, (int) vectorString.size())); + } + } + } else if ($1->isMatrix()) { + TMatrixFields fields; + if (! parseContext.parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { + fields.wholeRow = false; + fields.wholeCol = false; + fields.row = 0; + fields.col = 0; + parseContext.recover(); + } + + if (fields.wholeRow || fields.wholeCol) { + parseContext.error($2.line, " non-scalar fields not implemented yet", ".", ""); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->setIConst(0); + TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line); + $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize())); + } else { + constUnion *unionArray = new constUnion[1]; + unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row); + TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line); + $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + $$->setType(TType($1->getBasicType())); + } + } else if ($1->getBasicType() == EbtStruct) { + bool fieldFound = false; + TTypeList* fields = $1->getType().getStruct(); + if (fields == 0) { + parseContext.error($2.line, "structure has no fields", "Internal Error", ""); + parseContext.recover(); + $$ = $1; + } else { + unsigned int i; + for (i = 0; i < fields->size(); ++i) { + if ((*fields)[i].type->getFieldName() == *$3.string) { + fieldFound = true; + break; + } + } + if (fieldFound) { + if ($1->getType().getQualifier() == EvqConst) { + $$ = parseContext.addConstStruct(*$3.string, $1, $2.line); + if ($$ == 0) { + parseContext.recover(); + $$ = $1; + } + else { + $$->setType(*(*fields)[i].type); + // change the qualifier of the return type, not of the structure field + // as the structure definition is shared between various structures. + $$->getTypePointer()->changeQualifier(EvqConst); + } + } else { + constUnion *unionArray = new constUnion[1]; + unionArray->setIConst(i); + TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line); + $$ = parseContext.intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line); + $$->setType(*(*fields)[i].type); + } + } else { + parseContext.error($2.line, " no such field in structure", $3.string->c_str(), ""); + parseContext.recover(); + $$ = $1; + } + } + } else { + parseContext.error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str(), ""); + parseContext.recover(); + $$ = $1; + } + // don't delete $3.string, it's from the pool + } + | postfix_expression INC_OP { + if (parseContext.lValueErrorCheck($2.line, "++", $1)) + parseContext.recover(); + $$ = parseContext.intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.unaryOpError($2.line, "++", $1->getCompleteString()); + parseContext.recover(); + $$ = $1; + } + } + | postfix_expression DEC_OP { + if (parseContext.lValueErrorCheck($2.line, "--", $1)) + parseContext.recover(); + $$ = parseContext.intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.unaryOpError($2.line, "--", $1->getCompleteString()); + parseContext.recover(); + $$ = $1; + } + } + ; + +integer_expression + : expression { + if (parseContext.integerErrorCheck($1, "[]")) + parseContext.recover(); + $$ = $1; + } + ; + +function_call + : function_call_or_method { + TFunction* fnCall = $1.function; + TOperator op = fnCall->getBuiltInOp(); + + if (op == EOpArrayLength) { + if ($1.intermNode->getAsTyped() == 0 || $1.intermNode->getAsTyped()->getType().getArraySize() == 0) { + parseContext.error($1.line, "", fnCall->getName().c_str(), "array must be declared with a size before using this method"); + parseContext.recover(); + } + + constUnion *unionArray = new constUnion[1]; + unionArray->setIConst($1.intermNode->getAsTyped()->getType().getArraySize()); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.line); + } else if (op != EOpNull) { + // + // Then this should be a constructor. + // Don't go through the symbol table for constructors. + // Their parameters will be verified algorithmically. + // + TType type(EbtVoid); // use this to get the type back + if (parseContext.constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) { + $$ = 0; + } else { + // + // It's a constructor, of type 'type'. + // + $$ = parseContext.addConstructor($1.intermNode, &type, op, fnCall, $1.line); + } + + if ($$ == 0) { + parseContext.recover(); + $$ = parseContext.intermediate.setAggregateOperator(0, op, $1.line); + } + $$->setType(type); + } else { + // + // Not a constructor. Find it in the symbol table. + // + const TFunction* fnCandidate; + bool builtIn; + fnCandidate = parseContext.findFunction($1.line, fnCall, &builtIn); + if (fnCandidate) { + // + // A declared function. But, it might still map to a built-in + // operation. + // + op = fnCandidate->getBuiltInOp(); + if (builtIn && op != EOpNull) { + // + // A function call mapped to a built-in operation. + // + if (fnCandidate->getParamCount() == 1) { + // + // Treat it like a built-in unary operator. + // + $$ = parseContext.intermediate.addUnaryMath(op, $1.intermNode, 0, parseContext.symbolTable); + if ($$ == 0) { + parseContext.error($1.intermNode->getLine(), " wrong operand type", "Internal Error", + "built in unary operator function. Type: %s", + static_cast($1.intermNode)->getCompleteString().c_str()); + YYERROR; + } + } else { + $$ = parseContext.intermediate.setAggregateOperator($1.intermAggregate, op, $1.line); + } + } else { + // This is a real function call + + $$ = parseContext.intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line); + $$->setType(fnCandidate->getReturnType()); + + // this is how we know whether the given function is a builtIn function or a user defined function + // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also + // if builtIn == true, it's definitely a builtIn function with EOpNull + if (!builtIn) + $$->getAsAggregate()->setUserDefined(); + $$->getAsAggregate()->setName(fnCandidate->getMangledName()); + + TQualifier qual; + TQualifierList& qualifierList = $$->getAsAggregate()->getQualifier(); + for (int i = 0; i < fnCandidate->getParamCount(); ++i) { + qual = (*fnCandidate)[i].type->getQualifier(); + if (qual == EvqOut || qual == EvqInOut) { + if (parseContext.lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) { + parseContext.error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", ""); + parseContext.recover(); + } + } + qualifierList.push_back(qual); + } + } + $$->setType(fnCandidate->getReturnType()); + } else { + // error message was put out by PaFindFunction() + // Put on a dummy node for error recovery + constUnion *unionArray = new constUnion[1]; + unionArray->setFConst(0.0f); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line); + parseContext.recover(); + } + } + delete fnCall; + } + ; + +function_call_or_method + : function_call_generic { + $$ = $1; + } + | postfix_expression DOT function_call_generic { + if ($1->isArray() && $3.function->getName() == "length") { + // + // implement array.length() + // + if (parseContext.extensionErrorCheck($3.line, "GL_3DL_array_objects")) { + parseContext.recover(); + $$ = $3; + } else { + $$ = $3; + $$.intermNode = $1; + $$.function->relateToOperator(EOpArrayLength); + } + } else { + parseContext.error($3.line, "methods are not supported", "", ""); + parseContext.recover(); + $$ = $3; + } + } + ; + +function_call_generic + : function_call_header_with_parameters RIGHT_PAREN { + $$ = $1; + $$.line = $2.line; + } + | function_call_header_no_parameters RIGHT_PAREN { + $$ = $1; + $$.line = $2.line; + } + ; + +function_call_header_no_parameters + : function_call_header VOID_TYPE { + $$.function = $1; + $$.intermNode = 0; + } + | function_call_header { + $$.function = $1; + $$.intermNode = 0; + } + ; + +function_call_header_with_parameters + : function_call_header assignment_expression { + TParameter param = { 0, new TType($2->getType()) }; + $1->addParameter(param); + $$.function = $1; + $$.intermNode = $2; + } + | function_call_header_with_parameters COMMA assignment_expression { + TParameter param = { 0, new TType($3->getType()) }; + $1.function->addParameter(param); + $$.function = $1.function; + $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, $3, $2.line); + } + ; + +function_call_header + : function_identifier LEFT_PAREN { + $$ = $1; + } + ; + +// Grammar Note: Constructors look like functions, but are recognized as types. + +function_identifier + : type_specifier { + // + // Constructor + // + if ($1.array) { + if (parseContext.extensionErrorCheck($1.line, "GL_3DL_array_objects")) { + parseContext.recover(); + $1.setArray(false); + } + } + + if ($1.userDef) { + TString tempString = ""; + TType type($1); + TFunction *function = new TFunction(&tempString, type, EOpConstructStruct); + $$ = function; + } else { + TOperator op = EOpNull; + switch ($1.type) { + case EbtFloat: + if ($1.matrix) { + switch($1.size) { + case 2: op = EOpConstructMat2; break; + case 3: op = EOpConstructMat3; break; + case 4: op = EOpConstructMat4; break; + } + } else { + switch($1.size) { + case 1: op = EOpConstructFloat; break; + case 2: op = EOpConstructVec2; break; + case 3: op = EOpConstructVec3; break; + case 4: op = EOpConstructVec4; break; + } + } + break; + case EbtInt: + switch($1.size) { + case 1: op = EOpConstructInt; break; + case 2: FRAG_VERT_ONLY("ivec2", $1.line); op = EOpConstructIVec2; break; + case 3: FRAG_VERT_ONLY("ivec3", $1.line); op = EOpConstructIVec3; break; + case 4: FRAG_VERT_ONLY("ivec4", $1.line); op = EOpConstructIVec4; break; + } + break; + case EbtBool: + switch($1.size) { + case 1: op = EOpConstructBool; break; + case 2: FRAG_VERT_ONLY("bvec2", $1.line); op = EOpConstructBVec2; break; + case 3: FRAG_VERT_ONLY("bvec3", $1.line); op = EOpConstructBVec3; break; + case 4: FRAG_VERT_ONLY("bvec4", $1.line); op = EOpConstructBVec4; break; + } + break; + } + if (op == EOpNull) { + parseContext.error($1.line, "cannot construct this type", TType::getBasicString($1.type), ""); + parseContext.recover(); + $1.type = EbtFloat; + op = EOpConstructFloat; + } + TString tempString = ""; + TType type($1); + TFunction *function = new TFunction(&tempString, type, op); + $$ = function; + } + } + | IDENTIFIER { + if (parseContext.reservedErrorCheck($1.line, *$1.string)) + parseContext.recover(); + TType type(EbtVoid); + TFunction *function = new TFunction($1.string, type); + $$ = function; + } + | FIELD_SELECTION { + if (parseContext.reservedErrorCheck($1.line, *$1.string)) + parseContext.recover(); + TType type(EbtVoid); + TFunction *function = new TFunction($1.string, type); + $$ = function; + } + ; + +unary_expression + : postfix_expression { + $$ = $1; + } + | INC_OP unary_expression { + if (parseContext.lValueErrorCheck($1.line, "++", $2)) + parseContext.recover(); + $$ = parseContext.intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.unaryOpError($1.line, "++", $2->getCompleteString()); + parseContext.recover(); + $$ = $2; + } + } + | DEC_OP unary_expression { + if (parseContext.lValueErrorCheck($1.line, "--", $2)) + parseContext.recover(); + $$ = parseContext.intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.unaryOpError($1.line, "--", $2->getCompleteString()); + parseContext.recover(); + $$ = $2; + } + } + | unary_operator unary_expression { + if ($1.op != EOpNull) { + $$ = parseContext.intermediate.addUnaryMath($1.op, $2, $1.line, parseContext.symbolTable); + if ($$ == 0) { + char* errorOp = ""; + switch($1.op) { + case EOpNegative: errorOp = "-"; break; + case EOpLogicalNot: errorOp = "!"; break; + case EOpBitwiseNot: errorOp = "~"; break; + default: break; + } + parseContext.unaryOpError($1.line, errorOp, $2->getCompleteString()); + parseContext.recover(); + $$ = $2; + } + } else + $$ = $2; + } + ; +// Grammar Note: No traditional style type casts. + +unary_operator + : PLUS { $$.line = $1.line; $$.op = EOpNull; } + | DASH { $$.line = $1.line; $$.op = EOpNegative; } + | BANG { $$.line = $1.line; $$.op = EOpLogicalNot; } + | TILDE { PACK_UNPACK_ONLY("~", $1.line); + $$.line = $1.line; $$.op = EOpBitwiseNot; } + ; +// Grammar Note: No '*' or '&' unary ops. Pointers are not supported. + +multiplicative_expression + : unary_expression { $$ = $1; } + | multiplicative_expression STAR unary_expression { + FRAG_VERT_ONLY("*", $2.line); + $$ = parseContext.intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + $$ = $1; + } + } + | multiplicative_expression SLASH unary_expression { + FRAG_VERT_ONLY("/", $2.line); + $$ = parseContext.intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + $$ = $1; + } + } + | multiplicative_expression PERCENT unary_expression { + PACK_UNPACK_ONLY("%", $2.line); + $$ = parseContext.intermediate.addBinaryMath(EOpMod, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "%", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + $$ = $1; + } + } + ; + +additive_expression + : multiplicative_expression { $$ = $1; } + | additive_expression PLUS multiplicative_expression { + $$ = parseContext.intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + $$ = $1; + } + } + | additive_expression DASH multiplicative_expression { + $$ = parseContext.intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + $$ = $1; + } + } + ; + +shift_expression + : additive_expression { $$ = $1; } + | shift_expression LEFT_OP additive_expression { + PACK_UNPACK_ONLY("<<", $2.line); + $$ = parseContext.intermediate.addBinaryMath(EOpLeftShift, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "<<", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + $$ = $1; + } + } + | shift_expression RIGHT_OP additive_expression { + PACK_UNPACK_ONLY(">>", $2.line); + $$ = parseContext.intermediate.addBinaryMath(EOpRightShift, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, ">>", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + $$ = $1; + } + } + ; + +relational_expression + : shift_expression { $$ = $1; } + | relational_expression LEFT_ANGLE shift_expression { + $$ = parseContext.intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->setBConst(false); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); + } + } + | relational_expression RIGHT_ANGLE shift_expression { + $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->setBConst(false); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); + } + } + | relational_expression LE_OP shift_expression { + $$ = parseContext.intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->setBConst(false); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); + } + } + | relational_expression GE_OP shift_expression { + $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->setBConst(false); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); + } + } + ; + +equality_expression + : relational_expression { $$ = $1; } + | equality_expression EQ_OP relational_expression { + $$ = parseContext.intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->setBConst(false); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); + } else if (($1->isArray() || $3->isArray()) && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects")) + parseContext.recover(); + } + | equality_expression NE_OP relational_expression { + $$ = parseContext.intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->setBConst(false); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); + } else if (($1->isArray() || $3->isArray()) && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects")) + parseContext.recover(); + } + ; + +and_expression + : equality_expression { $$ = $1; } + | and_expression AMPERSAND equality_expression { + PACK_UNPACK_ONLY("&", $2.line); + $$ = parseContext.intermediate.addBinaryMath(EOpAnd, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "&", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + $$ = $1; + } + } + ; + +exclusive_or_expression + : and_expression { $$ = $1; } + | exclusive_or_expression CARET and_expression { + PACK_UNPACK_ONLY("^", $2.line); + $$ = parseContext.intermediate.addBinaryMath(EOpExclusiveOr, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "^", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + $$ = $1; + } + } + ; + +inclusive_or_expression + : exclusive_or_expression { $$ = $1; } + | inclusive_or_expression VERTICAL_BAR exclusive_or_expression { + PACK_UNPACK_ONLY("|", $2.line); + $$ = parseContext.intermediate.addBinaryMath(EOpInclusiveOr, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "|", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + $$ = $1; + } + } + ; + +logical_and_expression + : inclusive_or_expression { $$ = $1; } + | logical_and_expression AND_OP inclusive_or_expression { + $$ = parseContext.intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->setBConst(false); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); + } + } + ; + +logical_xor_expression + : logical_and_expression { $$ = $1; } + | logical_xor_expression XOR_OP logical_and_expression { + $$ = parseContext.intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->setBConst(false); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); + } + } + ; + +logical_or_expression + : logical_xor_expression { $$ = $1; } + | logical_or_expression OR_OP logical_xor_expression { + $$ = parseContext.intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, parseContext.symbolTable); + if ($$ == 0) { + parseContext.binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->setBConst(false); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); + } + } + ; + +conditional_expression + : logical_or_expression { $$ = $1; } + | logical_or_expression QUESTION expression COLON assignment_expression { + if (parseContext.boolErrorCheck($2.line, $1)) + parseContext.recover(); + + $$ = parseContext.intermediate.addSelection($1, $3, $5, $2.line); + if ($3->getType() != $5->getType()) + $$ = 0; + + if ($$ == 0) { + parseContext.binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString()); + parseContext.recover(); + $$ = $5; + } + } + ; + +assignment_expression + : conditional_expression { $$ = $1; } + | unary_expression assignment_operator assignment_expression { + if (parseContext.lValueErrorCheck($2.line, "assign", $1)) + parseContext.recover(); + $$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.line); + if ($$ == 0) { + parseContext.assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + $$ = $1; + } else if (($1->isArray() || $3->isArray()) && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects")) + parseContext.recover(); + } + ; + +assignment_operator + : EQUAL { $$.line = $1.line; $$.op = EOpAssign; } + | MUL_ASSIGN { FRAG_VERT_ONLY("*=", $1.line); $$.line = $1.line; $$.op = EOpMulAssign; } + | DIV_ASSIGN { FRAG_VERT_ONLY("/=", $1.line); $$.line = $1.line; $$.op = EOpDivAssign; } + | MOD_ASSIGN { PACK_UNPACK_ONLY("%=", $1.line); $$.line = $1.line; $$.op = EOpModAssign; } + | ADD_ASSIGN { $$.line = $1.line; $$.op = EOpAddAssign; } + | SUB_ASSIGN { $$.line = $1.line; $$.op = EOpSubAssign; } + | LEFT_ASSIGN { PACK_UNPACK_ONLY("<<=", $1.line); $$.line = $1.line; $$.op = EOpLeftShiftAssign; } + | RIGHT_ASSIGN { PACK_UNPACK_ONLY("<<=", $1.line); $$.line = $1.line; $$.op = EOpRightShiftAssign; } + | AND_ASSIGN { PACK_UNPACK_ONLY("&=", $1.line); $$.line = $1.line; $$.op = EOpAndAssign; } + | XOR_ASSIGN { PACK_UNPACK_ONLY("^=", $1.line); $$.line = $1.line; $$.op = EOpExclusiveOrAssign; } + | OR_ASSIGN { PACK_UNPACK_ONLY("|=", $1.line); $$.line = $1.line; $$.op = EOpInclusiveOrAssign; } + ; + +expression + : assignment_expression { + $$ = $1; + } + | expression COMMA assignment_expression { + $$ = parseContext.intermediate.addComma($1, $3, $2.line); + if ($$ == 0) { + parseContext.binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString()); + parseContext.recover(); + $$ = $3; + } + } + ; + +constant_expression + : conditional_expression { + if (parseContext.constErrorCheck($1)) + parseContext.recover(); + $$ = $1; + } + ; + +declaration + : function_prototype SEMICOLON { $$ = 0; } + | init_declarator_list SEMICOLON { + if ($1.intermAggregate) + $1.intermAggregate->setOperator(EOpSequence); + $$ = $1.intermAggregate; + } + ; + +function_prototype + : function_declarator RIGHT_PAREN { + // + // Multiple declarations of the same function are allowed. + // + // If this is a definition, the definition production code will check for redefinitions + // (we don't know at this point if it's a definition or not). + // + // Redeclarations are allowed. But, return types and parameter qualifiers must match. + // + TFunction* prevDec = static_cast(parseContext.symbolTable.find($1->getMangledName())); + if (prevDec) { + if (prevDec->getReturnType() != $1->getReturnType()) { + parseContext.error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString(), ""); + parseContext.recover(); + } + for (int i = 0; i < prevDec->getParamCount(); ++i) { + if ((*prevDec)[i].type->getQualifier() != (*$1)[i].type->getQualifier()) { + parseContext.error($2.line, "overloaded functions must have the same parameter qualifiers", (*$1)[i].type->getQualifierString(), ""); + parseContext.recover(); + } + } + } + + // + // If this is a redeclaration, it could also be a definition, + // in which case, we want to use the variable names from this one, and not the one that's + // being redeclared. So, pass back up this declaration, not the one in the symbol table. + // + $$.function = $1; + $$.line = $2.line; + + parseContext.symbolTable.insert(*$$.function); + } + ; + +function_declarator + : function_header { + $$ = $1; + } + | function_header_with_parameters { + $$ = $1; + } + ; + + +function_header_with_parameters + : function_header parameter_declaration { + // Add the parameter + $$ = $1; + if ($2.param.type->getBasicType() != EbtVoid) + $1->addParameter($2.param); + else + delete $2.param.type; + } + | function_header_with_parameters COMMA parameter_declaration { + // + // Only first parameter of one-parameter functions can be void + // The check for named parameters not being void is done in parameter_declarator + // + if ($3.param.type->getBasicType() == EbtVoid) { + // + // This parameter > first is void + // + parseContext.error($2.line, "cannot be an argument type except for '(void)'", "void", ""); + parseContext.recover(); + delete $3.param.type; + } else { + // Add the parameter + $$ = $1; + $1->addParameter($3.param); + } + } + ; + +function_header + : fully_specified_type IDENTIFIER LEFT_PAREN { + if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) { + parseContext.error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier), ""); + parseContext.recover(); + } + // make sure a sampler is not involved as well... + if (parseContext.structQualifierErrorCheck($2.line, $1)) + parseContext.recover(); + + // Add the function as a prototype after parsing it (we do not support recursion) + TFunction *function; + TType type($1); + function = new TFunction($2.string, type); + $$ = function; + } + ; + +parameter_declarator + // Type + name + : type_specifier IDENTIFIER { + if ($1.type == EbtVoid) { + parseContext.error($2.line, "illegal use of type 'void'", $2.string->c_str(), ""); + parseContext.recover(); + } + if (parseContext.reservedErrorCheck($2.line, *$2.string)) + parseContext.recover(); + TParameter param = {$2.string, new TType($1)}; + $$.line = $2.line; + $$.param = param; + } + | type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + // Check that we can make an array out of this type + if (parseContext.arrayTypeErrorCheck($3.line, $1)) + parseContext.recover(); + + if (parseContext.reservedErrorCheck($2.line, *$2.string)) + parseContext.recover(); + + int size; + if (parseContext.arraySizeErrorCheck($3.line, $4, size)) + parseContext.recover(); + $1.setArray(true, size); + + TType* type = new TType($1); + TParameter param = { $2.string, type }; + $$.line = $2.line; + $$.param = param; + } + ; + +parameter_declaration + // + // The only parameter qualifier a parameter can have are + // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST. + // + + // + // Type + name + // + : type_qualifier parameter_qualifier parameter_declarator { + $$ = $3; + if (parseContext.paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) + parseContext.recover(); + } + | parameter_qualifier parameter_declarator { + $$ = $2; + if (parseContext.parameterSamplerErrorCheck($2.line, $1, *$2.param.type)) + parseContext.recover(); + if (parseContext.paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type)) + parseContext.recover(); + } + // + // Only type + // + | type_qualifier parameter_qualifier parameter_type_specifier { + $$ = $3; + if (parseContext.paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) + parseContext.recover(); + } + | parameter_qualifier parameter_type_specifier { + $$ = $2; + if (parseContext.parameterSamplerErrorCheck($2.line, $1, *$2.param.type)) + parseContext.recover(); + if (parseContext.paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type)) + parseContext.recover(); + } + ; + +parameter_qualifier + : /* empty */ { + $$ = EvqIn; + } + | IN_QUAL { + $$ = EvqIn; + } + | OUT_QUAL { + $$ = EvqOut; + } + | INOUT_QUAL { + $$ = EvqInOut; + } + ; + +parameter_type_specifier + : type_specifier { + TParameter param = { 0, new TType($1) }; + $$.param = param; + } + ; + +init_declarator_list + : single_declaration { + $$ = $1; + } + | init_declarator_list COMMA IDENTIFIER { + $$ = $1; + if (parseContext.structQualifierErrorCheck($3.line, $$.type)) + parseContext.recover(); + + if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $$.type)) + parseContext.recover(); + + if (parseContext.nonInitErrorCheck($3.line, *$3.string, $$.type)) + parseContext.recover(); + } + | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET { + if (parseContext.structQualifierErrorCheck($3.line, $1.type)) + parseContext.recover(); + + if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $1.type)) + parseContext.recover(); + + $$ = $1; + + if (parseContext.arrayTypeErrorCheck($4.line, $1.type) || parseContext.arrayQualifierErrorCheck($4.line, $1.type)) + parseContext.recover(); + else { + $1.type.setArray(true); + TVariable* variable; + if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + parseContext.recover(); + } + } + | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + if (parseContext.structQualifierErrorCheck($3.line, $1.type)) + parseContext.recover(); + + if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $1.type)) + parseContext.recover(); + + $$ = $1; + + if (parseContext.arrayTypeErrorCheck($4.line, $1.type) || parseContext.arrayQualifierErrorCheck($4.line, $1.type)) + parseContext.recover(); + else { + int size; + if (parseContext.arraySizeErrorCheck($4.line, $5, size)) + parseContext.recover(); + $1.type.setArray(true, size); + TVariable* variable; + if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + parseContext.recover(); + } + } + | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer { + if (parseContext.structQualifierErrorCheck($3.line, $1.type)) + parseContext.recover(); + + $$ = $1; + + TVariable* variable = 0; + if (parseContext.arrayTypeErrorCheck($4.line, $1.type) || parseContext.arrayQualifierErrorCheck($4.line, $1.type)) + parseContext.recover(); + else { + $1.type.setArray(true, $7->getType().getArraySize()); + if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + parseContext.recover(); + } + + if (parseContext.extensionErrorCheck($$.line, "GL_3DL_array_objects")) + parseContext.recover(); + else { + TIntermNode* intermNode; + if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $7, intermNode, variable)) { + // + // build the intermediate representation + // + if (intermNode) + $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $6.line); + else + $$.intermAggregate = $1.intermAggregate; + } else { + parseContext.recover(); + $$.intermAggregate = 0; + } + } + } + | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer { + if (parseContext.structQualifierErrorCheck($3.line, $1.type)) + parseContext.recover(); + + $$ = $1; + + TVariable* variable = 0; + if (parseContext.arrayTypeErrorCheck($4.line, $1.type) || parseContext.arrayQualifierErrorCheck($4.line, $1.type)) + parseContext.recover(); + else { + int size; + if (parseContext.arraySizeErrorCheck($4.line, $5, size)) + parseContext.recover(); + $1.type.setArray(true, size); + if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + parseContext.recover(); + } + + if (parseContext.extensionErrorCheck($$.line, "GL_3DL_array_objects")) + parseContext.recover(); + else { + TIntermNode* intermNode; + if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $8, intermNode, variable)) { + // + // build the intermediate representation + // + if (intermNode) + $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $7.line); + else + $$.intermAggregate = $1.intermAggregate; + } else { + parseContext.recover(); + $$.intermAggregate = 0; + } + } + } + | init_declarator_list COMMA IDENTIFIER EQUAL initializer { + if (parseContext.structQualifierErrorCheck($3.line, $1.type)) + parseContext.recover(); + + $$ = $1; + + TIntermNode* intermNode; + if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) { + // + // build the intermediate representation + // + if (intermNode) + $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $4.line); + else + $$.intermAggregate = $1.intermAggregate; + } else { + parseContext.recover(); + $$.intermAggregate = 0; + } + } + ; + +single_declaration + : fully_specified_type { + $$.type = $1; + $$.intermAggregate = 0; + } + | fully_specified_type IDENTIFIER { + $$.intermAggregate = 0; + $$.type = $1; + + if (parseContext.structQualifierErrorCheck($2.line, $$.type)) + parseContext.recover(); + + if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $$.type)) + parseContext.recover(); + + if (parseContext.nonInitErrorCheck($2.line, *$2.string, $$.type)) + parseContext.recover(); + } + | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET { + $$.intermAggregate = 0; + if (parseContext.structQualifierErrorCheck($2.line, $1)) + parseContext.recover(); + + if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $1)) + parseContext.recover(); + + $$.type = $1; + + if (parseContext.arrayTypeErrorCheck($3.line, $1) || parseContext.arrayQualifierErrorCheck($3.line, $1)) + parseContext.recover(); + else { + $1.setArray(true); + TVariable* variable; + if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable)) + parseContext.recover(); + } + } + | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + $$.intermAggregate = 0; + if (parseContext.structQualifierErrorCheck($2.line, $1)) + parseContext.recover(); + + if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $1)) + parseContext.recover(); + + $$.type = $1; + + if (parseContext.arrayTypeErrorCheck($3.line, $1) || parseContext.arrayQualifierErrorCheck($3.line, $1)) + parseContext.recover(); + else { + int size; + if (parseContext.arraySizeErrorCheck($3.line, $4, size)) + parseContext.recover(); + + $1.setArray(true, size); + TVariable* variable; + if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable)) + parseContext.recover(); + } + } + | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer { + $$.intermAggregate = 0; + + if (parseContext.structQualifierErrorCheck($2.line, $1)) + parseContext.recover(); + + $$.type = $1; + + TVariable* variable = 0; + if (parseContext.arrayTypeErrorCheck($3.line, $1) || parseContext.arrayQualifierErrorCheck($3.line, $1)) + parseContext.recover(); + else { + $1.setArray(true, $6->getType().getArraySize()); + if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable)) + parseContext.recover(); + } + + if (parseContext.extensionErrorCheck($$.line, "GL_3DL_array_objects")) + parseContext.recover(); + else { + TIntermNode* intermNode; + if (!parseContext.executeInitializer($2.line, *$2.string, $1, $6, intermNode, variable)) { + // + // Build intermediate representation + // + if (intermNode) + $$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $5.line); + else + $$.intermAggregate = 0; + } else { + parseContext.recover(); + $$.intermAggregate = 0; + } + } + } + | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer { + $$.intermAggregate = 0; + + if (parseContext.structQualifierErrorCheck($2.line, $1)) + parseContext.recover(); + + $$.type = $1; + + TVariable* variable = 0; + if (parseContext.arrayTypeErrorCheck($3.line, $1) || parseContext.arrayQualifierErrorCheck($3.line, $1)) + parseContext.recover(); + else { + int size; + if (parseContext.arraySizeErrorCheck($3.line, $4, size)) + parseContext.recover(); + + $1.setArray(true, size); + if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable)) + parseContext.recover(); + } + + if (parseContext.extensionErrorCheck($$.line, "GL_3DL_array_objects")) + parseContext.recover(); + else { + TIntermNode* intermNode; + if (!parseContext.executeInitializer($2.line, *$2.string, $1, $7, intermNode, variable)) { + // + // Build intermediate representation + // + if (intermNode) + $$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $6.line); + else + $$.intermAggregate = 0; + } else { + parseContext.recover(); + $$.intermAggregate = 0; + } + } + } + | fully_specified_type IDENTIFIER EQUAL initializer { + if (parseContext.structQualifierErrorCheck($2.line, $1)) + parseContext.recover(); + + $$.type = $1; + + TIntermNode* intermNode; + if (!parseContext.executeInitializer($2.line, *$2.string, $1, $4, intermNode)) { + // + // Build intermediate representation + // + if (intermNode) + $$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $3.line); + else + $$.intermAggregate = 0; + } else { + parseContext.recover(); + $$.intermAggregate = 0; + } + } + +// +// Place holder for the pack/unpack languages. +// +// | buffer_specifier { +// $$.intermAggregate = 0; +// } + ; + +// Grammar Note: No 'enum', or 'typedef'. + +// +// Place holder for the pack/unpack languages. +// +//%type buffer_declaration +//%type buffer_specifier input_or_output buffer_declaration_list +//buffer_specifier +// : input_or_output LEFT_BRACE buffer_declaration_list RIGHT_BRACE { +// } +// ; +// +//input_or_output +// : INPUT { +// if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "input")) +// parseContext.recover(); +// UNPACK_ONLY("input", $1.line); +// $$.qualifier = EvqInput; +// } +// | OUTPUT { +// if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "output")) +// parseContext.recover(); +// PACK_ONLY("output", $1.line); +// $$.qualifier = EvqOutput; +// } +// ; + +// +// Place holder for the pack/unpack languages. +// +//buffer_declaration_list +// : buffer_declaration { +// } +// | buffer_declaration_list buffer_declaration { +// } +// ; + +// +// Input/output semantics: +// float must be 16 or 32 bits +// float alignment restrictions? +// check for only one input and only one output +// sum of bitfields has to be multiple of 32 +// + +// +// Place holder for the pack/unpack languages. +// +//buffer_declaration +// : type_specifier IDENTIFIER COLON constant_expression SEMICOLON { +// if (parseContext.reservedErrorCheck($2.line, *$2.string, parseContext)) +// parseContext.recover(); +// $$.variable = new TVariable($2.string, $1); +// if (! parseContext.symbolTable.insert(*$$.variable)) { +// parseContext.error($2.line, "redefinition", $$.variable->getName().c_str(), ""); +// parseContext.recover(); +// // don't have to delete $$.variable, the pool pop will take care of it +// } +// } +// ; + +fully_specified_type + : type_specifier { + $$ = $1; + + if ($1.array) { + if (parseContext.extensionErrorCheck($1.line, "GL_3DL_array_objects")) { + parseContext.recover(); + $1.setArray(false); + } + } + } + | type_qualifier type_specifier { + if ($2.array && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects")) { + parseContext.recover(); + $2.setArray(false); + } + if ($2.array && parseContext.arrayQualifierErrorCheck($2.line, $1)) { + parseContext.recover(); + $2.setArray(false); + } + + if ($1.qualifier == EvqAttribute && + ($2.type == EbtBool || $2.type == EbtInt)) { + parseContext.error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), ""); + parseContext.recover(); + } + if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) && + ($2.type == EbtBool || $2.type == EbtInt)) { + parseContext.error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), ""); + parseContext.recover(); + } + $$ = $2; + $$.qualifier = $1.qualifier; + } + ; + +type_qualifier + : CONST_QUAL { + $$.setBasic(EbtVoid, EvqConst, $1.line); + } + | ATTRIBUTE { + VERTEX_ONLY("attribute", $1.line); + if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "attribute")) + parseContext.recover(); + $$.setBasic(EbtVoid, EvqAttribute, $1.line); + } + | VARYING { + if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "varying")) + parseContext.recover(); + if (parseContext.language == EShLangVertex) + $$.setBasic(EbtVoid, EvqVaryingOut, $1.line); + else + $$.setBasic(EbtVoid, EvqVaryingIn, $1.line); + } + | UNIFORM { + if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "uniform")) + parseContext.recover(); + $$.setBasic(EbtVoid, EvqUniform, $1.line); + } + ; + +type_specifier + : type_specifier_nonarray { + $$ = $1; + } + | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET { + $$ = $1; + + if (parseContext.arrayTypeErrorCheck($2.line, $1)) + parseContext.recover(); + else { + int size; + if (parseContext.arraySizeErrorCheck($2.line, $3, size)) + parseContext.recover(); + $$.setArray(true, size); + } + } + ; + +type_specifier_nonarray + : VOID_TYPE { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtVoid, qual, $1.line); + } + | FLOAT_TYPE { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + } + | INT_TYPE { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, $1.line); + } + | BOOL_TYPE { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, $1.line); + } +// | UNSIGNED INT_TYPE { +// PACK_UNPACK_ONLY("unsigned", $1.line); +// TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; +// $$.setBasic(EbtInt, qual, $1.line); +// } + | VEC2 { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + $$.setAggregate(2); + } + | VEC3 { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + $$.setAggregate(3); + } + | VEC4 { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + $$.setAggregate(4); + } + | BVEC2 { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, $1.line); + $$.setAggregate(2); + } + | BVEC3 { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, $1.line); + $$.setAggregate(3); + } + | BVEC4 { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, $1.line); + $$.setAggregate(4); + } + | IVEC2 { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, $1.line); + $$.setAggregate(2); + } + | IVEC3 { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, $1.line); + $$.setAggregate(3); + } + | IVEC4 { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, $1.line); + $$.setAggregate(4); + } + | MATRIX2 { + FRAG_VERT_ONLY("mat2", $1.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + $$.setAggregate(2, true); + } + | MATRIX3 { + FRAG_VERT_ONLY("mat3", $1.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + $$.setAggregate(3, true); + } + | MATRIX4 { + FRAG_VERT_ONLY("mat4", $1.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, $1.line); + $$.setAggregate(4, true); + } + | SAMPLER1D { + FRAG_VERT_ONLY("sampler1D", $1.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler1D, qual, $1.line); + } + | SAMPLER2D { + FRAG_VERT_ONLY("sampler2D", $1.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler2D, qual, $1.line); + } + | SAMPLER3D { + FRAG_VERT_ONLY("sampler3D", $1.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler3D, qual, $1.line); + } + | SAMPLERCUBE { + FRAG_VERT_ONLY("samplerCube", $1.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSamplerCube, qual, $1.line); + } + | SAMPLER1DSHADOW { + FRAG_VERT_ONLY("sampler1DShadow", $1.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler1DShadow, qual, $1.line); + } + | SAMPLER2DSHADOW { + FRAG_VERT_ONLY("sampler2DShadow", $1.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler2DShadow, qual, $1.line); + } + | SAMPLERRECTARB { + // ARB_texture_rectangle + + FRAG_VERT_ONLY("samplerRectARB", $1.line); + if (parseContext.extensionErrorCheck($1.line, "GL_ARB_texture_rectangle")) + parseContext.recover(); + + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSamplerRect, qual, $1.line); + } + | SAMPLERRECTSHADOWARB { + // ARB_texture_rectangle + + FRAG_VERT_ONLY("samplerRectShadowARB", $1.line); + if (parseContext.extensionErrorCheck($1.line, "GL_ARB_texture_rectangle")) + parseContext.recover(); + + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSamplerRectShadow, qual, $1.line); + } + | struct_specifier { + FRAG_VERT_ONLY("struct", $1.line); + $$ = $1; + $$.qualifier = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + } + | TYPE_NAME { + // + // This is for user defined type names. The lexical phase looked up the + // type. + // + TType& structure = static_cast($1.symbol)->getType(); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtStruct, qual, $1.line); + $$.userDef = &structure; + } + ; + +struct_specifier + : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE { + TType* structure = new TType($4, *$2.string); + TVariable* userTypeDef = new TVariable($2.string, *structure, true); + if (! parseContext.symbolTable.insert(*userTypeDef)) { + parseContext.error($2.line, "redefinition", $2.string->c_str(), "struct"); + parseContext.recover(); + } + $$.setBasic(EbtStruct, EvqTemporary, $1.line); + $$.userDef = structure; + } + | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE { + TType* structure = new TType($3, TString("")); + $$.setBasic(EbtStruct, EvqTemporary, $1.line); + $$.userDef = structure; + } + ; + +struct_declaration_list + : struct_declaration { + $$ = $1; + } + | struct_declaration_list struct_declaration { + $$ = $1; + for (unsigned int i = 0; i < $2->size(); ++i) { + for (unsigned int j = 0; j < $$->size(); ++j) { + if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) { + parseContext.error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str()); + parseContext.recover(); + } + } + $$->push_back((*$2)[i]); + } + } + ; + +struct_declaration + : type_specifier struct_declarator_list SEMICOLON { + $$ = $2; + + if (parseContext.voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) { + parseContext.recover(); + } + for (unsigned int i = 0; i < $$->size(); ++i) { + // + // Careful not to replace already know aspects of type, like array-ness + // + (*$$)[i].type->setType($1.type, $1.size, $1.matrix, $1.userDef); + + // don't allow arrays of arrays + if ((*$$)[i].type->isArray()) { + if (parseContext.arrayTypeErrorCheck($1.line, $1)) + parseContext.recover(); + } + if ($1.array) + (*$$)[i].type->setArraySize($1.arraySize); + if ($1.userDef) + (*$$)[i].type->setTypeName($1.userDef->getTypeName()); + } + } + ; + +struct_declarator_list + : struct_declarator { + $$ = NewPoolTTypeList(); + $$->push_back($1); + } + | struct_declarator_list COMMA struct_declarator { + $$->push_back($3); + } + ; + +struct_declarator + : IDENTIFIER { + $$.type = new TType(EbtVoid); + $$.line = $1.line; + $$.type->setFieldName(*$1.string); + } + | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + $$.type = new TType(EbtVoid); + $$.line = $1.line; + $$.type->setFieldName(*$1.string); + + int size; + if (parseContext.arraySizeErrorCheck($2.line, $3, size)) + parseContext.recover(); + $$.type->setArraySize(size); + } + ; + +initializer + : assignment_expression { $$ = $1; } + ; + +declaration_statement + : declaration { $$ = $1; } + ; + +statement + : compound_statement { $$ = $1; } + | simple_statement { $$ = $1; } + ; + +// Grammar Note: No labeled statements; 'goto' is not supported. + +simple_statement + : declaration_statement { $$ = $1; } + | expression_statement { $$ = $1; } + | selection_statement { $$ = $1; } + | iteration_statement { $$ = $1; } + | jump_statement { $$ = $1; } + ; + +compound_statement + : LEFT_BRACE RIGHT_BRACE { $$ = 0; } + | LEFT_BRACE { parseContext.symbolTable.push(); } statement_list { parseContext.symbolTable.pop(); } RIGHT_BRACE { + if ($3 != 0) + $3->setOperator(EOpSequence); + $$ = $3; + } + ; + +statement_no_new_scope + : compound_statement_no_new_scope { $$ = $1; } + | simple_statement { $$ = $1; } + ; + +compound_statement_no_new_scope + // Statement that doesn't create a new scope, for selection_statement, iteration_statement + : LEFT_BRACE RIGHT_BRACE { + $$ = 0; + } + | LEFT_BRACE statement_list RIGHT_BRACE { + if ($2) + $2->setOperator(EOpSequence); + $$ = $2; + } + ; + +statement_list + : statement { + $$ = parseContext.intermediate.makeAggregate($1, 0); + } + | statement_list statement { + $$ = parseContext.intermediate.growAggregate($1, $2, 0); + } + ; + +expression_statement + : SEMICOLON { $$ = 0; } + | expression SEMICOLON { $$ = static_cast($1); } + ; + +selection_statement + : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { + if (parseContext.boolErrorCheck($1.line, $3)) + parseContext.recover(); + $$ = parseContext.intermediate.addSelection($3, $5, $1.line); + } + ; + +selection_rest_statement + : statement ELSE statement { + $$.node1 = $1; + $$.node2 = $3; + } + | statement { + $$.node1 = $1; + $$.node2 = 0; + } + ; + +// Grammar Note: No 'switch'. Switch statements not supported. + +condition + // In 1996 c++ draft, conditions can include single declarations + : expression { + $$ = $1; + if (parseContext.boolErrorCheck($1->getLine(), $1)) + parseContext.recover(); + } + | fully_specified_type IDENTIFIER EQUAL initializer { + TIntermNode* intermNode; + if (parseContext.structQualifierErrorCheck($2.line, $1)) + parseContext.recover(); + if (parseContext.boolErrorCheck($2.line, $1)) + parseContext.recover(); + + if (!parseContext.executeInitializer($2.line, *$2.string, $1, $4, intermNode)) + $$ = $4; + else { + parseContext.recover(); + $$ = 0; + } + } + ; + +iteration_statement + : WHILE LEFT_PAREN { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope { + parseContext.symbolTable.pop(); + $$ = parseContext.intermediate.addLoop($6, $4, 0, true, $1.line); + --parseContext.loopNestingLevel; + } + | DO { ++parseContext.loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { + if (parseContext.boolErrorCheck($8.line, $6)) + parseContext.recover(); + + $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.line); + --parseContext.loopNestingLevel; + } + | FOR LEFT_PAREN { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { + parseContext.symbolTable.pop(); + $$ = parseContext.intermediate.makeAggregate($4, $2.line); + $$ = parseContext.intermediate.growAggregate( + $$, + parseContext.intermediate.addLoop($7, reinterpret_cast($5.node1), reinterpret_cast($5.node2), true, $1.line), + $1.line); + $$->getAsAggregate()->setOperator(EOpSequence); + --parseContext.loopNestingLevel; + } + ; + +for_init_statement + : expression_statement { + $$ = $1; + } + | declaration_statement { + $$ = $1; + } + ; + +conditionopt + : condition { + $$ = $1; + } + | /* May be null */ { + $$ = 0; + } + ; + +for_rest_statement + : conditionopt SEMICOLON { + $$.node1 = $1; + $$.node2 = 0; + } + | conditionopt SEMICOLON expression { + $$.node1 = $1; + $$.node2 = $3; + } + ; + +jump_statement + : CONTINUE SEMICOLON { + if (parseContext.loopNestingLevel <= 0) { + parseContext.error($1.line, "continue statement only allowed in loops", "", ""); + parseContext.recover(); + } + $$ = parseContext.intermediate.addBranch(EOpContinue, $1.line); + } + | BREAK SEMICOLON { + if (parseContext.loopNestingLevel <= 0) { + parseContext.error($1.line, "break statement only allowed in loops", "", ""); + parseContext.recover(); + } + $$ = parseContext.intermediate.addBranch(EOpBreak, $1.line); + } + | RETURN SEMICOLON { + $$ = parseContext.intermediate.addBranch(EOpReturn, $1.line); + if (parseContext.currentFunctionType->getBasicType() != EbtVoid) { + parseContext.error($1.line, "non-void function must return a value", "return", ""); + parseContext.recover(); + } + } + | RETURN expression SEMICOLON { + $$ = parseContext.intermediate.addBranch(EOpReturn, $2, $1.line); + parseContext.functionReturnsValue = true; + if (parseContext.currentFunctionType->getBasicType() == EbtVoid) { + parseContext.error($1.line, "void function cannot return a value", "return", ""); + parseContext.recover(); + } else if (*(parseContext.currentFunctionType) != $2->getType()) { + parseContext.error($1.line, "function return is not matching type:", "return", ""); + parseContext.recover(); + } + } + | DISCARD SEMICOLON { + FRAG_ONLY("discard", $1.line); + $$ = parseContext.intermediate.addBranch(EOpKill, $1.line); + } + ; + +// Grammar Note: No 'goto'. Gotos are not supported. + +translation_unit + : external_declaration { + $$ = $1; + parseContext.treeRoot = $$; + } + | translation_unit external_declaration { + $$ = parseContext.intermediate.growAggregate($1, $2, 0); + parseContext.treeRoot = $$; + } + ; + +external_declaration + : function_definition { + $$ = $1; + } + | declaration { + $$ = $1; + } + ; + +function_definition + : function_prototype { + TFunction& function = *($1.function); + TFunction* prevDec = static_cast(parseContext.symbolTable.find(function.getMangledName())); + // + // Note: 'prevDec' could be 'function' if this is the first time we've seen function + // as it would have just been put in the symbol table. Otherwise, we're looking up + // an earlier occurance. + // + if (prevDec->isDefined()) { + // + // Then this function already has a body. + // + parseContext.error($1.line, "function already has a body", function.getName().c_str(), ""); + parseContext.recover(); + } + prevDec->setDefined(); + + // + // Raise error message if main function takes any parameters or return anything other than void + // + if (function.getName() == "main") { + if (function.getParamCount() > 0) { + parseContext.error($1.line, "function cannot take any parameter(s)", function.getName().c_str(), ""); + parseContext.recover(); + } + if (function.getReturnType().getBasicType() != EbtVoid) { + parseContext.error($1.line, "", function.getReturnType().getBasicString(), "main function cannot return a value"); + parseContext.recover(); + } + } + + // + // New symbol table scope for body of function plus its arguments + // + parseContext.symbolTable.push(); + + // + // Remember the return type for later checking for RETURN statements. + // + parseContext.currentFunctionType = &(prevDec->getReturnType()); + parseContext.functionReturnsValue = false; + + // + // Insert parameters into the symbol table. + // If the parameter has no name, it's not an error, just don't insert it + // (could be used for unused args). + // + // Also, accumulate the list of parameters into the HIL, so lower level code + // knows where to find parameters. + // + TIntermAggregate* paramNodes = new TIntermAggregate; + for (int i = 0; i < function.getParamCount(); i++) { + TParameter& param = function[i]; + if (param.name != 0) { + TVariable *variable = new TVariable(param.name, *param.type); + // + // Insert the parameters with name in the symbol table. + // + if (! parseContext.symbolTable.insert(*variable)) { + parseContext.error($1.line, "redefinition", variable->getName().c_str(), ""); + parseContext.recover(); + delete variable; + } + // + // Transfer ownership of name pointer to symbol table. + // + param.name = 0; + + // + // Add the parameter to the HIL + // + paramNodes = parseContext.intermediate.growAggregate( + paramNodes, + parseContext.intermediate.addSymbol(variable->getUniqueId(), + variable->getName(), + variable->getType(), $1.line), + $1.line); + } else { + paramNodes = parseContext.intermediate.growAggregate(paramNodes, parseContext.intermediate.addSymbol(0, "", *param.type, $1.line), $1.line); + } + } + parseContext.intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line); + $1.intermAggregate = paramNodes; + parseContext.loopNestingLevel = 0; + } + compound_statement_no_new_scope { + //?? Check that all paths return a value if return type != void ? + // May be best done as post process phase on intermediate code + if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) { + parseContext.error($1.line, "function does not return a value:", "", $1.function->getName().c_str()); + parseContext.recover(); + } + parseContext.symbolTable.pop(); + $$ = parseContext.intermediate.growAggregate($1.intermAggregate, $3, 0); + parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.line); + $$->getAsAggregate()->setName($1.function->getMangledName().c_str()); + $$->getAsAggregate()->setType($1.function->getReturnType()); + + // store the pragma information for debug and optimize and other vendor specific + // information. This information can be queried from the parse tree + $$->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize); + $$->getAsAggregate()->setDebug(parseContext.contextPragma.debug); + $$->getAsAggregate()->addToPragmaTable(parseContext.contextPragma.pragmaTable); + } + ; + +%% diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp new file mode 100644 index 0000000..a01899a --- /dev/null +++ b/glslang/MachineIndependent/intermOut.cpp @@ -0,0 +1,491 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#include "localintermediate.h" + +// +// Two purposes: +// 1. Show an example of how to iterate tree. Functions can +// also directly call Traverse() on children themselves to +// have finer grained control over the process than shown here. +// See the last function for how to get started. +// 2. Print out a text based description of the tree. +// + +// +// Use this class to carry along data from node to node in +// the traversal +// +class TOutputTraverser : public TIntermTraverser { +public: + TOutputTraverser(TInfoSink& i) : infoSink(i) { } + TInfoSink& infoSink; +}; + +TString TType::getCompleteString() const +{ + char buf[100]; + char *p = &buf[0]; + + if (qualifier != EvqTemporary && qualifier != EvqGlobal) + p += sprintf(p, "%s ", getQualifierString()); + if (array) + p += sprintf(p, "array of "); + if (matrix) + p += sprintf(p, "%dX%d matrix of ", size, size); + else if (size > 1) + p += sprintf(p, "%d-component vector of ", size); + + sprintf(p, "%s", getBasicString()); + + return TString(buf); +} + +// +// Helper functions for printing, not part of traversing. +// + +void OutputTreeText(TInfoSink& infoSink, TIntermNode* node, const int depth) +{ + int i; + + infoSink.debug << FormatSourceLoc(node->getLine()); + + for (i = 0; i < depth; ++i) + infoSink.debug << " "; +} + +// +// The rest of the file are the traversal functions. The last one +// is the one that starts the traversal. +// +// Return true from interior nodes to have the external traversal +// continue on to children. If you process children yourself, +// return false. +// + +void OutputSymbol(TIntermSymbol* node, TIntermTraverser* it) +{ + TOutputTraverser* oit = static_cast(it); + + OutputTreeText(oit->infoSink, node, oit->depth); + + char buf[100]; + sprintf(buf, "'%s' (%s)\n", + node->getSymbol().c_str(), + node->getCompleteString().c_str()); + + oit->infoSink.debug << buf; +} + +bool OutputBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it) +{ + TOutputTraverser* oit = static_cast(it); + TInfoSink& out = oit->infoSink; + + OutputTreeText(out, node, oit->depth); + + switch (node->getOp()) { + case EOpAssign: out.debug << "move second child to first child"; break; + case EOpAddAssign: out.debug << "add second child into first child"; break; + case EOpSubAssign: out.debug << "subtract second child into first child"; break; + case EOpMulAssign: out.debug << "multiply second child into first child"; break; + case EOpVectorTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break; + case EOpVectorTimesScalarAssign: out.debug << "vector scale second child into first child"; break; + case EOpMatrixTimesScalarAssign: out.debug << "matrix scale second child into first child"; break; + case EOpMatrixTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break; + case EOpDivAssign: out.debug << "divide second child into first child"; break; + case EOpModAssign: out.debug << "mod second child into first child"; break; + case EOpAndAssign: out.debug << "and second child into first child"; break; + case EOpInclusiveOrAssign: out.debug << "or second child into first child"; break; + case EOpExclusiveOrAssign: out.debug << "exclusive or second child into first child"; break; + case EOpLeftShiftAssign: out.debug << "left shift second child into first child"; break; + case EOpRightShiftAssign: out.debug << "right shift second child into first child"; break; + + case EOpIndexDirect: out.debug << "direct index"; break; + case EOpIndexIndirect: out.debug << "indirect index"; break; + case EOpIndexDirectStruct: out.debug << "direct index for structure"; break; + case EOpVectorSwizzle: out.debug << "vector swizzle"; break; + + case EOpAdd: out.debug << "add"; break; + case EOpSub: out.debug << "subtract"; break; + case EOpMul: out.debug << "component-wise multiply"; break; + case EOpDiv: out.debug << "divide"; break; + case EOpMod: out.debug << "mod"; break; + case EOpRightShift: out.debug << "right-shift"; break; + case EOpLeftShift: out.debug << "left-shift"; break; + case EOpAnd: out.debug << "bitwise and"; break; + case EOpInclusiveOr: out.debug << "inclusive-or"; break; + case EOpExclusiveOr: out.debug << "exclusive-or"; break; + case EOpEqual: out.debug << "Compare Equal"; break; + case EOpNotEqual: out.debug << "Compare Not Equal"; break; + case EOpLessThan: out.debug << "Compare Less Than"; break; + case EOpGreaterThan: out.debug << "Compare Greater Than"; break; + case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break; + case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break; + + case EOpVectorTimesScalar: out.debug << "vector-scale"; break; + case EOpVectorTimesMatrix: out.debug << "vector-times-matrix"; break; + case EOpMatrixTimesVector: out.debug << "matrix-times-vector"; break; + case EOpMatrixTimesScalar: out.debug << "matrix-scale"; break; + case EOpMatrixTimesMatrix: out.debug << "matrix-multiply"; break; + + case EOpLogicalOr: out.debug << "logical-or"; break; + case EOpLogicalXor: out.debug << "logical-xor"; break; + case EOpLogicalAnd: out.debug << "logical-and"; break; + default: out.debug << ""; + } + + out.debug << " (" << node->getCompleteString() << ")"; + + out.debug << "\n"; + + return true; +} + +bool OutputUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it) +{ + TOutputTraverser* oit = static_cast(it); + TInfoSink& out = oit->infoSink; + + OutputTreeText(out, node, oit->depth); + + switch (node->getOp()) { + case EOpNegative: out.debug << "Negate value"; break; + case EOpVectorLogicalNot: + case EOpLogicalNot: out.debug << "Negate conditional"; break; + case EOpBitwiseNot: out.debug << "Bitwise not"; break; + + case EOpPostIncrement: out.debug << "Post-Increment"; break; + case EOpPostDecrement: out.debug << "Post-Decrement"; break; + case EOpPreIncrement: out.debug << "Pre-Increment"; break; + case EOpPreDecrement: out.debug << "Pre-Decrement"; break; + + case EOpConvIntToBool: out.debug << "Convert int to bool"; break; + case EOpConvFloatToBool:out.debug << "Convert float to bool";break; + case EOpConvBoolToFloat:out.debug << "Convert bool to float";break; + case EOpConvIntToFloat: out.debug << "Convert int to float"; break; + case EOpConvFloatToInt: out.debug << "Convert float to int"; break; + case EOpConvBoolToInt: out.debug << "Convert bool to int"; break; + + case EOpRadians: out.debug << "radians"; break; + case EOpDegrees: out.debug << "degrees"; break; + case EOpSin: out.debug << "sine"; break; + case EOpCos: out.debug << "cosine"; break; + case EOpTan: out.debug << "tangent"; break; + case EOpAsin: out.debug << "arc sine"; break; + case EOpAcos: out.debug << "arc cosine"; break; + case EOpAtan: out.debug << "arc tangent"; break; + + case EOpExp: out.debug << "exp"; break; + case EOpLog: out.debug << "log"; break; + case EOpExp2: out.debug << "exp2"; break; + case EOpLog2: out.debug << "log2"; break; + case EOpSqrt: out.debug << "sqrt"; break; + case EOpInverseSqrt: out.debug << "inverse sqrt"; break; + + case EOpAbs: out.debug << "Absolute value"; break; + case EOpSign: out.debug << "Sign"; break; + case EOpFloor: out.debug << "Floor"; break; + case EOpCeil: out.debug << "Ceiling"; break; + case EOpFract: out.debug << "Fraction"; break; + + case EOpLength: out.debug << "length"; break; + case EOpNormalize: out.debug << "normalize"; break; + case EOpDPdx: out.debug << "dPdx"; break; + case EOpDPdy: out.debug << "dPdy"; break; + case EOpFwidth: out.debug << "fwidth"; break; + + case EOpAny: out.debug << "any"; break; + case EOpAll: out.debug << "all"; break; + + default: out.debug.message(EPrefixError, "Bad unary op"); + } + + out.debug << " (" << node->getCompleteString() << ")"; + + out.debug << "\n"; + + return true; +} + +bool OutputAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it) +{ + TOutputTraverser* oit = static_cast(it); + TInfoSink& out = oit->infoSink; + + if (node->getOp() == EOpNull) { + out.debug.message(EPrefixError, "node is still EOpNull!"); + return true; + } + + OutputTreeText(out, node, oit->depth); + + switch (node->getOp()) { + case EOpSequence: out.debug << "Sequence\n"; return true; + case EOpComma: out.debug << "Comma\n"; return true; + case EOpFunction: out.debug << "Function Definition: " << node->getName(); break; + case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break; + case EOpParameters: out.debug << "Function Parameters: "; break; + + case EOpConstructFloat: out.debug << "Construct float"; break; + case EOpConstructVec2: out.debug << "Construct vec2"; break; + case EOpConstructVec3: out.debug << "Construct vec3"; break; + case EOpConstructVec4: out.debug << "Construct vec4"; break; + case EOpConstructBool: out.debug << "Construct bool"; break; + case EOpConstructBVec2: out.debug << "Construct bvec2"; break; + case EOpConstructBVec3: out.debug << "Construct bvec3"; break; + case EOpConstructBVec4: out.debug << "Construct bvec4"; break; + case EOpConstructInt: out.debug << "Construct int"; break; + case EOpConstructIVec2: out.debug << "Construct ivec2"; break; + case EOpConstructIVec3: out.debug << "Construct ivec3"; break; + case EOpConstructIVec4: out.debug << "Construct ivec4"; break; + case EOpConstructMat2: out.debug << "Construct mat2"; break; + case EOpConstructMat3: out.debug << "Construct mat3"; break; + case EOpConstructMat4: out.debug << "Construct mat4"; break; + case EOpConstructStruct: out.debug << "Construct structure"; break; + + case EOpLessThan: out.debug << "Compare Less Than"; break; + case EOpGreaterThan: out.debug << "Compare Greater Than"; break; + case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break; + case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break; + case EOpVectorEqual: out.debug << "Equal"; break; + case EOpVectorNotEqual: out.debug << "NotEqual"; break; + + case EOpMod: out.debug << "mod"; break; + case EOpPow: out.debug << "pow"; break; + + case EOpAtan: out.debug << "arc tangent"; break; + + case EOpMin: out.debug << "min"; break; + case EOpMax: out.debug << "max"; break; + case EOpClamp: out.debug << "clamp"; break; + case EOpMix: out.debug << "mix"; break; + case EOpStep: out.debug << "step"; break; + case EOpSmoothStep: out.debug << "smoothstep"; break; + + case EOpDistance: out.debug << "distance"; break; + case EOpDot: out.debug << "dot-product"; break; + case EOpCross: out.debug << "cross-product"; break; + case EOpFaceForward: out.debug << "face-forward"; break; + case EOpReflect: out.debug << "reflect"; break; + case EOpRefract: out.debug << "refract"; break; + case EOpMul: out.debug << "component-wise multiply"; break; + + case EOpItof: out.debug << "itof"; break; + case EOpFtoi: out.debug << "ftoi"; break; + case EOpSkipPixels: out.debug << "skipPixels"; break; + case EOpReadInput: out.debug << "readInput"; break; + case EOpWritePixel: out.debug << "writePixel"; break; + case EOpBitmapLsb: out.debug << "bitmapLSB"; break; + case EOpBitmapMsb: out.debug << "bitmapMSB"; break; + case EOpWriteOutput: out.debug << "writeOutput"; break; + case EOpReadPixel: out.debug << "readPixel"; break; + + default: out.debug.message(EPrefixError, "Bad aggregation op"); + } + + if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) + out.debug << " (" << node->getCompleteString() << ")"; + + out.debug << "\n"; + + return true; +} + +bool OutputSelection(bool /* preVisit */, TIntermSelection* node, TIntermTraverser* it) +{ + TOutputTraverser* oit = static_cast(it); + TInfoSink& out = oit->infoSink; + + OutputTreeText(out, node, oit->depth); + + out.debug << "Test condition and select"; + out.debug << " (" << node->getCompleteString() << ")\n"; + + ++oit->depth; + + OutputTreeText(oit->infoSink, node, oit->depth); + out.debug << "Condition\n"; + node->getCondition()->traverse(it); + + OutputTreeText(oit->infoSink, node, oit->depth); + if (node->getTrueBlock()) { + out.debug << "true case\n"; + node->getTrueBlock()->traverse(it); + } else + out.debug << "true case is null\n"; + + if (node->getFalseBlock()) { + OutputTreeText(oit->infoSink, node, oit->depth); + out.debug << "false case\n"; + node->getFalseBlock()->traverse(it); + } + + --oit->depth; + + return false; +} + +void OutputConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it) +{ + TOutputTraverser* oit = static_cast(it); + TInfoSink& out = oit->infoSink; + + int size = node->getType().getObjectSize(); + + for (int i = 0; i < size; i++) { + OutputTreeText(out, node, oit->depth); + switch (node->getUnionArrayPointer()[i].getType()) { + case EbtBool: + if (node->getUnionArrayPointer()[i].getBConst()) + out.debug << "true"; + else + out.debug << "false"; + + out.debug << " (" << "const bool" << ")"; + + out.debug << "\n"; + break; + case EbtFloat: + { + char buf[300]; + sprintf(buf, "%f (%s)", node->getUnionArrayPointer()[i].getFConst(), "const float"); + + out.debug << buf << "\n"; + } + break; + case EbtInt: + { + char buf[300]; + sprintf(buf, "%d (%s)", node->getUnionArrayPointer()[i].getIConst(), "const int"); + + out.debug << buf << "\n"; + break; + } + default: + out.info.message(EPrefixInternalError, "Unknown constant", node->getLine()); + break; + } + } +} + +bool OutputLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it) +{ + TOutputTraverser* oit = static_cast(it); + TInfoSink& out = oit->infoSink; + + OutputTreeText(out, node, oit->depth); + + out.debug << "Loop with condition "; + if (! node->testFirst()) + out.debug << "not "; + out.debug << "tested first\n"; + + ++oit->depth; + + OutputTreeText(oit->infoSink, node, oit->depth); + if (node->getTest()) { + out.debug << "Loop Condition\n"; + node->getTest()->traverse(it); + } else + out.debug << "No loop condition\n"; + + OutputTreeText(oit->infoSink, node, oit->depth); + if (node->getBody()) { + out.debug << "Loop Body\n"; + node->getBody()->traverse(it); + } else + out.debug << "No loop body\n"; + + if (node->getTerminal()) { + OutputTreeText(oit->infoSink, node, oit->depth); + out.debug << "Loop Terminal Expression\n"; + node->getTerminal()->traverse(it); + } + + --oit->depth; + + return false; +} + +bool OutputBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it) +{ + TOutputTraverser* oit = static_cast(it); + TInfoSink& out = oit->infoSink; + + OutputTreeText(out, node, oit->depth); + + switch (node->getFlowOp()) { + case EOpKill: out.debug << "Branch: Kill"; break; + case EOpBreak: out.debug << "Branch: Break"; break; + case EOpContinue: out.debug << "Branch: Continue"; break; + case EOpReturn: out.debug << "Branch: Return"; break; + default: out.debug << "Branch: Unknown Branch"; break; + } + + if (node->getExpression()) { + out.debug << " with expression\n"; + ++oit->depth; + node->getExpression()->traverse(it); + --oit->depth; + } else + out.debug << "\n"; + + return false; +} + +// +// This function is the one to call externally to start the traversal. +// Individual functions can be initialized to 0 to skip processing of that +// type of node. It's children will still be processed. +// +void TIntermediate::outputTree(TIntermNode* root) +{ + if (root == 0) + return; + + TOutputTraverser it(infoSink); + + it.visitAggregate = OutputAggregate; + it.visitBinary = OutputBinary; + it.visitConstantUnion = OutputConstantUnion; + it.visitSelection = OutputSelection; + it.visitSymbol = OutputSymbol; + it.visitUnary = OutputUnary; + it.visitLoop = OutputLoop; + it.visitBranch = OutputBranch; + + root->traverse(&it); +} diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h new file mode 100644 index 0000000..ae30c73 --- /dev/null +++ b/glslang/MachineIndependent/localintermediate.h @@ -0,0 +1,86 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _LOCAL_INTERMEDIATE_INCLUDED_ +#define _LOCAL_INTERMEDIATE_INCLUDED_ + +#include "../Include/intermediate.h" +#include "../Public/ShaderLang.h" +#include "SymbolTable.h" + +struct TVectorFields { + int offsets[4]; + int num; +}; + +// +// Set of helper functions to help parse and build the tree. +// +class TInfoSink; +class TIntermediate { +public: + POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + + TIntermediate(TInfoSink& i) : infoSink(i) { } + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc); + TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); + TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&); + TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); + TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc); + TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&); + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc); + TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc); + TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc); + TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc); + TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc); + TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc); + TIntermConstantUnion* addConstantUnion(constUnion*, const TType&, TSourceLoc); + TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ; + bool parseConstTree(TSourceLoc, TIntermNode*, constUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false); + TIntermNode* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc); + TIntermBranch* addBranch(TOperator, TSourceLoc); + TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc); + TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc); + bool postProcess(TIntermNode*, EShLanguage); + void remove(TIntermNode*); + void outputTree(TIntermNode*); + +protected: + TInfoSink& infoSink; + +private: + void operator=(TIntermediate&); // prevent assignments +}; + +#endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/glslang/MachineIndependent/parseConst.cpp b/glslang/MachineIndependent/parseConst.cpp new file mode 100644 index 0000000..ae07319 --- /dev/null +++ b/glslang/MachineIndependent/parseConst.cpp @@ -0,0 +1,266 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#include "ParseHelper.h" + +// +// Use this class to carry along data from node to node in +// the traversal +// +class TConstTraverser : public TIntermTraverser { +public: + TConstTraverser(constUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t) : unionArray(cUnion), type(t), + constructorType(constructType), singleConstantParam(singleConstParam), infoSink(sink), symbolTable(symTable), error(false), isMatrix(false), matrixSize(0) { index = 0; tOp = EOpNull;} + int index ; + constUnion *unionArray; + TOperator tOp; + TType type; + TOperator constructorType; + bool singleConstantParam; + TInfoSink& infoSink; + TSymbolTable& symbolTable; + bool error; + int size; // size of the constructor ( 4 for vec4) + bool isMatrix; + int matrixSize; // dimension of the matrix (nominal size and not the instance size) +}; + +// +// The rest of the file are the traversal functions. The last one +// is the one that starts the traversal. +// +// Return true from interior nodes to have the external traversal +// continue on to children. If you process children yourself, +// return false. +// + +void ParseSymbol(TIntermSymbol* node, TIntermTraverser* it) +{ + TConstTraverser* oit = static_cast(it); + oit->infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine()); + return; + +} + +bool ParseBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it) +{ + TConstTraverser* oit = static_cast(it); + + TQualifier qualifier = node->getType().getQualifier(); + + if (qualifier != EvqConst) { + char buf[200]; + sprintf(buf, "'constructor' : assigning non-constant to %s", oit->type.getCompleteString().c_str()); + oit->infoSink.info.message(EPrefixError, buf, node->getLine()); + oit->error = true; + return false; + } + + oit->infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine()); + + return false; +} + +bool ParseUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it) +{ + TConstTraverser* oit = static_cast(it); + + char buf[200]; + sprintf(buf, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str()); + oit->infoSink.info.message(EPrefixError, buf, node->getLine()); + oit->error = true; + return false; +} + +bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it) +{ + TConstTraverser* oit = static_cast(it); + + if (!node->isConstructor() && node->getOp() != EOpComma) { + char buf[200]; + sprintf(buf, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str()); + oit->infoSink.info.message(EPrefixError, buf, node->getLine()); + oit->error = true; + return false; + } + + if (node->getSequence().size() == 0) { + oit->error = true; + return false; + } + + bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion(); + if (flag) + { + oit->singleConstantParam = true; + oit->constructorType = node->getOp(); + oit->size = node->getType().getObjectSize(); + + if (node->getType().isMatrix()) { + oit->isMatrix = true; + oit->matrixSize = node->getType().getNominalSize(); + } + } + + for (TIntermSequence::iterator p = node->getSequence().begin(); + p != node->getSequence().end(); p++) { + + if (node->getOp() == EOpComma) + oit->index = 0; + + (*p)->traverse(oit); + } + if (flag) + { + oit->singleConstantParam = false; + oit->constructorType = EOpNull; + oit->size = 0; + oit->isMatrix = false; + oit->matrixSize = 0; + } + return false; +} + +bool ParseSelection(bool /* preVisit */, TIntermSelection* node, TIntermTraverser* it) +{ + TConstTraverser* oit = static_cast(it); + oit->infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine()); + oit->error = true; + return false; +} + +void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it) +{ + TConstTraverser* oit = static_cast(it); + constUnion* leftUnionArray = oit->unionArray; + int instanceSize = oit->type.getObjectSize(); + + if (oit->index >= instanceSize) + return; + + if (!oit->singleConstantParam) { + int size = node->getType().getObjectSize(); + + constUnion *rightUnionArray = node->getUnionArrayPointer(); + for (int i=0; i < size; i++) { + if (oit->index >= instanceSize) + return; + leftUnionArray[oit->index] = rightUnionArray[i]; + + (oit->index)++; + } + } else { + int size, totalSize, matrixSize; + bool isMatrix = false; + size = oit->size; + matrixSize = oit->matrixSize; + isMatrix = oit->isMatrix; + totalSize = oit->index + size ; + constUnion *rightUnionArray = node->getUnionArrayPointer(); + if (!isMatrix) { + int count = 0; + for (int i = oit->index; i < totalSize; i++) { + if (i >= instanceSize) + return; + + leftUnionArray[i] = rightUnionArray[count]; + + (oit->index)++; + + if (node->getType().getObjectSize() > 1) + count++; + } + } else { // for matrix constructors + int count = 0; + int index = oit->index; + for (int i = index; i < totalSize; i++) { + if (i >= instanceSize) + return; + if (index - i == 0 || (i - index) % (matrixSize + 1) == 0 ) + leftUnionArray[i] = rightUnionArray[count]; + else + leftUnionArray[i].setFConst(0.0f); + + (oit->index)++; + + if (node->getType().getObjectSize() > 1) + count++; + } + } + } +} + +bool ParseLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it) +{ + TConstTraverser* oit = static_cast(it); + oit->infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine()); + oit->error = true; + return false; +} + +bool ParseBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it) +{ + TConstTraverser* oit = static_cast(it); + oit->infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine()); + oit->error = true; + return false; +} + +// +// This function is the one to call externally to start the traversal. +// Individual functions can be initialized to 0 to skip processing of that +// type of node. It's children will still be processed. +// +bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, constUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam) +{ + if (root == 0) + return false; + + TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t); + + it.visitAggregate = ParseAggregate; + it.visitBinary = ParseBinary; + it.visitConstantUnion = ParseConstantUnion; + it.visitSelection = ParseSelection; + it.visitSymbol = ParseSymbol; + it.visitUnary = ParseUnary; + it.visitLoop = ParseLoop; + it.visitBranch = ParseBranch; + + root->traverse(&it); + if (it.error) + return true; + else + return false; +} diff --git a/glslang/MachineIndependent/preprocessor/Makefile b/glslang/MachineIndependent/preprocessor/Makefile new file mode 100644 index 0000000..b6402ce --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/Makefile @@ -0,0 +1,38 @@ +CC = gcc + +OBJECTS = atom.o cpp.o cppstruct.o memory.o scanner.o symbols.o tokens.o +AR=ar +SRCS=scanner.c atom.c memory.c tokens. cpp.c cppstruct.c symbols.c + +default: all +all : libPreprocessor.a +libPreprocessor.a : $(OBJECTS) + $(AR) rvu $@ $(OBJECTS) + ranlib $@ + +%.o : %.c + $(CC) -c $< + +# +# Cleanup +# +.PHONY : clean +clean : + $(RM) *.o *.a + +depend: + makedepend -Y -- $(SRCS) + +# DO NOT DELETE + +scanner.o: slglobals.h memory.h atom.h scanner.h parser.h cpp.h tokens.h +scanner.o: symbols.h compile.h +atom.o: slglobals.h memory.h atom.h scanner.h parser.h cpp.h tokens.h +atom.o: symbols.h compile.h +memory.o: memory.h +cpp.o: slglobals.h memory.h atom.h scanner.h parser.h cpp.h tokens.h +cpp.o: symbols.h compile.h +cppstruct.o: slglobals.h memory.h atom.h scanner.h parser.h cpp.h tokens.h +cppstruct.o: symbols.h compile.h +symbols.o: slglobals.h memory.h atom.h scanner.h parser.h cpp.h tokens.h +symbols.o: symbols.h compile.h diff --git a/glslang/MachineIndependent/preprocessor/atom.c b/glslang/MachineIndependent/preprocessor/atom.c new file mode 100644 index 0000000..39af441 --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/atom.c @@ -0,0 +1,768 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +// +// atom.c +// + +#include +#include +#include +#include + +#include "slglobals.h" + +#undef malloc +#undef realloc +#undef free + +/////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////// String table: ////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +static const struct { + int val; + const char *str; +} tokens[] = { + { CPP_AND_OP, "&&" }, + { CPP_AND_ASSIGN, "&=" }, + { CPP_SUB_ASSIGN, "-=" }, + { CPP_MOD_ASSIGN, "%=" }, + { CPP_ADD_ASSIGN, "+=" }, + { CPP_DIV_ASSIGN, "/=" }, + { CPP_MUL_ASSIGN, "*=" }, + { CPP_RIGHT_BRACKET, ":>" }, + { CPP_EQ_OP, "==" }, + { CPP_XOR_OP, "^^" }, + { CPP_XOR_ASSIGN, "^=" }, + { CPP_FLOATCONSTANT, "" }, + { CPP_GE_OP, ">=" }, + { CPP_RIGHT_OP, ">>" }, + { CPP_RIGHT_ASSIGN, ">>=" }, + { CPP_IDENTIFIER, "" }, + { CPP_INTCONSTANT, "" }, + { CPP_LE_OP, "<=" }, + { CPP_LEFT_OP, "<<" }, + { CPP_LEFT_ASSIGN, "<<=" }, + { CPP_LEFT_BRACKET, "<:" }, + { CPP_LEFT_BRACE, "<%" }, + { CPP_DEC_OP, "--" }, + { CPP_RIGHT_BRACE, "%>" }, + { CPP_NE_OP, "!=" }, + { CPP_OR_OP, "||" }, + { CPP_OR_ASSIGN, "|=" }, + { CPP_INC_OP, "++" }, + { CPP_STRCONSTANT, "" }, + { CPP_TYPEIDENTIFIER, "" }, +}; + +/////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////// String table: ////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +#define INIT_STRING_TABLE_SIZE 16384 + +typedef struct StringTable_Rec { + char *strings; + int nextFree; + int size; +} StringTable; + +/* + * InitStringTable() - Initialize the string table. + * + */ + +static int InitStringTable(StringTable *stable) +{ + stable->strings = (char *) malloc(INIT_STRING_TABLE_SIZE); + if (!stable->strings) + return 0; + // Zero-th offset means "empty" so don't use it. + stable->nextFree = 1; + stable->size = INIT_STRING_TABLE_SIZE; + return 1; +} // InitStringTable + +/* + * FreeStringTable() - Free the string table. + * + */ + +static void FreeStringTable(StringTable *stable) +{ + if (stable->strings) + free(stable->strings); + stable->strings = NULL; + stable->nextFree = 0; + stable->size = 0; +} // FreeStringTable + +/* + * HashString() - Hash a string with the base hash function. + * + */ + +static int HashString(const char *s) +{ + int hval = 0; + + while (*s) { + hval = (hval*13507 + *s*197) ^ (hval >> 2); + s++; + } + return hval & 0x7fffffff; +} // HashString + +/* + * HashString2() - Hash a string with the incrimenting hash function. + * + */ + +static int HashString2(const char *s) +{ + int hval = 0; + + while (*s) { + hval = (hval*729 + *s*37) ^ (hval >> 1); + s++; + } + return hval; +} // HashString2 + +/* + * AddString() - Add a string to a string table. Return it's offset. + * + */ + +static int AddString(StringTable *stable, const char *s) +{ + int len, loc; + char *str; + + len = (int) strlen(s); + if (stable->nextFree + len + 1 >= stable->size) { + assert(stable->size < 1000000); + str = (char *) malloc(stable->size*2); + memcpy(str, stable->strings, stable->size); + free(stable->strings); + stable->strings = str; + } + loc = stable->nextFree; + strcpy(&stable->strings[loc], s); + stable->nextFree += len + 1; + return loc; +} // AddString + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////// Hash table: /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +#define INIT_HASH_TABLE_SIZE 2047 +#define HASH_TABLE_MAX_COLLISIONS 3 + +typedef struct HashEntry_Rec { + int index; // String table offset of string representation + int value; // Atom (symbol) value +} HashEntry; + +typedef struct HashTable_Rec { + HashEntry *entry; + int size; + int entries; + int counts[HASH_TABLE_MAX_COLLISIONS + 1]; +} HashTable; + +/* + * InitHashTable() - Initialize the hash table. + * + */ + +static int InitHashTable(HashTable *htable, int fsize) +{ + int ii; + + htable->entry = (HashEntry *) malloc(sizeof(HashEntry)*fsize); + if (!htable->entry) + return 0; + htable->size = fsize; + for (ii = 0; ii < fsize; ii++) { + htable->entry[ii].index = 0; + htable->entry[ii].value = 0; + } + htable->entries = 0; + for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++) + htable->counts[ii] = 0; + return 1; +} // InitHashTable + +/* + * FreeHashTable() - Free the hash table. + * + */ + +static void FreeHashTable(HashTable *htable) +{ + if (htable->entry) + free(htable->entry); + htable->entry = NULL; + htable->size = 0; + htable->entries = 0; +} // FreeHashTable + +/* + * Empty() - See if a hash table entry is empty. + * + */ + +static int Empty(HashTable *htable, int hashloc) +{ + assert(hashloc >= 0 && hashloc < htable->size); + if (htable->entry[hashloc].index == 0) { + return 1; + } else { + return 0; + } +} // Empty + +/* + * Match() - See if a hash table entry is matches a string. + * + */ + +static int Match(HashTable *htable, StringTable *stable, const char *s, int hashloc) +{ + int strloc; + + strloc = htable->entry[hashloc].index; + if (!strcmp(s, &stable->strings[strloc])) { + return 1; + } else { + return 0; + } +} // Match + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////// Atom table: /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +#define INIT_ATOM_TABLE_SIZE 1024 + + +struct AtomTable_Rec { + StringTable stable; // String table. + HashTable htable; // Hashes string to atom number and token value. Multiple strings can + // have the same token value but each unique string is a unique atom. + int *amap; // Maps atom value to offset in string table. Atoms all map to unique + // strings except for some undefined values in the lower, fixed part + // of the atom table that map to "". The lowest 256 atoms + // correspond to single character ASCII values except for alphanumeric + // characters and '_', which can be other tokens. Next come the + // language tokens with their atom values equal to the token value. + // Then come predefined atoms, followed by user specified identifiers. + int *arev; // Reversed atom for symbol table use. + int nextFree; + int size; +}; + +static AtomTable latable = { { 0 } }; +AtomTable *atable = &latable; + +static int AddAtomFixed(AtomTable *atable, const char *s, int atom); + +/* + * GrowAtomTable() - Grow the atom table to at least "size" if it's smaller. + * + */ + +static int GrowAtomTable(AtomTable *atable, int size) +{ + int *newmap, *newrev; + + if (atable->size < size) { + if (atable->amap) { + newmap = realloc(atable->amap, sizeof(int)*size); + newrev = realloc(atable->arev, sizeof(int)*size); + } else { + newmap = malloc(sizeof(int)*size); + newrev = malloc(sizeof(int)*size); + atable->size = 0; + } + if (!newmap || !newrev) { + /* failed to grow -- error */ + if (newmap) + atable->amap = newmap; + if (newrev) + atable->amap = newrev; + return -1; + } + memset(&newmap[atable->size], 0, (size - atable->size) * sizeof(int)); + memset(&newrev[atable->size], 0, (size - atable->size) * sizeof(int)); + atable->amap = newmap; + atable->arev = newrev; + atable->size = size; + } + return 0; +} // GrowAtomTable + +/* + * lReverse() - Reverse the bottom 20 bits of a 32 bit int. + * + */ + +static int lReverse(int fval) +{ + unsigned int in = fval; + int result = 0, cnt = 0; + + while(in) { + result <<= 1; + result |= in&1; + in >>= 1; + cnt++; + } + + // Don't use all 31 bits. One million atoms is plenty and sometimes the + // upper bits are used for other things. + + if (cnt < 20) + result <<= 20 - cnt; + return result; +} // lReverse + +/* + * AllocateAtom() - Allocate a new atom. Associated with the "undefined" value of -1. + * + */ + +static int AllocateAtom(AtomTable *atable) +{ + if (atable->nextFree >= atable->size) + GrowAtomTable(atable, atable->nextFree*2); + atable->amap[atable->nextFree] = -1; + atable->arev[atable->nextFree] = lReverse(atable->nextFree); + atable->nextFree++; + return atable->nextFree - 1; +} // AllocateAtom + +/* + * SetAtomValue() - Allocate a new atom associated with "hashindex". + * + */ + +static void SetAtomValue(AtomTable *atable, int atomnumber, int hashindex) +{ + atable->amap[atomnumber] = atable->htable.entry[hashindex].index; + atable->htable.entry[hashindex].value = atomnumber; +} // SetAtomValue + +/* + * FindHashLoc() - Find the hash location for this string. Return -1 it hash table is full. + * + */ + +static int FindHashLoc(AtomTable *atable, const char *s) +{ + int hashloc, hashdelta, count; + int FoundEmptySlot = 0; + int collision[HASH_TABLE_MAX_COLLISIONS + 1]; + + hashloc = HashString(s) % atable->htable.size; + if (!Empty(&atable->htable, hashloc)) { + if (Match(&atable->htable, &atable->stable, s, hashloc)) + return hashloc; + collision[0] = hashloc; + hashdelta = HashString2(s); + count = 0; + while (count < HASH_TABLE_MAX_COLLISIONS) { + hashloc = ((hashloc + hashdelta) & 0x7fffffff) % atable->htable.size; + if (!Empty(&atable->htable, hashloc)) { + if (Match(&atable->htable, &atable->stable, s, hashloc)) { + return hashloc; + } + } else { + FoundEmptySlot = 1; + break; + } + count++; + collision[count] = hashloc; + } + + if (!FoundEmptySlot) { + if (cpp->options.DumpAtomTable) { + int ii; + char str[200]; + sprintf(str, "*** Hash failed with more than %d collisions. Must increase hash table size. ***", + HASH_TABLE_MAX_COLLISIONS); + CPPShInfoLogMsg(str); + + sprintf(str, "*** New string \"%s\", hash=%04x, delta=%04x", s, collision[0], hashdelta); + CPPShInfoLogMsg(str); + for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++) { + sprintf(str, "*** Collides on try %d at hash entry %04x with \"%s\"", + ii + 1, collision[ii], GetAtomString(atable, atable->htable.entry[collision[ii]].value)); + CPPShInfoLogMsg(str); + } + } + return -1; + } else { + atable->htable.counts[count]++; + } + } + return hashloc; +} // FindHashLoc + +/* + * IncreaseHashTableSize() + * + */ + +static int IncreaseHashTableSize(AtomTable *atable) +{ + int ii, strloc, oldhashloc, value, size; + AtomTable oldtable; + char *s; + + // Save the old atom table and create a new one: + + oldtable = *atable; + size = oldtable.htable.size*2 + 1; + if (!InitAtomTable(atable, size)) + return 0; + + // Add all the existing values to the new atom table preserving their atom values: + + for (ii = atable->nextFree; ii < oldtable.nextFree; ii++) { + strloc = oldtable.amap[ii]; + s = &oldtable.stable.strings[strloc]; + oldhashloc = FindHashLoc(&oldtable, s); + assert(oldhashloc >= 0); + value = oldtable.htable.entry[oldhashloc].value; + AddAtomFixed(atable, s, value); + } + FreeAtomTable(&oldtable); + return 1; +} // IncreaseHashTableSize + +/* + * LookUpAddStringHash() - Lookup a string in the hash table. If it's not there, add it and + * initialize the atom value in the hash table to 0. Return the hash table index. + */ + +static int LookUpAddStringHash(AtomTable *atable, const char *s) +{ + int hashloc, strloc; + + while(1) { + hashloc = FindHashLoc(atable, s); + if (hashloc >= 0) + break; + IncreaseHashTableSize(atable); + } + + if (Empty(&atable->htable, hashloc)) { + atable->htable.entries++; + strloc = AddString(&atable->stable, s); + atable->htable.entry[hashloc].index = strloc; + atable->htable.entry[hashloc].value = 0; + } + return hashloc; +} // LookUpAddStringHash + +/* + * LookUpAddString() - Lookup a string in the hash table. If it's not there, add it and + * initialize the atom value in the hash table to the next atom number. + * Return the atom value of string. + */ + +int LookUpAddString(AtomTable *atable, const char *s) +{ + int hashindex, atom; + + hashindex = LookUpAddStringHash(atable, s); + atom = atable->htable.entry[hashindex].value; + if (atom == 0) { + atom = AllocateAtom(atable); + SetAtomValue(atable, atom, hashindex); + } + return atom; +} // LookUpAddString + +/* + * GetAtomString() + * + */ + +const char *GetAtomString(AtomTable *atable, int atom) +{ + int soffset; + + if (atom > 0 && atom < atable->nextFree) { + soffset = atable->amap[atom]; + if (soffset > 0 && soffset < atable->stable.nextFree) { + return &atable->stable.strings[soffset]; + } else { + return ""; + } + } else { + if (atom == 0) { + return ""; + } else { + if (atom == EOF) { + return ""; + } else { + return ""; + } + } + } +} // GetAtomString + +/* + * GetReversedAtom() + * + */ + +int GetReversedAtom(AtomTable *atable, int atom) +{ + if (atom > 0 && atom < atable->nextFree) { + return atable->arev[atom]; + } else { + return 0; + } +} // GetReversedAtom + +/* + * AddAtom() - Add a string to the atom, hash and string tables if it isn't already there. + * Return it's atom index. + */ + +int AddAtom(AtomTable *atable, const char *s) +{ + int atom; + + atom = LookUpAddString(atable, s); + return atom; +} // AddAtom + +/* + * AddAtomFixed() - Add an atom to the hash and string tables if it isn't already there. + * Assign it the atom value of "atom". + */ + +static int AddAtomFixed(AtomTable *atable, const char *s, int atom) +{ + int hashindex, lsize; + + hashindex = LookUpAddStringHash(atable, s); + if (atable->nextFree >= atable->size || atom >= atable->size) { + lsize = atable->size*2; + if (lsize <= atom) + lsize = atom + 1; + GrowAtomTable(atable, lsize); + } + atable->amap[atom] = atable->htable.entry[hashindex].index; + atable->htable.entry[hashindex].value = atom; + //if (atom >= atable->nextFree) + // atable->nextFree = atom + 1; + while (atom >= atable->nextFree) { + atable->arev[atable->nextFree] = lReverse(atable->nextFree); + atable->nextFree++; + } + return atom; +} // AddAtomFixed + +/* + * InitAtomTable() - Initialize the atom table. + * + */ + +int InitAtomTable(AtomTable *atable, int htsize) +{ + int ii; + + htsize = htsize <= 0 ? INIT_HASH_TABLE_SIZE : htsize; + if (!InitStringTable(&atable->stable)) + return 0; + if (!InitHashTable(&atable->htable, htsize)) + return 0; + + atable->nextFree = 0; + atable->amap = NULL; + atable->size = 0; + GrowAtomTable(atable, INIT_ATOM_TABLE_SIZE); + if (!atable->amap) + return 0; + + // Initialize lower part of atom table to "" atom: + + AddAtomFixed(atable, "", 0); + for (ii = 0; ii < FIRST_USER_TOKEN_SY; ii++) + atable->amap[ii] = atable->amap[0]; + + // Add single character tokens to the atom table: + + { + const char *s = "~!%^&*()-+=|,.<>/?;:[]{}#"; + char t[2]; + + t[1] = '\0'; + while (*s) { + t[0] = *s; + AddAtomFixed(atable, t, s[0]); + s++; + } + } + + // Add multiple character scanner tokens : + + for (ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++) + AddAtomFixed(atable, tokens[ii].str, tokens[ii].val); + + // Add error symbol if running in error mode: + + if (cpp->options.ErrorMode) + AddAtomFixed(atable, "error", ERROR_SY); + + AddAtom(atable, "<*** end fixed atoms ***>"); + + return 1; +} // InitAtomTable + +/////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////// Debug Printing Functions: ////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +/* + * PrintAtomTable() + * + */ + +void PrintAtomTable(AtomTable *atable) +{ + int ii; + char str[200]; + + for (ii = 0; ii < atable->nextFree; ii++) { + sprintf(str, "%d: \"%s\"", ii, &atable->stable.strings[atable->amap[ii]]); + CPPDebugLogMsg(str); + } + sprintf(str, "Hash table: size=%d, entries=%d, collisions=", + atable->htable.size, atable->htable.entries); + CPPDebugLogMsg(str); + for (ii = 0; ii < HASH_TABLE_MAX_COLLISIONS; ii++) { + sprintf(str, " %d", atable->htable.counts[ii]); + CPPDebugLogMsg(str); + } + +} // PrintAtomTable + + +/* + * GetStringOfAtom() + * + */ + +char* GetStringOfAtom(AtomTable *atable, int atom) +{ + char* chr_str; + chr_str=&atable->stable.strings[atable->amap[atom]]; + return chr_str; +} // GetStringOfAtom + +/* + * FreeAtomTable() - Free the atom table and associated memory + * + */ + +void FreeAtomTable(AtomTable *atable) +{ + FreeStringTable(&atable->stable); + FreeHashTable(&atable->htable); + if (atable->amap) + free(atable->amap); + if (atable->arev) + free(atable->arev); + atable->amap = NULL; + atable->arev = NULL; + atable->nextFree = 0; + atable->size = 0; +} // FreeAtomTable + +/////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////// End of atom.c /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + diff --git a/glslang/MachineIndependent/preprocessor/atom.h b/glslang/MachineIndependent/preprocessor/atom.h new file mode 100644 index 0000000..6d8898d --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/atom.h @@ -0,0 +1,96 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// atom.h +// + +#if !defined(__ATOM_H) +#define __ATOM_H 1 + +typedef struct AtomTable_Rec AtomTable; + +extern AtomTable *atable; + +int InitAtomTable(AtomTable *atable, int htsize); +void FreeAtomTable(AtomTable *atable); +int AddAtom(AtomTable *atable, const char *s); +void PrintAtomTable(AtomTable *atable); +int LookUpAddString(AtomTable *atable, const char *s); +const char *GetAtomString(AtomTable *atable, int atom); +int GetReversedAtom(AtomTable *atable, int atom); +char* GetStringOfAtom(AtomTable *atable, int atom); +#endif // !defined(__ATOM_H) diff --git a/glslang/MachineIndependent/preprocessor/compile.h b/glslang/MachineIndependent/preprocessor/compile.h new file mode 100644 index 0000000..08a9280 --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/compile.h @@ -0,0 +1,132 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// compile.h +// + +#if !defined(__COMPILE_H) +#define __COMPILE_H 1 + +int InitCPPStruct(void); + +typedef struct Options_Rec{ + const char *profileString; + int ErrorMode; + int Quiet; + + // Debug The Compiler options: + int DumpAtomTable; +} Options; + +struct CPPStruct_Rec { + // Public members + SourceLoc *pLastSourceLoc; // Set at the start of each statement by the tree walkers + Options options; // Compile options and parameters + + // Private members + SourceLoc lastSourceLoc; + + // Scanner data: + + SourceLoc *tokenLoc; // Source location of most recent token seen by the scanner + int mostRecentToken; // Most recent token seen by the scanner + InputSrc *currentInput; + int previous_token; + int notAVersionToken; // used to make sure that #version is the first token seen in the file, if present + + void *pC; // storing the parseContext of the compile object in cpp. + + // Private members: + SourceLoc ltokenLoc; + int ifdepth; //current #if-#else-#endif nesting in the cpp.c file (pre-processor) + int elsedepth[64]; //Keep a track of #if depth..Max allowed is 64. + int elsetracker; //#if-#else and #endif constructs...Counter. + const char *ErrMsg; + int CompileError; //Indicate compile error when #error, #else,#elif mismatch. + + // + // Globals used to communicate between PaParseStrings() and yy_input()and + // also across the files.(gen_glslang.cpp and scanner.c) + // + int PaWhichStr; // which string we're parsing + int* PaStrLen; // array of lengths of the PaArgv strings + int PaArgc; // count of strings in the array + char** PaArgv; // our array of strings to parse + unsigned int tokensBeforeEOF : 1; +}; + +#endif // !defined(__COMPILE_H) diff --git a/glslang/MachineIndependent/preprocessor/cpp.c b/glslang/MachineIndependent/preprocessor/cpp.c new file mode 100644 index 0000000..221f1a8 --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/cpp.c @@ -0,0 +1,1037 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// cpp.c +// + +#include +#include +#include +#include +#include + +#include "slglobals.h" + +static int CPPif(yystypepp * yylvalpp); + +/* Don't use memory.c's replacements, as we clean up properly here */ +#undef malloc +#undef free + +static int bindAtom = 0; +static int constAtom = 0; +static int defaultAtom = 0; +static int defineAtom = 0; +static int definedAtom = 0; +static int elseAtom = 0; +static int elifAtom = 0; +static int endifAtom = 0; +static int ifAtom = 0; +static int ifdefAtom = 0; +static int ifndefAtom = 0; +static int includeAtom = 0; +static int lineAtom = 0; +static int pragmaAtom = 0; +static int texunitAtom = 0; +static int undefAtom = 0; +static int errorAtom = 0; +static int __LINE__Atom = 0; +static int __FILE__Atom = 0; +static int __VERSION__Atom = 0; +static int versionAtom = 0; +static int extensionAtom = 0; + +static Scope *macros = 0; +#define MAX_MACRO_ARGS 64 +#define MAX_IF_NESTING 64 + +static SourceLoc ifloc; /* outermost #if */ + +int InitCPP(void) +{ + char buffer[64], *t; + const char *f; + // Add various atoms needed by the CPP line scanner: + bindAtom = LookUpAddString(atable, "bind"); + constAtom = LookUpAddString(atable, "const"); + defaultAtom = LookUpAddString(atable, "default"); + defineAtom = LookUpAddString(atable, "define"); + definedAtom = LookUpAddString(atable, "defined"); + elifAtom = LookUpAddString(atable, "elif"); + elseAtom = LookUpAddString(atable, "else"); + endifAtom = LookUpAddString(atable, "endif"); + ifAtom = LookUpAddString(atable, "if"); + ifdefAtom = LookUpAddString(atable, "ifdef"); + ifndefAtom = LookUpAddString(atable, "ifndef"); + includeAtom = LookUpAddString(atable, "include"); + lineAtom = LookUpAddString(atable, "line"); + pragmaAtom = LookUpAddString(atable, "pragma"); + texunitAtom = LookUpAddString(atable, "texunit"); + undefAtom = LookUpAddString(atable, "undef"); + errorAtom = LookUpAddString(atable, "error"); + __LINE__Atom = LookUpAddString(atable, "__LINE__"); + __FILE__Atom = LookUpAddString(atable, "__FILE__"); + __VERSION__Atom = LookUpAddString(atable, "__VERSION__"); + versionAtom = LookUpAddString(atable, "version"); + extensionAtom = LookUpAddString(atable, "extension"); + macros = NewScopeInPool(mem_CreatePool(0, 0)); + strcpy(buffer, "PROFILE_"); + t = buffer + strlen(buffer); + f = cpp->options.profileString; + while ((isalnum(*f) || *f == '_') && t < buffer + sizeof(buffer) - 1) + *t++ = toupper(*f++); + *t = 0; + return 1; +} // InitCPP + +int FreeCPP(void) +{ + if (macros) + { + mem_FreePool(macros->pool); + macros = 0; + } + + return 1; +} + +int FinalCPP(void) +{ + if (cpp->ifdepth) + CPPErrorToInfoLog("#if mismatch"); + return 1; +} + +static int CPPdefine(yystypepp * yylvalpp) +{ + int token, name, args[MAX_MACRO_ARGS], argc; + const char *message; + MacroSymbol mac; + Symbol *symb; + SourceLoc dummyLoc; + memset(&mac, 0, sizeof(mac)); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != CPP_IDENTIFIER) { + CPPErrorToInfoLog("#define"); + return token; + } + name = yylvalpp->sc_ident; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token == '(' && !yylvalpp->sc_int) { + // gather arguments + argc = 0; + do { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (argc == 0 && token == ')') break; + if (token != CPP_IDENTIFIER) { + CPPErrorToInfoLog("#define"); + return token; + } + if (argc < MAX_MACRO_ARGS) + args[argc++] = yylvalpp->sc_ident; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } while (token == ','); + if (token != ')') { + CPPErrorToInfoLog("#define"); + return token; + } + mac.argc = argc; + mac.args = mem_Alloc(macros->pool, argc * sizeof(int)); + memcpy(mac.args, args, argc * sizeof(int)); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + mac.body = NewTokenStream(GetAtomString(atable, name), macros->pool); + while (token != '\n') { + while (token == '\\') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token == '\n') + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + else + RecordToken(mac.body, '\\', yylvalpp); + } + RecordToken(mac.body, token, yylvalpp); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + }; + + symb = LookUpSymbol(macros, name); + if (symb) { + if (!symb->details.mac.undef) { + // already defined -- need to make sure they are identical + if (symb->details.mac.argc != mac.argc) goto error; + for (argc=0; argc < mac.argc; argc++) + if (symb->details.mac.args[argc] != mac.args[argc]) + goto error; + RewindTokenStream(symb->details.mac.body); + RewindTokenStream(mac.body); + do { + int old_lval, old_token; + old_token = ReadToken(symb->details.mac.body, yylvalpp); + old_lval = yylvalpp->sc_int; + token = ReadToken(mac.body, yylvalpp); + if (token != old_token || yylvalpp->sc_int != old_lval) { + error: + StoreStr("Macro Redefined"); + StoreStr(GetStringOfAtom(atable,name)); + message=GetStrfromTStr(); + DecLineNumber(); + CPPShInfoLogMsg(message); + IncLineNumber(); + ResetTString(); + break; } + } while (token > 0); + } + //FreeMacro(&symb->details.mac); + } else { + dummyLoc.file = 0; + dummyLoc.line = 0; + symb = AddSymbol(&dummyLoc, macros, name, MACRO_S); + } + symb->details.mac = mac; + return '\n'; +} // CPPdefine + +static int CPPundef(yystypepp * yylvalpp) +{ + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + Symbol *symb; + if(token == '\n'){ + CPPErrorToInfoLog("#undef"); + return token; + } + if (token != CPP_IDENTIFIER) + goto error; + symb = LookUpSymbol(macros, yylvalpp->sc_ident); + if (symb) { + symb->details.mac.undef = 1; + } + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '\n') { + error: + CPPErrorToInfoLog("#undef"); + } + return token; +} // CPPundef + +/* CPPelse -- skip forward to appropriate spot. This is actually used +** to skip to and #endif after seeing an #else, AND to skip to a #else, +** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false +*/ + +static int CPPelse(int matchelse, yystypepp * yylvalpp) +{ + int atom,depth=0; + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + while (token > 0) { + if (token != '#') { + while (token != '\n') + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + continue; + } + if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER) + continue; + atom = yylvalpp->sc_ident; + if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){ + depth++; cpp->ifdepth++; cpp->elsetracker++; + } + else if (atom == endifAtom) { + if(--depth<=0){ + cpp->elsedepth[cpp->elsetracker]=0; + --cpp->elsetracker; + if (cpp->ifdepth) + --cpp->ifdepth; + break; + } + --cpp->elsetracker; + --cpp->ifdepth; + } + else if (((int)(matchelse) != 0)&& depth==0) { + if (atom == elseAtom ) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '\n') { + CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline"); + while (token != '\n') + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + break; + } + else if (atom == elifAtom) { + /* we decrement cpp->ifdepth here, because CPPif will increment + * it and we really want to leave it alone */ + if (cpp->ifdepth){ + --cpp->ifdepth; + --cpp->elsetracker; + } + return CPPif(yylvalpp); + } + } + else if((atom==elseAtom) && (!ChkCorrectElseNesting())){ + CPPErrorToInfoLog("#else after a #else"); + cpp->CompileError=1; + } + }; + return token; +} + +enum eval_prec { + MIN_PREC, + COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY, + MAX_PREC +}; + +static int op_logor(int a, int b) { return a || b; } +static int op_logand(int a, int b) { return a && b; } +static int op_or(int a, int b) { return a | b; } +static int op_xor(int a, int b) { return a ^ b; } +static int op_and(int a, int b) { return a & b; } +static int op_eq(int a, int b) { return a == b; } +static int op_ne(int a, int b) { return a != b; } +static int op_ge(int a, int b) { return a >= b; } +static int op_le(int a, int b) { return a <= b; } +static int op_gt(int a, int b) { return a > b; } +static int op_lt(int a, int b) { return a < b; } +static int op_shl(int a, int b) { return a << b; } +static int op_shr(int a, int b) { return a >> b; } +static int op_add(int a, int b) { return a + b; } +static int op_sub(int a, int b) { return a - b; } +static int op_mul(int a, int b) { return a * b; } +static int op_div(int a, int b) { return a / b; } +static int op_mod(int a, int b) { return a % b; } +static int op_pos(int a) { return a; } +static int op_neg(int a) { return -a; } +static int op_cmpl(int a) { return ~a; } +static int op_not(int a) { return !a; } + +struct { + int token, prec, (*op)(int, int); +} binop[] = { + { CPP_OR_OP, LOGOR, op_logor }, + { CPP_AND_OP, LOGAND, op_logand }, + { '|', OR, op_or }, + { '^', XOR, op_xor }, + { '&', AND, op_and }, + { CPP_EQ_OP, EQUAL, op_eq }, + { CPP_NE_OP, EQUAL, op_ne }, + { '>', RELATION, op_gt }, + { CPP_GE_OP, RELATION, op_ge }, + { '<', RELATION, op_lt }, + { CPP_LE_OP, RELATION, op_le }, + { CPP_LEFT_OP, SHIFT, op_shl }, + { CPP_RIGHT_OP, SHIFT, op_shr }, + { '+', ADD, op_add }, + { '-', ADD, op_sub }, + { '*', MUL, op_mul }, + { '/', MUL, op_div }, + { '%', MUL, op_mod }, +}; + +struct { + int token, (*op)(int); +} unop[] = { + { '+', op_pos }, + { '-', op_neg }, + { '~', op_cmpl }, + { '!', op_not }, +}; + +#define ALEN(A) (sizeof(A)/sizeof(A[0])) + +static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp) +{ + int i, val; + Symbol *s; + if (token == CPP_IDENTIFIER) { + if (yylvalpp->sc_ident == definedAtom) { + int needclose = 0; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token == '(') { + needclose = 1; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + if (token != CPP_IDENTIFIER) + goto error; + *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident)) + ? !s->details.mac.undef : 0; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (needclose) { + if (token != ')') + goto error; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + } else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + return eval(token, prec, res, err, yylvalpp); + } else { + goto error; + } + } else if (token == CPP_INTCONSTANT) { + *res = yylvalpp->sc_int; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } else if (token == '(') { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + token = eval(token, MIN_PREC, res, err, yylvalpp); + if (!*err) { + if (token != ')') + goto error; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + } else { + for (i = ALEN(unop) - 1; i >= 0; i--) { + if (unop[i].token == token) + break; + } + if (i >= 0) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + token = eval(token, UNARY, res, err, yylvalpp); + *res = unop[i].op(*res); + } else { + goto error; + } + } + while (!*err) { + if (token == ')' || token == '\n') break; + for (i = ALEN(binop) - 1; i >= 0; i--) { + if (binop[i].token == token) + break; + } + if (i < 0 || binop[i].prec <= prec) + break; + val = *res; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + token = eval(token, binop[i].prec, res, err, yylvalpp); + *res = binop[i].op(val, *res); + } + return token; +error: + CPPErrorToInfoLog("incorrect preprocessor directive"); + *err = 1; + *res = 0; + return token; +} // eval + +static int CPPif(yystypepp * yylvalpp) { + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + int res = 0, err = 0; + cpp->elsetracker++; + if (!cpp->ifdepth++) + ifloc = *cpp->tokenLoc; + if(cpp->ifdepth >MAX_IF_NESTING){ + CPPErrorToInfoLog("max #if nesting depth exceeded"); + return 0; + } + token = eval(token, MIN_PREC, &res, &err, yylvalpp); + if (token != '\n') { + CPPWarningToInfoLog("unexpected tokens following the preprocessor directive - expected a newline"); + while (token != '\n') + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + if (!res && !err) { + token = CPPelse(1, yylvalpp); + } + + return token; +} // CPPif + +static int CPPifdef(int defined, yystypepp * yylvalpp) +{ + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + int name = yylvalpp->sc_ident; + if(++cpp->ifdepth >MAX_IF_NESTING){ + CPPErrorToInfoLog("max #if nesting depth exceeded"); + return 0; + } + cpp->elsetracker++; + if (token != CPP_IDENTIFIER) { + defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef"); + } else { + Symbol *s = LookUpSymbol(macros, name); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '\n') { + CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline"); + while (token != '\n') + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + if (((s && !s->details.mac.undef) ? 1 : 0) != defined) + token = CPPelse(1, yylvalpp); + } + return token; +} // CPPifdef + +static int CPPline(yystypepp * yylvalpp) +{ + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if(token=='\n'){ + DecLineNumber(); + CPPErrorToInfoLog("#line"); + IncLineNumber(); + return token; + } + else if (token == CPP_INTCONSTANT) { + yylvalpp->sc_int=atoi(yylvalpp->symbol_name); + SetLineNumber(yylvalpp->sc_int); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + if (token == CPP_INTCONSTANT) { + yylvalpp->sc_int=atoi(yylvalpp->symbol_name); + SetStringNumber(yylvalpp->sc_int); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if(token!='\n') + CPPErrorToInfoLog("#line"); + } + else if (token == '\n'){ + return token; + } + else{ + CPPErrorToInfoLog("#line"); + } + } + else{ + CPPErrorToInfoLog("#line"); + } + return token; +} + +static int CPPerror(yystypepp * yylvalpp) { + + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + const char *message; + + while (token != '\n') { + if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){ + StoreStr(yylvalpp->symbol_name); + }else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){ + StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident)); + }else { + StoreStr(GetStringOfAtom(atable,token)); + } + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + DecLineNumber(); + //store this msg into the shader's information log..set the Compile Error flag!!!! + message=GetStrfromTStr(); + CPPShInfoLogMsg(message); + ResetTString(); + cpp->CompileError=1; + IncLineNumber(); + return '\n'; +}//CPPerror + +static int CPPpragma(yystypepp * yylvalpp) +{ + char SrcStrName[2]; + char** allTokens; + int tokenCount = 0; + int maxTokenCount = 10; + const char* SrcStr; + int i; + + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + if (token=='\n') { + DecLineNumber(); + CPPErrorToInfoLog("#pragma"); + IncLineNumber(); + return token; + } + + allTokens = (char**)malloc(sizeof(char*) * maxTokenCount); + + while (token != '\n') { + if (tokenCount >= maxTokenCount) { + maxTokenCount *= 2; + allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount); + } + switch (token) { + case CPP_IDENTIFIER: + SrcStr = GetAtomString(atable, yylvalpp->sc_ident); + allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); + strcpy(allTokens[tokenCount++], SrcStr); + break; + case CPP_INTCONSTANT: + SrcStr = yylvalpp->symbol_name; + allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); + strcpy(allTokens[tokenCount++], SrcStr); + break; + case CPP_FLOATCONSTANT: + SrcStr = yylvalpp->symbol_name; + allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); + strcpy(allTokens[tokenCount++], SrcStr); + break; + case -1: + // EOF + CPPShInfoLogMsg("#pragma directive must end with a newline"); + return token; + default: + SrcStrName[0] = token; + SrcStrName[1] = '\0'; + allTokens[tokenCount] = (char*)malloc(2); + strcpy(allTokens[tokenCount++], SrcStrName); + } + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + + cpp->currentInput->ungetch(cpp->currentInput, token, yylvalpp); + HandlePragma((const char**)allTokens, tokenCount); + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + for (i = 0; i < tokenCount; ++i) { + free (allTokens[i]); + } + free (allTokens); + + return token; +} // CPPpragma + +#define GL2_VERSION_NUMBER 110 + +static int CPPversion(yystypepp * yylvalpp) +{ + + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + if (cpp->notAVersionToken == 1) + CPPShInfoLogMsg("#version must occur before any other statement in the program"); + + if(token=='\n'){ + DecLineNumber(); + CPPErrorToInfoLog("#version"); + IncLineNumber(); + return token; + } + if (token != CPP_INTCONSTANT) + CPPErrorToInfoLog("#version"); + + yylvalpp->sc_int=atoi(yylvalpp->symbol_name); + //SetVersionNumber(yylvalpp->sc_int); + + if (yylvalpp->sc_int != GL2_VERSION_NUMBER) + CPPShInfoLogMsg("Version number not supported by GL2"); + + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + + if (token == '\n'){ + return token; + } + else{ + CPPErrorToInfoLog("#version"); + } + return token; +} // CPPversion + +static int CPPextension(yystypepp * yylvalpp) +{ + + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + char extensionName[80]; + + if(token=='\n'){ + DecLineNumber(); + CPPShInfoLogMsg("extension name not specified"); + IncLineNumber(); + return token; + } + + if (token != CPP_IDENTIFIER) + CPPErrorToInfoLog("#extension"); + + strcpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident)); + + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != ':') { + CPPShInfoLogMsg("':' missing after extension name"); + return token; + } + + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != CPP_IDENTIFIER) { + CPPShInfoLogMsg("behavior for extension not specified"); + return token; + } + + updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident)); + + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token == '\n'){ + return token; + } + else{ + CPPErrorToInfoLog("#extension"); + } + return token; +} // CPPextension + +int readCPPline(yystypepp * yylvalpp) +{ + int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + const char *message; + int isVersion = 0; + + if (token == CPP_IDENTIFIER) { + if (yylvalpp->sc_ident == defineAtom) { + token = CPPdefine(yylvalpp); + } else if (yylvalpp->sc_ident == elseAtom) { + if(ChkCorrectElseNesting()){ + if (!cpp->ifdepth ){ + CPPErrorToInfoLog("#else mismatch"); + cpp->CompileError=1; + } + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '\n') { + CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline"); + while (token != '\n') + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + token = CPPelse(0, yylvalpp); + }else{ + CPPErrorToInfoLog("#else after a #else"); + cpp->ifdepth=0; + cpp->notAVersionToken = 1; + return 0; + } + } else if (yylvalpp->sc_ident == elifAtom) { + if (!cpp->ifdepth){ + CPPErrorToInfoLog("#elif mismatch"); + cpp->CompileError=1; + } + // this token is really a dont care, but we still need to eat the tokens + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + while (token != '\n') + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + token = CPPelse(0, yylvalpp); + } else if (yylvalpp->sc_ident == endifAtom) { + cpp->elsedepth[cpp->elsetracker]=0; + --cpp->elsetracker; + if (!cpp->ifdepth){ + CPPErrorToInfoLog("#endif mismatch"); + cpp->CompileError=1; + } + else + --cpp->ifdepth; + } else if (yylvalpp->sc_ident == ifAtom) { + token = CPPif(yylvalpp); + } else if (yylvalpp->sc_ident == ifdefAtom) { + token = CPPifdef(1, yylvalpp); + } else if (yylvalpp->sc_ident == ifndefAtom) { + token = CPPifdef(0, yylvalpp); + } else if (yylvalpp->sc_ident == lineAtom) { + token = CPPline(yylvalpp); + } else if (yylvalpp->sc_ident == pragmaAtom) { + token = CPPpragma(yylvalpp); + } else if (yylvalpp->sc_ident == undefAtom) { + token = CPPundef(yylvalpp); + } else if (yylvalpp->sc_ident == errorAtom) { + token = CPPerror(yylvalpp); + } else if (yylvalpp->sc_ident == versionAtom) { + token = CPPversion(yylvalpp); + isVersion = 1; + } else if (yylvalpp->sc_ident == extensionAtom) { + token = CPPextension(yylvalpp); + } else { + StoreStr("Invalid Directive"); + StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident)); + message=GetStrfromTStr(); + CPPShInfoLogMsg(message); + ResetTString(); + } + } + while (token != '\n' && token != 0 && token != EOF) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + + cpp->notAVersionToken = !isVersion; + + return token; +} // readCPPline + +void FreeMacro(MacroSymbol *s) { + DeleteTokenStream(s->body); +} + +static int eof_scan(InputSrc *in, yystypepp * yylvalpp) { return -1; } +static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) { } + +static void PushEofSrc() { + InputSrc *in = malloc(sizeof(InputSrc)); + memset(in, 0, sizeof(InputSrc)); + in->scan = eof_scan; + in->getch = eof_scan; + in->ungetch = noop; + in->prev = cpp->currentInput; + cpp->currentInput = in; +} + +static void PopEofSrc() { + if (cpp->currentInput->scan == eof_scan) { + InputSrc *in = cpp->currentInput; + cpp->currentInput = in->prev; + free(in); + } +} + +static TokenStream *PrescanMacroArg(TokenStream *a, yystypepp * yylvalpp) { + int token; + TokenStream *n; + RewindTokenStream(a); + do { + token = ReadToken(a, yylvalpp); + if (token == CPP_IDENTIFIER && LookUpSymbol(macros, yylvalpp->sc_ident)) + break; + } while (token > 0); + if (token <= 0) return a; + n = NewTokenStream("macro arg", 0); + PushEofSrc(); + ReadFromTokenStream(a, 0, 0); + while ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) > 0) { + if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp->sc_ident, yylvalpp)) + continue; + RecordToken(n, token, yylvalpp); + } + PopEofSrc(); + DeleteTokenStream(a); + return n; +} // PrescanMacroArg + +typedef struct MacroInputSrc { + InputSrc base; + MacroSymbol *mac; + TokenStream **args; +} MacroInputSrc; + +/* macro_scan --- +** return the next token for a macro expanion, handling macro args +*/ +static int macro_scan(MacroInputSrc *in, yystypepp * yylvalpp) { + int i; + int token = ReadToken(in->mac->body, yylvalpp); + if (token == CPP_IDENTIFIER) { + for (i = in->mac->argc-1; i>=0; i--) + if (in->mac->args[i] == yylvalpp->sc_ident) break; + if (i >= 0) { + ReadFromTokenStream(in->args[i], yylvalpp->sc_ident, 0); + return cpp->currentInput->scan(cpp->currentInput, yylvalpp); + } + } + if (token > 0) return token; + in->mac->busy = 0; + cpp->currentInput = in->base.prev; + if (in->args) { + for (i=in->mac->argc-1; i>=0; i--) + DeleteTokenStream(in->args[i]); + free(in->args); + } + free(in); + return cpp->currentInput->scan(cpp->currentInput, yylvalpp); +} // macro_scan + +/* MacroExpand +** check an identifier (atom) to see if it a macro that should be expanded. +** If it is, push an InputSrc that will produce the appropriate expansion +** and return TRUE. If not, return FALSE. +*/ + +int MacroExpand(int atom, yystypepp * yylvalpp) +{ + Symbol *sym = LookUpSymbol(macros, atom); + MacroInputSrc *in; + int i,j, token, depth=0; + const char *message; + if (atom == __LINE__Atom) { + yylvalpp->sc_int = GetLineNumber(); + sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int); + UngetToken(CPP_INTCONSTANT, yylvalpp); + return 1; + } + if (atom == __FILE__Atom) { + yylvalpp->sc_int = GetStringNumber(); + sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int); + UngetToken(CPP_INTCONSTANT, yylvalpp); + return 1; + } + if (atom == __VERSION__Atom) { + strcpy(yylvalpp->symbol_name,"100"); + yylvalpp->sc_int = atoi(yylvalpp->symbol_name); + UngetToken(CPP_INTCONSTANT, yylvalpp); + return 1; + } + if (!sym || sym->details.mac.undef) return 0; + if (sym->details.mac.busy) return 0; // no recursive expansions + in = malloc(sizeof(*in)); + memset(in, 0, sizeof(*in)); + in->base.scan = (void *)macro_scan; + in->base.line = cpp->currentInput->line; + in->base.name = cpp->currentInput->name; + in->mac = &sym->details.mac; + if (sym->details.mac.args) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token != '(') { + UngetToken(token, yylvalpp); + yylvalpp->sc_ident = atom; + return 0; + } + in->args = malloc(in->mac->argc * sizeof(TokenStream *)); + for (i=0; imac->argc; i++) + in->args[i] = NewTokenStream("macro arg", 0); + i=0;j=0; + do{ + depth = 0; + while(1) { + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token <= 0) { + StoreStr("EOF in Macro "); + StoreStr(GetStringOfAtom(atable,atom)); + message=GetStrfromTStr(); + CPPShInfoLogMsg(message); + ResetTString(); + return 1; + } + if((in->mac->argc==0) && (token!=')')) break; + if (depth == 0 && (token == ',' || token == ')')) break; + if (token == '(') depth++; + if (token == ')') depth--; + RecordToken(in->args[i], token, yylvalpp); + j=1; + } + if (token == ')') { + if((in->mac->argc==1) &&j==0) + break; + i++; + break; + } + i++; + }while(i < in->mac->argc); + + if (i < in->mac->argc) { + StoreStr("Too few args in Macro "); + StoreStr(GetStringOfAtom(atable,atom)); + message=GetStrfromTStr(); + CPPShInfoLogMsg(message); + ResetTString(); + } else if (token != ')') { + depth=0; + while (token >= 0 && (depth > 0 || token != ')')) { + if (token == ')') depth--; + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); + if (token == '(') depth++; + } + + if (token <= 0) { + StoreStr("EOF in Macro "); + StoreStr(GetStringOfAtom(atable,atom)); + message=GetStrfromTStr(); + CPPShInfoLogMsg(message); + ResetTString(); + return 1; + } + StoreStr("Too many args in Macro "); + StoreStr(GetStringOfAtom(atable,atom)); + message=GetStrfromTStr(); + CPPShInfoLogMsg(message); + ResetTString(); + } + for (i=0; imac->argc; i++) { + in->args[i] = PrescanMacroArg(in->args[i], yylvalpp); + } + } +#if 0 + printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file), + loc.line, GetAtomString(atable, atom)); + for (i=0; imac->argc; i++) { + printf("\targ %s = '", GetAtomString(atable, in->mac->args[i])); + DumpTokenStream(stdout, in->args[i]); + printf("'\n"); + } +#endif + /*retain the input source*/ + in->base.prev = cpp->currentInput; + sym->details.mac.busy = 1; + RewindTokenStream(sym->details.mac.body); + cpp->currentInput = &in->base; + return 1; +} // MacroExpand + +int ChkCorrectElseNesting(void) +{ + if(cpp->elsedepth[cpp->elsetracker]==0){ + cpp->elsedepth[cpp->elsetracker]=1; + return 1; + } + return 0; +} + + diff --git a/glslang/MachineIndependent/preprocessor/cpp.h b/glslang/MachineIndependent/preprocessor/cpp.h new file mode 100644 index 0000000..10ecd12 --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/cpp.h @@ -0,0 +1,119 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// cpp.h +// + +#if !defined(__CPP_H) +#define __CPP_H 1 + +#include "parser.h" +#include "tokens.h" + +int InitCPP(void); +int FinalCPP(void); +int readCPPline(yystypepp * yylvalpp); +int MacroExpand(int atom, yystypepp * yylvalpp); +int ChkCorrectElseNesting(void); + +typedef struct MacroSymbol { + int argc; + int *args; + TokenStream *body; + unsigned busy:1; + unsigned undef:1; +} MacroSymbol; + +void FreeMacro(MacroSymbol *); +int PredefineMacro(char *); + +void CPPDebugLogMsg(const char *msg); // Prints information into debug log +void CPPShInfoLogMsg(const char*); // Store cpp Err Msg into Sh.Info.Log +void CPPWarningToInfoLog(const char *msg); // Prints warning messages into info log +void HandlePragma(const char**, int numTokens); // #pragma directive container. +void ResetTString(void); // #error Message as TString. +void CPPErrorToInfoLog(char*); // Stick all cpp errors into Sh.Info.log . +void StoreStr(char*); // Store the TString in Parse Context. +void SetLineNumber(int); // Set line number. +void SetStringNumber(int); // Set string number. +int GetLineNumber(void); // Get the current String Number. +int GetStringNumber(void); // Get the current String Number. +const char* GetStrfromTStr(void); // Convert TString to String. +void updateExtensionBehavior(const char* extName, const char* behavior); +int FreeCPP(void); + +#endif // !(defined(__CPP_H) diff --git a/glslang/MachineIndependent/preprocessor/cppstruct.c b/glslang/MachineIndependent/preprocessor/cppstruct.c new file mode 100644 index 0000000..b1b15fa --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/cppstruct.c @@ -0,0 +1,185 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// cppstruct.c +// + +#include +#include + +#include "slglobals.h" + +CPPStruct *cpp = NULL; +static int refCount = 0; + +int InitPreprocessor(void); +int ResetPreprocessor(void); +int FreeCPPStruct(void); +int FinalizePreprocessor(void); + +/* + * InitCPPStruct() - Initilaize the CPP structure. + * + */ + +int InitCPPStruct(void) +{ + int len; + char *p; + + cpp = (CPPStruct *) malloc(sizeof(CPPStruct)); + if (cpp == NULL) + return 0; + + refCount++; + + // Initialize public members: + cpp->pLastSourceLoc = &cpp->lastSourceLoc; + + p = (char *) &cpp->options; + len = sizeof(cpp->options); + while (--len >= 0) + p[len] = 0; + + ResetPreprocessor(); + return 1; +} // InitCPPStruct + +int ResetPreprocessor(void) +{ + // Initialize private members: + + cpp->lastSourceLoc.file = 0; + cpp->lastSourceLoc.line = 0; + cpp->pC=0; + cpp->CompileError=0; + cpp->ifdepth=0; + for(cpp->elsetracker=0; cpp->elsetracker<64; cpp->elsetracker++) + cpp->elsedepth[cpp->elsetracker]=0; + cpp->elsetracker=0; + cpp->tokensBeforeEOF = 0; + return 1; +} + +//Intializing the Preprocessor. + +int InitPreprocessor(void) +{ + # define CPP_STUFF true + # ifdef CPP_STUFF + FreeCPPStruct(); + InitCPPStruct(); + cpp->options.Quiet = 1; + cpp->options.profileString = "generic"; + if (!InitAtomTable(atable, 0)) + return 1; + if (!InitScanner(cpp)) + return 1; + # endif + return 0; +} + +//FreeCPPStruct() - Free the CPP structure. + +int FreeCPPStruct(void) +{ + if (refCount) + { + free(cpp); + refCount--; + } + + return 1; +} + +//Finalizing the Preprocessor. + +int FinalizePreprocessor(void) +{ + # define CPP_STUFF true + # ifdef CPP_STUFF + FreeAtomTable(atable); + FreeCPPStruct(); + FreeScanner(); + # endif + return 0; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////// End of cppstruct.c ////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/glslang/MachineIndependent/preprocessor/memory.c b/glslang/MachineIndependent/preprocessor/memory.c new file mode 100644 index 0000000..74e20ff --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/memory.c @@ -0,0 +1,191 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +#include +#include +#include + +#ifdef __STDC99__ +#include +#elif defined (_WIN64) +typedef unsigned __int64 uintptr_t; +#else +typedef unsigned int uintptr_t; +#endif + +#include "memory.h" + +// default alignment and chunksize, if called with 0 arguments +#define CHUNKSIZE (64*1024) +#define ALIGN 8 + +// we need to call the `real' malloc and free, not our replacements +#undef malloc +#undef free + +struct chunk { + struct chunk *next; +}; + +struct cleanup { + struct cleanup *next; + void (*fn)(void *); + void *arg; +}; + +struct MemoryPool_rec { + struct chunk *next; + uintptr_t free, end; + size_t chunksize; + uintptr_t alignmask; + struct cleanup *cleanup; +}; + +MemoryPool *mem_CreatePool(size_t chunksize, unsigned int align) +{ + MemoryPool *pool; + + if (align == 0) align = ALIGN; + if (chunksize == 0) chunksize = CHUNKSIZE; + if (align & (align-1)) return 0; + if (chunksize < sizeof(MemoryPool)) return 0; + if (chunksize & (align-1)) return 0; + if (!(pool = malloc(chunksize))) return 0; + pool->next = 0; + pool->chunksize = chunksize; + pool->alignmask = (uintptr_t)(align)-1; + pool->free = ((uintptr_t)(pool + 1) + pool->alignmask) & ~pool->alignmask; + pool->end = (uintptr_t)pool + chunksize; + pool->cleanup = 0; + return pool; +} + +void mem_FreePool(MemoryPool *pool) +{ + struct cleanup *cleanup; + struct chunk *p, *next; + + for (cleanup = pool->cleanup; cleanup; cleanup = cleanup->next) { + cleanup->fn(cleanup->arg); + } + for (p = (struct chunk *)pool; p; p = next) { + next = p->next; + free(p); + } +} + +void *mem_Alloc(MemoryPool *pool, size_t size) +{ + struct chunk *ch; + void *rv = (void *)pool->free; + size = (size + pool->alignmask) & ~pool->alignmask; + if (size <= 0) size = pool->alignmask; + pool->free += size; + if (pool->free > pool->end || pool->free < (uintptr_t)rv) { + size_t minreq = (size + sizeof(struct chunk) + pool->alignmask) + & ~pool->alignmask; + pool->free = (uintptr_t)rv; + if (minreq >= pool->chunksize) { + // request size is too big for the chunksize, so allocate it as + // a single chunk of the right size + ch = malloc(minreq); + if (!ch) return 0; + } else { + ch = malloc(pool->chunksize); + if (!ch) return 0; + pool->free = (uintptr_t)ch + minreq; + pool->end = (uintptr_t)ch + pool->chunksize; + } + ch->next = pool->next; + pool->next = ch; + rv = (void *)(((uintptr_t)(ch+1) + pool->alignmask) & ~pool->alignmask); + } + return rv; +} + +int mem_AddCleanup(MemoryPool *pool, void (*fn)(void *), void *arg) { + struct cleanup *cleanup; + + pool->free = (pool->free + sizeof(void *) - 1) & ~(sizeof(void *)-1); + cleanup = mem_Alloc(pool, sizeof(struct cleanup)); + if (!cleanup) return -1; + cleanup->next = pool->cleanup; + cleanup->fn = fn; + cleanup->arg = arg; + pool->cleanup = cleanup; + return 0; +} diff --git a/glslang/MachineIndependent/preprocessor/memory.h b/glslang/MachineIndependent/preprocessor/memory.h new file mode 100644 index 0000000..dbd6fbd --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/memory.h @@ -0,0 +1,89 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +#ifndef __MEMORY_H +#define __MEMORY_H + +typedef struct MemoryPool_rec MemoryPool; + +extern MemoryPool *mem_CreatePool(size_t chunksize, unsigned align); +extern void mem_FreePool(MemoryPool *); +extern void *mem_Alloc(MemoryPool *p, size_t size); +extern void *mem_Realloc(MemoryPool *p, void *old, size_t oldsize, size_t newsize); +extern int mem_AddCleanup(MemoryPool *p, void (*fn)(void *), void *arg); + +#endif /* __MEMORY_H */ diff --git a/glslang/MachineIndependent/preprocessor/parser.h b/glslang/MachineIndependent/preprocessor/parser.h new file mode 100644 index 0000000..1b42844 --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/parser.h @@ -0,0 +1,126 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +#ifndef BISON_PARSER_H +# define BISON_PARSER_H + +#ifndef yystypepp +typedef struct { + int sc_int; + float sc_fval; + int sc_ident; + char symbol_name[MAX_SYMBOL_NAME_LEN+1]; +} yystypepp; + +# define YYSTYPE_IS_TRIVIAL 1 +#endif +# define CPP_AND_OP 257 +# define CPP_SUB_ASSIGN 259 +# define CPP_MOD_ASSIGN 260 +# define CPP_ADD_ASSIGN 261 +# define CPP_DIV_ASSIGN 262 +# define CPP_MUL_ASSIGN 263 +# define CPP_EQ_OP 264 +# define CPP_XOR_OP 265 +# define ERROR_SY 266 +# define CPP_FLOATCONSTANT 267 +# define CPP_GE_OP 268 +# define CPP_RIGHT_OP 269 +# define CPP_IDENTIFIER 270 +# define CPP_INTCONSTANT 271 +# define CPP_LE_OP 272 +# define CPP_LEFT_OP 273 +# define CPP_DEC_OP 274 +# define CPP_NE_OP 275 +# define CPP_OR_OP 276 +# define CPP_INC_OP 277 +# define CPP_STRCONSTANT 278 +# define CPP_TYPEIDENTIFIER 279 + +# define FIRST_USER_TOKEN_SY 289 + +# define CPP_RIGHT_ASSIGN 280 +# define CPP_LEFT_ASSIGN 281 +# define CPP_AND_ASSIGN 282 +# define CPP_OR_ASSIGN 283 +# define CPP_XOR_ASSIGN 284 +# define CPP_LEFT_BRACKET 285 +# define CPP_RIGHT_BRACKET 286 +# define CPP_LEFT_BRACE 287 +# define CPP_RIGHT_BRACE 288 + +#endif /* not BISON_PARSER_H */ diff --git a/glslang/MachineIndependent/preprocessor/preprocess.h b/glslang/MachineIndependent/preprocessor/preprocess.h new file mode 100644 index 0000000..8f8a596 --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/preprocess.h @@ -0,0 +1,84 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +# include "slglobals.h" +extern CPPStruct *cpp; +int InitCPPStruct(void); +int InitScanner(CPPStruct *cpp); +int InitAtomTable(AtomTable *atable, int htsize); +int ScanFromString(char *s); +char* GetStringOfAtom(AtomTable *atable, int atom); diff --git a/glslang/MachineIndependent/preprocessor/scanner.c b/glslang/MachineIndependent/preprocessor/scanner.c new file mode 100644 index 0000000..6d562a4 --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/scanner.c @@ -0,0 +1,794 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// scanner.c +// + +#include +#include +#include +#include + +#if 0 + #include + #else + #define isinff(x) (((*(int *)&(x) & 0x7f800000L)==0x7f800000L) && \ + ((*(int *)&(x) & 0x007fffffL)==0000000000L)) +#endif + +#include "slglobals.h" + + +typedef struct StringInputSrc { + InputSrc base; + char *p; +} StringInputSrc; + +static int eof_scan(InputSrc *is, yystypepp * yylvalpp) +{ + return EOF; +} // eof_scan + +static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) {} + +static InputSrc eof_inputsrc = { 0, &eof_scan, &eof_scan, &noop }; + +static int byte_scan(InputSrc *, yystypepp * yylvalpp); + +#define EOL_SY '\n' + +#if defined(_WIN32) + #define DBG_BREAKPOINT() __asm int 3 + #elif defined(_M_AMD64) + #define DBG_BREAKPOINT() assert(!"Dbg_Breakpoint"); + #else + #define DBG_BREAKPOINT() + #endif + + #if defined(_WIN32) && !defined(_M_AMD64) + __int64 RDTSC ( void ) { + + __int64 v; + + __asm __emit 0x0f + __asm __emit 0x31 + __asm mov dword ptr v, eax + __asm mov dword ptr v+4, edx + + return v; + } +#endif + + +int InitScanner(CPPStruct *cpp) +{ + // Add various atoms needed by the CPP line scanner: + if (!InitCPP()) + return 0; + + cpp->mostRecentToken = 0; + cpp->tokenLoc = &cpp->ltokenLoc; + + cpp->ltokenLoc.file = 0; + cpp->ltokenLoc.line = 0; + + cpp->currentInput = &eof_inputsrc; + cpp->previous_token = '\n'; + cpp->notAVersionToken = 0; + + return 1; +} // InitScanner + +int FreeScanner(void) +{ + return (FreeCPP()); +} + +/* + * str_getch() + * takes care of reading from multiple strings. + * returns the next-char from the input stream. + * returns EOF when the complete shader is parsed. + */ +static int str_getch(StringInputSrc *in) +{ + for(;;){ + if (*in->p){ + if (*in->p == '\n') { + in->base.line++; + IncLineNumber(); + } + return *in->p++; + } + if(++(cpp->PaWhichStr) < cpp->PaArgc){ + free(in); + SetStringNumber(cpp->PaWhichStr); + SetLineNumber(1); + ScanFromString(cpp->PaArgv[cpp->PaWhichStr]); + in=(StringInputSrc*)cpp->currentInput; + continue; + } + else{ + cpp->currentInput = in->base.prev; + cpp->PaWhichStr=0; + free(in); + return EOF; + } + } +} // str_getch + +static void str_ungetch(StringInputSrc *in, int ch, yystypepp *type) { + if (in->p[-1] == ch)in->p--; + else { + *(in->p)='\0'; //this would take care of shifting to the previous string. + cpp->PaWhichStr--; + } + if (ch == '\n') { + in->base.line--; + DecLineNumber(); + } +} // str_ungetch + +int ScanFromString(char *s) +{ + + StringInputSrc *in = malloc(sizeof(StringInputSrc)); + memset(in, 0, sizeof(StringInputSrc)); + in->p = s; + in->base.line = 1; + in->base.scan = byte_scan; + in->base.getch = (int (*)(InputSrc *, yystypepp *))str_getch; + in->base.ungetch = (void (*)(InputSrc *, int, yystypepp *))str_ungetch; + in->base.prev = cpp->currentInput; + cpp->currentInput = &in->base; + + return 1; +} // ScanFromString; + + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////// Floating point constants: ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +/* + * lBuildFloatValue() - Quick and dirty conversion to floating point. Since all + * we need is single precision this should be quite precise. + */ + +static float lBuildFloatValue(const char *str, int len, int exp) +{ + double val, expval, ten; + int ii, llen, absexp; + float rv; + + val = 0.0; + llen = len; + for (ii = 0; ii < len; ii++) + val = val*10.0 + (str[ii] - '0'); + if (exp != 0) { + absexp = exp > 0 ? exp : -exp; + expval = 1.0f; + ten = 10.0; + while (absexp) { + if (absexp & 1) + expval *= ten; + ten *= ten; + absexp >>= 1; + } + if (exp >= 0) { + val *= expval; + } else { + val /= expval; + } + } + rv = (float)val; + if (isinff(rv)) { + CPPErrorToInfoLog(" ERROR___FP_CONST_OVERFLOW"); + } + return rv; +} // lBuildFloatValue + + +/* + * lFloatConst() - Scan a floating point constant. Assumes that the scanner + * has seen at least one digit, followed by either a decimal '.' or the + * letter 'e'. + */ + +static int lFloatConst(char *str, int len, int ch, yystypepp * yylvalpp) +{ + int HasDecimal, declen, exp, ExpSign; + int str_len; + float lval; + + HasDecimal = 0; + declen = 0; + exp = 0; + + str_len=len; + if (ch == '.') { + str[len++]=ch; + HasDecimal = 1; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + while (ch >= '0' && ch <= '9') { + if (len < MAX_SYMBOL_NAME_LEN) { + declen++; + if (len > 0 || ch != '0') { + str[len] = ch; + len++;str_len++; + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } else { + CPPErrorToInfoLog("ERROR___FP_CONST_TOO_LONG"); + len = 1,str_len=1; + } + } + } + + // Exponent: + + if (ch == 'e' || ch == 'E') { + ExpSign = 1; + str[len++]=ch; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '+') { + str[len++]=ch; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } else if (ch == '-') { + ExpSign = -1; + str[len++]=ch; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + if (ch >= '0' && ch <= '9') { + while (ch >= '0' && ch <= '9') { + exp = exp*10 + ch - '0'; + str[len++]=ch; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + } else { + CPPErrorToInfoLog("ERROR___ERROR_IN_EXPONENT"); + } + exp *= ExpSign; + } + + if (len == 0) { + lval = 0.0f; + strcpy(str,"0.0"); + } else { + str[len]='\0'; + lval = lBuildFloatValue(str, str_len, exp - declen); + } + // Suffix: + + yylvalpp->sc_fval = lval; + strcpy(yylvalpp->symbol_name,str); + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return CPP_FLOATCONSTANT; +} // lFloatConst + +/////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////// Normal Scanner ////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +static int byte_scan(InputSrc *in, yystypepp * yylvalpp) +{ + char symbol_name[MAX_SYMBOL_NAME_LEN + 1]; + char string_val[MAX_STRING_LEN + 1]; + int AlreadyComplained; + int len, ch, ii, ival = 0; + + for (;;) { + yylvalpp->sc_int = 0; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + + while (ch == ' ' || ch == '\t' || ch == '\r') { + yylvalpp->sc_int = 1; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + + cpp->ltokenLoc.file = cpp->currentInput->name; + cpp->ltokenLoc.line = cpp->currentInput->line; + len = 0; + switch (ch) { + default: + return ch; // Single character token + case EOF: + return -1; + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': + do { + if (len < MAX_SYMBOL_NAME_LEN) { + symbol_name[len] = ch; + len++; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } else { + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + } while ((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + ch == '_'); + if (len >= MAX_SYMBOL_NAME_LEN) + len = MAX_SYMBOL_NAME_LEN - 1; + symbol_name[len] = '\0'; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + yylvalpp->sc_ident = LookUpAddString(atable, symbol_name); + return CPP_IDENTIFIER; + break; + case '0': + yylvalpp->symbol_name[len++] = ch; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == 'x' || ch == 'X') { + yylvalpp->symbol_name[len++] = ch; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if ((ch >= '0' && ch <= '9') || + (ch >= 'A' && ch <= 'F') || + (ch >= 'a' && ch <= 'f')) + { + AlreadyComplained = 0; + ival = 0; + do { + yylvalpp->symbol_name[len++] = ch; + if (ival <= 0x0fffffff) { + if (ch >= '0' && ch <= '9') { + ii = ch - '0'; + } else if (ch >= 'A' && ch <= 'F') { + ii = ch - 'A' + 10; + } else { + ii = ch - 'a' + 10; + } + ival = (ival << 4) | ii; + } else { + if (!AlreadyComplained) + CPPErrorToInfoLog("ERROR___HEX_CONST_OVERFLOW"); + AlreadyComplained = 1; + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while ((ch >= '0' && ch <= '9') || + (ch >= 'A' && ch <= 'F') || + (ch >= 'a' && ch <= 'f')); + } else { + CPPErrorToInfoLog("ERROR___ERROR_IN_HEX_CONSTANT"); + } + yylvalpp->symbol_name[len] = '\0'; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + yylvalpp->sc_int = ival; + return CPP_INTCONSTANT; + } else if (ch >= '0' && ch <= '7') { // octal integer constants + AlreadyComplained = 0; + ival = 0; + do { + yylvalpp->symbol_name[len++] = ch; + if (ival <= 0x1fffffff) { + ii = ch - '0'; + ival = (ival << 3) | ii; + } else { + if (!AlreadyComplained) + CPPErrorToInfoLog("ERROR___OCT_CONST_OVERFLOW"); + AlreadyComplained = 1; + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while (ch >= '0' && ch <= '7'); + if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') + return lFloatConst(yylvalpp->symbol_name, len, ch, yylvalpp); + yylvalpp->symbol_name[len] = '\0'; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + yylvalpp->sc_int = ival; + return CPP_INTCONSTANT; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + ch = '0'; + } + // Fall through... + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + do { + if (len < MAX_SYMBOL_NAME_LEN) { + if (len > 0 || ch != '0') { + yylvalpp->symbol_name[len] = ch; + len++; + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + } while (ch >= '0' && ch <= '9'); + if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') { + return lFloatConst(yylvalpp->symbol_name, len, ch, yylvalpp); + } else { + yylvalpp->symbol_name[len] = '\0'; + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + ival = 0; + AlreadyComplained = 0; + for (ii = 0; ii < len; ii++) { + ch = yylvalpp->symbol_name[ii] - '0'; + if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) { + if (!AlreadyComplained) + CPPErrorToInfoLog("ERROR___INTEGER_CONST_OVERFLOW"); + AlreadyComplained = 1; + } + ival = ival*10 + ch; + } + yylvalpp->sc_int = ival; + if(ival==0) + strcpy(yylvalpp->symbol_name,"0"); + return CPP_INTCONSTANT; + } + break; + case '-': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '-') { + return CPP_DEC_OP; + } else if (ch == '=') { + return CPP_SUB_ASSIGN; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '-'; + } + case '+': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '+') { + return CPP_INC_OP; + } else if (ch == '=') { + return CPP_ADD_ASSIGN; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '+'; + } + case '*': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '=') { + return CPP_MUL_ASSIGN; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '*'; + } + case '%': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '=') { + return CPP_MOD_ASSIGN; + } else if (ch == '>'){ + return CPP_RIGHT_BRACE; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '%'; + } + case ':': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '>') { + return CPP_RIGHT_BRACKET; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return ':'; + } + case '^': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '^') { + return CPP_XOR_OP; + } else { + if (ch == '=') + return CPP_XOR_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '^'; + } + } + + case '=': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '=') { + return CPP_EQ_OP; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '='; + } + case '!': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '=') { + return CPP_NE_OP; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '!'; + } + case '|': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '|') { + return CPP_OR_OP; + } else { + if (ch == '=') + return CPP_OR_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '|'; + } + } + case '&': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '&') { + return CPP_AND_OP; + } else { + if (ch == '=') + return CPP_AND_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '&'; + } + } + case '<': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '<') { + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if(ch == '=') + return CPP_LEFT_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return CPP_LEFT_OP; + } + } else { + if (ch == '=') { + return CPP_LE_OP; + } else { + if (ch == '%') + return CPP_LEFT_BRACE; + else if (ch == ':') + return CPP_LEFT_BRACKET; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '<'; + } + } + } + case '>': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '>') { + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if(ch == '=') + return CPP_RIGHT_ASSIGN; + else{ + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return CPP_RIGHT_OP; + } + } else { + if (ch == '=') { + return CPP_GE_OP; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '>'; + } + } + case '.': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch >= '0' && ch <= '9') { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return lFloatConst(yylvalpp->symbol_name, 0, '.', yylvalpp); + } else { + if (ch == '.') { + return -1; // Special EOF hack + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '.'; + } + } + case '/': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '/') { + do { + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } while (ch != '\n' && ch != EOF); + if (ch == EOF) + return -1; + return '\n'; + } else if (ch == '*') { + int nlcount = 0; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + do { + while (ch != '*') { + if (ch == '\n') nlcount++; + if (ch == EOF) { + CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT"); + return -1; + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == EOF) { + CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT"); + return -1; + } + } while (ch != '/'); + if (nlcount) { + return '\n'; + } + // Go try it again... + } else if (ch == '=') { + return CPP_DIV_ASSIGN; + } else { + cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); + return '/'; + } + break; + case '"': + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + while (ch != '"' && ch != '\n' && ch != EOF) { + if (ch == '\\') { + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + if (ch == '\n' || ch == EOF) { + break; + } + } + if (len < MAX_STRING_LEN) { + string_val[len] = ch; + len++; + ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); + } + }; + string_val[len] = '\0'; + if (ch == '"') { + yylvalpp->sc_ident = LookUpAddString(atable, string_val); + return CPP_STRCONSTANT; + } else { + CPPErrorToInfoLog("ERROR___CPP_EOL_IN_STRING"); + return ERROR_SY; + } + } + } +} // byte_scan + +int yylex_CPP(char* buf, int maxSize) +{ + yystypepp yylvalpp; + int token = '\n'; + + for(;;) { + + char* tokenString = 0; + token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp); + if(check_EOF(token)) + return 0; + if (token == '#') { + if (cpp->previous_token == '\n'|| cpp->previous_token == 0) { + token = readCPPline(&yylvalpp); + if(check_EOF(token)) + return 0; + continue; + } else { + CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line"); + return 0; + } + } + cpp->previous_token = token; + // expand macros + if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) { + cpp->notAVersionToken = 1; + continue; + } + + if (token == '\n') + continue; + + if (token == CPP_IDENTIFIER) { + cpp->notAVersionToken = 1; + tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident); + } else if (token == CPP_FLOATCONSTANT||token == CPP_INTCONSTANT){ + cpp->notAVersionToken = 1; + tokenString = yylvalpp.symbol_name; + } else { + cpp->notAVersionToken = 1; + tokenString = GetStringOfAtom(atable,token); + } + + if (tokenString) { + if ((signed)strlen(tokenString) >= maxSize) { + cpp->tokensBeforeEOF = 1; + return maxSize; + } else if (strlen(tokenString) > 0) { + strcpy(buf, tokenString); + cpp->tokensBeforeEOF = 1; + return (int)strlen(tokenString); + } + + return 0; + } + } + + return 0; +} // yylex + +//Checks if the token just read is EOF or not. +int check_EOF(int token) +{ + if(token==-1){ + if(cpp->ifdepth >0){ + CPPErrorToInfoLog("#endif missing!! Compilation stopped"); + cpp->CompileError=1; + } + return 1; + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////// End of scanner.c ////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + diff --git a/glslang/MachineIndependent/preprocessor/scanner.h b/glslang/MachineIndependent/preprocessor/scanner.h new file mode 100644 index 0000000..fb4d057 --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/scanner.h @@ -0,0 +1,118 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// scanner.h +// + +#if !defined(__SCANNER_H) +#define __SCANNER_H 1 + +#define MAX_SYMBOL_NAME_LEN 128 +#define MAX_STRING_LEN 512 + +#include "parser.h" + +// Not really atom table stuff but needed first... + +typedef struct SourceLoc_Rec { + unsigned short file, line; +} SourceLoc; + +int yyparse (void); + +int yylex_CPP(char* buf, int maxSize); + +typedef struct InputSrc { + struct InputSrc *prev; + int (*scan)(struct InputSrc *, yystypepp *); + int (*getch)(struct InputSrc *, yystypepp *); + void (*ungetch)(struct InputSrc *, int, yystypepp *); + int name; /* atom */ + int line; +} InputSrc; + +int InitScanner(CPPStruct *cpp); // Intialise the cpp scanner. +int ScanFromString(char *); // Start scanning the input from the string mentioned. +int check_EOF(int); // check if we hit a EOF abruptly +void CPPErrorToInfoLog(char *); // sticking the msg,line into the Shader's.Info.log +void SetLineNumber(int); +void SetStringNumber(int); +void IncLineNumber(void); +void DecLineNumber(void); +int FreeScanner(void); // Free the cpp scanner +#endif // !(defined(__SCANNER_H) + diff --git a/glslang/MachineIndependent/preprocessor/slglobals.h b/glslang/MachineIndependent/preprocessor/slglobals.h new file mode 100644 index 0000000..ebe27c3 --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/slglobals.h @@ -0,0 +1,115 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// slglobals.h +// + +#if !defined(__SLGLOBALS_H) +#define __SLGLOBALS_H 1 + +typedef struct CPPStruct_Rec CPPStruct; + +extern CPPStruct *cpp; + +#undef CPPC_DEBUG_THE_COMPILER +#if defined(_DEBUG) +#define CPPC_DEBUG_THE_COMPILER 1 +#endif + +#undef CPPC_ENABLE_TOOLS +#define CPPC_ENABLE_TOOLS 1 + +#include "memory.h" +#include "atom.h" +#include "scanner.h" +#include "cpp.h" +#include "tokens.h" +#include "symbols.h" +#include "compile.h" +#if !defined(NO_PARSER) +#include "parser.h" +#endif + +#if !defined(NULL) +#define NULL 0 +#endif + +#endif // !(defined(__SLGLOBALS_H) + + + + diff --git a/glslang/MachineIndependent/preprocessor/symbols.c b/glslang/MachineIndependent/preprocessor/symbols.c new file mode 100644 index 0000000..2929ef1 --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/symbols.c @@ -0,0 +1,318 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// symbols.c +// + +#include +#include +#include +#include + +#include "slglobals.h" + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////// Symbol Table Variables: /////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +Scope *ScopeList = NULL; +Scope *CurrentScope = NULL; +Scope *GlobalScope = NULL; + +static void unlinkScope(void *_scope) { + Scope *scope = _scope; + + if (scope->next) + scope->next->prev = scope->prev; + if (scope->prev) + scope->prev->next = scope->next; + else + ScopeList = scope->next; +} + +/* + * NewScope() + * + */ +Scope *NewScopeInPool(MemoryPool *pool) +{ + Scope *lScope; + + lScope = mem_Alloc(pool, sizeof(Scope)); + lScope->pool = pool; + lScope->parent = NULL; + lScope->funScope = NULL; + lScope->symbols = NULL; + + lScope->level = 0; + + lScope->programs = NULL; + if ((lScope->next = ScopeList)) + ScopeList->prev = lScope; + lScope->prev = 0; + ScopeList = lScope; + mem_AddCleanup(pool, unlinkScope, lScope); + return lScope; +} // NewScope + +/* + * PushScope() + * + */ + +void PushScope(Scope *fScope) +{ + Scope *lScope; + + if (CurrentScope) { + fScope->level = CurrentScope->level + 1; + if (fScope->level == 1) { + if (!GlobalScope) { + /* HACK - CTD -- if GlobalScope==NULL and level==1, we're + * defining a function in the superglobal scope. Things + * will break if we leave the level as 1, so we arbitrarily + * set it to 2 */ + fScope->level = 2; + } + } + if (fScope->level >= 2) { + lScope = fScope; + while (lScope->level > 2) + lScope = lScope->next; + fScope->funScope = lScope; + } + } else { + fScope->level = 0; + } + fScope->parent = CurrentScope; + CurrentScope = fScope; +} // PushScope + +/* + * PopScope() + * + */ + +Scope *PopScope(void) +{ + Scope *lScope; + + lScope = CurrentScope; + if (CurrentScope) + CurrentScope = CurrentScope->parent; + return lScope; +} // PopScope + +/* + * NewSymbol() - Allocate a new symbol node; + * + */ + +Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind) +{ + Symbol *lSymb; + char *pch; + int ii; + + lSymb = (Symbol *) mem_Alloc(fScope->pool, sizeof(Symbol)); + lSymb->left = NULL; + lSymb->right = NULL; + lSymb->next = NULL; + lSymb->name = name; + lSymb->loc = *loc; + lSymb->kind = kind; + + // Clear union area: + + pch = (char *) &lSymb->details; + for (ii = 0; ii < sizeof(lSymb->details); ii++) + *pch++ = 0; + return lSymb; +} // NewSymbol + +/* + * lAddToTree() - Using a binary tree is not a good idea for basic atom values because they + * are generated in order. We'll fix this later (by reversing the bit pattern). + */ + +static void lAddToTree(Symbol **fSymbols, Symbol *fSymb) +{ + Symbol *lSymb; + int lrev, frev; + + lSymb = *fSymbols; + if (lSymb) { + frev = GetReversedAtom(atable, fSymb->name); + while (lSymb) { + lrev = GetReversedAtom(atable, lSymb->name); + if (lrev == frev) { + CPPErrorToInfoLog("GetAtomString(atable, fSymb->name)"); + break; + } else { + if (lrev > frev) { + if (lSymb->left) { + lSymb = lSymb->left; + } else { + lSymb->left = fSymb; + break; + } + } else { + if (lSymb->right) { + lSymb = lSymb->right; + } else { + lSymb->right = fSymb; + break; + } + } + } + } + } else { + *fSymbols = fSymb; + } +} // lAddToTree + + +/* + * AddSymbol() - Add a variable, type, or function name to a scope. + * + */ + +Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind) +{ + Symbol *lSymb; + + if (!fScope) + fScope = CurrentScope; + lSymb = NewSymbol(loc, fScope, atom, kind); + lAddToTree(&fScope->symbols, lSymb); + return lSymb; +} // AddSymbol + + +/*********************************************************************************************/ +/************************************ Symbol Semantic Functions ******************************/ +/*********************************************************************************************/ + +/* + * LookUpLocalSymbol() + * + */ + +Symbol *LookUpLocalSymbol(Scope *fScope, int atom) +{ + Symbol *lSymb; + int rname, ratom; + + ratom = GetReversedAtom(atable, atom); + if (!fScope) + fScope = CurrentScope; + lSymb = fScope->symbols; + while (lSymb) { + rname = GetReversedAtom(atable, lSymb->name); + if (rname == ratom) { + return lSymb; + } else { + if (rname > ratom) { + lSymb = lSymb->left; + } else { + lSymb = lSymb->right; + } + } + } + return NULL; +} // LookUpLocalSymbol + +/* + * LookUpSymbol() + * + */ + +Symbol *LookUpSymbol(Scope *fScope, int atom) +{ + Symbol *lSymb; + + if (!fScope) + fScope = CurrentScope; + while (fScope) { + lSymb = LookUpLocalSymbol(fScope, atom); + if (lSymb) + return lSymb; + fScope = fScope->parent; + } + return NULL; +} // LookUpSymbol + diff --git a/glslang/MachineIndependent/preprocessor/symbols.h b/glslang/MachineIndependent/preprocessor/symbols.h new file mode 100644 index 0000000..618418c --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/symbols.h @@ -0,0 +1,145 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// symbols.h +// + +#if !defined(__SYMBOLS_H) +#define __SYMBOLS_H 1 + +#include "memory.h" + +typedef enum symbolkind { + MACRO_S +} symbolkind; + +// Typedefs for things defined here in "symbols.h": + +typedef struct Scope_Rec Scope; +typedef struct Symbol_Rec Symbol; + +typedef struct SymbolList_Rec { + struct SymbolList_Rec *next; + Symbol *symb; +} SymbolList; + +struct Scope_Rec { + Scope *next, *prev; // doubly-linked list of all scopes + Scope *parent; + Scope *funScope; // Points to base scope of enclosing function + MemoryPool *pool; // pool used for allocation in this scope + Symbol *symbols; + + int level; // 0 = super globals, 1 = globals, etc. + + // Only used at global scope (level 1): + SymbolList *programs; // List of programs for this compilation. +}; + + +// Symbol table is a simple binary tree. + +#include "cpp.h" // to get MacroSymbol def + +struct Symbol_Rec { + Symbol *left, *right; + Symbol *next; + int name; // Name atom + SourceLoc loc; + symbolkind kind; + union { + MacroSymbol mac; + } details; +}; + +extern Scope *CurrentScope; +extern Scope *GlobalScope; +extern Scope *ScopeList; + +Scope *NewScopeInPool(MemoryPool *); +#define NewScope() NewScopeInPool(CurrentScope->pool) +void PushScope(Scope *fScope); +Scope *PopScope(void); +Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind); +Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind); +Symbol *LookUpLocalSymbol(Scope *fScope, int atom); +Symbol *LookUpSymbol(Scope *fScope, int atom); +void CPPErrorToInfoLog(char *); + + +#endif // !defined(__SYMBOLS_H) + diff --git a/glslang/MachineIndependent/preprocessor/tokens.c b/glslang/MachineIndependent/preprocessor/tokens.c new file mode 100644 index 0000000..c2f7911 --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/tokens.c @@ -0,0 +1,472 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// tokens.c +// + +#include +#include +#include +#include +#include + +#include "slglobals.h" + +/////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////// Preprocessor and Token Recorder and Playback: //////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +/* + * idstr() + * Copy a string to a malloc'ed block and convert it into something suitable + * for an ID + * + */ + +static char *idstr(const char *fstr, MemoryPool *pool) +{ + size_t len; + char *str, *t; + const char *f; + + len = strlen(fstr); + if (!pool) + str = (char *) malloc(len + 1); + else + str = (char *) mem_Alloc(pool, len + 1); + + for (f=fstr, t=str; *f; f++) { + if (isalnum(*f)) *t++ = *f; + else if (*f == '.' || *f == '/') *t++ = '_'; + } + *t = 0; + return str; +} // idstr + + +/* + * lNewBlock() + * + */ + +static TokenBlock *lNewBlock(TokenStream *fTok, MemoryPool *pool) +{ + TokenBlock *lBlock; + + if (!pool) + lBlock = (TokenBlock *) malloc(sizeof(TokenBlock) + 256); + else + lBlock = (TokenBlock *) mem_Alloc(pool, sizeof(TokenBlock) + 256); + lBlock->count = 0; + lBlock->current = 0; + lBlock->data = (unsigned char *) lBlock + sizeof(TokenBlock); + lBlock->max = 256; + lBlock->next = NULL; + if (fTok->head) { + fTok->current->next = lBlock; + } else { + fTok->head = lBlock; + } + fTok->current = lBlock; + return lBlock; +} // lNewBlock + +/* + * lAddByte() + * + */ + +static void lAddByte(TokenStream *fTok, unsigned char fVal) +{ + TokenBlock *lBlock; + lBlock = fTok->current; + if (lBlock->count >= lBlock->max) + lBlock = lNewBlock(fTok, 0); + lBlock->data[lBlock->count++] = fVal; +} // lAddByte + + + +/* + * lReadByte() - Get the next byte from a stream. + * + */ + +static int lReadByte(TokenStream *pTok) +{ + TokenBlock *lBlock; + int lval = -1; + + lBlock = pTok->current; + if (lBlock) { + if (lBlock->current >= lBlock->count) { + lBlock = lBlock->next; + if (lBlock) + lBlock->current = 0; + pTok->current = lBlock; + } + if (lBlock) + lval = lBlock->data[lBlock->current++]; + } + return lval; +} // lReadByte + +/////////////////////////////////////// Global Functions:////////////////////////////////////// + +/* + * NewTokenStream() + * + */ + +TokenStream *NewTokenStream(const char *name, MemoryPool *pool) +{ + TokenStream *pTok; + + if (!pool) + pTok = (TokenStream *) malloc(sizeof(TokenStream)); + else + pTok = (TokenStream*)mem_Alloc(pool, sizeof(TokenStream)); + pTok->next = NULL; + pTok->name = idstr(name, pool); + pTok->head = NULL; + pTok->current = NULL; + lNewBlock(pTok, pool); + return pTok; +} // NewTokenStream + +/* + * DeleteTokenStream() + * + */ + +void DeleteTokenStream(TokenStream *pTok) +{ + TokenBlock *pBlock, *nBlock; + + if (pTok) { + pBlock = pTok->head; + while (pBlock) { + nBlock = pBlock->next; + free(pBlock); + pBlock = nBlock; + } + if (pTok->name) + free(pTok->name); + free(pTok); + } +} // DeleteTokenStream + +/* + * RecordToken() - Add a token to the end of a list for later playback or printout. + * + */ + +void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp) +{ + const char *s; + unsigned char *str=NULL; + + if (token > 256) + lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80)); + else + lAddByte(pTok, (unsigned char)(token & 0x7f)); + switch (token) { + case CPP_IDENTIFIER: + case CPP_TYPEIDENTIFIER: + case CPP_STRCONSTANT: + s = GetAtomString(atable, yylvalpp->sc_ident); + while (*s) + lAddByte(pTok, (unsigned char) *s++); + lAddByte(pTok, 0); + break; + case CPP_FLOATCONSTANT: + case CPP_INTCONSTANT: + str=yylvalpp->symbol_name; + while (*str){ + lAddByte(pTok,(unsigned char) *str); + *str++; + } + lAddByte(pTok, 0); + break; + case '(': + lAddByte(pTok, (unsigned char)(yylvalpp->sc_int ? 1 : 0)); + default: + break; + } +} // RecordToken + +/* + * RewindTokenStream() - Reset a token stream in preperation for reading. + * + */ + +void RewindTokenStream(TokenStream *pTok) +{ + if (pTok->head) { + pTok->current = pTok->head; + pTok->current->current = 0; + } +} // RewindTokenStream + +/* + * ReadToken() - Read the next token from a stream. + * + */ + +int ReadToken(TokenStream *pTok, yystypepp * yylvalpp) +{ + char symbol_name[MAX_SYMBOL_NAME_LEN + 1]; + char string_val[MAX_STRING_LEN + 1]; + int ltoken, len; + char ch; + + ltoken = lReadByte(pTok); + if (ltoken >= 0) { + if (ltoken > 127) + ltoken += 128; + switch (ltoken) { + case CPP_IDENTIFIER: + case CPP_TYPEIDENTIFIER: + len = 0; + ch = lReadByte(pTok); + while ((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + ch == '_') + { + if (len < MAX_SYMBOL_NAME_LEN) { + symbol_name[len] = ch; + len++; + ch = lReadByte(pTok); + } + } + symbol_name[len] = '\0'; + assert(ch == '\0'); + yylvalpp->sc_ident = LookUpAddString(atable, symbol_name); + return CPP_IDENTIFIER; + break; + case CPP_STRCONSTANT: + len = 0; + while ((ch = lReadByte(pTok)) != 0) + if (len < MAX_STRING_LEN) + string_val[len++] = ch; + string_val[len] = 0; + yylvalpp->sc_ident = LookUpAddString(atable, string_val); + break; + case CPP_FLOATCONSTANT: + len = 0; + ch = lReadByte(pTok); + while ((ch >= '0' && ch <= '9')||(ch=='e'||ch=='E'||ch=='.')||(ch=='+'||ch=='-')) + { + if (len < MAX_SYMBOL_NAME_LEN) { + symbol_name[len] = ch; + len++; + ch = lReadByte(pTok); + } + } + symbol_name[len] = '\0'; + assert(ch == '\0'); + strcpy(yylvalpp->symbol_name,symbol_name); + yylvalpp->sc_fval=(float)atof(yylvalpp->symbol_name); + break; + case CPP_INTCONSTANT: + len = 0; + ch = lReadByte(pTok); + while ((ch >= '0' && ch <= '9')) + { + if (len < MAX_SYMBOL_NAME_LEN) { + symbol_name[len] = ch; + len++; + ch = lReadByte(pTok); + } + } + symbol_name[len] = '\0'; + assert(ch == '\0'); + strcpy(yylvalpp->symbol_name,symbol_name); + yylvalpp->sc_int=atoi(yylvalpp->symbol_name); + break; + case '(': + yylvalpp->sc_int = lReadByte(pTok); + break; + } + return ltoken; + } + return EOF_SY; +} // ReadToken + +typedef struct TokenInputSrc { + InputSrc base; + TokenStream *tokens; + int (*final)(CPPStruct *); +} TokenInputSrc; + +static int scan_token(TokenInputSrc *in, yystypepp * yylvalpp) +{ + int token = ReadToken(in->tokens, yylvalpp); + int (*final)(CPPStruct *); + cpp->tokenLoc->file = cpp->currentInput->name; + cpp->tokenLoc->line = cpp->currentInput->line; + if (token == '\n') { + in->base.line++; + return token; + } + if (token > 0) return token; + cpp->currentInput = in->base.prev; + final = in->final; + free(in); + if (final && !final(cpp)) return -1; + return cpp->currentInput->scan(cpp->currentInput, yylvalpp); +} + +int ReadFromTokenStream(TokenStream *ts, int name, int (*final)(CPPStruct *)) +{ + TokenInputSrc *in = malloc(sizeof(TokenInputSrc)); + memset(in, 0, sizeof(TokenInputSrc)); + in->base.name = name; + in->base.prev = cpp->currentInput; + in->base.scan = (int (*)(InputSrc *, yystypepp *))scan_token; + in->base.line = 1; + in->tokens = ts; + in->final = final; + RewindTokenStream(ts); + cpp->currentInput = &in->base; + return 1; +} + +typedef struct UngotToken { + InputSrc base; + int token; + yystypepp lval; +} UngotToken; + +static int reget_token(UngotToken *t, yystypepp * yylvalpp) +{ + int token = t->token; + *yylvalpp = t->lval; + cpp->currentInput = t->base.prev; + free(t); + return token; +} + +void UngetToken(int token, yystypepp * yylvalpp) { + UngotToken *t = malloc(sizeof(UngotToken)); + memset(t, 0, sizeof(UngotToken)); + t->token = token; + t->lval = *yylvalpp; + t->base.scan = (void *)reget_token; + t->base.prev = cpp->currentInput; + t->base.name = cpp->currentInput->name; + t->base.line = cpp->currentInput->line; + cpp->currentInput = &t->base; +} + + +void DumpTokenStream(FILE *fp, TokenStream *s, yystypepp * yylvalpp) { + int token; + char str[100]; + + if (fp == 0) fp = stdout; + RewindTokenStream(s); + while ((token = ReadToken(s, yylvalpp)) > 0) { + switch (token) { + case CPP_IDENTIFIER: + case CPP_TYPEIDENTIFIER: + sprintf(str, "%s ", GetAtomString(atable, yylvalpp->sc_ident)); + break; + case CPP_STRCONSTANT: + sprintf(str, "\"%s\"", GetAtomString(atable, yylvalpp->sc_ident)); + break; + case CPP_FLOATCONSTANT: + //printf("%g9.6 ", yylvalpp->sc_fval); + break; + case CPP_INTCONSTANT: + //printf("%d ", yylvalpp->sc_int); + break; + default: + if (token >= 127) + sprintf(str, "%s ", GetAtomString(atable, token)); + else + sprintf(str, "%c", token); + break; + } + CPPDebugLogMsg(str); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////// End of tokens.c /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/glslang/MachineIndependent/preprocessor/tokens.h b/glslang/MachineIndependent/preprocessor/tokens.h new file mode 100644 index 0000000..dda09ca --- /dev/null +++ b/glslang/MachineIndependent/preprocessor/tokens.h @@ -0,0 +1,122 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// tokens.h +// + +#if !defined(__TOKENS_H) +#define __TOKENS_H 1 + +#include "parser.h" + +#define EOF_SY (-1) + +typedef struct TokenBlock_Rec TokenBlock; + +typedef struct TokenStream_Rec { + struct TokenStream_Rec *next; + char *name; + TokenBlock *head; + TokenBlock *current; +} TokenStream; + +struct TokenBlock_Rec { + TokenBlock *next; + int current; + int count; + int max; + unsigned char *data; +}; + +extern TokenStream stdlib_cpp_stream; + + +TokenStream *NewTokenStream(const char *name, MemoryPool *pool); +void DeleteTokenStream(TokenStream *pTok); +void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp); +void RewindTokenStream(TokenStream *pTok); +int ReadToken(TokenStream *pTok, yystypepp * yylvalpp); +int ReadFromTokenStream(TokenStream *pTok, int name, int (*final)(CPPStruct *)); +void UngetToken(int, yystypepp * yylvalpp); + +#if defined(CPPC_ENABLE_TOOLS) + +void DumpTokenStream(FILE *, TokenStream *, yystypepp * yylvalpp); + +#endif // defined(CPPC_ENABLE_TOOLS) + +#endif // !defined(__TOKENS_H) diff --git a/glslang/MachineIndependent/unistd.h b/glslang/MachineIndependent/unistd.h new file mode 100644 index 0000000..c7c9147 --- /dev/null +++ b/glslang/MachineIndependent/unistd.h @@ -0,0 +1 @@ +// This is a NULL file and is meant to be empty diff --git a/glslang/OSDependent/Linux/Makefile b/glslang/OSDependent/Linux/Makefile new file mode 100644 index 0000000..dc8d074 --- /dev/null +++ b/glslang/OSDependent/Linux/Makefile @@ -0,0 +1,62 @@ +#### +#### This Makefile should be used in the Linux Compiler build. This Makefile build the OSDependent +#### component as a static library. +#### + +# +# Compilation related +# +INCLUDE = -I. -I../.. -I../../Include -I../../../OGLCompilersDLL +WARNINGS = -Wall -Wwrite-strings -Wpointer-arith -Wcast-align -Wstrict-prototypes \ + -Wnested-externs +DEFINE = -Dlinux -D__i386__ + +CPP = g++ +CPPOPTIONS = -O3 -Wno-deprecated -D_ALT_NS=1 +CPPOPTIONS = -g -Wno-deprecated -D_ALT_NS=1 +CPPFLAGS = $(CPPOPTIONS) $(DEFINE) $(INCLUDE) + +# +# Linking related +# +AR = ar +STATIC_OPTION = rcs + +# +# Misc +# +export PERL = perl +export RM = rm -f +export MV = mv -f +export DEPEND = g++ -M + +# +# Object file variables are defined here. +# +OSSRCS = ossource.cpp +OSOBJS = ossource.o + +LIBNAME = libOssource.a + +all : $(LIBNAME) + +$(LIBNAME) : $(OSOBJS) + $(AR) $(STATIC_OPTION) $(LIBNAME) $(OSOBJS) + +%.o : %.cpp + $(CPP) $(CPPFLAGS) -c $< + + +# +# Dependency +# +depend : $(OSSRCS) + $(DEPEND) $(CPPFLAGS) $(OSSRCS) > depend +include depend + +# +# Cleanup +# +.PHONY : clean +clean : + $(RM) *.o *.a diff --git a/glslang/OSDependent/Linux/osinclude.h b/glslang/OSDependent/Linux/osinclude.h new file mode 100644 index 0000000..883c993 --- /dev/null +++ b/glslang/OSDependent/Linux/osinclude.h @@ -0,0 +1,78 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef __OSINCLUDE_H +#define __OSINCLUDE_H + +// +// This file contains any Linux specific functions. +// + +#if !(defined(linux)) +#error Trying to include a Linux specific file in a non-Linux build. +#endif + +#include +#include +#include +#include +#include "Include/InitializeGlobals.h" +#include "Include/PoolAlloc.h" + +#define _vsnprintf vsnprintf + + +void DetachThreadLinux(void *); + +// +// Thread Local Storage Operations +// +typedef unsigned int OS_TLSIndex; +#define OS_INVALID_TLS_INDEX 0xFFFFFFFF + +OS_TLSIndex OS_AllocTLSIndex(); +bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue); +bool OS_FreeTLSIndex(OS_TLSIndex nIndex); + + +inline void * OS_GetTLSValue(OS_TLSIndex nIndex) +{ + // + // This function should return 0 if nIndex is invalid. + // + assert(nIndex != OS_INVALID_TLS_INDEX); + return pthread_getspecific(nIndex); +} + +#endif // __OSINCLUDE_H diff --git a/glslang/OSDependent/Linux/ossource.cpp b/glslang/OSDependent/Linux/ossource.cpp new file mode 100644 index 0000000..08757b7 --- /dev/null +++ b/glslang/OSDependent/Linux/ossource.cpp @@ -0,0 +1,141 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +// +// This file contains the Linux specific functions +// +#include "osinclude.h" +#include "InitializeDll.h" + +#if !(defined(linux)) +#error Trying to build a Linux specific file in a non-Linux build. +#endif + + +// +// Thread cleanup +// + +// +// Wrapper for Linux call to DetachThread. This is required as pthread_cleanup_push() expects +// the cleanup routine to return void. +// +void DetachThreadLinux(void *) +{ + DetachThread(); +} + + +// +// Registers cleanup handler, sets cancel type and state, and excecutes the thread specific +// cleanup handler. This function will be called in the Standalone.cpp for regression +// testing. When OpenGL applications are run with the driver code, Linux OS does the +// thread cleanup. +// +void OS_CleanupThreadData(void) +{ + int old_cancel_state, old_cancel_type; + void *cleanupArg = NULL; + + // + // Set thread cancel state and push cleanup handler. + // + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancel_state); + pthread_cleanup_push(DetachThreadLinux, (void *) cleanupArg); + + // + // Put the thread in deferred cancellation mode. + // + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &old_cancel_type); + + // + // Pop cleanup handler and execute it prior to unregistering the cleanup handler. + // + pthread_cleanup_pop(1); + + // + // Restore the thread's previous cancellation mode. + // + pthread_setcanceltype(old_cancel_state, NULL); +} + + +// +// Thread Local Storage Operations +// +OS_TLSIndex OS_AllocTLSIndex() +{ + pthread_key_t pPoolIndex; + + // + // Create global pool key. + // + if ((pthread_key_create(&pPoolIndex, NULL)) != 0) { + assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); + return false; + } + else + return pPoolIndex; +} + + +bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) +{ + if (nIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } + + if (pthread_setspecific(nIndex, lpvValue) == 0) + return true; + else + return false; +} + + +bool OS_FreeTLSIndex(OS_TLSIndex nIndex) +{ + if (nIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } + + // + // Delete the global pool key. + // + if (pthread_key_delete(nIndex) == 0) + return true; + else + return false; +} diff --git a/glslang/OSDependent/Windows/main.cpp b/glslang/OSDependent/Windows/main.cpp new file mode 100644 index 0000000..ee4ad55 --- /dev/null +++ b/glslang/OSDependent/Windows/main.cpp @@ -0,0 +1,69 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#include "InitializeDll.h" + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + + if (!InitProcess()) + return FALSE; + break; + case DLL_THREAD_ATTACH: + + if (!InitThread()) + return FALSE; + break; + + case DLL_THREAD_DETACH: + + if (!DetachThread()) + return FALSE; + break; + + case DLL_PROCESS_DETACH: + + DetachProcess(); + break; + + default: + assert(0 && "DllMain(): Reason for calling DLL Main is unknown"); + return FALSE; + } + + return TRUE; +} diff --git a/glslang/OSDependent/Windows/osinclude.h b/glslang/OSDependent/Windows/osinclude.h new file mode 100644 index 0000000..652f558 --- /dev/null +++ b/glslang/OSDependent/Windows/osinclude.h @@ -0,0 +1,69 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef __OSINCLUDE_H +#define __OSINCLUDE_H + +// +// This file contains contains the window's specific datatypes and +// declares any windows specific functions. +// + +#if !(defined(_WIN32) || defined(_WIN64)) +#error Trying to include a windows specific file in a non windows build. +#endif + +#define STRICT +#define VC_EXTRALEAN 1 +#include +#include + + +// +// Thread Local Storage Operations +// +typedef DWORD OS_TLSIndex; +#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES) + +OS_TLSIndex OS_AllocTLSIndex(); +bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue); +bool OS_FreeTLSIndex(OS_TLSIndex nIndex); + +inline void* OS_GetTLSValue(OS_TLSIndex nIndex) +{ + assert(nIndex != OS_INVALID_TLS_INDEX); + return TlsGetValue(nIndex); +} + +#endif // __OSINCLUDE_H diff --git a/glslang/OSDependent/Windows/ossource.cpp b/glslang/OSDependent/Windows/ossource.cpp new file mode 100644 index 0000000..3c2cb85 --- /dev/null +++ b/glslang/OSDependent/Windows/ossource.cpp @@ -0,0 +1,85 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// + +#include "osinclude.h" +// +// This file contains contains the window's specific functions +// + +#if !(defined(_WIN32) || defined(_WIN64)) +#error Trying to build a windows specific file in a non windows build. +#endif + + +// +// Thread Local Storage Operations +// +OS_TLSIndex OS_AllocTLSIndex() +{ + DWORD dwIndex = TlsAlloc(); + if (dwIndex == TLS_OUT_OF_INDEXES) { + assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); + return OS_INVALID_TLS_INDEX; + } + + return dwIndex; +} + + +bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) +{ + if (nIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } + + if (TlsSetValue(nIndex, lpvValue)) + return true; + else + return false; +} + + +bool OS_FreeTLSIndex(OS_TLSIndex nIndex) +{ + if (nIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } + + if (TlsFree(nIndex)) + return true; + else + return false; +} diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h new file mode 100644 index 0000000..581ad3c --- /dev/null +++ b/glslang/Public/ShaderLang.h @@ -0,0 +1,212 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _COMPILER_INTERFACE_INCLUDED_ +#define _COMPILER_INTERFACE_INCLUDED_ + +#include "../Include/ResourceLimits.h" + +#ifdef _WIN32 +#define C_DECL __cdecl +#ifdef SH_EXPORTING + #define SH_IMPORT_EXPORT __declspec(dllexport) +#else + #define SH_IMPORT_EXPORT __declspec(dllimport) +#endif +#else +#define SH_IMPORT_EXPORT +#define __fastcall +#define C_DECL +#endif + +// +// This is the platform independent interface between an OGL driver +// and the shading language compiler/linker. +// + +#ifdef __cplusplus + extern "C" { +#endif +// +// Driver must call this first, once, before doing any other +// compiler/linker operations. +// +SH_IMPORT_EXPORT int ShInitialize(); +// +// Driver should call this at shutdown. +// +SH_IMPORT_EXPORT int __fastcall ShFinalize(); +// +// Types of languages the compiler can consume. +// +typedef enum { + EShLangVertex, + EShLangFragment, + EShLangPack, + EShLangUnpack, + EShLangCount, +} EShLanguage; + +// +// Types of output the linker will create. +// +typedef enum { + EShExVertexFragment, + EShExPackFragment, + EShExUnpackFragment, + EShExFragment +} EShExecutable; + +// +// Optimization level for the compiler. +// +typedef enum { + EShOptNoGeneration, + EShOptNone, + EShOptSimple, // Optimizations that can be done quickly + EShOptFull, // Optimizations that will take more time +} EShOptimizationLevel; + +// +// Build a table for bindings. This can be used for locating +// attributes, uniforms, globals, etc., as needed. +// +typedef struct { + char* name; + int binding; +} ShBinding; + +typedef struct { + int numBindings; + ShBinding* bindings; // array of bindings +} ShBindingTable; + +// +// ShHandle held by but opaque to the driver. It is allocated, +// managed, and de-allocated by the compiler/linker. It's contents +// are defined by and used by the compiler and linker. For example, +// symbol table information and object code passed from the compiler +// to the linker can be stored where ShHandle points. +// +// If handle creation fails, 0 will be returned. +// +typedef void* ShHandle; + +// +// Driver calls these to create and destroy compiler/linker +// objects. +// +SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader +SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair +SH_IMPORT_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object) +SH_IMPORT_EXPORT void ShDestruct(ShHandle); + +// +// The return value of ShCompile is boolean, indicating +// success or failure. +// +// The info-log should be written by ShCompile into +// ShHandle, so it can answer future queries. +// +SH_IMPORT_EXPORT int ShCompile( + const ShHandle, + const char* const shaderStrings[], + const int numStrings, + const EShOptimizationLevel, + const TBuiltInResource *resources, + int debugOptions + ); + + +// +// Similar to ShCompile, but accepts an opaque handle to an +// intermediate language structure. +// +SH_IMPORT_EXPORT int ShCompileIntermediate( + ShHandle compiler, + ShHandle intermediate, + const EShOptimizationLevel, + int debuggable // boolean + ); + +SH_IMPORT_EXPORT int ShLink( + const ShHandle, // linker object + const ShHandle h[], // compiler objects to link together + const int numHandles, + ShHandle uniformMap, // updated with new uniforms + short int** uniformsAccessed, // returned with indexes of uniforms accessed + int* numUniformsAccessed); + +SH_IMPORT_EXPORT int ShLinkExt( + const ShHandle, // linker object + const ShHandle h[], // compiler objects to link together + const int numHandles); + +// +// ShSetEncrpytionMethod is a place-holder for specifying +// how source code is encrypted. +// +SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle); + +// +// All the following return 0 if the information is not +// available in the object passed down, or the object is bad. +// +SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle); +SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle); +SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing +SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings +SH_IMPORT_EXPORT int ShGetPhysicalAttributeBindings(const ShHandle, const ShBindingTable**); // for all attributes +// +// Tell the linker to never assign a vertex attribute to this list of physical attributes +// +SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count); + +// +// Returns the location ID of the named uniform. +// Returns -1 if error. +// +SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name); + +enum TDebugOptions { + EDebugOpNone = 0x000, + EDebugOpIntermediate = 0x001, + EDebugOpAssembly = 0x002, + EDebugOpObjectCode = 0x004, + EDebugOpLinkMaps = 0x008 +}; +#ifdef __cplusplus + } +#endif + +#endif // _COMPILER_INTERFACE_INCLUDED_ diff --git a/tools/bison.exe b/tools/bison.exe new file mode 100644 index 0000000000000000000000000000000000000000..4881bf604916b1331205bdd5f32624831e2a2331 GIT binary patch literal 196096 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

Y%&V;-)+npYsq0 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 YcfY#-V)nRSdX^UC{nvVu+I#bV0CDn^H~;_u literal 0 HcmV?d00001 diff --git a/tools/bison.hairy b/tools/bison.hairy new file mode 100644 index 0000000..260b687 --- /dev/null +++ b/tools/bison.hairy @@ -0,0 +1,334 @@ + +extern int timeclock; + + +int yyerror; /* Yyerror and yycost are set by guards. */ +int yycost; /* If yyerror is set to a nonzero value by a */ + /* guard, the reduction with which the guard */ + /* is associated is not performed, and the */ + /* error recovery mechanism is invoked. */ + /* Yycost indicates the cost of performing */ + /* the reduction given the attributes of the */ + /* symbols. */ + + +/* YYMAXDEPTH indicates the size of the parser's state and value */ +/* stacks. */ + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 500 +#endif + +/* YYMAXRULES must be at least as large as the number of rules that */ +/* could be placed in the rule queue. That number could be determined */ +/* from the grammar and the size of the stack, but, as yet, it is not. */ + +#ifndef YYMAXRULES +#define YYMAXRULES 100 +#endif + +#ifndef YYMAXBACKUP +#define YYMAXBACKUP 100 +#endif + + +short yyss[YYMAXDEPTH]; /* the state stack */ +YYSTYPE yyvs[YYMAXDEPTH]; /* the semantic value stack */ +YYLTYPE yyls[YYMAXDEPTH]; /* the location stack */ +short yyrq[YYMAXRULES]; /* the rule queue */ +int yychar; /* the lookahead symbol */ + +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +YYSTYPE yytval; /* the semantic value for the state */ + /* at the top of the state stack. */ + +YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ + +YYLTYPE yytloc; /* location data for the state at the */ + /* top of the state stack */ + + +int yynunlexed; +short yyunchar[YYMAXBACKUP]; +YYSTYPE yyunval[YYMAXBACKUP]; +YYLTYPE yyunloc[YYMAXBACKUP]; + +short *yygssp; /* a pointer to the top of the state */ + /* stack; only set during error */ + /* recovery. */ + +YYSTYPE *yygvsp; /* a pointer to the top of the value */ + /* stack; only set during error */ + /* recovery. */ + +YYLTYPE *yyglsp; /* a pointer to the top of the */ + /* location stack; only set during */ + /* error recovery. */ + + +/* Yyget is an interface between the parser and the lexical analyzer. */ +/* It is costly to provide such an interface, but it avoids requiring */ +/* the lexical analyzer to be able to back up the scan. */ + +yyget() +{ + if (yynunlexed > 0) + { + yynunlexed--; + yychar = yyunchar[yynunlexed]; + yylval = yyunval[yynunlexed]; + yylloc = yyunloc[yynunlexed]; + } + else if (yychar <= 0) + yychar = 0; + else + { + yychar = yylex(); + if (yychar < 0) + yychar = 0; + else yychar = YYTRANSLATE(yychar); + } +} + + + +yyunlex(chr, val, loc) +int chr; +YYSTYPE val; +YYLTYPE loc; +{ + yyunchar[yynunlexed] = chr; + yyunval[yynunlexed] = val; + yyunloc[yynunlexed] = loc; + yynunlexed++; +} + + + +yyrestore(first, last) +register short *first; +register short *last; +{ + register short *ssp; + register short *rp; + register int symbol; + register int state; + register int tvalsaved; + + ssp = yygssp; + yyunlex(yychar, yylval, yylloc); + + tvalsaved = 0; + while (first != last) + { + symbol = yystos[*ssp]; + if (symbol < YYNTBASE) + { + yyunlex(symbol, yytval, yytloc); + tvalsaved = 1; + ssp--; + } + + ssp--; + + if (first == yyrq) + first = yyrq + YYMAXRULES; + + first--; + + for (rp = yyrhs + yyprhs[*first]; symbol = *rp; rp++) + { + if (symbol < YYNTBASE) + state = yytable[yypact[*ssp] + symbol]; + else + { + state = yypgoto[symbol - YYNTBASE] + *ssp; + + if (state >= 0 && state <= YYLAST && yycheck[state] == *ssp) + state = yytable[state]; + else + state = yydefgoto[symbol - YYNTBASE]; + } + + *++ssp = state; + } + } + + if ( ! tvalsaved && ssp > yyss) + { + yyunlex(yystos[*ssp], yytval, yytloc); + ssp--; + } + + yygssp = ssp; +} + + + +int +yyparse() +{ + register int yystate; + register int yyn; + register short *yyssp; + register short *yyrq0; + register short *yyptr; + register YYSTYPE *yyvsp; + + int yylen; + YYLTYPE *yylsp; + short *yyrq1; + short *yyrq2; + + yystate = 0; + yyssp = yyss - 1; + yyvsp = yyvs - 1; + yylsp = yyls - 1; + yyrq0 = yyrq; + yyrq1 = yyrq0; + yyrq2 = yyrq0; + + yychar = yylex(); + if (yychar < 0) + yychar = 0; + else yychar = YYTRANSLATE(yychar); + +yynewstate: + + if (yyssp >= yyss + YYMAXDEPTH - 1) + { + yyabort("Parser Stack Overflow"); + YYABORT; + } + + *++yyssp = yystate; + +yyresume: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + yyn += yychar; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar) + goto yydefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + yystate = yyn; + + yyptr = yyrq2; + while (yyptr != yyrq1) + { + yyn = *yyptr++; + yylen = yyr2[yyn]; + yyvsp -= yylen; + yylsp -= yylen; + + yyguard(yyn, yyvsp, yylsp); + if (yyerror) + goto yysemerr; + + yyaction(yyn, yyvsp, yylsp); + *++yyvsp = yyval; + + yylsp++; + if (yylen == 0) + { + yylsp->timestamp = timeclock; + yylsp->first_line = yytloc.first_line; + yylsp->first_column = yytloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } + + if (yyptr == yyrq + YYMAXRULES) + yyptr = yyrq; + } + + if (yystate == YYFINAL) + YYACCEPT; + + yyrq2 = yyptr; + yyrq1 = yyrq0; + + *++yyvsp = yytval; + *++yylsp = yytloc; + yytval = yylval; + yytloc = yylloc; + yyget(); + + goto yynewstate; + +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +yyreduce: + + *yyrq0++ = yyn; + + if (yyrq0 == yyrq + YYMAXRULES) + yyrq0 = yyrq; + + if (yyrq0 == yyrq2) + { + yyabort("Parser Rule Queue Overflow"); + YYABORT; + } + + yyssp -= yyr2[yyn]; + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yysemerr: + *--yyptr = yyn; + yyrq2 = yyptr; + yyvsp += yyr2[yyn]; + +yyerrlab: + + yygssp = yyssp; + yygvsp = yyvsp; + yyglsp = yylsp; + yyrestore(yyrq0, yyrq2); + yyrecover(); + yystate = *yygssp; + yyssp = yygssp; + yyvsp = yygvsp; + yyrq0 = yyrq; + yyrq1 = yyrq0; + yyrq2 = yyrq0; + goto yyresume; +} + +$ diff --git a/tools/bison.simple b/tools/bison.simple new file mode 100644 index 0000000..690fb2e --- /dev/null +++ b/tools/bison.simple @@ -0,0 +1,699 @@ +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not __GNUC__ */ +#if HAVE_ALLOCA_H +#include +#else /* not HAVE_ALLOCA_H */ +#ifdef _AIX + #pragma alloca +#else /* not _AIX */ +char *alloca (); +#endif /* not _AIX */ +#endif /* not HAVE_ALLOCA_H */ +#endif /* not __GNUC__ */ + +extern void yyerror(char* s); + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include +#else /* not sparc */ +#if (defined (MSDOS) && !defined (__TURBOC__)) || defined (WIN32) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (from, to, count) + char *from; + char *to; + size_t count; +{ + register char *f = from; + register char *t = to; + register size_t i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *from, char *to, size_t count) +{ + register char *f = from; + register char *t = to; + register size_t i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#ifndef YYPARSE_PARAM_DECL +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif +#else +#define YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#endif + +extern YY_DECL; + +int +yyparse(YYPARSE_PARAM_DECL YYPARSE_PARAM) { + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + size_t yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + size_t size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + +$ /* the action file gets copied in in place of this dollarsign */ + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} diff --git a/tools/flex.exe b/tools/flex.exe new file mode 100644 index 0000000000000000000000000000000000000000..58f10ce3561e8b693e3e4d3ef247bc6507c38608 GIT binary patch literal 181248 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