Adding Struct related types

Added TField, TFieldListCollection, TStructure
and TInterfaceBlock for structures and uniform
blocks.

In the TType class, changed structure's type
from TTypeList to TStructure and made related
changes in other files to reflect this change.

Change-Id: Ided4c535651a566952c3314c8c4f31c2d0ccdcca
Reviewed-on: https://swiftshader-review.googlesource.com/3451
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/compiler/Initialize.cpp b/src/OpenGL/compiler/Initialize.cpp
index 8bb7c82..7bad154 100644
--- a/src/OpenGL/compiler/Initialize.cpp
+++ b/src/OpenGL/compiler/Initialize.cpp
@@ -399,19 +399,17 @@
     //
     // Depth range in window coordinates
     //
-	TTypeList *members = NewPoolTTypeList();
-	TTypeLine near = {new TType(EbtFloat, EbpHigh, EvqGlobal, 1), 0};
-	TTypeLine far = {new TType(EbtFloat, EbpHigh, EvqGlobal, 1), 0};
-	TTypeLine diff = {new TType(EbtFloat, EbpHigh, EvqGlobal, 1), 0};
-	near.type->setFieldName("near");
-	far.type->setFieldName("far");
-	diff.type->setFieldName("diff");
-	members->push_back(near);
-	members->push_back(far);
-	members->push_back(diff);
-	TVariable *depthRangeParameters = new TVariable(NewPoolTString("gl_DepthRangeParameters"), TType(members, "gl_DepthRangeParameters"), true);
+	TFieldList *fields = NewPoolTFieldList();
+	TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near"), 0);
+	TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far"), 0);
+	TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff"), 0);
+	fields->push_back(near);
+	fields->push_back(far);
+	fields->push_back(diff);
+	TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields);
+	TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true);
 	symbolTable.insert(COMMON_BUILTINS, *depthRangeParameters);
-	TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(members, "gl_DepthRangeParameters"));
+	TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct));
 	depthRange->setQualifier(EvqUniform);
 	symbolTable.insert(COMMON_BUILTINS, *depthRange);
 
