Full thread safety working:
authorJohn Kessenich <cepheus@frii.com>
Sun, 8 Sep 2013 21:04:46 +0000 (21:04 +0000)
committerJohn Kessenich <cepheus@frii.com>
Sun, 8 Sep 2013 21:04:46 +0000 (21:04 +0000)
 - don't use [] for map lookups, it can modify the map
 - copy up built-in symbols out of shared symbol table levels before modifying them
 - enforce shallow vs. deep TType copies
 - combine maxArraySize with the array dimensions vector, encapsulate
 - remove chaining of array types

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22953 e7fa87d3-cd2b-0410-9028-fcbf551c1848

17 files changed:
Install/Windows/glslangValidator.exe
Test/120.frag
Test/baseResults/120.frag.out
Test/baseResults/300.vert.out
Test/baseResults/array100.frag.out
glslang/Include/Types.h
glslang/Include/intermediate.h
glslang/MachineIndependent/Constant.cpp
glslang/MachineIndependent/Initialize.cpp
glslang/MachineIndependent/Intermediate.cpp
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.h
glslang/MachineIndependent/Scan.cpp
glslang/MachineIndependent/ShaderLang.cpp
glslang/MachineIndependent/SymbolTable.cpp
glslang/MachineIndependent/SymbolTable.h
glslang/MachineIndependent/glslang.y

index b31e3fc..2598017 100644 (file)
Binary files a/Install/Windows/glslangValidator.exe and b/Install/Windows/glslangValidator.exe differ
index c00eccb..e6ed62a 100644 (file)
@@ -114,3 +114,12 @@ void v2()
 {
     return v1();  // ERROR, no expression allowed, even though void
 }
+
+void atest()
+{
+    vec4 v = gl_TexCoord[1];
+    v += gl_TexCoord[3];
+}
+
+varying vec4 gl_TexCoord[6];  // okay, assigning a size
+varying vec4 gl_TexCoord[5];  // ERROR, changing size
index 7d28dcd..49efdfc 100644 (file)
@@ -27,7 +27,8 @@ ERROR: 0:94: 'a' : variables with qualifier 'const' must be initialized
 ERROR: 0:97: 'out' : overloaded functions must have the same parameter qualifiers \r
 ERROR: 0:99: 'return' : function return is not matching type: \r
 ERROR: 0:115: 'return' : void function cannot return a value \r
-ERROR: 29 compilation errors.  No code generated.\r
+ERROR: 0:125: 'gl_TexCoord' : redeclaration of array with size \r
+ERROR: 30 compilation errors.  No code generated.\r
 \r
 ERROR: node is still EOpNull!\r
 0:21  Function Definition: main( (void)\r
@@ -265,6 +266,20 @@ ERROR: node is still EOpNull!
 0:115    Sequence\r
 0:115      Branch: Return with expression\r
 0:115        Function Call: v1( (void)\r
+0:118  Function Definition: atest( (void)\r
+0:118    Function Parameters: \r
+0:120    Sequence\r
+0:120      Sequence\r
+0:120        move second child to first child (4-component vector of float)\r
+0:120          'v' (4-component vector of float)\r
+0:120          direct index (smooth in 4-component vector of float)\r
+0:120            'gl_TexCoord' (smooth in unsized array of 4-component vector of float)\r
+0:120            1 (const int)\r
+0:121      add second child into first child (4-component vector of float)\r
+0:121        'v' (4-component vector of float)\r
+0:121        direct index (smooth in 4-component vector of float)\r
+0:121          'gl_TexCoord' (smooth in unsized array of 4-component vector of float)\r
+0:121          3 (const int)\r
 0:?   Linker Objects\r
 0:?     'i' (smooth in 4-component vector of float)\r
 0:?     'o' (out 4-component vector of float)\r
index 7f75c65..550b748 100644 (file)
@@ -134,7 +134,7 @@ ERROR: node is still EOpNull!
 0:?     'rep2' (centroid smooth sample out highp 4-component vector of float)\r
 0:?     'rep3' (in highp 4-component vector of float)\r
 0:?     's' (smooth out structure)\r
-0:?     'ubInst' (layout(shared ) uniform 1-element array of block)\r
+0:?     'ubInst' (layout(shared ) uniform unsized array of block)\r
 0:?     'gl_VertexID' (gl_VertexId highp int)\r
 0:?     'gl_InstanceID' (gl_InstanceId highp int)\r
 \r
index 83577c9..4dd0235 100644 (file)
@@ -5,7 +5,7 @@ ERROR: 0:9: 'arrayed type' : not supported for this version or the enabled exten
 ERROR: 0:11: 'arrayed constructor' : not supported for this version or the enabled extensions \r
 ERROR: 0:21: '[' :  array index out of range '2'\r
 ERROR: 0:25: 'assign' :  cannot convert from '4-element array of mediump float' to '5-element array of mediump float'\r
-ERROR: 0:26: 'assign' :  cannot convert from '4-element array of mediump float' to '1-element array of mediump float'\r
+ERROR: 0:26: 'assign' :  cannot convert from '4-element array of mediump float' to 'unsized array of mediump float'\r
 ERROR: 0:28: 'foo' : no matching overloaded function found \r
 ERROR: 0:31: 'arrayed constructor' : not supported for this version or the enabled extensions \r
 ERROR: 0:35: '[' :  array index out of range '5'\r
@@ -49,7 +49,7 @@ ERROR: node is still EOpNull!
 0:24        Function Call: foo(f1[5]; (4-element array of mediump float)\r
 0:24          'g5' (5-element array of mediump float)\r
 0:25      'g5' (5-element array of mediump float)\r
-0:26      'gu' (1-element array of mediump float)\r
+0:26      'gu' (unsized array of mediump float)\r
 0:28      0.000000\r
 0:29      Function Call: bar(f1[5]; (void)\r
 0:29        'g5' (5-element array of mediump float)\r
@@ -64,7 +64,7 @@ ERROR: node is still EOpNull!
 0:31        true case\r
 0:32        move second child to first child (mediump float)\r
 0:32          direct index (mediump float)\r
-0:32            'gu' (1-element array of mediump float)\r
+0:32            'gu' (unsized array of mediump float)\r
 0:32            0 (const int)\r
 0:32          2.000000\r
 0:35      move second child to first child (mediump float)\r
index e4f6055..feee5b9 100644 (file)
@@ -174,12 +174,21 @@ inline TIdentifierList* NewPoolTIdentifierList()
 // for the vast majority of non-array types.  Note that means if it
 // is used, it will be containing at least one size.
 
-typedef TVector<int>* TArraySizes;
+struct TArraySizes {
+    TArraySizes() : maxArraySize(0) { }
+    int getSize() { return sizes.front(); }  // TArraySizes only exists if there is at least one dimension
+    void setSize(int s) { sizes.push_back(s); }
+    bool isArrayOfArrays() { return sizes.size() > 1; }
+protected:
+    TVector<int> sizes;
+    friend class TType;
+    int maxArraySize; // for tracking maximum referenced index, before an explicit size is given
+};
 
-inline TArraySizes NewPoolTArraySizes()
+inline TArraySizes* NewPoolTArraySizes()
 {
-    void* memory = GetThreadPoolAllocator().allocate(sizeof(TVector<int>));
-    return new(memory) TVector<int>;
+    void* memory = GetThreadPoolAllocator().allocate(sizeof(TArraySizes));
+    return new(memory) TArraySizes;
 }
 
 //
@@ -347,7 +356,7 @@ public:
     int vectorSize : 4;
     int matrixCols : 4;
     int matrixRows : 4;
-    TArraySizes arraySizes;
+    TArraySizes* arraySizes;
     const TType* userDef;
     TSourceLoc loc;
 
@@ -398,16 +407,16 @@ public:
 
 typedef std::map<TTypeList*, TTypeList*> TStructureMap;
 typedef std::map<TTypeList*, TTypeList*>::const_iterator TStructureMapIterator;
+
 //
 // Base class for things that have a type.
 //
 class TType {
 public:
     POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
-    explicit TType(TBasicType t, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0) :
+    explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0) :
                             basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(0),
-                            structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0),
-                            fieldName(0), typeName(0)
+                            structure(0), structureSize(0), fieldName(0), typeName(0)
                             {
                                 sampler.clear();
                                 qualifier.clear();
@@ -415,8 +424,7 @@ public:
                             }
     TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0) :
                             basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(0),
-                            structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0),
-                            fieldName(0), typeName(0)
+                            structure(0), structureSize(0), fieldName(0), typeName(0)
                             {
                                 sampler.clear();
                                 qualifier.clear();
@@ -426,7 +434,7 @@ public:
                             }
     explicit TType(const TPublicType &p) :
                             basicType(p.basicType), vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), arraySizes(p.arraySizes),
-                            structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), typeName(0)
+                            structure(0), structureSize(0), fieldName(0), typeName(0)
                             {
                                 if (basicType == EbtSampler)
                                     sampler = p.sampler;
@@ -440,7 +448,7 @@ public:
                             }
     TType(TTypeList* userDef, const TString& n, TStorageQualifier blockQualifier = EvqGlobal) :
                             basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), arraySizes(0),
