Fix constant vector construction for emulated types.

Emulated vectors have fewer elements than their underlying type, e.g.
v4i16 is stored in the lower half of a v8i16 vector, but for constant
vector construction we need to provide values for all the elements of
the underlying vector.

Bug b/65124545

Change-Id: Iaf942c4d517b1d4d464894ec501f7d339ae86438
Reviewed-on: https://swiftshader-review.googlesource.com/11908
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
(cherry picked from commit 69674fb1f01c657bfeb5f2cb6389d4a959b973f6)
Reviewed-on: https://swiftshader-review.googlesource.com/11928
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index b299f6d..8abb17a 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -159,6 +159,26 @@
 		return T(type)->getPrimitiveSizeInBits() / 8;
 	}
 
+	static unsigned int elementCount(Type *type)
+	{
+		uintptr_t t = reinterpret_cast<uintptr_t>(type);
+		if(t < EmulatedTypeCount)
+		{
+			switch(t)
+			{
+			case Type_v2i32: return 2;
+			case Type_v4i16: return 4;
+			case Type_v2i16: return 2;
+			case Type_v8i8:  return 8;
+			case Type_v4i8:  return 4;
+			case Type_v2f32: return 2;
+			default: assert(false);
+			}
+		}
+
+		return llvm::cast<llvm::VectorType>(T(type))->getNumElements();
+	}
+
 	Nucleus::Nucleus()
 	{
 		::codegenMutex.lock();   // Reactor and LLVM are currently not thread safe
@@ -905,31 +925,33 @@
 	Value *Nucleus::createConstantVector(const int64_t *constants, Type *type)
 	{
 		assert(llvm::isa<llvm::VectorType>(T(type)));
-		const int numConstants = llvm::cast<llvm::VectorType>(T(type))->getNumElements();
-		assert(numConstants <= 16);
+		const int numConstants = elementCount(type);                                       // Number of provided constants for the (emulated) type.
+		const int numElements = llvm::cast<llvm::VectorType>(T(type))->getNumElements();   // Number of elements of the underlying vector type.
+		assert(numElements <= 16 && numConstants <= numElements);
 		llvm::Constant *constantVector[16];
 
-		for(int i = 0; i < numConstants; i++)
+		for(int i = 0; i < numElements; i++)
 		{
-			constantVector[i] = llvm::ConstantInt::get(T(type)->getContainedType(0), constants[i]);
+			constantVector[i] = llvm::ConstantInt::get(T(type)->getContainedType(0), constants[i % numConstants]);
 		}
 
-		return V(llvm::ConstantVector::get(llvm::ArrayRef<llvm::Constant*>(constantVector, numConstants)));
+		return V(llvm::ConstantVector::get(llvm::ArrayRef<llvm::Constant*>(constantVector, numElements)));
 	}
 
 	Value *Nucleus::createConstantVector(const double *constants, Type *type)
 	{
 		assert(llvm::isa<llvm::VectorType>(T(type)));
-		const int numConstants = llvm::cast<llvm::VectorType>(T(type))->getNumElements();
-		assert(numConstants <= 8);
+		const int numConstants = elementCount(type);                                       // Number of provided constants for the (emulated) type.
+		const int numElements = llvm::cast<llvm::VectorType>(T(type))->getNumElements();   // Number of elements of the underlying vector type.
+		assert(numElements <= 8 && numConstants <= numElements);
 		llvm::Constant *constantVector[8];
 
-		for(int i = 0; i < numConstants; i++)
+		for(int i = 0; i < numElements; i++)
 		{
-			constantVector[i] = llvm::ConstantFP::get(T(type)->getContainedType(0), constants[i]);
+			constantVector[i] = llvm::ConstantFP::get(T(type)->getContainedType(0), constants[i % numConstants]);
 		}
 
-		return V(llvm::ConstantVector::get(llvm::ArrayRef<llvm::Constant*>(constantVector, numConstants)));
+		return V(llvm::ConstantVector::get(llvm::ArrayRef<llvm::Constant*>(constantVector, numElements)));
 	}
 
 	Type *Void::getType()