Make Function arguments type-safe.

Change-Id: I3d4262ea4be0c7b1128b2ca410e985cc6f58c9c9
Reviewed-on: https://swiftshader-review.googlesource.com/1970
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/Main/FrameBuffer.cpp b/src/Main/FrameBuffer.cpp
index cd387c8..aa3e55f 100644
--- a/src/Main/FrameBuffer.cpp
+++ b/src/Main/FrameBuffer.cpp
@@ -236,8 +236,8 @@
 
 		Function<Void(Pointer<Byte>, Pointer<Byte>)> function;
 		{
-			Pointer<Byte> dst(function.arg(0));
-			Pointer<Byte> src(function.arg(1));
+			Pointer<Byte> dst(function.Arg<0>());
+			Pointer<Byte> src(function.Arg<1>());
 
 			For(Int y = 0, y < height, y++)
 			{
diff --git a/src/Reactor/Nucleus.cpp b/src/Reactor/Nucleus.cpp
index 094481b..2325c7f 100644
--- a/src/Reactor/Nucleus.cpp
+++ b/src/Reactor/Nucleus.cpp
@@ -294,7 +294,7 @@
 		return function;
 	}
 
-	llvm::Argument *Nucleus::getArgument(llvm::Function *function, unsigned int index)
+	llvm::Value *Nucleus::getArgument(llvm::Function *function, unsigned int index)
 	{
 		llvm::Function::arg_iterator args = function->arg_begin();
 
@@ -847,9 +847,9 @@
 		return Type::getX86_MMXTy(*Nucleus::getContext());
 	}
 
-	Bool::Bool(Argument *argument)
+	Bool::Bool(Argument<Bool> argument)
 	{
-		storeValue(argument);
+		storeValue(argument.value);
 	}
 
 	Bool::Bool()
@@ -921,9 +921,9 @@
 		return Type::getInt1Ty(*Nucleus::getContext());
 	}
 
-	Byte::Byte(Argument *argument)
+	Byte::Byte(Argument<Byte> argument)
 	{
-		storeValue(argument);
+		storeValue(argument.value);
 	}
 
 	Byte::Byte(RValue<Int> cast)
@@ -1187,9 +1187,9 @@
 		return Type::getInt8Ty(*Nucleus::getContext());
 	}
 
-	SByte::SByte(Argument *argument)
+	SByte::SByte(Argument<SByte> argument)
 	{
-		storeValue(argument);
+		storeValue(argument.value);
 	}
 
 	SByte::SByte(RValue<Int> cast)
@@ -1441,9 +1441,9 @@
 		return Type::getInt8Ty(*Nucleus::getContext());
 	}
 
-	Short::Short(Argument *argument)
+	Short::Short(Argument<Short> argument)
 	{
-		storeValue(argument);
+		storeValue(argument.value);
 	}
 
 	Short::Short(RValue<Int> cast)
@@ -1688,9 +1688,9 @@
 		return Type::getInt16Ty(*Nucleus::getContext());
 	}
 
-	UShort::UShort(Argument *argument)
+	UShort::UShort(Argument<UShort> argument)
 	{
-		storeValue(argument);
+		storeValue(argument.value);
 	}
 
 	UShort::UShort(RValue<UInt> cast)
@@ -3747,9 +3747,9 @@
 		return VectorType::get(UShort::getType(), 8);
 	}
 
-	Int::Int(Argument *argument)
+	Int::Int(Argument<Int> argument)
 	{
-		storeValue(argument);
+		storeValue(argument.value);
 	}
 
 	Int::Int(RValue<Byte> cast)
@@ -4225,9 +4225,9 @@
 		return VectorType::get(Long::getType(), 2);
 	}
 
-	UInt::UInt(Argument *argument)
+	UInt::UInt(Argument<UInt> argument)
 	{
-		storeValue(argument);
+		storeValue(argument.value);
 	}
 
 	UInt::UInt(RValue<UShort> cast)