-                            structure(userDef), maxArraySize(0), arrayInformationType(0), fieldName(0)
+                            structure(userDef), fieldName(0)
                             {
                                 sampler.clear();
                                 qualifier.clear();
@@ -451,32 +459,37 @@ public:
                                 }
                                                                typeName = NewPoolTString(n.c_str());
                             }
-       TType() {}
     virtual ~TType() {}
-
-    // "dumb" copy, using built-in operator=(), not for use across pool pops.
-    // It will also cause multiple copies of TType to point to the same information.
-    // This only works if that information (like a structure's list of types) does not 
-    // change.
-       explicit TType(const TType& type) { *this = type; }
-
-       void copyType(const TType& copyOf, const TStructureMap& remapper)
-       {
+    
+    // Not for use across pool pops; it will cause multiple instances of TType to point to the same information.
+    // This only works if that information (like a structure's list of types) does not change and 
+    // the instances are sharing the same pool. 
+    void shallowCopy(const TType& copyOf)
+    {
                basicType = copyOf.basicType;
         sampler = copyOf.sampler;
                qualifier = copyOf.qualifier;
                vectorSize = copyOf.vectorSize;
                matrixCols = copyOf.matrixCols;
                matrixRows = copyOf.matrixRows;
+        arraySizes = copyOf.arraySizes;
+        structure = copyOf.structure;
+        structureSize = copyOf.structureSize;
+           fieldName = copyOf.fieldName;
+           typeName = copyOf.typeName;
+    }
 
-        if (copyOf.arraySizes) {
+       void deepCopy(const TType& copyOf, const TStructureMap& remapper)
+       {
+        shallowCopy(copyOf);
+
+        if (arraySizes) {
             arraySizes = NewPoolTArraySizes();
             *arraySizes = *copyOf.arraySizes;
-        } else
-            arraySizes = 0;
+        }
 
-               TStructureMapIterator iter;
-               if (copyOf.structure) {
+               if (structure) {
+               TStructureMapIterator iter;
                if ((iter = remapper.find(structure)) == remapper.end()) {
                                // create the new structure here
                                structure = NewPoolTTypeList();
@@ -489,20 +502,12 @@ public:
                        } else {
                                structure = iter->second;
                        }
-               } else
-                       structure = 0;
+               }
 
-               fieldName = 0;
-               if (copyOf.fieldName)
+               if (fieldName)
                        fieldName = NewPoolTString(copyOf.fieldName->c_str());
-               typeName = 0;
-               if (copyOf.typeName)
+               if (typeName)
                        typeName = NewPoolTString(copyOf.typeName->c_str());
-               
-               structureSize = copyOf.structureSize;
-               maxArraySize = copyOf.maxArraySize;
-               assert(copyOf.arrayInformationType == 0);
-               arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level
        }
 
     // Merge type from parent, where a parentType is at the beginning of a declaration,
@@ -523,17 +528,16 @@ public:
        TType* clone(const TStructureMap& remapper)
        {
                TType *newType = new TType();
-               newType->copyType(*this, remapper);
+               newType->deepCopy(*this, remapper);
 
                return newType;
        }
 
     virtual void dereference()
     {
-        if (arraySizes) {
+        if (arraySizes)
             arraySizes = 0;
-            maxArraySize = 0;
-        } else if (matrixCols > 0) {
+        else if (matrixCols > 0) {
             vectorSize = matrixRows;
             matrixCols = 0;
             matrixRows = 0;
@@ -576,8 +580,8 @@ public:
 
        virtual bool isMatrix() const { return matrixCols ? true : false; }
     virtual bool isArray() const  { return arraySizes != 0; }
-    int getArraySize() const { return arraySizes->front(); }
-    void setArraySizes(TArraySizes s) 
+    int getArraySize() const { return arraySizes->sizes.front(); }
+    void setArraySizes(TArraySizes* s) 
     {
         // copy; we don't want distinct types sharing the same descriptor
         if (! arraySizes)
@@ -585,11 +589,9 @@ public:
         *arraySizes = *s;
     }
     
-    void changeArraySize(int s) { arraySizes->front() = s; }
-    void setMaxArraySize (int s) { maxArraySize = s; }
-    int getMaxArraySize () const { return maxArraySize; }
-    void setArrayInformationType(TType* t) { arrayInformationType = t; }
-    TType* getArrayInformationType() { return arrayInformationType; }
+    void changeArraySize(int s) { arraySizes->sizes.front() = s; }
+    void setMaxArraySize (int s) { arraySizes->maxArraySize = s; }
+    int getMaxArraySize () const { return arraySizes->maxArraySize; }
     virtual bool isVector() const { return vectorSize > 1; }
     virtual bool isScalar() const { return vectorSize == 1; }
     const char* getBasicString() const 
@@ -660,10 +662,10 @@ public:
         if (qualifier.storage != EvqTemporary && qualifier.storage != EvqGlobal)
             p += snprintf(p, end - p, "%s ", getStorageQualifierString());
         if (arraySizes) {
-            if (arraySizes->front() == 0)
+            if (arraySizes->sizes.front() == 0)
                 p += snprintf(p, end - p, "unsized array of ");
             else
-                p += snprintf(p, end - p, "%d-element array of ", arraySizes->front());
+                p += snprintf(p, end - p, "%d-element array of ", arraySizes->sizes.front());
         }
         if (qualifier.precision != EpqNone)
             p += snprintf(p, end - p, "%s ", getPrecisionQualifierString());
@@ -706,6 +708,8 @@ public:
         if (isArray())
             totalSize *= Max(getArraySize(), getMaxArraySize());
 
+        // TODO: desktop arrays: it should be ill-defined to get object size if the array is not sized, so the max() above maybe should be an assert
+
         return totalSize;
     }
 
@@ -730,7 +734,7 @@ public:
     {
         return sameElementType(right) &&
                (arraySizes == 0 && right.arraySizes == 0 ||
-                (arraySizes && right.arraySizes && *arraySizes == *right.arraySizes));
+                (arraySizes && right.arraySizes && arraySizes->sizes == right.arraySizes->sizes));
         // don't check the qualifier, it's not ever what's being sought after
     }
 
@@ -740,6 +744,10 @@ public:
     }
 
 protected:
+    // Require consumer to pick between deep copy and shallow copy.
+    TType(const TType& type);
+    TType& operator=(const TType& type);
+
     void buildMangledName(TString&);
     int getStructSize() const;
 
@@ -750,12 +758,10 @@ protected:
     TSampler sampler;
     TQualifier qualifier;
 
-    TArraySizes arraySizes;
+    TArraySizes* arraySizes;
 
-    TTypeList* structure;      // 0 unless this is a struct
-    mutable int structureSize; // a cache, updated on first access
-    int maxArraySize;
-    TType* arrayInformationType;
+    TTypeList* structure;       // 0 unless this is a struct
+    mutable int structureSize;  // a cache, updated on first access
        TString *fieldName;         // for structure field names
        TString *typeName;          // for structure field type name
 };
