Support unsigned array indices.

Change-Id: I4136781005cbd0551461adecdd94d8e3cc8688d0
Reviewed-on: https://swiftshader-review.googlesource.com/8570
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index 480ac6b..e6b4b94 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -451,8 +451,13 @@
 		return value;
 	}
 
-	Value *Nucleus::createGEP(Value *ptr, Type *type, Value *index)
+	Value *Nucleus::createGEP(Value *ptr, Type *type, Value *index, bool unsignedIndex)
 	{
+		if(unsignedIndex && sizeof(void*) == 8)
+		{
+			index = createZExt(index, Long::getType());
+		}
+
 		assert(ptr->getType()->getContainedType(0) == type);
 		return V(::builder->CreateGEP(ptr, index));
 	}
@@ -6282,17 +6287,17 @@
 
 	RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, int offset)
 	{
-		return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, Byte::getType(), V(Nucleus::createConstantInt(offset))));
+		return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, Byte::getType(), V(Nucleus::createConstantInt(offset)), false));
 	}
 
 	RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, RValue<Int> offset)
 	{
-		return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, Byte::getType(), offset.value));
+		return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, Byte::getType(), offset.value, false));
 	}
 
 	RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, RValue<UInt> offset)
 	{
-		return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, Byte::getType(), offset.value));
+		return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, Byte::getType(), offset.value, true));
 	}
 
 	RValue<Pointer<Byte>> operator+=(Pointer<Byte> &lhs, int offset)
diff --git a/src/Reactor/Nucleus.hpp b/src/Reactor/Nucleus.hpp
index 196ca76..831ed40 100644
--- a/src/Reactor/Nucleus.hpp
+++ b/src/Reactor/Nucleus.hpp
@@ -96,7 +96,7 @@
 		// Memory instructions
 		static Value *createLoad(Value *ptr, Type *type, bool isVolatile = false, unsigned int align = 0);
 		static Value *createStore(Value *value, Value *ptr, Type *type, bool isVolatile = false, unsigned int align = 0);
-		static Value *createGEP(Value *ptr, Type *type, Value *index);
+		static Value *createGEP(Value *ptr, Type *type, Value *index, bool unsignedIndex);
 
 		// Atomic instructions
 		static Value *createAtomicAdd(Value *ptr, Value *value);
diff --git a/src/Reactor/Reactor.hpp b/src/Reactor/Reactor.hpp
index 859e98f..74a3f6c 100644
--- a/src/Reactor/Reactor.hpp
+++ b/src/Reactor/Reactor.hpp
@@ -90,7 +90,7 @@
 
 		Value *loadValue(unsigned int alignment = 0) const;
 		Value *storeValue(Value *value, unsigned int alignment = 0) const;
-		Value *getAddress(Value *index) const;
+		Value *getAddress(Value *index, bool unsignedIndex) const;
 	};
 
 	template<class T>
@@ -2120,7 +2120,9 @@
 
 		Reference<T> operator*();
 		Reference<T> operator[](int index);
+		Reference<T> operator[](unsigned int index);
 		Reference<T> operator[](RValue<Int> index);
+		Reference<T> operator[](RValue<UInt> index);
 
 		static Type *getType();
 
@@ -2149,7 +2151,9 @@
 		Array(int size = S);
 
 		Reference<T> operator[](int index);
+		Reference<T> operator[](unsigned int index);
 		Reference<T> operator[](RValue<Int> index);
+		Reference<T> operator[](RValue<UInt> index);
 	};
 
 //	RValue<Array<T>> operator++(Array<T> &val, int);   // Post-increment
@@ -2245,9 +2249,9 @@
 	}
 
 	template<class T>
-	Value *LValue<T>::getAddress(Value *index) const
+	Value *LValue<T>::getAddress(Value *index, bool unsignedIndex) const
 	{
-		return Nucleus::createGEP(address, T::getType(), index);
+		return Nucleus::createGEP(address, T::getType(), index, unsignedIndex);
 	}
 
 	template<class T>