diff --git a/src/OpenGL/compiler/Intermediate.cpp b/src/OpenGL/compiler/Intermediate.cpp
index 779565b..8307b15 100644
--- a/src/OpenGL/compiler/Intermediate.cpp
+++ b/src/OpenGL/compiler/Intermediate.cpp
@@ -993,16 +993,16 @@
 
 bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
 {
-    const TTypeList* fields = leftNodeType.getStruct();
+    const TFieldList& fields = leftNodeType.getStruct()->fields();
 
-    size_t structSize = fields->size();
+    size_t structSize = fields.size();
     int index = 0;
 
     for (size_t j = 0; j < structSize; j++) {
-        int size = (*fields)[j].type->getObjectSize();
+        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]))
+            if (fields[j]->type()->getBasicType() == EbtStruct) {
+                if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
                     return false;
             } else {
                 if (leftUnionArray[index] != rightUnionArray[index])
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index 55c512e..562a577 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -326,20 +326,13 @@
 			{

 				ASSERT(leftType.isStruct());

 

-				const TTypeList *structure = leftType.getStruct();

-				const TString &fieldName = rightType.getFieldName();

+				const TFieldList& fields = leftType.getStruct()->fields();

+				int index = right->getAsConstantUnion()->getIConst(0);

 				int fieldOffset = 0;

 

-				for(size_t i = 0; i < structure->size(); i++)

+				for(int i = 0; i < index; i++)

 				{

-					const TType &fieldType = *(*structure)[i].type;

-

-					if(fieldType.getFieldName() == fieldName)

-					{

-						break;

-					}

-

-					fieldOffset += fieldType.totalRegisterCount();

+					fieldOffset += fields[i]->type()->totalRegisterCount();

 				}

 

 				copy(result, left, fieldOffset);

@@ -1439,12 +1432,12 @@
 

 		if(type.isStruct())

 		{

-			TTypeList *structure = type.getStruct();

+			const TFieldList& fields = type.getStruct()->fields();

 			int elements = 0;

 

-			for(TTypeList::const_iterator field = structure->begin(); field != structure->end(); field++)

+			for(TFieldList::const_iterator field = fields.begin(); field != fields.end(); field++)

 			{

-				const TType &fieldType = *field->type;

+				const TType &fieldType = *((*field)->type());

 

 				if(fieldType.totalRegisterCount() <= registers)

 				{

@@ -1472,7 +1465,7 @@
 		{

 			if(type.isStruct())

 			{

-				return registerSize(*type.getStruct()->begin()->type, 0);

+				return registerSize(*((*(type.getStruct()->fields().begin()))->type()), 0);

 			}

 

 			return type.isMatrix() ? type.getSecondarySize() : type.getNominalSize();

@@ -1487,12 +1480,12 @@
 

 		if(type.isStruct())

 		{

-			TTypeList *structure = type.getStruct();

+			const TFieldList& fields = type.getStruct()->fields();

 			int elements = 0;

 

-			for(TTypeList::const_iterator field = structure->begin(); field != structure->end(); field++)

+			for(TFieldList::const_iterator field = fields.begin(); field != fields.end(); field++)

 			{

-				const TType &fieldType = *field->type;

+				const TType &fieldType = *((*field)->type());

 				

 				if(fieldType.totalRegisterCount() <= registers)

 				{

@@ -1520,7 +1513,6 @@
 		{

 			TIntermTyped *arg = argument->getAsTyped();

 			const TType &type = arg->getType();

-			const TTypeList *structure = type.getStruct();

 			index = (index >= arg->totalRegisterCount()) ? arg->totalRegisterCount() - 1 : index;

 

 			int size = registerSize(type, index);

@@ -1771,23 +1763,20 @@
 				break;

 			case EOpIndexDirectStruct:

 				{

-					const TTypeList *structure = left->getType().getStruct();

-					const TString &fieldName = right->getType().getFieldName();

+					const TFieldList& fields = left->getType().getStruct()->fields();

+					int index = right->getAsConstantUnion()->getIConst(0);

+					int fieldOffset = 0;

 

-					int offset = 0;

-					for(TTypeList::const_iterator field = structure->begin(); field != structure->end(); field++)

+					for(int i = 0; i < index; i++)

 					{

-						if(field->type->getFieldName() == fieldName)

-						{

-							dst.type = registerType(left);

-							dst.index += offset;

-							dst.mask = writeMask(right);

-							

-							return 0xE4;

-						}

-

-						offset += field->type->totalRegisterCount();

+						fieldOffset += fields[i]->type()->totalRegisterCount();

 					}

+

+					dst.type = registerType(left);

+					dst.index += fieldOffset;

+					dst.mask = writeMask(right);

+

+					return 0xE4;

 				}

 				break;

 			case EOpVectorSwizzle:

@@ -2354,7 +2343,7 @@
 

 	void OutputASM::declareUniform(const TType &type, const TString &name, int index)

 	{

-		const TTypeList *structure = type.getStruct();

+		const TStructure *structure = type.getStruct();

 		ActiveUniforms &activeUniforms = shaderObject->activeUniforms;

 

 		if(!structure)

@@ -2371,16 +2360,17 @@
 		}

 		else

 		{

+			const TFieldList& fields = structure->fields();

 			if(type.isArray())

 			{

 				int elementIndex = index;

 

 				for(int i = 0; i < type.getArraySize(); i++)

 				{

-					for(size_t j = 0; j < structure->size(); j++)

+					for(size_t j = 0; j < fields.size(); j++)

 					{

-						const TType &fieldType = *(*structure)[j].type;

-						const TString &fieldName = fieldType.getFieldName();

+						const TType &fieldType = *(fields[j]->type());

+						const TString &fieldName = fields[j]->name();

 

 						const TString uniformName = name + "[" + str(i) + "]." + fieldName;

 						declareUniform(fieldType, uniformName, elementIndex);

@@ -2392,10 +2382,10 @@
 			{

 				int fieldIndex = index;

 

-				for(size_t i = 0; i < structure->size(); i++)

+				for(size_t i = 0; i < fields.size(); i++)

 				{

-					const TType &fieldType = *(*structure)[i].type;

-					const TString &fieldName = fieldType.getFieldName();

+					const TType &fieldType = *(fields[i]->type());

+					const TString &fieldName = fields[i]->name();

 

 					const TString uniformName = name + "." + fieldName;

 					declareUniform(fieldType, uniformName, fieldIndex);

diff --git a/src/OpenGL/compiler/ParseHelper.cpp b/src/OpenGL/compiler/ParseHelper.cpp
index b403feb..22e38a7 100644
--- a/src/OpenGL/compiler/ParseHelper.cpp
+++ b/src/OpenGL/compiler/ParseHelper.cpp
@@ -522,7 +522,7 @@
         return true;
     }
 
-    if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) {
+    if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) {
         error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
         return true;
     }
@@ -682,9 +682,9 @@
         return true;
 
     if (type.getBasicType() == EbtStruct) {
-        TTypeList& structure = *type.getStruct();
-        for (unsigned int i = 0; i < structure.size(); ++i) {
-            if (containsSampler(*structure[i].type))
+        const TFieldList& fields = type.getStruct()->fields();
+        for(unsigned int i = 0; i < fields.size(); ++i) {
+            if (containsSampler(*fields[i]->type()))
                 return true;
         }
     }
@@ -1232,12 +1232,12 @@
 
     if(op == EOpConstructStruct)
     {
-        TTypeList &fields = *type->getStruct();
+        const TFieldList &fields = type->getStruct()->fields();
         TIntermSequence &args = aggregateArguments->getSequence();
 
         for(size_t i = 0; i < fields.size(); i++)
         {
-            if(args[i]->getAsTyped()->getType() != *fields[i].type)
+            if(args[i]->getAsTyped()->getType() != *fields[i]->type())
             {
                 error(line, "Structure constructor arguments do not match structure fields", "Error");
                 recover();
@@ -1405,17 +1405,17 @@
 //
 TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line)
 {
-    const TTypeList* fields = node->getType().getStruct();
+    const TFieldList &fields = node->getType().getStruct()->fields();
     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) {
+    for ( index = 0; index < fields.size(); ++index) {
+        if (fields[index]->name() == identifier) {
             break;
         } else {
-            instanceSize += (*fields)[index].type->getObjectSize();
+            instanceSize += fields[index]->type()->getObjectSize();
         }
     }
 
diff --git a/src/OpenGL/compiler/SymbolTable.cpp b/src/OpenGL/compiler/SymbolTable.cpp
index 1935478..2881977 100644
--- a/src/OpenGL/compiler/SymbolTable.cpp
+++ b/src/OpenGL/compiler/SymbolTable.cpp
@@ -26,12 +26,11 @@
 
 TType::TType(const TPublicType &p) :
     type(p.type), precision(p.precision), primarySize(p.primarySize), secondarySize(p.secondarySize), qualifier(p.qualifier), array(p.array), arraySize(p.arraySize),
-    maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
+    maxArraySize(0), arrayInformationType(0), structure(0), deepestStructNesting(0), mangled(0)
 {
     if (p.userDef)
     {
         structure = p.userDef->getStruct();
-        typeName = NewPoolTString(p.userDef->getTypeName().c_str());
         computeDeepestStructNesting();
     }
 }
@@ -52,19 +51,23 @@
     case EbtUInt:               mangledName += 'u';      break;
     case EbtBool:               mangledName += 'b';      break;
     case EbtSampler2D:          mangledName += "s2";     break;
-    case EbtSamplerCube:        mangledName += "sC";     break;
-    case EbtSamplerExternalOES: mangledName += "sE";     break;
 	case EbtSampler3D:          mangledName += "s3";     break;
-	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);
-            }
-        }
+	case EbtSamplerCube:        mangledName += "sC";     break;
+	case EbtSampler2DArray:		mangledName += "s2a";    break;
+	case EbtSamplerExternalOES: mangledName += "sext";   break;
+	case EbtISampler2D:  		mangledName += "is2";    break;
+	case EbtISampler3D: 		mangledName += "is3";    break;
+	case EbtISamplerCube:		mangledName += "isC";    break;
+	case EbtISampler2DArray:	mangledName += "is2a";   break;
+	case EbtUSampler2D: 		mangledName += "us2";    break;
+	case EbtUSampler3D:  		mangledName += "us3";    break;
+	case EbtUSamplerCube:		mangledName += "usC";    break;
+	case EbtUSampler2DArray:	mangledName += "us2a";   break;
+	case EbtSampler2DShadow:	mangledName += "s2s";    break;
+	case EbtSamplerCubeShadow:  mangledName += "sCs";    break;
+	case EbtSampler2DArrayShadow: mangledName += "s2as"; break;
+	case EbtStruct:             mangledName += structure->mangledName(); break;
+	case EbtInterfaceBlock:	    mangledName += interfaceBlock->mangledName(); break;
     default:
         break;
     }
@@ -89,46 +92,68 @@
         return 0;
     }
 
-    if (structureSize == 0)
-        for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
-            structureSize += ((*tl).type)->getObjectSize();
-
-    return structureSize;
+    return getStruct()->objectSize();
 }
 
 void TType::computeDeepestStructNesting()
 {
-    if (!structure)
-    {
-        return;
-    }
-
-    int maxNesting = 0;
-    for (TTypeList::const_iterator tl = structure->begin(); tl != structure->end(); tl++)
-    {
-        maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting());
-    }
-
-    deepestStructNesting = 1 + maxNesting;
+	deepestStructNesting = structure ? structure->deepestNesting() : 0;
 }
 
-bool TType::isStructureContainingArrays() const
+bool TStructure::containsArrays() const
 {
-    if (!structure)
-    {
-        return false;
-    }
+	for(size_t i = 0; i < mFields->size(); ++i)
+	{
+		const TType *fieldType = (*mFields)[i]->type();
+		if(fieldType->isArray() || fieldType->isStructureContainingArrays())
+			return true;
+	}
+	return false;
+}
 
-    for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
-    {
-        if (member->type->isArray() ||
-            member->type->isStructureContainingArrays())
-        {
-            return true;
-        }
-    }
+bool TStructure::containsSamplers() const
+{
+	for(size_t i = 0; i < mFields->size(); ++i)
+	{
+		const TType *fieldType = (*mFields)[i]->type();
+		if(IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
+			return true;
+	}
+	return false;
+}
 
-    return false;
+TString TFieldListCollection::buildMangledName() const
+{
+	TString mangledName(mangledNamePrefix());
+	mangledName += *mName;
+	for(size_t i = 0; i < mFields->size(); ++i)
+	{
+		mangledName += '-';
+		mangledName += (*mFields)[i]->type()->getMangledName();
+	}
+	return mangledName;
+}
+
+size_t TFieldListCollection::calculateObjectSize() const
+{
+	size_t size = 0;
+	for(size_t i = 0; i < mFields->size(); ++i)
+	{
+		size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
+		if(fieldSize > INT_MAX - size)
+			size = INT_MAX;
+		else
+			size += fieldSize;
+	}
+	return size;
+}
+
+int TStructure::calculateDeepestNesting() const
+{
+	int maxNesting = 0;
+	for(size_t i = 0; i < mFields->size(); ++i)
+		maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
+	return 1 + maxNesting;
 }
 
 //
diff --git a/src/OpenGL/compiler/Types.h b/src/OpenGL/compiler/Types.h
index b89c860..9887bf2 100644
--- a/src/OpenGL/compiler/Types.h
+++ b/src/OpenGL/compiler/Types.h
@@ -16,21 +16,211 @@
 class TType;
 struct TPublicType;
 
-//
-// Need to have association of line numbers to types in a list for building structs.
-//
-struct TTypeLine {
-    TType* type;
-    int line;
-};
-typedef TVector<TTypeLine> TTypeList;
-
-inline TTypeList* NewPoolTTypeList()
+class TField
 {
-    void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TTypeList));
-    return new(memory) TTypeList;
+public:
+	POOL_ALLOCATOR_NEW_DELETE();
+	TField(TType *type, TString *name, const TSourceLoc &line)
+		: mType(type),
+		mName(name),
+		mLine(line)
+	{
+	}
+
+	// TODO(alokp): We should only return const type.
+	// Fix it by tweaking grammar.
+	TType *type()
+	{
+		return mType;
+	}
+	const TType *type() const
+	{
+		return mType;
+	}
+
+	const TString &name() const
+	{
+		return *mName;
+	}
+	const TSourceLoc &line() const
+	{
+		return mLine;
+	}
+
+private:
+	TType *mType;
+	TString *mName;
+	TSourceLoc mLine;
+};
+
+typedef TVector<TField *> TFieldList;
+inline TFieldList *NewPoolTFieldList()
+{
+	void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
+	return new(memory)TFieldList;
 }
 
+class TFieldListCollection
+{
+public:
+	const TString &name() const
+	{
+		return *mName;
+	}
+	const TFieldList &fields() const
+	{
+		return *mFields;
+	}
+
+	const TString &mangledName() const
+	{
+		if(mMangledName.empty())
+			mMangledName = buildMangledName();
+		return mMangledName;
+	}
+	size_t objectSize() const
+	{
+		if(mObjectSize == 0)
+			mObjectSize = calculateObjectSize();
+		return mObjectSize;
+	};
+
+protected:
+	TFieldListCollection(const TString *name, TFieldList *fields)
+		: mName(name),
+		mFields(fields),
+		mObjectSize(0)
+	{
+	}
+	TString buildMangledName() const;
+	size_t calculateObjectSize() const;
+	virtual TString mangledNamePrefix() const = 0;
+
+	const TString *mName;
+	TFieldList *mFields;
+
+	mutable TString mMangledName;
+	mutable size_t mObjectSize;
+};
+
+// May also represent interface blocks
+class TStructure : public TFieldListCollection
+{
+public:
+	POOL_ALLOCATOR_NEW_DELETE();
+	TStructure(const TString *name, TFieldList *fields)
+		: TFieldListCollection(name, fields),
+		mDeepestNesting(0),
+		mUniqueId(0),
+		mAtGlobalScope(false)
+	{
+	}
+
+	int deepestNesting() const
+	{
+		if(mDeepestNesting == 0)
+			mDeepestNesting = calculateDeepestNesting();
+		return mDeepestNesting;
+	}
+	bool containsArrays() const;
+	bool containsSamplers() const;
+
+	bool equals(const TStructure &other) const;
+
+	void setUniqueId(int uniqueId)
+	{
+		mUniqueId = uniqueId;
+	}
+
+	int uniqueId() const
+	{
+		ASSERT(mUniqueId != 0);
+		return mUniqueId;
+	}
+
+	void setAtGlobalScope(bool atGlobalScope)
+	{
+		mAtGlobalScope = atGlobalScope;
+	}
+
+	bool atGlobalScope() const
+	{
+		return mAtGlobalScope;
+	}
+
+private:
+	// TODO(zmo): Find a way to get rid of the const_cast in function
+	// setName().  At the moment keep this function private so only
+	// friend class RegenerateStructNames may call it.
+	friend class RegenerateStructNames;
+	void setName(const TString &name)
+	{
+		TString *mutableName = const_cast<TString *>(mName);
+		*mutableName = name;
+	}
+
+	virtual TString mangledNamePrefix() const
+	{
+		return "struct-";
+	}
+	int calculateDeepestNesting() const;
+
+	mutable int mDeepestNesting;
+	int mUniqueId;
+	bool mAtGlobalScope;
+};
+
+class TInterfaceBlock : public TFieldListCollection
+{
+public:
+	POOL_ALLOCATOR_NEW_DELETE();
+	TInterfaceBlock(const TString *name, TFieldList *fields, const TString *instanceName,
+		int arraySize, const TLayoutQualifier &layoutQualifier)
+		: TFieldListCollection(name, fields),
+		mInstanceName(instanceName),
+		mArraySize(arraySize),
+		mBlockStorage(layoutQualifier.blockStorage),
+		mMatrixPacking(layoutQualifier.matrixPacking)
+	{
+	}
+
+	const TString &instanceName() const
+	{
+		return *mInstanceName;
+	}
+	bool hasInstanceName() const
+	{
+		return mInstanceName != NULL;
+	}
+	bool isArray() const
+	{
+		return mArraySize > 0;
+	}
+	int arraySize() const
+	{
+		return mArraySize;
+	}
+	TLayoutBlockStorage blockStorage() const
+	{
+		return mBlockStorage;
+	}
+	TLayoutMatrixPacking matrixPacking() const
+	{
+		return mMatrixPacking;
+	}
+
+private:
+	virtual TString mangledNamePrefix() const
+	{
+		return "iblock-";
+	}
+
+	const TString *mInstanceName; // for interface block instance names
+	int mArraySize; // 0 if not an array
+	TLayoutBlockStorage mBlockStorage;
+	TLayoutMatrixPacking mMatrixPacking;
+};
+
 //
 // Base class for things that have a type.
 //
@@ -40,23 +230,34 @@
     POOL_ALLOCATOR_NEW_DELETE();
     TType() {}
 	TType(TBasicType t, int s0 = 1, int s1 = 1) :
-		type(t), precision(EbpUndefined), qualifier(EvqGlobal), primarySize(s0), secondarySize(s1), array(false), arraySize(0),
-            maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
+		type(t), precision(EbpUndefined), qualifier(EvqGlobal), invariant(false), layoutQualifier(TLayoutQualifier::create()),
+		primarySize(s0), secondarySize(s1), array(false), arraySize(0), maxArraySize(0), arrayInformationType(0), interfaceBlock(0),
+		structure(0), deepestStructNesting(0), mangled(0)
     {
     }
     TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s0 = 1, int s1 = 1, bool a = false) :
-            type(t), precision(p), qualifier(q), primarySize(s0), secondarySize(s1), array(a), arraySize(0),
-            maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
+		type(t), precision(p), qualifier(q), invariant(false), layoutQualifier(TLayoutQualifier::create()),
+		primarySize(s0), secondarySize(s1), array(a), arraySize(0), maxArraySize(0), arrayInformationType(0), interfaceBlock(0),
+		structure(0), deepestStructNesting(0), mangled(0)
     {
     }
     explicit TType(const TPublicType &p);
-    TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
-            type(EbtStruct), precision(p), qualifier(EvqTemporary), primarySize(1), secondarySize(1), array(false), arraySize(0),
-            maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0)
+	TType(TStructure* userDef, TPrecision p = EbpUndefined) :
+		type(EbtStruct), precision(p), qualifier(EvqTemporary), invariant(false), layoutQualifier(TLayoutQualifier::create()),
+		primarySize(1), secondarySize(1), array(false), arraySize(0), maxArraySize(0), arrayInformationType(0), interfaceBlock(0),
+		structure(userDef), deepestStructNesting(0), mangled(0)
     {
-        typeName = NewPoolTString(n.c_str());
     }
 
+	TType(TInterfaceBlock *interfaceBlockIn, TQualifier qualifierIn,
+		TLayoutQualifier layoutQualifierIn, int arraySizeIn)
+		: type(EbtInterfaceBlock), precision(EbpUndefined), qualifier(qualifierIn),
+		invariant(false), layoutQualifier(layoutQualifierIn),
+		primarySize(1), secondarySize(1), array(arraySizeIn > 0), arraySize(arraySizeIn), maxArraySize(0), arrayInformationType(0),
+		interfaceBlock(interfaceBlockIn), structure(0), deepestStructNesting(0), mangled(0)
+	{
+	}
+
     TBasicType getBasicType() const { return type; }
     void setBasicType(TBasicType t) { type = t; }
 
@@ -66,6 +267,11 @@
     TQualifier getQualifier() const { return qualifier; }
     void setQualifier(TQualifier q) { qualifier = q; }
 
+	bool isInvariant() const { return invariant; }
+
+	TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; }
+	void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; }
+
     // One-dimensional size of single instance type
 	int getNominalSize() const { return primarySize; }
 	void setNominalSize(int s) { primarySize = s; }
@@ -100,15 +306,14 @@
 
 	int elementRegisterCount() const
 	{
-		TTypeList *structure = getStruct();
-
 		if(structure)
 		{
 			int registerCount = 0;
 
-			for(size_t i = 0; i < structure->size(); i++)
+			const TFieldList& fields = getStruct()->fields();
+			for(size_t i = 0; i < fields.size(); i++)
 			{
-				registerCount += (*structure)[i].type->totalRegisterCount();
+				registerCount += fields[i]->type()->totalRegisterCount();
 			}
 
 			return registerCount;
@@ -148,35 +353,18 @@
     void setArrayInformationType(TType* t) { arrayInformationType = t; }
     TType* getArrayInformationType() const { return arrayInformationType; }
 
+	TInterfaceBlock *getInterfaceBlock() const { return interfaceBlock; }
+	void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn) { interfaceBlock = interfaceBlockIn; }
+	bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
+
 	bool isVector() const { return primarySize > 1 && !isMatrix(); }
 	bool isScalar() const { return primarySize == 1 && !isMatrix() && !structure; }
 	bool isRegister() const { return !isMatrix() && !structure && !array; }   // Fits in a 4-element register
 	bool isStruct() const { return structure != 0; }
 	bool isScalarInt() const { return isScalar() && IsInteger(type); }
 
-    TTypeList* getStruct() const { return structure; }
-    void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); }
-
-    const TString& getTypeName() const
-    {
-        assert(typeName);
-        return *typeName;
-    }
-    void setTypeName(const TString& n)
-    {
-        typeName = NewPoolTString(n.c_str());
-    }
-
-    bool isField() const { return fieldName != 0; }
-    const TString& getFieldName() const
-    {
-        assert(fieldName);
-        return *fieldName;
-    }
-    void setFieldName(const TString& n)
-    {
-        fieldName = NewPoolTString(n.c_str());
-    }
+	TStructure* getStruct() const { return structure; }
+	void setStruct(TStructure* s) { structure = s; computeDeepestStructNesting(); }
 
     TString& getMangledName() {
         if (!mangled) {
@@ -233,9 +421,20 @@
     // For type "nesting2", this method would return 2 -- the number
     // of structures through which indirection must occur to reach the
     // deepest field (nesting2.field1.position).
-    int getDeepestStructNesting() const { return deepestStructNesting; }
+    int getDeepestStructNesting() const
+    {
+        return structure ? structure->deepestNesting() : 0;
+    }
 
-    bool isStructureContainingArrays() const;
+    bool isStructureContainingArrays() const
+    {
+        return structure ? structure->containsArrays() : false;
+    }
+
+    bool isStructureContainingSamplers() const
+    {
+        return structure ? structure->containsSamplers() : false;
+    }
 
 protected:
     void buildMangledName(TString&);
@@ -245,6 +444,8 @@
     TBasicType type;
     TPrecision precision;
     TQualifier qualifier;
+	bool invariant;
+	TLayoutQualifier layoutQualifier;
     unsigned char primarySize;   // size of vector or matrix, not size of array
 	unsigned char secondarySize; // secondarySize: 1 for vectors, >1 for matrices
     bool array;
@@ -252,13 +453,13 @@
     int maxArraySize;
     TType *arrayInformationType;
 
-    TTypeList *structure;      // 0 unless this is a struct
-    mutable int structureSize;
+	// 0 unless this is an interface block, or interface block member variable
+	TInterfaceBlock *interfaceBlock;
+
+	TStructure *structure;      // 0 unless this is a struct
     int deepestStructNesting;
 
-    TString *fieldName;         // for structure field names
     TString *mangled;
-    TString *typeName;          // for structure field type name
 };
 
 //
@@ -311,6 +512,11 @@
 		secondarySize = s1;
 	}
 
+	bool isUnsizedArray() const
+	{
+		return array && arraySize == 0;
+	}
+
     void setArray(bool a, int s = 0)
     {
         array = a;
@@ -332,6 +538,38 @@
 
         return userDef->isStructureContainingArrays();
     }
+
+	bool isMatrix() const
+	{
+		return primarySize > 1 && secondarySize > 1;
+	}
+
+	bool isVector() const
+	{
+		return primarySize > 1 && secondarySize == 1;
+	}
+
+	int getCols() const
+	{
+		ASSERT(isMatrix());
+		return primarySize;
+	}
+
+	int getRows() const
+	{
+		ASSERT(isMatrix());
+		return secondarySize;
+	}
+
+	int getNominalSize() const
+	{
+		return primarySize;
+	}
+
+	bool isAggregate() const
+	{
+		return array || isMatrix() || isVector();
+	}
 };
 
 #endif // _TYPES_INCLUDED_
diff --git a/src/OpenGL/compiler/glslang.y b/src/OpenGL/compiler/glslang.y
index b7d7a06..a145694 100644
--- a/src/OpenGL/compiler/glslang.y
+++ b/src/OpenGL/compiler/glslang.y
@@ -75,8 +75,8 @@
             TQualifier qualifier;
             TFunction* function;
             TParameter param;
-            TTypeLine typeLine;
-            TTypeList* typeList;
+            TField* field;
+            TFieldList* fieldList;
         };
     } interm;
 }
@@ -176,8 +176,8 @@
 %type <interm.type> type_qualifier fully_specified_type type_specifier storage_qualifier interpolation_qualifier
 %type <interm.type> type_specifier_no_prec type_specifier_nonarray
 %type <interm.type> struct_specifier
-%type <interm.typeLine> struct_declarator
-%type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list
+%type <interm.field> struct_declarator
+%type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list
 %type <interm.function> function_header function_declarator function_identifier
 %type <interm.function> function_header_with_parameters function_call_header
 %type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
@@ -316,7 +316,7 @@
             $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConstExpr), $2.line);
         } else if ($1->isArray()) {
             if ($1->getType().getStruct())
-                $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName()));
+                $$->setType(TType($1->getType().getStruct()));
             else
                 $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->getSecondarySize()));
 