index f87428a..d735bda 100644 (file)
@@ -372,11 +372,11 @@ struct TIntermNodePair {
 //
 class TIntermTyped : public TIntermNode {
 public:
-       TIntermTyped(const TType& t) : type(t)  { }
+       TIntermTyped(const TType& t) { type.shallowCopy(t); }
     virtual TIntermTyped* getAsTyped()         { return this; }
-    virtual void setType(const TType& t) { type = t; }
+    virtual void setType(const TType& t) { type.shallowCopy(t); }
     virtual const TType& getType() const { return type; }
-    virtual TType* getTypePointer() { return &type; }
+    virtual TType& getWritableType() { return type; }
     
     virtual TBasicType getBasicType() const { return type.getBasicType(); }
     virtual TQualifier& getQualifier() { return type.getQualifier(); }
index 77cfcb1..8aa4ed8 100644 (file)
@@ -71,7 +71,8 @@ bool CompareStruct(const TType& leftNodeType, TConstUnion* rightUnionArray, TCon
 bool CompareStructure(const TType& leftNodeType, TConstUnion* rightUnionArray, TConstUnion* leftUnionArray)
 {
     if (leftNodeType.isArray()) {
-        TType typeWithoutArrayness(leftNodeType);
+        TType typeWithoutArrayness;
+        typeWithoutArrayness.shallowCopy(leftNodeType);  // TODO: arrays of arrays: the shallow copy won't work if arrays are shared and dereferenced
         typeWithoutArrayness.dereference();
 
         int arraySize = leftNodeType.getArraySize();
@@ -137,7 +138,8 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
 
     // For most cases, the return type matches the argument type, so set that
     // up and just code to exceptions below.
-    TType returnType(getType());
+    TType returnType;
+    returnType.shallowCopy(getType());
 
     //
     // A pair of nodes is to be folded together
@@ -157,7 +159,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
         unionArray = new TConstUnion[constantNode->getType().getObjectSize()];
         for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
             unionArray[i] = *getUnionArrayPointer();
-        returnType = node->getType();
+        returnType.shallowCopy(node->getType());
         objectSize = constantNode->getType().getObjectSize();
     }
 
@@ -192,7 +194,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
                 newConstArray[column * getMatrixRows() + row].setDConst(sum);
             }
         }
-        returnType = TType(getType().getBasicType(), EvqConst, 0, getMatrixRows(), node->getMatrixCols());
+        returnType.shallowCopy(TType(getType().getBasicType(), EvqConst, 0, getMatrixRows(), node->getMatrixCols()));
         break;
     case EOpDiv:
         newConstArray = new TConstUnion[objectSize];
@@ -232,7 +234,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
             newConstArray[i].setDConst(sum);
         }
 
-        returnType = TType(getBasicType(), EvqConst, getMatrixRows());
+        returnType.shallowCopy(TType(getBasicType(), EvqConst, getMatrixRows()));
         break;
 
     case EOpVectorTimesMatrix:
@@ -244,7 +246,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
             newConstArray[i].setDConst(sum);
         }
 
-        returnType = TType(getBasicType(), EvqConst, node->getMatrixCols());
+        returnType.shallowCopy(TType(getBasicType(), EvqConst, node->getMatrixCols()));
         break;
 
     case EOpMod:
@@ -307,13 +309,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
         assert(objectSize == 1);
         newConstArray = new TConstUnion[1];
         newConstArray->setBConst(*unionArray < *rightUnionArray);
-        returnType = TType(EbtBool, EvqConst);
+        returnType.shallowCopy(TType(EbtBool, EvqConst));
         break;
     case EOpGreaterThan:
         assert(objectSize == 1);
         newConstArray = new TConstUnion[1];
         newConstArray->setBConst(*unionArray > *rightUnionArray);
-        returnType = TType(EbtBool, EvqConst);
+        returnType.shallowCopy(TType(EbtBool, EvqConst));
         break;
     case EOpLessThanEqual:
     {
@@ -322,7 +324,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
         constant.setBConst(*unionArray > *rightUnionArray);
         newConstArray = new TConstUnion[1];
         newConstArray->setBConst(!constant.getBConst());
-        returnType = TType(EbtBool, EvqConst);
+        returnType.shallowCopy(TType(EbtBool, EvqConst));
         break;
     }
     case EOpGreaterThanEqual:
@@ -332,7 +334,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
         constant.setBConst(*unionArray < *rightUnionArray);
         newConstArray = new TConstUnion[1];
         newConstArray->setBConst(!constant.getBConst());
-        returnType = TType(EbtBool, EvqConst);
+        returnType.shallowCopy(TType(EbtBool, EvqConst));
         break;
     }
 
@@ -351,7 +353,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
 
         newConstArray = new TConstUnion[1];
         newConstArray->setBConst(! boolNodeFlag);
-        returnType = TType(EbtBool, EvqConst);
+        returnType.shallowCopy(TType(EbtBool, EvqConst));
         break;
 
     case EOpNotEqual:
@@ -369,7 +371,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
 
         newConstArray = new TConstUnion[1];
         newConstArray->setBConst(! boolNodeFlag);
-        returnType = TType(EbtBool, EvqConst);
+        returnType.shallowCopy(TType(EbtBool, EvqConst));
         break;
 
     default:
@@ -607,7 +609,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
     }
 
     TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
-    newNode->getTypePointer()->getQualifier().storage = EvqConst;
+    newNode->getWritableType().getQualifier().storage = EvqConst;
     newNode->setLoc(getLoc());
 
     return newNode;
@@ -775,7 +777,7 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
     }
 
     TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType());
-    newNode->getTypePointer()->getQualifier().storage = EvqConst;
+    newNode->getWritableType().getQualifier().storage = EvqConst;
     newNode->setLoc(aggrNode->getLoc());
 
     return newNode;
index 7739d74..0080c77 100644 (file)
@@ -1654,8 +1654,8 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb
         if (version < FirstProfileVersion || profile == ECompatibilityProfile || (! ForwardCompatibility && profile != EEsProfile && version < 420)) {
             TPrecisionQualifier pq = profile == EEsProfile ? EpqMedium : EpqNone;
             TType fragData(EbtFloat, EvqFragColor, 4);
-            TArraySizes arraySizes = NewPoolTArraySizes();
-            arraySizes->push_back(resources.maxDrawBuffers);
+            TArraySizes* arraySizes = NewPoolTArraySizes();
+            arraySizes->setSize(resources.maxDrawBuffers);
             fragData.setArraySizes(arraySizes);
             symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
         }
index 9baa293..a484742 100644 (file)
@@ -716,8 +716,8 @@ TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, T
         TIntermTyped *commaAggregate = growAggregate(left, right, loc);
         commaAggregate->getAsAggregate()->setOperator(EOpComma);
         commaAggregate->setType(right->getType());
-        commaAggregate->getTypePointer()->getQualifier().storage = EvqTemporary;
-        commaAggregate->getTypePointer()->getQualifier().precision = right->getTypePointer()->getQualifier().precision;
+        commaAggregate->getWritableType().getQualifier().storage = EvqTemporary;
+        commaAggregate->getWritableType().getQualifier().precision = right->getType().getQualifier().precision;
 
         return commaAggregate;
     }
@@ -1028,7 +1028,7 @@ bool TIntermUnary::promote()
     }
 
     setType(operand->getType());
-    getTypePointer()->getQualifier().storage = EvqTemporary;
+    getWritableType().getQualifier().storage = EvqTemporary;
 
     return true;
 }
index b03063e..2ad40e7 100644 (file)
@@ -482,8 +482,7 @@ TIntermTyped* TParseContext::handleVariable(TSourceLoc loc, TSymbol* symbol, TSt
 
         if (variable->getType().getQualifier().storage == EvqConst ) {
             TConstUnion* constArray = variable->getConstUnionPointer();
-            TType t(variable->getType());
-            node = intermediate.addConstantUnion(constArray, t, loc);
+            node = intermediate.addConstantUnion(constArray, variable->getType(), loc);
         } else
             node = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), loc);
     }
@@ -527,9 +526,7 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
             if (base->isArray()) {
                 if (base->getType().getArraySize() == 0) {
                     if (base->getType().getMaxArraySize() <= index->getAsConstantUnion()->getUnionArrayPointer()->getIConst())
-                        arraySetMaxSize(base->getAsSymbolNode(), base->getTypePointer(), index->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, loc);
-                    else
-                        arraySetMaxSize(base->getAsSymbolNode(), base->getTypePointer(), 0, false, loc);
+                        arraySetMaxSize(loc, base->getAsSymbolNode(), index->getAsConstantUnion()->getUnionArrayPointer()->getIConst() + 1);
                 } else if ( index->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= base->getType().getArraySize() ||
                             index->getAsConstantUnion()->getUnionArrayPointer()->getIConst() < 0)
                     error(loc, "", "[", "array index out of range '%d'", index->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
@@ -554,7 +551,8 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
         unionArray->setDConst(0.0);
         result = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), loc);
     } else {
-        TType newType(base->getType());
+        TType newType;
+        newType.shallowCopy(base->getType());
         if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst)
             newType.getQualifier().storage = EvqConst;
         newType.dereference();