@@ -6765,62 +6765,62 @@
 		return VectorType::get(Float::getType(), 4);
 	}
 
-	RValue<Pointer<Byte> > operator+(RValue<Pointer<Byte> > lhs, int offset)
+	RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, int offset)
 	{
-		return RValue<Pointer<Byte> >(Nucleus::createGEP(lhs.value, Nucleus::createConstantInt(offset)));
+		return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, Nucleus::createConstantInt(offset)));
 	}
 
-	RValue<Pointer<Byte> > operator+(RValue<Pointer<Byte> > lhs, RValue<Int> offset)
+	RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, RValue<Int> offset)
 	{
-		return RValue<Pointer<Byte> >(Nucleus::createGEP(lhs.value, offset.value));
+		return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, offset.value));
 	}
 
-	RValue<Pointer<Byte> > operator+(RValue<Pointer<Byte> > lhs, RValue<UInt> offset)
+	RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, RValue<UInt> offset)
 	{
-		return RValue<Pointer<Byte> >(Nucleus::createGEP(lhs.value, offset.value));
+		return RValue<Pointer<Byte>>(Nucleus::createGEP(lhs.value, offset.value));
 	}
 
-	RValue<Pointer<Byte> > operator+=(const Pointer<Byte> &lhs, int offset)
+	RValue<Pointer<Byte>> operator+=(const Pointer<Byte> &lhs, int offset)
 	{
 		return lhs = lhs + offset;
 	}
 
-	RValue<Pointer<Byte> > operator+=(const Pointer<Byte> &lhs, RValue<Int> offset)
+	RValue<Pointer<Byte>> operator+=(const Pointer<Byte> &lhs, RValue<Int> offset)
 	{
 		return lhs = lhs + offset;
 	}
 
-	RValue<Pointer<Byte> > operator+=(const Pointer<Byte> &lhs, RValue<UInt> offset)
+	RValue<Pointer<Byte>> operator+=(const Pointer<Byte> &lhs, RValue<UInt> offset)
 	{
 		return lhs = lhs + offset;
 	}
 
-	RValue<Pointer<Byte> > operator-(RValue<Pointer<Byte> > lhs, int offset)
+	RValue<Pointer<Byte>> operator-(RValue<Pointer<Byte>> lhs, int offset)
 	{
 		return lhs + -offset;
 	}
 
-	RValue<Pointer<Byte> > operator-(RValue<Pointer<Byte> > lhs, RValue<Int> offset)
+	RValue<Pointer<Byte>> operator-(RValue<Pointer<Byte>> lhs, RValue<Int> offset)
 	{
 		return lhs + -offset;
 	}
 
-	RValue<Pointer<Byte> > operator-(RValue<Pointer<Byte> > lhs, RValue<UInt> offset)
+	RValue<Pointer<Byte>> operator-(RValue<Pointer<Byte>> lhs, RValue<UInt> offset)
 	{
 		return lhs + -offset;
 	}
 
-	RValue<Pointer<Byte> > operator-=(const Pointer<Byte> &lhs, int offset)
+	RValue<Pointer<Byte>> operator-=(const Pointer<Byte> &lhs, int offset)
 	{
 		return lhs = lhs - offset;
 	}
 
-	RValue<Pointer<Byte> > operator-=(const Pointer<Byte> &lhs, RValue<Int> offset)
+	RValue<Pointer<Byte>> operator-=(const Pointer<Byte> &lhs, RValue<Int> offset)
 	{
 		return lhs = lhs - offset;
 	}
 
-	RValue<Pointer<Byte> > operator-=(const Pointer<Byte> &lhs, RValue<UInt> offset)
+	RValue<Pointer<Byte>> operator-=(const Pointer<Byte> &lhs, RValue<UInt> offset)
 	{
 		return lhs = lhs - offset;
 	}