@@ -391,15 +391,16 @@
             }
         } else if ($1->getBasicType() == EbtStruct) {
             bool fieldFound = false;
-            const TTypeList* fields = $1->getType().getStruct();
-            if (fields == 0) {
+            const TStructure* structure = $1->getType().getStruct();
+            if (structure == 0) {
                 context->error($2.line, "structure has no fields", "Internal Error");
                 context->recover();
                 $$ = $1;
             } else {
                 unsigned int i;
-                for (i = 0; i < fields->size(); ++i) {
-                    if ((*fields)[i].type->getFieldName() == *$3.string) {
+                const TFieldList& fields = structure->fields();
+                for (i = 0; i < fields.size(); ++i) {
+                    if (fields[i]->name() == *$3.string) {
                         fieldFound = true;
                         break;
                     }
@@ -412,7 +413,7 @@
                             $$ = $1;
                         }
                         else {
-                            $$->setType(*(*fields)[i].type);
+                            $$->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()->setQualifier(EvqConstExpr);
@@ -420,9 +421,9 @@
                     } else {
                         ConstantUnion *unionArray = new ConstantUnion[1];
                         unionArray->setIConst(i);
-                        TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, $3.line);
+                        TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(fields[i]->type()), $3.line);
                         $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line);
-                        $$->setType(*(*fields)[i].type);
+                        $$->setType(*fields[i]->type());
                     }
                 } else {
                     context->error($2.line, " no such field in structure", $3.string->c_str());
@@ -2007,7 +2008,7 @@
         if (context->reservedErrorCheck($2.line, *$2.string))
             context->recover();
 
-        TType* structure = new TType($5, *$2.string);
+        TType* structure = new TType(new TStructure($2.string, $5));
         TVariable* userTypeDef = new TVariable($2.string, *structure, true);
         if (! context->symbolTable.declare(*userTypeDef)) {
             context->error($2.line, "redefinition", $2.string->c_str(), "struct");
@@ -2018,7 +2019,8 @@
         context->exitStructDeclaration();
     }
     | STRUCT LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
-        TType* structure = new TType($4, TString(""));
+        TString emptyName("");
+        TType* structure = new TType(new TStructure(&emptyName, $4));
         $$.setBasic(EbtStruct, EvqTemporary, $1.line);
         $$.userDef = structure;
         context->exitStructDeclaration();
@@ -2032,9 +2034,10 @@
     | struct_declaration_list struct_declaration {
         $$ = $1;
         for (unsigned int i = 0; i < $2->size(); ++i) {
+            TField* field = (*$2)[i];
             for (unsigned int j = 0; j < $$->size(); ++j) {
-                if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) {
-                    context->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str());
+                if ((*$$)[j]->name() == field->name()) {
+                    context->error((*$2)[i]->line(), "duplicate field name in structure:", "struct", field->name().c_str());
                     context->recover();
                 }
             }
@@ -2047,14 +2050,14 @@
     : type_specifier struct_declarator_list SEMICOLON {
         $$ = $2;
 
-        if (context->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {
+        if (context->voidErrorCheck($1.line, (*$2)[0]->name(), $1)) {
             context->recover();
         }
         for (unsigned int i = 0; i < $$->size(); ++i) {
             //
             // Careful not to replace already known aspects of type, like array-ness
             //
-            TType* type = (*$$)[i].type;
+            TType* type = (*$$)[i]->type();
             type->setBasicType($1.type);
             type->setNominalSize($1.primarySize);
             type->setSecondarySize($1.secondarySize);
@@ -2069,7 +2072,6 @@
                 type->setArraySize($1.arraySize);
             if ($1.userDef) {
                 type->setStruct($1.userDef->getStruct());
-                type->setTypeName($1.userDef->getTypeName());
             }
         }
     }
@@ -2077,7 +2079,7 @@
 
 struct_declarator_list
     : struct_declarator {
-        $$ = NewPoolTTypeList();
+        $$ = NewPoolTFieldList();
         $$->push_back($1);
     }
     | struct_declarator_list COMMA struct_declarator {
@@ -2090,22 +2092,20 @@
         if (context->reservedErrorCheck($1.line, *$1.string))
             context->recover();
 
-        $$.type = new TType(EbtVoid, EbpUndefined);
-        $$.line = $1.line;
-        $$.type->setFieldName(*$1.string);
+        TType* type = new TType(EbtVoid, EbpUndefined);
+        $$ = new TField(type, $1.string, $1.line);
     }
     | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
         if (context->reservedErrorCheck($1.line, *$1.string))
             context->recover();
 
-        $$.type = new TType(EbtVoid, EbpUndefined);
-        $$.line = $1.line;
-        $$.type->setFieldName(*$1.string);
-
+        TType* type = new TType(EbtVoid, EbpUndefined);
         int size;
-        if (context->arraySizeErrorCheck($2.line, $3, size))
+        if (context->arraySizeErrorCheck($3->getLine(), $3, size))
             context->recover();
-        $$.type->setArraySize(size);
+        type->setArraySize(size);
+
+        $$ = new TField(type, $1.string, $1.line);
     }
     ;
 
diff --git a/src/OpenGL/compiler/glslang_tab.cpp b/src/OpenGL/compiler/glslang_tab.cpp
index e3777f0..e2b3472 100644
--- a/src/OpenGL/compiler/glslang_tab.cpp
+++ b/src/OpenGL/compiler/glslang_tab.cpp
@@ -285,8 +285,8 @@
             TQualifier qualifier;
             TFunction* function;
             TParameter param;
-            TTypeLine typeLine;
-            TTypeList* typeList;
+            TField* field;
+            TFieldList* fieldList;
         };
     } interm;
 
@@ -731,26 +731,26 @@
 static const yytype_uint16 yyrline[] =
 {
        0,   190,   190,   225,   228,   233,   238,   243,   248,   254,
-     257,   336,   339,   440,   450,   463,   471,   571,   574,   582,
-     586,   593,   597,   604,   610,   619,   627,   704,   711,   721,
-     724,   734,   744,   766,   767,   768,   769,   777,   778,   787,
-     796,   809,   810,   818,   829,   830,   839,   851,   852,   862,
-     872,   882,   895,   896,   906,   919,   920,   934,   935,   949,
-     950,   964,   965,   978,   979,   992,   993,  1006,  1007,  1024,
-    1025,  1038,  1039,  1040,  1041,  1043,  1044,  1045,  1047,  1049,
-    1051,  1053,  1058,  1061,  1072,  1080,  1107,  1112,  1122,  1160,
-    1163,  1170,  1178,  1199,  1220,  1231,  1260,  1265,  1275,  1280,
-    1290,  1293,  1296,  1299,  1305,  1312,  1315,  1337,  1355,  1379,
-    1402,  1406,  1424,  1432,  1464,  1484,  1572,  1582,  1588,  1591,
-    1597,  1603,  1610,  1619,  1628,  1631,  1634,  1641,  1645,  1652,
-    1656,  1661,  1666,  1676,  1686,  1695,  1705,  1712,  1715,  1718,
-    1724,  1731,  1734,  1740,  1743,  1746,  1752,  1755,  1770,  1774,
-    1778,  1782,  1786,  1790,  1795,  1800,  1805,  1810,  1815,  1820,
-    1825,  1830,  1835,  1840,  1845,  1850,  1856,  1862,  1868,  1874,
-    1880,  1886,  1892,  1898,  1904,  1909,  1914,  1923,  1928,  1933,
-    1938,  1943,  1948,  1953,  1958,  1963,  1968,  1973,  1978,  1983,
-    1988,  1993,  2006,  2006,  2020,  2020,  2029,  2032,  2047,  2079,
-    2083,  2089,  2097,  2113,  2117,  2121,  2122,  2128,  2129,  2130,
+     257,   336,   339,   441,   451,   464,   472,   572,   575,   583,
+     587,   594,   598,   605,   611,   620,   628,   705,   712,   722,
+     725,   735,   745,   767,   768,   769,   770,   778,   779,   788,
+     797,   810,   811,   819,   830,   831,   840,   852,   853,   863,
+     873,   883,   896,   897,   907,   920,   921,   935,   936,   950,
+     951,   965,   966,   979,   980,   993,   994,  1007,  1008,  1025,
+    1026,  1039,  1040,  1041,  1042,  1044,  1045,  1046,  1048,  1050,
+    1052,  1054,  1059,  1062,  1073,  1081,  1108,  1113,  1123,  1161,
+    1164,  1171,  1179,  1200,  1221,  1232,  1261,  1266,  1276,  1281,
+    1291,  1294,  1297,  1300,  1306,  1313,  1316,  1338,  1356,  1380,
+    1403,  1407,  1425,  1433,  1465,  1485,  1573,  1583,  1589,  1592,
+    1598,  1604,  1611,  1620,  1629,  1632,  1635,  1642,  1646,  1653,
+    1657,  1662,  1667,  1677,  1687,  1696,  1706,  1713,  1716,  1719,
+    1725,  1732,  1735,  1741,  1744,  1747,  1753,  1756,  1771,  1775,
+    1779,  1783,  1787,  1791,  1796,  1801,  1806,  1811,  1816,  1821,
+    1826,  1831,  1836,  1841,  1846,  1851,  1857,  1863,  1869,  1875,
+    1881,  1887,  1893,  1899,  1905,  1910,  1915,  1924,  1929,  1934,
+    1939,  1944,  1949,  1954,  1959,  1964,  1969,  1974,  1979,  1984,
+    1989,  1994,  2007,  2007,  2021,  2021,  2031,  2034,  2050,  2081,
+    2085,  2091,  2098,  2113,  2117,  2121,  2122,  2128,  2129,  2130,
     2131,  2132,  2136,  2137,  2137,  2137,  2147,  2148,  2152,  2152,
     2153,  2153,  2158,  2161,  2171,  2174,  2180,  2181,  2185,  2193,
     2197,  2207,  2212,  2229,  2229,  2234,  2234,  2241,  2241,  2249,
@@ -2458,7 +2458,7 @@
             (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConstExpr), (yyvsp[(2) - (4)].lex).line);
         } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) {
             if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getStruct())