@@ -634,7 +632,7 @@ TIntermTyped* TParseContext::handleDotDereference(TSourceLoc loc, TIntermTyped*
                         result->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.
-                        result->getTypePointer()->getQualifier().storage = EvqConst;
+                        result->getWritableType().getQualifier().storage = EvqConst;
                     }
                 } else {
                     TConstUnion *unionArray = new TConstUnion[1];
@@ -1213,7 +1211,7 @@ bool TParseContext::reservedErrorCheck(TSourceLoc loc, const TString& identifier
 //
 bool TParseContext::constructorError(TSourceLoc loc, TIntermNode* node, TFunction& function, TOperator op, TType& type)
 {
-    type = function.getReturnType();
+    type.shallowCopy(function.getReturnType());
 
     bool constructingMatrix = false;
     switch(op) {
@@ -1617,33 +1615,6 @@ bool TParseContext::containsSampler(const TType& type)
     return false;
 }
 
-bool TParseContext::insertBuiltInArrayAtGlobalLevel()
-{
-    TString *name = NewPoolTString("gl_TexCoord");
-    TSymbol* symbol = symbolTable.find(*name);
-    if (! symbol) {
-        // assume it was not added due to version/profile
-
-        return false;
-    }
-    const TVariable* variable = symbol->getAsVariable();
-
-    if (! variable) {
-        infoSink.info.message(EPrefixInternalError, "variable expected");
-        return true;
-    }
-
-    TVariable* newVariable = new TVariable(name, variable->getType());
-
-    if (! symbolTable.insert(*newVariable)) {
-        delete newVariable;
-        infoSink.info.message(EPrefixInternalError, "inserting new symbol");
-        return true;
-    }
-
-    return false;
-}
-
 //
 // Do size checking for an array type's size.
 //
@@ -1688,7 +1659,7 @@ bool TParseContext::arrayQualifierError(TSourceLoc loc, const TPublicType& type)
 //
 // Require array to have size
 //
-void TParseContext::arraySizeRequiredCheck(TSourceLoc loc, int& size)
+void TParseContext::arraySizeRequiredCheck(TSourceLoc loc, int size)
 {
     if (size == 0) {
         error(loc, "array size required", "", "");
@@ -1703,18 +1674,18 @@ void TParseContext::arrayDimError(TSourceLoc loc)
     profileRequires(loc, ECompatibilityProfile, 430, 0, "arrays of arrays");
 }
 
-void TParseContext::arrayDimCheck(TSourceLoc loc, TArraySizes sizes1, TArraySizes sizes2)
+void TParseContext::arrayDimCheck(TSourceLoc loc, TArraySizes* sizes1, TArraySizes* sizes2)
 {
     if (sizes1 && sizes2 ||
-        sizes1 && sizes1->size() > 1 ||
-        sizes2 && sizes2->size() > 1)
+        sizes1 && sizes1->isArrayOfArrays() ||
+        sizes2 && sizes2->isArrayOfArrays())
         arrayDimError(loc);
 }
 
-void TParseContext::arrayDimCheck(TSourceLoc loc, const TType* type, TArraySizes sizes2)
+void TParseContext::arrayDimCheck(TSourceLoc loc, const TType* type, TArraySizes* sizes2)
 {
     if (type && type->isArray() && sizes2 ||
-        sizes2 && sizes2->size() > 1)
+        sizes2 && sizes2->isArrayOfArrays())
         arrayDimError(loc);
 }
 
@@ -1733,6 +1704,8 @@ void TParseContext::arrayCheck(TSourceLoc loc, TString& identifier, const TPubli
     // However, reserved arrays cannot be modified in a shared symbol table, so add a new
     // one at a non-shared level in the table.
     //
+    // Redeclarations have to take place at the same scope; otherwise they are hiding declarations
+    //
 
     bool currentScope;
     TSymbol* symbol = symbolTable.find(identifier, 0, &currentScope);
@@ -1764,23 +1737,19 @@ void TParseContext::arrayCheck(TSourceLoc loc, TString& identifier, const TPubli
             return;
         }
 
-        TType* t = variable->getArrayInformationType();
-        while (t != 0) {
-            if (t->getMaxArraySize() > type.arraySizes->front()) {
-                error(loc, "higher index value already used for the array", identifier.c_str(), "");
-                return;
-            }
-            t->setArraySizes(type.arraySizes);
-            t = t->getArrayInformationType();
-        }
+        // For read-only built-ins, add a new variable for holding the declared array size of an implicitly-sized shared array.
+        if (variable->isReadOnly())
+            variable = symbolTable.copyUp(variable);
 
+        // TODO: desktop unsized arrays: include modified built-in arrays (gl_TexCoord) in the linker objects subtree
+        
         variable->getWritableType().setArraySizes(type.arraySizes);
     } 
 
     voidErrorCheck(loc, identifier, type);
 }
 
-bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc loc)
+bool TParseContext::arraySetMaxSize(TSourceLoc loc, TIntermSymbol *node, int size)
 {
     TSymbol* symbol = symbolTable.find(node->getName());
     if (symbol == 0) {
@@ -1794,41 +1763,26 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size,
         return true;
     }
 
-    // There are multiple copies of the array type tagging results of operations.
-    // Chain these together, so they can all reflect the final size.
-    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->getName() == "gl_TexCoord") {
-        TSymbol* texCoord = symbolTable.find("gl_MaxTextureCoords");
-        if (! texCoord || ! texCoord->getAsVariable()) {
-            infoSink.info.message(EPrefixInternalError, "gl_MaxTextureCoords not defined", loc);
-            return true;
-        }
+    // TODO: desktop linker: make this a link-time check (note if it's here, an explicit declaration skips it)
+    //if (node->getName() == "gl_TexCoord") {
+    //    TSymbol* texCoord = symbolTable.find("gl_MaxTextureCoords");
+    //    if (! texCoord || ! texCoord->getAsVariable()) {
+    //        infoSink.info.message(EPrefixInternalError, "gl_MaxTextureCoords not defined", loc);
+    //        return true;
+    //    }
 
-        int texCoordValue = texCoord->getAsVariable()->getConstUnionPointer()[0].getIConst();
-        if (texCoordValue <= size) {
-            error(loc, "", "[", "gl_TexCoord can only have a max array size of up to gl_MaxTextureCoords", "");
-            return true;
-        }
-    }
+    //    int texCoordValue = texCoord->getAsVariable()->getConstUnionPointer()[0].getIConst();
+    //    if (texCoordValue <= size) {
+    //        error(loc, "", "[", "gl_TexCoord can only have a max array size of up to gl_MaxTextureCoords", "");
+    //        return true;
+    //    }
+    //}
 
-    // We don't 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 it's updated when a higher maxArraySize comes in.
-    if (! updateFlag)
-        return false;
+    // For read-only built-ins, add a new variable for holding the maximum array size of an implicitly-sized shared array.
+    if (variable->isReadOnly())
+        variable = symbolTable.copyUp(variable);
 
-    size++;
     variable->getWritableType().setMaxArraySize(size);
-    type->setMaxArraySize(size);
-    TType* tt = type;
-
-    while(tt->getArrayInformationType() != 0) {
-        tt = tt->getArrayInformationType();
-        tt->setMaxArraySize(size);
-    }
 
     return false;
 }
@@ -2104,9 +2058,10 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType& type
     if (op == EOpConstructStruct)
         memberTypes = type.getStruct()->begin();
     
-    TType elementType(type);
+    TType elementType;
+    elementType.shallowCopy(type);
     if (type.isArray())
