Reactor: Fix Trunc generic code generation

This commit fixes `Trunc(Float)` and `Trunc(Float4)` generic LLVM code
generation.  If `Trunc(x)` is implemented with `Float(Int(x))`, it will
result in quality warning in dEQP.

Bug: b/115344057
Test: dEQP-GLES3.functional.shaders.builtin_functions.precision.trunc
Test: dEQP-GLES3.functional.shaders.builtin_functions.precision.modf
Change-Id: I62d2dd1907e345fb00307b6c0d4d74613237f94b
Reviewed-on: https://swiftshader-review.googlesource.com/21029
Tested-by: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index a69c794..92e4586 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -202,6 +202,13 @@
 		return ::builder->CreateCall(floor, ARGS(x));
 	}
 
+	llvm::Value *lowerTrunc(llvm::Value *x)
+	{
+		llvm::Function *trunc = llvm::Intrinsic::getDeclaration(
+			::module, llvm::Intrinsic::trunc, {x->getType()});
+		return ::builder->CreateCall(trunc, ARGS(x));
+	}
+
 	// Packed add/sub saturatation
 	llvm::Value *lowerPSAT(llvm::Value *x, llvm::Value *y, bool isAdd, bool isSigned)
 	{
@@ -535,6 +542,7 @@
 		{
 			func_.emplace("floorf", reinterpret_cast<void*>(floorf));
 			func_.emplace("nearbyintf", reinterpret_cast<void*>(nearbyintf));
+			func_.emplace("truncf", reinterpret_cast<void*>(truncf));
 		}
 
 		void *findSymbol(const std::string &name) const
@@ -6274,10 +6282,12 @@
 			return x86::roundss(x, 3);
 		}
 		else
-#endif
 		{
 			return Float(Int(x));   // Rounded toward zero
 		}
+#else
+		return RValue<Float>(V(lowerTrunc(V(x.value))));
+#endif
 	}
 
 	RValue<Float> Frac(RValue<Float> x)
@@ -6745,10 +6755,12 @@
 			return x86::roundps(x, 3);
 		}
 		else
-#endif
 		{
 			return Float4(Int4(x));
 		}
+#else
+		return RValue<Float4>(V(lowerTrunc(V(x.value))));
+#endif
 	}
 
 	RValue<Float4> Frac(RValue<Float4> x)