-                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getStruct(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getTypeName()));
+                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getStruct()));
             else
                 (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getSecondarySize()));
 
@@ -2541,15 +2541,16 @@
             }
         } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType() == EbtStruct) {
             bool fieldFound = false;
-            const TTypeList* fields = (yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getStruct();
-            if (fields == 0) {
+            const TStructure* structure = (yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getStruct();
+            if (structure == 0) {
                 context->error((yyvsp[(2) - (3)].lex).line, "structure has no fields", "Internal Error");
                 context->recover();
                 (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
             } else {
                 unsigned int i;
-                for (i = 0; i < fields->size(); ++i) {
-                    if ((*fields)[i].type->getFieldName() == *(yyvsp[(3) - (3)].lex).string) {
+                const TFieldList& fields = structure->fields();
+                for (i = 0; i < fields.size(); ++i) {
+                    if (fields[i]->name() == *(yyvsp[(3) - (3)].lex).string) {
                         fieldFound = true;
                         break;
                     }
@@ -2562,7 +2563,7 @@
                             (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
                         }
                         else {
-                            (yyval.interm.intermTypedNode)->setType(*(*fields)[i].type);
+                            (yyval.interm.intermTypedNode)->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.
                             (yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConstExpr);
@@ -2570,9 +2571,9 @@
                     } else {
                         ConstantUnion *unionArray = new ConstantUnion[1];
                         unionArray->setIConst(i);
-                        TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, (yyvsp[(3) - (3)].lex).line);
+                        TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(fields[i]->type()), (yyvsp[(3) - (3)].lex).line);
                         (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirectStruct, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line);
-                        (yyval.interm.intermTypedNode)->setType(*(*fields)[i].type);
+                        (yyval.interm.intermTypedNode)->setType(*fields[i]->type());
                     }
                 } else {
                     context->error((yyvsp[(2) - (3)].lex).line, " no such field in structure", (yyvsp[(3) - (3)].lex).string->c_str());
@@ -4647,7 +4648,7 @@
         if (context->reservedErrorCheck((yyvsp[(2) - (6)].lex).line, *(yyvsp[(2) - (6)].lex).string))
             context->recover();
 
-        TType* structure = new TType((yyvsp[(5) - (6)].interm.typeList), *(yyvsp[(2) - (6)].lex).string);
+        TType* structure = new TType(new TStructure((yyvsp[(2) - (6)].lex).string, (yyvsp[(5) - (6)].interm.fieldList)));
         TVariable* userTypeDef = new TVariable((yyvsp[(2) - (6)].lex).string, *structure, true);
         if (! context->symbolTable.declare(*userTypeDef)) {
             context->error((yyvsp[(2) - (6)].lex).line, "redefinition", (yyvsp[(2) - (6)].lex).string->c_str(), "struct");
@@ -4667,7 +4668,8 @@
   case 195:
 
     {
-        TType* structure = new TType((yyvsp[(4) - (5)].interm.typeList), TString(""));
+        TString emptyName("");
+        TType* structure = new TType(new TStructure(&emptyName, (yyvsp[(4) - (5)].interm.fieldList)));
         (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yyvsp[(1) - (5)].lex).line);
         (yyval.interm.type).userDef = structure;
         context->exitStructDeclaration();
@@ -4677,22 +4679,23 @@
   case 196:
 
     {
-        (yyval.interm.typeList) = (yyvsp[(1) - (1)].interm.typeList);
+        (yyval.interm.fieldList) = (yyvsp[(1) - (1)].interm.fieldList);
     }
     break;
 
   case 197:
 
     {
-        (yyval.interm.typeList) = (yyvsp[(1) - (2)].interm.typeList);
-        for (unsigned int i = 0; i < (yyvsp[(2) - (2)].interm.typeList)->size(); ++i) {
-            for (unsigned int j = 0; j < (yyval.interm.typeList)->size(); ++j) {
-                if ((*(yyval.interm.typeList))[j].type->getFieldName() == (*(yyvsp[(2) - (2)].interm.typeList))[i].type->getFieldName()) {
-                    context->error((*(yyvsp[(2) - (2)].interm.typeList))[i].line, "duplicate field name in structure:", "struct", (*(yyvsp[(2) - (2)].interm.typeList))[i].type->getFieldName().c_str());
+        (yyval.interm.fieldList) = (yyvsp[(1) - (2)].interm.fieldList);
+        for (unsigned int i = 0; i < (yyvsp[(2) - (2)].interm.fieldList)->size(); ++i) {
+            TField* field = (*(yyvsp[(2) - (2)].interm.fieldList))[i];
+            for (unsigned int j = 0; j < (yyval.interm.fieldList)->size(); ++j) {
+                if ((*(yyval.interm.fieldList))[j]->name() == field->name()) {
+                    context->error((*(yyvsp[(2) - (2)].interm.fieldList))[i]->line(), "duplicate field name in structure:", "struct", field->name().c_str());
                     context->recover();
                 }
             }
-            (yyval.interm.typeList)->push_back((*(yyvsp[(2) - (2)].interm.typeList))[i]);
+            (yyval.interm.fieldList)->push_back((*(yyvsp[(2) - (2)].interm.fieldList))[i]);
         }
     }
     break;
@@ -4700,16 +4703,16 @@
   case 198:
 
     {
-        (yyval.interm.typeList) = (yyvsp[(2) - (3)].interm.typeList);
+        (yyval.interm.fieldList) = (yyvsp[(2) - (3)].interm.fieldList);
 
-        if (context->voidErrorCheck((yyvsp[(1) - (3)].interm.type).line, (*(yyvsp[(2) - (3)].interm.typeList))[0].type->getFieldName(), (yyvsp[(1) - (3)].interm.type))) {
+        if (context->voidErrorCheck((yyvsp[(1) - (3)].interm.type).line, (*(yyvsp[(2) - (3)].interm.fieldList))[0]->name(), (yyvsp[(1) - (3)].interm.type))) {
             context->recover();
         }
-        for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) {
+        for (unsigned int i = 0; i < (yyval.interm.fieldList)->size(); ++i) {
             //
             // Careful not to replace already known aspects of type, like array-ness
             //
-            TType* type = (*(yyval.interm.typeList))[i].type;
+            TType* type = (*(yyval.interm.fieldList))[i]->type();
             type->setBasicType((yyvsp[(1) - (3)].interm.type).type);
             type->setNominalSize((yyvsp[(1) - (3)].interm.type).primarySize);
             type->setSecondarySize((yyvsp[(1) - (3)].interm.type).secondarySize);
@@ -4724,7 +4727,6 @@
                 type->setArraySize((yyvsp[(1) - (3)].interm.type).arraySize);
             if ((yyvsp[(1) - (3)].interm.type).userDef) {
                 type->setStruct((yyvsp[(1) - (3)].interm.type).userDef->getStruct());
-                type->setTypeName((yyvsp[(1) - (3)].interm.type).userDef->getTypeName());
             }
         }
     }
@@ -4733,15 +4735,15 @@
   case 199:
 
     {
-        (yyval.interm.typeList) = NewPoolTTypeList();
-        (yyval.interm.typeList)->push_back((yyvsp[(1) - (1)].interm.typeLine));
+        (yyval.interm.fieldList) = NewPoolTFieldList();
+        (yyval.interm.fieldList)->push_back((yyvsp[(1) - (1)].interm.field));
     }
     break;
 
   case 200:
 
     {
-        (yyval.interm.typeList)->push_back((yyvsp[(3) - (3)].interm.typeLine));
+        (yyval.interm.fieldList)->push_back((yyvsp[(3) - (3)].interm.field));
     }
     break;
 
@@ -4751,9 +4753,8 @@
         if (context->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string))
             context->recover();
 
-        (yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined);
-        (yyval.interm.typeLine).line = (yyvsp[(1) - (1)].lex).line;
-        (yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (1)].lex).string);
+        TType* type = new TType(EbtVoid, EbpUndefined);
+        (yyval.interm.field) = new TField(type, (yyvsp[(1) - (1)].lex).string, (yyvsp[(1) - (1)].lex).line);
     }
     break;
 
@@ -4763,14 +4764,13 @@
         if (context->reservedErrorCheck((yyvsp[(1) - (4)].lex).line, *(yyvsp[(1) - (4)].lex).string))
             context->recover();
 
-        (yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined);
-        (yyval.interm.typeLine).line = (yyvsp[(1) - (4)].lex).line;
-        (yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (4)].lex).string);
-
+        TType* type = new TType(EbtVoid, EbpUndefined);
         int size;
-        if (context->arraySizeErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(3) - (4)].interm.intermTypedNode), size))
+        if (context->arraySizeErrorCheck((yyvsp[(3) - (4)].interm.intermTypedNode)->getLine(), (yyvsp[(3) - (4)].interm.intermTypedNode), size))
             context->recover();
-        (yyval.interm.typeLine).type->setArraySize(size);
+        type->setArraySize(size);
+
+        (yyval.interm.field) = new TField(type, (yyvsp[(1) - (4)].lex).string, (yyvsp[(1) - (4)].lex).line);
     }
     break;
 
diff --git a/src/OpenGL/compiler/glslang_tab.h b/src/OpenGL/compiler/glslang_tab.h
index 6ec3a32..e1ada23 100644
--- a/src/OpenGL/compiler/glslang_tab.h
+++ b/src/OpenGL/compiler/glslang_tab.h
@@ -201,8 +201,8 @@
             TQualifier qualifier;
             TFunction* function;
             TParameter param;
-            TTypeLine typeLine;
-            TTypeList* typeList;
+            TField* field;
+            TFieldList* fieldList;
         };
     } interm;