-        elementType.dereference();
+        elementType.dereference();  // TODO: arrays of arrays: shallow copy won't work if sharing same array structure and then doing a dereference
 
     bool singleArg;
     if (aggrNode) {
@@ -2280,7 +2235,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, const TType& typ
 //
 // Do everything needed to add an interface block.
 //
-void TParseContext::addBlock(TSourceLoc loc, TTypeList& typeList, const TString* instanceName, TArraySizes arraySizes)
+void TParseContext::addBlock(TSourceLoc loc, TTypeList& typeList, const TString* instanceName, TArraySizes* arraySizes)
 {
     // First, error checks
 
@@ -2291,7 +2246,7 @@ void TParseContext::addBlock(TSourceLoc loc, TTypeList& typeList, const TString*
         return;
 
     if (profile == EEsProfile && arraySizes)
-        arraySizeRequiredCheck(loc, arraySizes->front());        
+        arraySizeRequiredCheck(loc, arraySizes->getSize());        
 
     if (currentBlockDefaults.storage == EvqUniform) {
         requireProfile(loc, (EProfileMask)(~ENoProfileMask), "uniform block");
@@ -2370,8 +2325,7 @@ void TParseContext::addBlock(TSourceLoc loc, TTypeList& typeList, const TString*
 // For an identifier that is already declared, add more qualification to it.
 void TParseContext::addQualifierToExisting(TSourceLoc loc, TQualifier qualifier, const TString& identifier)
 {
-    bool sharedLevel;
-    TSymbol* existing = symbolTable.find(identifier, 0, 0, &sharedLevel);
+    TSymbol* existing = symbolTable.find(identifier);
     TVariable* variable = existing ? existing->getAsVariable() : 0;
     if (! variable) {
         error(loc, "identifier not previously declared", identifier.c_str(), "");
@@ -2389,13 +2343,9 @@ void TParseContext::addQualifierToExisting(TSourceLoc loc, TQualifier qualifier,
         return;
     }
 
-    //
-    // Don't change a shared variable; rather add a new one at the current scope.
-    //
-    if (sharedLevel) {
-        variable = new TVariable(&variable->getName(), variable->getType());
-        symbolTable.insert(*variable);
-    }
+    // For read-only built-ins, add a new variable for holding the modified qualifier.
+    if (variable->isReadOnly())
+        variable = symbolTable.copyUp(variable);
 
     if (qualifier.invariant)
         variable->getWritableType().getQualifier().invariant = true;
@@ -2646,8 +2596,9 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
     TIntermTyped* typedNode;
     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
     int arraySize = node->getType().getArraySize();
-    TType arrayElementType(node->getType());
-    arrayElementType.dereference();
+    TType arrayElementType;
+    arrayElementType.shallowCopy(node->getType());
+    arrayElementType.dereference();   // TODO: arrays of arrays: shallow copy won't work if sharing same array structure and then doing a dereference
 
     if (index >= node->getType().getArraySize() || index < 0) {
         error(loc, "", "[", "array index '%d' out of range", index);
index f077ce6..22ded39 100644 (file)
@@ -101,12 +101,11 @@ public:
     bool constructorError(TSourceLoc, TIntermNode*, TFunction&, TOperator, TType&);
     void arraySizeCheck(TSourceLoc, TIntermTyped* expr, int& size);
     bool arrayQualifierError(TSourceLoc, const TPublicType&);
-    void arraySizeRequiredCheck(TSourceLoc, int& size);
+    void arraySizeRequiredCheck(TSourceLoc, int size);
     void arrayDimError(TSourceLoc);
-    void arrayDimCheck(TSourceLoc, TArraySizes sizes1, TArraySizes sizes2);
-    void arrayDimCheck(TSourceLoc, const TType*, TArraySizes);
+    void arrayDimCheck(TSourceLoc, TArraySizes* sizes1, TArraySizes* sizes2);
+    void arrayDimCheck(TSourceLoc, const TType*, TArraySizes*);
     void arrayCheck(TSourceLoc, TString& identifier, const TPublicType&, TVariable*& variable);
-    bool insertBuiltInArrayAtGlobalLevel();
     bool voidErrorCheck(TSourceLoc, const TString&, const TPublicType&);
     void boolCheck(TSourceLoc, const TIntermTyped*);
     void boolCheck(TSourceLoc, const TPublicType&);
@@ -136,7 +135,7 @@ public:
     TIntermTyped* addConstructor(TIntermNode*, const TType&, TOperator, TFunction*, TSourceLoc);
     TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
     TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset);
-    void addBlock(TSourceLoc, TTypeList& typeList, const TString* instanceName = 0, TArraySizes arraySizes = 0);
+    void addBlock(TSourceLoc, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
     void addQualifierToExisting(TSourceLoc, TQualifier, const TString& identifier);
     void addQualifierToExisting(TSourceLoc, TQualifier, TIdentifierList&);
     void updateQualifierDefaults(TQualifier);
@@ -149,7 +148,7 @@ public:
     TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc);
     TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
 
-    bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
+    bool arraySetMaxSize(TSourceLoc, TIntermSymbol*, int);
 
     void requireProfile(TSourceLoc, EProfileMask profileMask, const char *featureDesc);
     void requireStage(TSourceLoc, EShLanguageMask languageMask, const char *featureDesc);
index e6232fb..446a014 100644 (file)
@@ -550,11 +550,12 @@ int TScanContext::tokenizeIdentifier()
     if (ReservedSet->find(tokenText) != ReservedSet->end())
         return reservedWord();
 
-    keyword = (*KeywordMap)[tokenText];
-    if (keyword == 0) {
+    std::map<std::string, int>::const_iterator it = KeywordMap->find(tokenText);
+    if (it == KeywordMap->end()) {
         // Should have an identifier of some sort
         return identifierOrType();
     }
+    keyword = it->second;
     field = false;
 
     switch (keyword) {
index 1b1b98d..7d7b75e 100644 (file)
@@ -449,9 +449,6 @@ bool CompileDeferred(
     if (! symbolTable.atGlobalLevel())
         parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
 
-    if (parseContext.insertBuiltInArrayAtGlobalLevel())
-        success = false;
-
     bool ret = parseContext.parseShaderStrings(ppContext, const_cast<char**>(shaderStrings), lengths, numStrings);
     if (! ret)
         success = false;
index 8fd892b..8e1c79d 100644 (file)
@@ -90,7 +90,7 @@ void TType::buildMangledName(TString& mangledName)
     case EbtStruct:
         mangledName += "struct-";
         if (typeName)
-               mangledName += *typeName;
+            mangledName += *typeName;
         for (unsigned int i = 0; i < structure->size(); ++i) {
             mangledName += '-';
             (*structure)[i].type->buildMangledName(mangledName);
@@ -107,9 +107,9 @@ void TType::buildMangledName(TString& mangledName)
     }
 
     if (arraySizes) {
-               const int maxSize = 11;
+        const int maxSize = 11;
         char buf[maxSize];
-        snprintf(buf, maxSize, "%d", arraySizes->front());
+        snprintf(buf, maxSize, "%d", arraySizes->sizes.front());
         mangledName += '[';
         mangledName += buf;
         mangledName += ']';
@@ -173,8 +173,8 @@ void TSymbolTable::dump(TInfoSink &infoSink) const
 //
 TFunction::~TFunction()
 {
-       for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
-               delete (*i).type;
+    for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
+        delete (*i).type;
 }
 
 //
@@ -182,8 +182,8 @@ TFunction::~TFunction()
 //
 TSymbolTableLevel::~TSymbolTableLevel()
 {
-       for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
-               delete (*it).second;
+    for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
+        delete (*it).second;
 
     delete [] defaultPrecision;
 }
@@ -213,58 +213,59 @@ void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
 void TSymbolTableLevel::readOnly()
 {
     for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
-        (*it).second->readOnly();
+        (*it).second->makeReadOnly();
 }
 
+//
+// Copy a symbol, but the copy is writable; call readOnly() afterward if that's not desired.
+//
 TSymbol::TSymbol(const TSymbol& copyOf)
 {
-       name = NewPoolTString(copyOf.name->c_str());
-       uniqueId = copyOf.uniqueId;
+    name = NewPoolTString(copyOf.name->c_str());
+    uniqueId = copyOf.uniqueId;
+    writable = true;
 }
 
 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 TConstUnion[1];
+    type.deepCopy(copyOf.type, remapper);
+    userType = copyOf.userType;
+
+    if (copyOf.unionArray) {
+        assert(!copyOf.type.getStruct());
+        assert(copyOf.type.getObjectSize() == 1);
+        unionArray = new TConstUnion[1];
         unionArray[0] = copyOf.unionArray[0];
-       } else
-               unionArray = 0;
+    } else
+        unionArray = 0;
 }
 
 TVariable* TVariable::clone(TStructureMap& remapper)
 {
-       TVariable *variable = new TVariable(*this, remapper);
+    TVariable *variable = new TVariable(*this, remapper);
 
-       return variable;
+    return variable;
 }
 
 TFunction::TFunction(const TFunction& copyOf, const 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;
+    for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
+        TParameter param;
+        parameters.push_back(param);
+        parameters.back().copyParam(copyOf.parameters[i], remapper);
+    }
+
+    returnType.deepCopy(copyOf.returnType, remapper);
+    mangledName = copyOf.mangledName;
+    op = copyOf.op;
+    defined = copyOf.defined;
 }
 
 TFunction* TFunction::clone(TStructureMap& remapper)
 {
-       TFunction *function = new TFunction(*this, remapper);
+    TFunction *function = new TFunction(*this, remapper);
 
-       return function;
+    return function;
 }
 
 TAnonMember* TAnonMember::clone(TStructureMap& remapper)
@@ -277,24 +278,24 @@ TAnonMember* TAnonMember::clone(TStructureMap& remapper)
 
 TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper)
 {
-       TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
+    TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
     symTableLevel->anonId = anonId;
-       tLevel::iterator iter;
-       for (iter = level.begin(); iter != level.end(); ++iter)
-               symTableLevel->insert(*iter->second->clone(remapper));
+    tLevel::iterator iter;
+    for (iter = level.begin(); iter != level.end(); ++iter)
+        symTableLevel->insert(*iter->second->clone(remapper));
 
-       return symTableLevel;
+    return symTableLevel;
 }
 
 void TSymbolTable::copyTable(const TSymbolTable& copyOf)
 {
     assert(adoptedLevels == copyOf.adoptedLevels);
 
-       TStructureMap remapper;
-       uniqueId = copyOf.uniqueId;
+    TStructureMap remapper;
+    uniqueId = copyOf.uniqueId;
     noBuiltInRedeclarations = copyOf.noBuiltInRedeclarations;
     for (unsigned int i = copyOf.adoptedLevels; i < copyOf.table.size(); ++i)
-               table.push_back(copyOf.table[i]->clone(remapper));
+        table.push_back(copyOf.table[i]->clone(remapper));
 }
 
 } // end namespace glslang
index 2a0352c..0b30723 100644 (file)
@@ -96,7 +96,8 @@ public:
     int getUniqueId() const { return uniqueId; }
     virtual void dump(TInfoSink &infoSink) const = 0;
 
-    void readOnly() { writable = false; }
+    bool isReadOnly() { return ! writable; }
+    void makeReadOnly() { writable = false; }
 
 protected:
        explicit TSymbol(const TSymbol&);
@@ -124,7 +125,7 @@ protected:
 //
 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) { }    
+    TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), userType(uT), unionArray(0) { type.shallowCopy(t); }
        virtual TVariable* clone(TStructureMap& remapper);
     virtual ~TVariable() { }
 
@@ -133,12 +134,11 @@ public:
     TType& getWritableType() { assert(writable); return type; }
     const TType& getType() const { return type; }
     bool isUserType() const { return userType; }
-    void updateArrayInformationType(TType *t) { assert(writable); arrayInformationType = t; }
-    TType* getArrayInformationType() { assert(writable); return arrayInformationType; }
 
     virtual void dump(TInfoSink &infoSink) const;
 
-    TConstUnion* getConstUnionPointer() {
+    TConstUnion* getConstUnionPointer()
+    {
         if (!unionArray)
             unionArray = new TConstUnion[type.getObjectSize()];
 
@@ -154,16 +154,15 @@ public:
     }
 
 protected:
-       explicit TVariable(TVariable&);
-       TVariable(const TVariable&, TStructureMap& remapper);
-    TVariable& operator=(TVariable&);
+    explicit TVariable(const TVariable&);
+    TVariable(const TVariable&, TStructureMap& remapper);
+    TVariable& operator=(const TVariable&);
 
     TType type;
     bool userType;
     // we are assuming that Pool Allocator will free the memory allocated to unionArray
     // when this object is destroyed
     TConstUnion *unionArray;
-    TType *arrayInformationType;  // this is used for updating maxArraySize in all the references to a given symbol
 };
 
 //
@@ -190,15 +189,13 @@ class TFunction : public TSymbol {
 public:
     explicit TFunction(TOperator o) :
         TSymbol(0),
-        returnType(TType(EbtVoid)),
         op(o),
         defined(false) { }
     TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) :
         TSymbol(name),
-        returnType(retType),
         mangledName(*name + '('),
         op(tOp),
-        defined(false) { }    
+        defined(false) { returnType.shallowCopy(retType); }    
        virtual TFunction* clone(TStructureMap& remapper);
        virtual ~TFunction();
 
@@ -455,7 +452,20 @@ public:
         return table[currentLevel()]->insert(symbol);
     }
 
-    TSymbol* find(const TString& name, bool* builtIn = 0, bool *currentScope = 0, bool *sharedLevel = 0)
+    //
+    // To copy a variable from a shared level up to the current level, so it can be 
+    // modified without impacting other users of the shared table.
+    //
+    TVariable* copyUp(TVariable* shared)
+    {        
+        TVariable* variable = shared->clone(remapper);
+        variable->setUniqueId(shared->getUniqueId());
+        table[currentLevel()]->insert(*variable);
+
+        return variable;
+    }
+
+    TSymbol* find(const TString& name, bool* builtIn = 0, bool *currentScope = 0)
     {
         int level = currentLevel();
         TSymbol* symbol;
@@ -467,9 +477,7 @@ public:
         if (builtIn)
             *builtIn = isBuiltInLevel(level);
         if (currentScope)
-            *currentScope = level == currentLevel();
-        if (sharedLevel)
-            *sharedLevel = isSharedLevel(level);
+            *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel();  // consider shared levels as "current scope" WRT user globals
 
         return symbol;
     }
@@ -502,6 +510,7 @@ protected:
     int uniqueId;     // for unique identification in code generation
     bool noBuiltInRedeclarations;
     unsigned int adoptedLevels;
+    TStructureMap remapper;  // for now, dummy for copyUp(), which is not yet used for structures
 };
 
 } // end namespace glslang
index 3de7e72..73688db 100644 (file)
@@ -90,7 +90,7 @@ using namespace glslang;
             glslang::TParameter param;\r
             glslang::TTypeLoc typeLine;\r
             glslang::TTypeList* typeList;\r
-            glslang::TArraySizes arraySizes;\r
+            glslang::TArraySizes* arraySizes;\r
             glslang::TIdentifierList* identifierList;\r
         };\r
     } interm;\r