@@ -7761,7 +7761,7 @@
 			return RValue<Int>(Nucleus::createCall(pmovmskb, As<MMX>(x).value));
 		}
 
-		//RValue<Int2> movd(RValue<Pointer<Int> > x)
+		//RValue<Int2> movd(RValue<Pointer<Int>> x)
 		//{
 		//	Value *element = Nucleus::createLoad(x.value);
 
diff --git a/src/Reactor/Nucleus.hpp b/src/Reactor/Nucleus.hpp
index b4758c0..e305b1a 100644
--- a/src/Reactor/Nucleus.hpp
+++ b/src/Reactor/Nucleus.hpp
@@ -88,7 +88,7 @@
 		static llvm::BasicBlock *getPredecessor(llvm::BasicBlock *basicBlock);

 

 		static llvm::Function *createFunction(llvm::Type *ReturnType, std::vector<llvm::Type*> &Params);

-		static llvm::Argument *getArgument(llvm::Function *function, unsigned int index);

+		static llvm::Value *getArgument(llvm::Function *function, unsigned int index);

 

 		// Terminators

 		static llvm::Value *createRetVoid();

@@ -293,7 +293,7 @@
 	public:

 		Variable(int arraySize = 0);

 

-		RValue<Pointer<T> > operator&();

+		RValue<Pointer<T>> operator&();

 	};

 

 	template<class T>

@@ -368,6 +368,14 @@
 		llvm::Value *value;   // FIXME: Make private

 	};

 

+	template<typename T>

+	struct Argument

+	{

+		explicit Argument(llvm::Value *value) : value(value) {}

+

+		llvm::Value *value;

+	};