@@ -2536,7 +2540,15 @@
 	template<class T>
 	Reference<T> Pointer<T>::operator[](int index)
 	{
-		Value *element = Nucleus::createGEP(LValue<Pointer<T>>::loadValue(), T::getType(), Nucleus::createConstantInt(index));
+		Value *element = Nucleus::createGEP(LValue<Pointer<T>>::loadValue(), T::getType(), Nucleus::createConstantInt(index), false);
+
+		return Reference<T>(element, alignment);
+	}
+
+	template<class T>
+	Reference<T> Pointer<T>::operator[](unsigned int index)
+	{
+		Value *element = Nucleus::createGEP(LValue<Pointer<T>>::loadValue(), T::getType(), Nucleus::createConstantInt(index), true);
 
 		return Reference<T>(element, alignment);
 	}
@@ -2544,7 +2556,15 @@
 	template<class T>
 	Reference<T> Pointer<T>::operator[](RValue<Int> index)
 	{
-		Value *element = Nucleus::createGEP(LValue<Pointer<T>>::loadValue(), T::getType(), index.value);
+		Value *element = Nucleus::createGEP(LValue<Pointer<T>>::loadValue(), T::getType(), index.value, false);
+
+		return Reference<T>(element, alignment);
+	}
+
+	template<class T>
+	Reference<T> Pointer<T>::operator[](RValue<UInt> index)
+	{
+		Value *element = Nucleus::createGEP(LValue<Pointer<T>>::loadValue(), T::getType(), index.value, true);
 
 		return Reference<T>(element, alignment);
 	}
@@ -2563,7 +2583,15 @@
 	template<class T, int S>
 	Reference<T> Array<T, S>::operator[](int index)
 	{
-		Value *element = LValue<T>::getAddress(Nucleus::createConstantInt(index));
+		Value *element = LValue<T>::getAddress(Nucleus::createConstantInt(index), false);
+
+		return Reference<T>(element);
+	}
+
+	template<class T, int S>
+	Reference<T> Array<T, S>::operator[](unsigned int index)
+	{
+		Value *element = LValue<T>::getAddress(Nucleus::createConstantInt(index), true);
 
 		return Reference<T>(element);
 	}
@@ -2571,7 +2599,15 @@
 	template<class T, int S>
 	Reference<T> Array<T, S>::operator[](RValue<Int> index)
 	{
-		Value *element = LValue<T>::getAddress(index.value);
+		Value *element = LValue<T>::getAddress(index.value, false);
+
+		return Reference<T>(element);
+	}
+
+	template<class T, int S>
+	Reference<T> Array<T, S>::operator[](RValue<UInt> index)
+	{
+		Value *element = LValue<T>::getAddress(index.value, true);
 
 		return Reference<T>(element);
 	}
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index 7ba4e50..9cd6fb8 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -804,7 +804,7 @@
 		return value;
 	}
 
-	Value *Nucleus::createGEP(Value *ptr, Type *type, Value *index)
+	Value *Nucleus::createGEP(Value *ptr, Type *type, Value *index, bool unsignedIndex)
 	{
 		assert(index->getType() == Ice::IceType_i32);
 
@@ -827,7 +827,14 @@
 
 		if(sizeof(void*) == 8)
 		{
-			index = createSExt(index, T(Ice::IceType_i64));
+			if(unsignedIndex)
+			{
+				index = createZExt(index, T(Ice::IceType_i64));
+			}
+			else
+			{
+				index = createSExt(index, T(Ice::IceType_i64));
+			}
 		}
 
 		return createAdd(ptr, index);
@@ -6272,12 +6279,12 @@
 
 	RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, RValue<Int> offset)
 	{
-		return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, Byte::getType(), offset.value));
+		return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, Byte::getType(), offset.value, false));
 	}
 
 	RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, RValue<UInt> offset)
 	{
-		return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, Byte::getType(), offset.value));
+		return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, Byte::getType(), offset.value, true));
 	}
 
 	RValue<Pointer<Byte>> operator+=(Pointer<Byte> &lhs, int offset)