@@ -334,13 +334,15 @@ function_call_header_no_parameters
 \r
 function_call_header_with_parameters\r
     : function_call_header assignment_expression {\r
-        TParameter param = { 0, new TType($2->getType()) };\r
+        TParameter param = { 0, new TType };\r
+        param.type->shallowCopy($2->getType());\r
         $1.function->addParameter(param);\r
         $$.function = $1.function;\r
         $$.intermNode = $2;\r
     }\r
     | function_call_header_with_parameters COMMA assignment_expression {\r
-        TParameter param = { 0, new TType($3->getType()) };\r
+        TParameter param = { 0, new TType };\r
+        param.type->shallowCopy($3->getType());\r
         $1.function->addParameter(param);\r
         $$.function = $1.function;\r
         $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, $3, $2.loc);\r
@@ -890,7 +892,7 @@ parameter_declarator
         if ($1.arraySizes) {\r
             parseContext.profileRequires($1.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");\r
             parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");\r
-            parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->front());\r
+            parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->getSize());\r
         }\r
         if ($1.basicType == EbtVoid) {\r
             parseContext.error($2.loc, "illegal use of type 'void'", $2.string->c_str(), "");\r
@@ -905,11 +907,11 @@ parameter_declarator
         if ($1.arraySizes) {\r
             parseContext.profileRequires($1.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");\r
             parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");\r
-            parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->front());\r
+            parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->getSize());\r
         }\r
         parseContext.arrayDimCheck($2.loc, $1.arraySizes, $3.arraySizes);\r
 \r
