Add support for GLSL length.
This CL adds support for the GLSL length command.
Bug: tint:5
Change-Id: I2704bc04e493fb3aef8e5cd58039b6b863cc80f8
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/20001
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/type_determiner.cc b/src/type_determiner.cc
index 06e45c5..dce43c1 100644
--- a/src/type_determiner.cc
+++ b/src/type_determiner.cc
@@ -668,6 +668,24 @@
}
return params[0]->result_type();
+ } else if (name == "length") {
+ if (params.size() != 1) {
+ error_ = "incorrect number of parameters for " + name +
+ ". Expected 1 got " + std::to_string(params.size());
+ return nullptr;
+ }
+ if (!params[0]->result_type()->is_float_scalar_or_vector()) {
+ error_ = "incorrect type for " + name +
+ ". Requires a float scalar or a float vector";
+ return nullptr;
+ }
+
+ *id = GLSLstd450Length;
+ auto* result_type = params[0]->result_type();
+
+ // Length returns a scalar of the same type as the parameter.
+ return result_type->is_float_scalar() ? result_type
+ : result_type->AsVector()->type();
}
return nullptr;
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index cbb52bf..4dbfc2f 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -1618,5 +1618,91 @@
GLSLData{"inversesqrt", GLSLstd450InverseSqrt},
GLSLData{"normalize", GLSLstd450Normalize}));
+TEST_F(TypeDeterminerTest, ImportData_Length_Scalar) {
+ ast::type::F32Type f32;
+
+ ast::ExpressionList params;
+ params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::IntLiteral>(&f32, 1.f)));
+
+ ASSERT_TRUE(td()->DetermineResultType(params)) << td()->error();
+
+ uint32_t id = 0;
+ auto* type = td()->GetImportData("GLSL.std.450", "length", params, &id);
+ ASSERT_NE(type, nullptr);
+ EXPECT_TRUE(type->is_float_scalar());
+ EXPECT_EQ(id, GLSLstd450Length);
+}
+
+TEST_F(TypeDeterminerTest, ImportData_Length_FloatVector) {
+ ast::type::F32Type f32;
+ ast::type::VectorType vec(&f32, 3);
+
+ ast::ExpressionList vals;
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 1.0f)));
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 1.0f)));
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 3.0f)));
+
+ ast::ExpressionList params;
+ params.push_back(
+ std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals)));
+
+ ASSERT_TRUE(td()->DetermineResultType(params)) << td()->error();
+
+ uint32_t id = 0;
+ auto* type = td()->GetImportData("GLSL.std.450", "length", params, &id);
+ ASSERT_NE(type, nullptr);
+ EXPECT_TRUE(type->is_float_scalar());
+ EXPECT_EQ(id, GLSLstd450Length);
+}
+
+TEST_F(TypeDeterminerTest, ImportData_Length_Error_Integer) {
+ ast::type::I32Type i32;
+
+ ast::ExpressionList params;
+ params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::IntLiteral>(&i32, 1)));
+
+ ASSERT_TRUE(td()->DetermineResultType(params)) << td()->error();
+
+ uint32_t id = 0;
+ auto* type = td()->GetImportData("GLSL.std.450", "length", params, &id);
+ ASSERT_EQ(type, nullptr);
+ EXPECT_EQ(
+ td()->error(),
+ "incorrect type for length. Requires a float scalar or a float vector");
+}
+
+TEST_F(TypeDeterminerTest, ImportData_Length_Error_NoParams) {
+ ast::ExpressionList params;
+ uint32_t id = 0;
+ auto* type = td()->GetImportData("GLSL.std.450", "length", params, &id);
+ ASSERT_EQ(type, nullptr);
+ EXPECT_EQ(td()->error(),
+ "incorrect number of parameters for length. Expected 1 got 0");
+}
+
+TEST_F(TypeDeterminerTest, ImportData_Length_Error_MultipleParams) {
+ ast::type::F32Type f32;
+ ast::ExpressionList params;
+ params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 1.f)));
+ params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 1.f)));
+ params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 1.f)));
+
+ ASSERT_TRUE(td()->DetermineResultType(params)) << td()->error();
+
+ uint32_t id = 0;
+ auto* type = td()->GetImportData("GLSL.std.450", "length", params, &id);
+ ASSERT_EQ(type, nullptr);
+ EXPECT_EQ(td()->error(),
+ "incorrect number of parameters for length. Expected 1 got 3");
+}
+
} // namespace
} // namespace tint