+

 	class MMX : public Variable<MMX>

 	{

 	public:

@@ -377,7 +385,7 @@
 	class Bool : public Variable<Bool>

 	{

 	public:

-		explicit Bool(llvm::Argument *argument);

+		Bool(Argument<Bool> argument);

 

 		Bool();

 		Bool(bool x);

@@ -400,7 +408,7 @@
 	class Byte : public Variable<Byte>

 	{

 	public:

-		explicit Byte(llvm::Argument *argument);

+		Byte(Argument<Byte> argument);

 

 		explicit Byte(RValue<Int> cast);

 		explicit Byte(RValue<UInt> cast);

@@ -458,7 +466,7 @@
 	class SByte : public Variable<SByte>

 	{

 	public:

-		explicit SByte(llvm::Argument *argument);

+		SByte(Argument<SByte> argument);

 

 		explicit SByte(RValue<Int> cast);

 		explicit SByte(RValue<Short> cast);

@@ -514,7 +522,7 @@
 	class Short : public Variable<Short>

 	{

 	public:

-		explicit Short(llvm::Argument *argument);

+		Short(Argument<Short> argument);

 

 		explicit Short(RValue<Int> cast);

 

@@ -569,7 +577,7 @@
 	class UShort : public Variable<UShort>

 	{

 	public:

-		explicit UShort(llvm::Argument *argument);

+		UShort(Argument<UShort> argument);

 

 		explicit UShort(RValue<UInt> cast);

 		explicit UShort(RValue<Int> cast);

@@ -1167,7 +1175,7 @@
 	class Int : public Variable<Int>

 	{

 	public:

-		explicit Int(llvm::Argument *argument);

+		Int(Argument<Int> argument);

 

 		explicit Int(RValue<Byte> cast);

 		explicit Int(RValue<SByte> cast);

@@ -1239,7 +1247,7 @@
 	class Long : public Variable<Long>

 	{

 	public:

-	//	explicit Long(llvm::Argument *argument);

+	//	Long(Argument<Long> argument);

 

 	//	explicit Long(RValue<Short> cast);

 	//	explicit Long(RValue<UShort> cast);

@@ -1302,12 +1310,12 @@
 //	RValue<Bool> operator==(RValue<Long> lhs, RValue<Long> rhs);

 

 //	RValue<Long> RoundLong(RValue<Float> cast);

-    RValue<Long> AddAtomic( RValue<Pointer<Long> > x, RValue<Long> y);

+    RValue<Long> AddAtomic( RValue<Pointer<Long>> x, RValue<Long> y);

 

 	class Long1 : public Variable<Long1>

 	{

 	public:

-	//	explicit Long1(llvm::Argument *argument);

+	//	Long1(Argument<Long1> argument);

 

 	//	explicit Long1(RValue<Short> cast);

 	//	explicit Long1(RValue<UShort> cast);

@@ -1437,7 +1445,7 @@
 	class UInt : public Variable<UInt>

 	{

 	public:

-		explicit UInt(llvm::Argument *argument);

+		UInt(Argument<UInt> argument);

 

 		explicit UInt(RValue<UShort> cast);

 		explicit UInt(RValue<Long> cast);

@@ -2393,11 +2401,11 @@
 	RValue<Float4> Ceil(RValue<Float4> x);

 

 	template<class T>

-	class Pointer : public Variable<Pointer<T> >

+	class Pointer : public Variable<Pointer<T>>

 	{

 	public:

 		template<class S>

-		Pointer(RValue<Pointer<S> > pointerS, int alignment = 1) : alignment(alignment)

+		Pointer(RValue<Pointer<S>> pointerS, int alignment = 1) : alignment(alignment)

 		{

 			llvm::Value *pointerT = Nucleus::createBitCast(pointerS.value, Nucleus::getPointerType(T::getType()));

 			LValue::storeValue(pointerT);

@@ -2411,17 +2419,17 @@
 			LValue::storeValue(pointerT);

 		}

 

-		explicit Pointer(llvm::Argument *argument);

+		Pointer(Argument<Pointer<T>> argument);

 		explicit Pointer(const void *external);

 

 		Pointer();

-		Pointer(RValue<Pointer<T> > rhs);

+		Pointer(RValue<Pointer<T>> rhs);

 		Pointer(const Pointer<T> &rhs);

-		Pointer(const Reference<Pointer<T> > &rhs);

+		Pointer(const Reference<Pointer<T>> &rhs);

 

-		RValue<Pointer<T> > operator=(RValue<Pointer<T> > rhs) const;

-		RValue<Pointer<T> > operator=(const Pointer<T> &rhs) const;

-		RValue<Pointer<T> > operator=(const Reference<Pointer<T> > &rhs) const;

+		RValue<Pointer<T>> operator=(RValue<Pointer<T>> rhs) const;

+		RValue<Pointer<T>> operator=(const Pointer<T> &rhs) const;

+		RValue<Pointer<T>> operator=(const Reference<Pointer<T>> &rhs) const;

 

 		Reference<T> operator*();

 

@@ -2431,19 +2439,19 @@
 		const int alignment;

 	};

 

-    RValue<Pointer<Byte> > operator+(RValue<Pointer<Byte> > lhs, int offset);

-    RValue<Pointer<Byte> > operator+(RValue<Pointer<Byte> > lhs, RValue<Int> offset);

-    RValue<Pointer<Byte> > operator+(RValue<Pointer<Byte> > lhs, RValue<UInt> offset);

-    RValue<Pointer<Byte> > operator+=(const Pointer<Byte> &lhs, int offset);

-    RValue<Pointer<Byte> > operator+=(const Pointer<Byte> &lhs, RValue<Int> offset);

-    RValue<Pointer<Byte> > operator+=(const Pointer<Byte> &lhs, RValue<UInt> offset);

+    RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, int offset);

+    RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, RValue<Int> offset);

+    RValue<Pointer<Byte>> operator+(RValue<Pointer<Byte>> lhs, RValue<UInt> offset);

+    RValue<Pointer<Byte>> operator+=(const Pointer<Byte> &lhs, int offset);

+    RValue<Pointer<Byte>> operator+=(const Pointer<Byte> &lhs, RValue<Int> offset);

+    RValue<Pointer<Byte>> operator+=(const Pointer<Byte> &lhs, RValue<UInt> offset);

 

-    RValue<Pointer<Byte> > operator-(RValue<Pointer<Byte> > lhs, int offset);

-    RValue<Pointer<Byte> > operator-(RValue<Pointer<Byte> > lhs, RValue<Int> offset);

-    RValue<Pointer<Byte> > operator-(RValue<Pointer<Byte> > lhs, RValue<UInt> offset);

-    RValue<Pointer<Byte> > operator-=(const Pointer<Byte> &lhs, int offset);

-    RValue<Pointer<Byte> > operator-=(const Pointer<Byte> &lhs, RValue<Int> offset);

-    RValue<Pointer<Byte> > operator-=(const Pointer<Byte> &lhs, RValue<UInt> offset);

+    RValue<Pointer<Byte>> operator-(RValue<Pointer<Byte>> lhs, int offset);

+    RValue<Pointer<Byte>> operator-(RValue<Pointer<Byte>> lhs, RValue<Int> offset);

+    RValue<Pointer<Byte>> operator-(RValue<Pointer<Byte>> lhs, RValue<UInt> offset);

+    RValue<Pointer<Byte>> operator-=(const Pointer<Byte> &lhs, int offset);

+    RValue<Pointer<Byte>> operator-=(const Pointer<Byte> &lhs, RValue<Int> offset);

+    RValue<Pointer<Byte>> operator-=(const Pointer<Byte> &lhs, RValue<UInt> offset);

 

 	template<class T, int S = 1>

 	class Array : public Variable<T>

@@ -2456,9 +2464,9 @@
 		Reference<T> operator[](RValue<UInt> index);

 	};

 

-//	RValue<Array<T> > operator++(const Array<T> &val, int);   // Post-increment

+//	RValue<Array<T>> operator++(const Array<T> &val, int);   // Post-increment

 //	const Array<T> &operator++(const Array<T> &val);   // Pre-increment

-//	RValue<Array<T> > operator--(const Array<T> &val, int);   // Post-decrement

+//	RValue<Array<T>> operator--(const Array<T> &val, int);   // Post-decrement

 //	const Array<T> &operator--(const Array<T> &val);   // Pre-decrement

 

 	llvm::BasicBlock *beginLoop();

@@ -2473,7 +2481,22 @@
 	void Return(const Pointer<T> &ret);

 

 	template<class T>

-	void Return(RValue<Pointer<T> > ret);

+	void Return(RValue<Pointer<T>> ret);

+

+	template<unsigned int index, typename... Arguments>

+	struct ArgI;

+

+	template<typename Arg0, typename... Arguments>

+	struct ArgI<0, Arg0, Arguments...>

+	{

+		typedef Arg0 Type;

+	};

+

+	template<unsigned int index, typename Arg0, typename... Arguments>

+	struct ArgI<index, Arg0, Arguments...>

+	{

+		typedef typename ArgI<index - 1, Arguments...>::Type Type;

+	};

 

 	// Generic template, leave undefined!

 	template<typename FunctionType>

@@ -2488,7 +2511,12 @@
 

 		virtual ~Function();

 

-		llvm::Argument *arg(int index);

+		template<int index>

+        Argument<typename ArgI<index, Arguments...>::Type> Arg() const

+        {

+			llvm::Value *arg = Nucleus::getArgument(function, index);

+            return Argument<typename ArgI<index, Arguments...>::Type>(arg);

+        }

 

 		Routine *operator()(const wchar_t *name, ...);

 

@@ -2498,6 +2526,12 @@
 		std::vector<llvm::Type*> arguments;

 	};

 

+	template<int index, typename Return, typename... Arguments>

+	Argument<typename ArgI<index, Arguments...>::Type> Arg(Function<Return(Arguments...)> &function)

+	{

+		return Argument<typename ArgI<index, Arguments...>::Type>(function.arg(index));

+	}

+

 	RValue<Long> Ticks();

 }

 

@@ -2509,9 +2543,9 @@
 	}

 

 	template<class T>

-	RValue<Pointer<T> > Variable<T>::operator&()

+	RValue<Pointer<T>> Variable<T>::operator&()

 	{

-		return RValue<Pointer<T> >(LValue::address);

+		return RValue<Pointer<T>>(LValue::address);

 	}

 

 	template<class T>

@@ -2740,9 +2774,9 @@
 	}

 

 	template<class T>

-	Pointer<T>::Pointer(llvm::Argument *argument) : alignment(1)

+	Pointer<T>::Pointer(Argument<Pointer<T>> argument) : alignment(1)

 	{

-		LValue::storeValue((llvm::Value*)argument);

+		LValue::storeValue(argument.value);

 	}

 

 	template<class T>

@@ -2767,7 +2801,7 @@
 	}

 

 	template<class T>

-	Pointer<T>::Pointer(RValue<Pointer<T> > rhs) : alignment(1)

+	Pointer<T>::Pointer(RValue<Pointer<T>> rhs) : alignment(1)

 	{

 		LValue::storeValue(rhs.value);

 	}

@@ -2780,14 +2814,14 @@
 	}

 

 	template<class T>

-	Pointer<T>::Pointer(const Reference<Pointer<T> > &rhs) : alignment(rhs.getAlignment())

+	Pointer<T>::Pointer(const Reference<Pointer<T>> &rhs) : alignment(rhs.getAlignment())

 	{

 		llvm::Value *value = rhs.loadValue();

 		LValue::storeValue(value);

 	}

 

 	template<class T>

-	RValue<Pointer<T> > Pointer<T>::operator=(RValue<Pointer<T> > rhs) const

+	RValue<Pointer<T>> Pointer<T>::operator=(RValue<Pointer<T>> rhs) const

 	{

 		LValue::storeValue(rhs.value);

 

@@ -2795,21 +2829,21 @@
 	}

 

 	template<class T>

-	RValue<Pointer<T> > Pointer<T>::operator=(const Pointer<T> &rhs) const

+	RValue<Pointer<T>> Pointer<T>::operator=(const Pointer<T> &rhs) const

 	{

 		llvm::Value *value = rhs.loadValue();

 		LValue::storeValue(value);

 

-		return RValue<Pointer<T> >(value);

+		return RValue<Pointer<T>>(value);

 	}

 

 	template<class T>

-	RValue<Pointer<T> > Pointer<T>::operator=(const Reference<Pointer<T> > &rhs) const

+	RValue<Pointer<T>> Pointer<T>::operator=(const Reference<Pointer<T>> &rhs) const

 	{

 		llvm::Value *value = rhs.loadValue();

 		LValue::storeValue(value);

 

-		return RValue<Pointer<T> >(value);

+		return RValue<Pointer<T>>(value);

 	}

 

 	template<class T>

@@ -2854,7 +2888,7 @@
 	}

 

 //	template<class T>