-        parseContext.arraySizeRequiredCheck($3.loc, $3.arraySizes->front());\r
+        parseContext.arraySizeRequiredCheck($3.loc, $3.arraySizes->getSize());\r
         parseContext.reservedErrorCheck($2.loc, *$2.string);\r
 \r
         $1.arraySizes = $3.arraySizes;\r
@@ -976,7 +978,7 @@ init_declarator_list
     | init_declarator_list COMMA IDENTIFIER array_specifier {\r
         parseContext.nonInitConstCheck($3.loc, *$3.string, $1.type);\r
         if (parseContext.profile == EEsProfile)\r
-            parseContext.arraySizeRequiredCheck($4.loc, $4.arraySizes->front());\r
+            parseContext.arraySizeRequiredCheck($4.loc, $4.arraySizes->getSize());\r
         parseContext.arrayDimCheck($3.loc, $1.type.arraySizes, $4.arraySizes);\r
 \r
         $$ = $1;\r
@@ -1047,7 +1049,7 @@ single_declaration
         $$.intermAggregate = 0;\r
         parseContext.nonInitConstCheck($2.loc, *$2.string, $1);        \r
         if (parseContext.profile == EEsProfile)\r
-            parseContext.arraySizeRequiredCheck($3.loc, $3.arraySizes->front());        \r
+            parseContext.arraySizeRequiredCheck($3.loc, $3.arraySizes->getSize());        \r
         parseContext.arrayDimCheck($2.loc, $1.arraySizes, $3.arraySizes);\r
 \r
         $$.type = $1;\r
@@ -1111,7 +1113,7 @@ fully_specified_type
             parseContext.profileRequires($1.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");\r
             parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");\r
             if (parseContext.profile == EEsProfile)\r
-                parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->front());\r
+                parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->getSize());\r
         }\r
 \r
         parseContext.precisionQualifierCheck($$.loc, $$);\r
@@ -1123,7 +1125,7 @@ fully_specified_type
             parseContext.profileRequires($2.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");\r
             parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type");\r
             if (parseContext.profile == EEsProfile)\r
-                parseContext.arraySizeRequiredCheck($2.loc, $2.arraySizes->front());\r
+                parseContext.arraySizeRequiredCheck($2.loc, $2.arraySizes->getSize());\r
         }\r
 \r
         if ($2.arraySizes && parseContext.arrayQualifierError($2.loc, $1))\r
@@ -1391,7 +1393,7 @@ array_specifier
     : LEFT_BRACKET RIGHT_BRACKET {\r
         $$.loc = $1.loc;\r
         $$.arraySizes = NewPoolTArraySizes();\r
-        $$.arraySizes->push_back(0);\r
+        $$.arraySizes->setSize(0);\r
     }\r
     | LEFT_BRACKET constant_expression RIGHT_BRACKET {\r
         $$.loc = $1.loc;\r
@@ -1399,18 +1401,18 @@ array_specifier
 \r
         int size;\r
         parseContext.arraySizeCheck($2->getLoc(), $2, size);\r
-        $$.arraySizes->push_back(size);\r
+        $$.arraySizes->setSize(size);\r
     }\r
     | array_specifier LEFT_BRACKET RIGHT_BRACKET {\r
         $$ = $1;\r
-        $$.arraySizes->push_back(0);\r
+        $$.arraySizes->setSize(0);\r
     }\r
     | array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET {\r
         $$ = $1;\r
 \r
         int size;\r
         parseContext.arraySizeCheck($3->getLoc(), $3, size);\r
-        $$.arraySizes->push_back(size);\r
+        $$.arraySizes->setSize(size);\r
     }\r
     ;\r
 \r
@@ -2114,7 +2116,7 @@ struct_declaration
             parseContext.profileRequires($1.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");\r
             parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");\r
             if (parseContext.profile == EEsProfile)\r
-                parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->front());\r
+                parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->getSize());\r
         }\r
 \r
         $$ = $2;\r
@@ -2132,7 +2134,7 @@ struct_declaration
             parseContext.profileRequires($2.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");\r
             parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type");\r
             if (parseContext.profile == EEsProfile)\r
-                parseContext.arraySizeRequiredCheck($2.loc, $2.arraySizes->front());\r
+                parseContext.arraySizeRequiredCheck($2.loc, $2.arraySizes->getSize());\r
         }\r
 \r
         $$ = $3;\r
@@ -2166,7 +2168,7 @@ struct_declarator
     }\r
     | IDENTIFIER array_specifier {        \r
         if (parseContext.profile == EEsProfile)\r
-            parseContext.arraySizeRequiredCheck($2.loc, $2.arraySizes->front());\r
+            parseContext.arraySizeRequiredCheck($2.loc, $2.arraySizes->getSize());\r
         parseContext.arrayDimCheck($1.loc, $2.arraySizes, 0);\r
 \r
         $$.type = new TType(EbtVoid);\r