Make LValue a template class.

This avoids having to store the type as a member field.

Bug swiftshader:12

Change-Id: I53ea4869a5b590027217d1e9cc015c0502ab530f
Reviewed-on: https://swiftshader-review.googlesource.com/7361
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index 47518ec..8d1c43d 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -810,31 +810,6 @@
 		return T(llvm::Type::getVoidTy(*::context));
 	}
 
-	LValue::LValue(Type *type, int arraySize) : type(type)
-	{
-		address = Nucleus::allocateStackVariable(type, arraySize);
-	}
-
-	Value *LValue::loadValue(unsigned int alignment) const
-	{
-		return Nucleus::createLoad(address, type, false, alignment);
-	}
-
-	Value *LValue::storeValue(Value *value, unsigned int alignment) const
-	{
-		return Nucleus::createStore(value, address, false, alignment);
-	}
-
-	Value *LValue::storeValue(Constant *constant, unsigned int alignment) const
-	{
-		return Nucleus::createStore(constant, address, false, alignment);
-	}
-
-	Value *LValue::getAddress(Value *index) const
-	{
-		return Nucleus::createGEP(address, index);
-	}
-
 	class MMX : public Variable<MMX>
 	{
 	public:
diff --git a/src/Reactor/Reactor.hpp b/src/Reactor/Reactor.hpp
index ba935ec..e8cc5c9 100644
--- a/src/Reactor/Reactor.hpp
+++ b/src/Reactor/Reactor.hpp
@@ -68,10 +68,11 @@
 	template<class T>
 	class Pointer;
 
+	template<class T>
 	class LValue
 	{
 	public:
-		LValue(Type *type, int arraySize = 0);
+		LValue(int arraySize = 0);
 
 		static bool isVoid()
 		{
@@ -84,12 +85,11 @@
 		Value *getAddress(Value *index) const;
 
 	protected:
-		Type *const type;
 		Value *address;
 	};
 
 	template<class T>
-	class Variable : public LValue
+	class Variable : public LValue<T>
 	{
 	public:
 		Variable(int arraySize = 0);
@@ -2210,7 +2210,7 @@
 		Pointer(RValue<Pointer<S>> pointerS, int alignment = 1) : alignment(alignment)
 		{
 			Value *pointerT = Nucleus::createBitCast(pointerS.value, Nucleus::getPointerType(T::getType()));
-			LValue::storeValue(pointerT);
+			LValue<Pointer<T>>::storeValue(pointerT);
 		}
 
 		template<class S>
@@ -2218,7 +2218,7 @@
 		{
 			Value *pointerS = pointer.loadValue(alignment);
 			Value *pointerT = Nucleus::createBitCast(pointerS, Nucleus::getPointerType(T::getType()));
-			LValue::storeValue(pointerT);
+			LValue<Pointer<T>>::storeValue(pointerT);
 		}
 
 		Pointer(Argument<Pointer<T>> argument);
@@ -2345,14 +2345,44 @@
 namespace sw
 {
 	template<class T>
-	Variable<T>::Variable(int arraySize) : LValue(T::getType(), arraySize)
+	LValue<T>::LValue(int arraySize)
+	{
+		address = Nucleus::allocateStackVariable(T::getType(), arraySize);
+	}
+
+	template<class T>
+	Value *LValue<T>::loadValue(unsigned int alignment) const
+	{
+		return Nucleus::createLoad(address, T::getType(), false, alignment);
+	}
+
+	template<class T>
+	Value *LValue<T>::storeValue(Value *value, unsigned int alignment) const
+	{
+		return Nucleus::createStore(value, address, false, alignment);
+	}
+
+	template<class T>
+	Value *LValue<T>::storeValue(Constant *constant, unsigned int alignment) const
+	{
+		return Nucleus::createStore(constant, address, false, alignment);
+	}
+
+	template<class T>
+	Value *LValue<T>::getAddress(Value *index) const
+	{
+		return Nucleus::createGEP(address, index);
+	}
+
+	template<class T>
+	Variable<T>::Variable(int arraySize) : LValue<T>(arraySize)
 	{
 	}
 
 	template<class T>
 	RValue<Pointer<T>> Variable<T>::operator&()
 	{
-		return RValue<Pointer<T>>(LValue::address);
+		return RValue<Pointer<T>>(LValue<T>::address);
 	}
 
 	template<class T>
@@ -2583,7 +2613,7 @@
 	template<class T>
 	Pointer<T>::Pointer(Argument<Pointer<T>> argument) : alignment(1)
 	{
-		LValue::storeValue(argument.value);
+		LValue<Pointer<T>>::storeValue(argument.value);
 	}
 
 	template<class T>
@@ -2591,39 +2621,39 @@
 	{
 		Constant *globalPointer = Nucleus::createConstantPointer(external, T::getType(), false, alignment);
 
-		LValue::storeValue(globalPointer);
+		LValue<Pointer<T>>::storeValue(globalPointer);
 	}
 
 	template<class T>
 	Pointer<T>::Pointer() : alignment(1)
 	{
-		LValue::storeValue(Nucleus::createNullPointer(T::getType()));
+		LValue<Pointer<T>>::storeValue(Nucleus::createNullPointer(T::getType()));
 	}
 
 	template<class T>
 	Pointer<T>::Pointer(RValue<Pointer<T>> rhs) : alignment(1)
 	{
-		LValue::storeValue(rhs.value);
+		LValue<Pointer<T>>::storeValue(rhs.value);
 	}
 
 	template<class T>
 	Pointer<T>::Pointer(const Pointer<T> &rhs) : alignment(rhs.alignment)
 	{
 		Value *value = rhs.loadValue();
-		LValue::storeValue(value);
+		LValue<Pointer<T>>::storeValue(value);
 	}
 
 	template<class T>
 	Pointer<T>::Pointer(const Reference<Pointer<T>> &rhs) : alignment(rhs.getAlignment())
 	{
 		Value *value = rhs.loadValue();
-		LValue::storeValue(value);
+		LValue<Pointer<T>>::storeValue(value);
 	}
 
 	template<class T>
 	RValue<Pointer<T>> Pointer<T>::operator=(RValue<Pointer<T>> rhs) const
 	{
-		LValue::storeValue(rhs.value);
+		LValue<Pointer<T>>::storeValue(rhs.value);
 
 		return rhs;
 	}
@@ -2632,7 +2662,7 @@
 	RValue<Pointer<T>> Pointer<T>::operator=(const Pointer<T> &rhs) const
 	{
 		Value *value = rhs.loadValue();
-		LValue::storeValue(value);
+		LValue<Pointer<T>>::storeValue(value);
 
 		return RValue<Pointer<T>>(value);
 	}
@@ -2641,7 +2671,7 @@
 	RValue<Pointer<T>> Pointer<T>::operator=(const Reference<Pointer<T>> &rhs) const
 	{
 		Value *value = rhs.loadValue();
-		LValue::storeValue(value);
+		LValue<Pointer<T>>::storeValue(value);
 
 		return RValue<Pointer<T>>(value);
 	}
@@ -2649,13 +2679,13 @@
 	template<class T>
 	Reference<T> Pointer<T>::operator*()
 	{
-		return Reference<T>(LValue::loadValue(), alignment);
+		return Reference<T>(LValue<Pointer<T>>::loadValue(), alignment);
 	}
 
 	template<class T>
 	Reference<T> Pointer<T>::operator[](int index)
 	{
-		Value *element = Nucleus::createGEP(LValue::loadValue(), (Value*)Nucleus::createConstantInt(index));
+		Value *element = Nucleus::createGEP(LValue<Pointer<T>>::loadValue(), (Value*)Nucleus::createConstantInt(index));
 
 		return Reference<T>(element, alignment);
 	}
@@ -2663,7 +2693,7 @@
 	template<class T>
 	Reference<T> Pointer<T>::operator[](RValue<Int> index)
 	{
-		Value *element = Nucleus::createGEP(LValue::loadValue(), index.value);
+		Value *element = Nucleus::createGEP(LValue<Pointer<T>>::loadValue(), index.value);
 
 		return Reference<T>(element, alignment);
 	}
@@ -2682,7 +2712,7 @@
 	template<class T, int S>
 	Reference<T> Array<T, S>::operator[](int index)
 	{
-		Value *element = LValue::getAddress((Value*)Nucleus::createConstantInt(index));
+		Value *element = LValue<T>::getAddress((Value*)Nucleus::createConstantInt(index));
 
 		return Reference<T>(element);
 	}
@@ -2690,7 +2720,7 @@
 	template<class T, int S>
 	Reference<T> Array<T, S>::operator[](RValue<Int> index)
 	{
-		Value *element = LValue::getAddress(index.value);
+		Value *element = LValue<T>::getAddress(index.value);
 
 		return Reference<T>(element);
 	}
@@ -2806,8 +2836,8 @@
 		return RValue<T>(Nucleus::createBitCast(val.value, T::getType()));
 	}
 
-	template<class T>
-	RValue<T> ReinterpretCast(const LValue &var)
+	template<class T, class S>
+	RValue<T> ReinterpretCast(const LValue<S> &var)
 	{
 		Value *val = var.loadValue();
 
@@ -2826,8 +2856,8 @@
 		return ReinterpretCast<T>(val);
 	}
 
-	template<class T>
-	RValue<T> As(const LValue &var)
+	template<class T, class S>
+	RValue<T> As(const LValue<S> &var)
 	{
 		return ReinterpretCast<T>(var);
 	}
@@ -2877,4 +2907,4 @@
 		onceBB__ = 0, Nucleus::createBr(endBB__), Nucleus::setInsertBlock(endBB__))
 }
 
-#endif   // sw_Reactor_hpp
\ No newline at end of file
+#endif   // sw_Reactor_hpp
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index 021005d..dbb4802 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -773,31 +773,6 @@
 		return T(Ice::IceType_void);
 	}
 
-	LValue::LValue(Type *type, int arraySize) : type(type)
-	{
-		address = Nucleus::allocateStackVariable(type, arraySize);
-	}
-
-	Value *LValue::loadValue(unsigned int alignment) const
-	{
-		return Nucleus::createLoad(address, type, false, alignment);
-	}
-
-	Value *LValue::storeValue(Value *value, unsigned int alignment) const
-	{
-		return Nucleus::createStore(value, address, false, alignment);
-	}
-
-	Value *LValue::storeValue(Constant *constant, unsigned int alignment) const
-	{
-		return Nucleus::createStore(constant, address, false, alignment);
-	}
-
-	Value *LValue::getAddress(Value *index) const
-	{
-		return Nucleus::createGEP(address, index);
-	}
-
 	Bool::Bool(Argument<Bool> argument)
 	{
 		storeValue(argument.value);