-//	RValue<Array<T> > operator++(const Array<T> &val, int)

+//	RValue<Array<T>> operator++(const Array<T> &val, int)

 //	{

 //		// FIXME: Requires storing the address of the array

 //	}

@@ -2866,7 +2900,7 @@
 //	}

 

 //	template<class T>

-//	RValue<Array<T> > operator--(const Array<T> &val, int)

+//	RValue<Array<T>> operator--(const Array<T> &val, int)

 //	{

 //		// FIXME: Requires storing the address of the array

 //	}

@@ -2916,7 +2950,7 @@
 	}

 

 	template<class T>

-	void Return(RValue<Pointer<T> > ret)

+	void Return(RValue<Pointer<T>> ret)

 	{

 		Nucleus::createRet(ret.value);

 		Nucleus::setInsertBlock(Nucleus::createBasicBlock());

@@ -2931,7 +2965,7 @@
 		for(llvm::Type *type : types)

 		{

 			arguments.push_back(type);

-		} 

+		}

 

 		function = Nucleus::createFunction(Return::getType(), arguments);

 		Nucleus::setFunction(function);

@@ -2944,12 +2978,6 @@
 	}

 

 	template<typename Return, typename... Arguments>

-	llvm::Argument *Function<Return(Arguments...)>::arg(int index)

-	{

-		return Nucleus::getArgument(function, index);

-	}

-

-	template<typename Return, typename... Arguments>

 	Routine *Function<Return(Arguments...)>::operator()(const wchar_t *name, ...)

 	{

 		wchar_t fullName[1024 + 1];

diff --git a/src/Renderer/Blitter.cpp b/src/Renderer/Blitter.cpp
index 677b343..07867db 100644
--- a/src/Renderer/Blitter.cpp
+++ b/src/Renderer/Blitter.cpp
@@ -589,7 +589,7 @@
 			{
 				unsigned short mask = (writeB ? 0x001F : 0x0000) | (writeG ? 0x07E0 : 0x0000) | (writeR ? 0xF800 : 0x0000);
 				unsigned short unmask = ~mask;
-				*Pointer<UShort>(element) = (*Pointer<UShort>(element) & UShort(unmask)) | 
+				*Pointer<UShort>(element) = (*Pointer<UShort>(element) & UShort(unmask)) |
 				                            (UShort(RoundInt(Float(c.z)) |
 				                                   (RoundInt(Float(c.y)) << Int(5)) |
 				                                   (RoundInt(Float(c.x)) << Int(11))) & UShort(mask));
@@ -966,10 +966,10 @@
 	{
 		Function<Void(Pointer<Byte>)> function;
 		{
-			Pointer<Byte> blit(function.arg(0));
+			Pointer<Byte> blit(function.Arg<0>());
 
-			Pointer<Byte> source = *Pointer<Pointer<Byte> >(blit + OFFSET(BlitData,source));
-			Pointer<Byte> dest = *Pointer<Pointer<Byte> >(blit + OFFSET(BlitData,dest));
+			Pointer<Byte> source = *Pointer<Pointer<Byte>>(blit + OFFSET(BlitData,source));
+			Pointer<Byte> dest = *Pointer<Pointer<Byte>>(blit + OFFSET(BlitData,dest));
 			Int sPitchB = *Pointer<Int>(blit + OFFSET(BlitData,sPitchB));
 			Int dPitchB = *Pointer<Int>(blit + OFFSET(BlitData,dPitchB));
 
@@ -1147,7 +1147,7 @@
 
 		criticalSection.lock();
 		Routine *blitRoutine = blitCache->query(state);
-		
+
 		if(!blitRoutine)
 		{
 			blitRoutine = generate(state);
@@ -1179,7 +1179,7 @@
 		data.h = 1.0f / (dRect.y1 - dRect.y0) * (sRect.y1 - sRect.y0);
 		data.x0 = (float)sRect.x0 + 0.5f * data.w;
 		data.y0 = (float)sRect.y0 + 0.5f * data.h;
-		
+
 		data.x0d = dRect.x0;
 		data.x1d = dRect.x1;
 		data.y0d = dRect.y0;
diff --git a/src/Renderer/QuadRasterizer.cpp b/src/Renderer/QuadRasterizer.cpp
index dfee2f6..5ca2622 100644
--- a/src/Renderer/QuadRasterizer.cpp
+++ b/src/Renderer/QuadRasterizer.cpp
@@ -53,16 +53,16 @@
 				Long pixelTime = Ticks();
 			#endif
 
-			Pointer<Byte> primitive(function.arg(0));
-			Int count(function.arg(1));
-			Int cluster(function.arg(2));
-			Pointer<Byte> data(function.arg(3));
+			Pointer<Byte> primitive(function.Arg<0>());
+			Int count(function.Arg<1>());
+			Int cluster(function.Arg<2>());
+			Pointer<Byte> data(function.Arg<3>());
 
 			Registers& r = *createRegisters(shader);
 			r.constants = *Pointer<Pointer<Byte> >(data + OFFSET(DrawData,constants));
 			r.cluster = cluster;
 			r.data = data;
-			
+
 			Do
 			{
 				r.primitive = primitive;
@@ -134,20 +134,20 @@
 		}
 
 		Int y = yMin;
-		
+
 		Do
 		{
 			Int x0a = Int(*Pointer<Short>(r.primitive + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span)));
 			Int x0b = Int(*Pointer<Short>(r.primitive + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span)));
 			Int x0 = Min(x0a, x0b);
-			
+
 			for(unsigned int q = 1; q < state.multiSample; q++)
 			{
 				x0a = Int(*Pointer<Short>(r.primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span)));
 				x0b = Int(*Pointer<Short>(r.primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span)));
 				x0 = Min(x0, Min(x0a, x0b));
 			}
-			
+
 			x0 &= 0xFFFFFFFE;
 
 			Int x1a = Int(*Pointer<Short>(r.primitive + OFFSET(Primitive,outline->right) + (y + 0) * sizeof(Primitive::Span)));
@@ -193,7 +193,7 @@
 						pitch = *Pointer<Int>(r.data + OFFSET(DrawData,depthPitchB));
 					}
 					else
-					{	
+					{
 						buffer = zBuffer + 8 * x0;
 					}
 
@@ -202,7 +202,7 @@
 						Float4 z = interpolate(xxxx, r.Dz[0], z, r.primitive + OFFSET(Primitive,z), false, false);
 
 						Float4 zValue;
-						
+
 						if(!state.quadLayoutDepthBuffer)
 						{
 							// FIXME: Properly optimizes?
diff --git a/src/Shader/SetupRoutine.cpp b/src/Shader/SetupRoutine.cpp
index 08cdf59..1e2e897 100644
--- a/src/Shader/SetupRoutine.cpp
+++ b/src/Shader/SetupRoutine.cpp
@@ -36,10 +36,10 @@
 	{
 		Function<Bool(Pointer<Byte>, Pointer<Byte>, Pointer<Byte>, Pointer<Byte>)> function;
 		{
-			Pointer<Byte> primitive(function.arg(0));
-			Pointer<Byte> tri(function.arg(1));
-			Pointer<Byte> polygon(function.arg(2));
-			Pointer<Byte> data(function.arg(3));
+			Pointer<Byte> primitive(function.Arg<0>());
+			Pointer<Byte> tri(function.Arg<1>());
+			Pointer<Byte> polygon(function.Arg<2>());
+			Pointer<Byte> data(function.Arg<3>());
 
 			Pointer<Byte> constants = *Pointer<Pointer<Byte> >(data + OFFSET(DrawData,constants));
 
diff --git a/src/Shader/VertexRoutine.cpp b/src/Shader/VertexRoutine.cpp
index 60b193d..b875517 100644
--- a/src/Shader/VertexRoutine.cpp
+++ b/src/Shader/VertexRoutine.cpp
@@ -36,10 +36,10 @@
 	{
 		Function<Void(Pointer<Byte>, Pointer<Byte>, Pointer<Byte>, Pointer<Byte>)> function;
 		{
-			Pointer<Byte> vertex(function.arg(0));
-			Pointer<Byte> batch(function.arg(1));
-			Pointer<Byte> task(function.arg(2));
-			Pointer<Byte> data(function.arg(3));
+			Pointer<Byte> vertex(function.Arg<0>());
+			Pointer<Byte> batch(function.Arg<1>());
+			Pointer<Byte> task(function.Arg<2>());
+			Pointer<Byte> data(function.Arg<3>());
 
 			const bool texldl = state.shaderContainsTexldl;