From 973bd6a7b4ad9a1754c92b86c468dd1a878f9efc Mon Sep 17 00:00:00 2001 From: dan sinclair Date: Tue, 7 Apr 2020 12:57:42 +0000 Subject: [PATCH] Add array accessor type determination. This Cl adds type determination for an array accessor for arrays, vectors and matrices. Bug: tint:5 Change-Id: Ifce539338fd1f9b539c13970f115a4dbc207ff5a Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/18842 Reviewed-by: David Neto --- src/type_determiner.cc | 30 +++++++++++ src/type_determiner.h | 2 + src/type_determiner_test.cc | 102 ++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) diff --git a/src/type_determiner.cc b/src/type_determiner.cc index bb25fbf532..488b9ad1d3 100644 --- a/src/type_determiner.cc +++ b/src/type_determiner.cc @@ -14,6 +14,9 @@ #include "src/type_determiner.h" +#include + +#include "src/ast/array_accessor_expression.h" #include "src/ast/assignment_statement.h" #include "src/ast/break_statement.h" #include "src/ast/case_statement.h" @@ -26,6 +29,9 @@ #include "src/ast/return_statement.h" #include "src/ast/scalar_constructor_expression.h" #include "src/ast/switch_statement.h" +#include "src/ast/type/array_type.h" +#include "src/ast/type/matrix_type.h" +#include "src/ast/type/vector_type.h" #include "src/ast/type_constructor_expression.h" #include "src/ast/unless_statement.h" #include "src/ast/variable_decl_statement.h" @@ -174,6 +180,9 @@ bool TypeDeterminer::DetermineResultType(ast::Expression* expr) { return true; } + if (expr->IsArrayAccessor()) { + return DetermineArrayAccessor(expr->AsArrayAccessor()); + } if (expr->IsConstructor()) { return DetermineConstructor(expr->AsConstructor()); } @@ -185,6 +194,27 @@ bool TypeDeterminer::DetermineResultType(ast::Expression* expr) { return false; } +bool TypeDeterminer::DetermineArrayAccessor( + ast::ArrayAccessorExpression* expr) { + if (!DetermineResultType(expr->array())) { + return false; + } + auto parent_type = expr->array()->result_type(); + if (parent_type->IsArray()) { + expr->set_result_type(parent_type->AsArray()->type()); + } else if (parent_type->IsVector()) { + expr->set_result_type(parent_type->AsVector()->type()); + } else if (parent_type->IsMatrix()) { + auto m = parent_type->AsMatrix(); + expr->set_result_type(ctx_.type_mgr().Get( + std::make_unique(m->type(), m->rows()))); + } else { + error_ = "invalid parent type in array accessor"; + return false; + } + return true; +} + bool TypeDeterminer::DetermineConstructor(ast::ConstructorExpression* expr) { if (expr->IsTypeConstructor()) { expr->set_result_type(expr->AsTypeConstructor()->type()); diff --git a/src/type_determiner.h b/src/type_determiner.h index 03ad01d7e4..770a1bd4f1 100644 --- a/src/type_determiner.h +++ b/src/type_determiner.h @@ -25,6 +25,7 @@ namespace tint { namespace ast { +class ArrayAccessorExpression; class ConstructorExpression; class IdentifierExpression; class Function; @@ -69,6 +70,7 @@ class TypeDeterminer { bool DetermineResultType(ast::Expression* expr); private: + bool DetermineArrayAccessor(ast::ArrayAccessorExpression* expr); bool DetermineConstructor(ast::ConstructorExpression* expr); bool DetermineIdentifier(ast::IdentifierExpression* expr); Context& ctx_; diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc index c4fec3a694..70dcd76086 100644 --- a/src/type_determiner_test.cc +++ b/src/type_determiner_test.cc @@ -18,6 +18,7 @@ #include #include "gtest/gtest.h" +#include "src/ast/array_accessor_expression.h" #include "src/ast/assignment_statement.h" #include "src/ast/break_statement.h" #include "src/ast/case_statement.h" @@ -32,8 +33,10 @@ #include "src/ast/return_statement.h" #include "src/ast/scalar_constructor_expression.h" #include "src/ast/switch_statement.h" +#include "src/ast/type/array_type.h" #include "src/ast/type/f32_type.h" #include "src/ast/type/i32_type.h" +#include "src/ast/type/matrix_type.h" #include "src/ast/type/vector_type.h" #include "src/ast/type_constructor_expression.h" #include "src/ast/unless_statement.h" @@ -376,6 +379,105 @@ TEST_F(TypeDeterminerTest, Stmt_VariableDecl) { EXPECT_TRUE(init_ptr->result_type()->IsI32()); } +TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Array) { + ast::type::I32Type i32; + ast::type::F32Type f32; + ast::type::ArrayType ary(&f32, 3); + + auto idx = std::make_unique( + std::make_unique(&i32, 2)); + + ast::Module m; + auto var = + std::make_unique("my_var", ast::StorageClass::kNone, &ary); + m.AddGlobalVariable(std::move(var)); + + // Register the global + EXPECT_TRUE(td()->Determine(&m)); + + ast::ArrayAccessorExpression acc( + std::make_unique("my_var"), std::move(idx)); + EXPECT_TRUE(td()->DetermineResultType(&acc)); + ASSERT_NE(acc.result_type(), nullptr); + EXPECT_TRUE(acc.result_type()->IsF32()); +} + +TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Matrix) { + ast::type::I32Type i32; + ast::type::F32Type f32; + ast::type::MatrixType mat(&f32, 3, 2); + + auto idx = std::make_unique( + std::make_unique(&i32, 2)); + + ast::Module m; + auto var = + std::make_unique("my_var", ast::StorageClass::kNone, &mat); + m.AddGlobalVariable(std::move(var)); + + // Register the global + EXPECT_TRUE(td()->Determine(&m)); + + ast::ArrayAccessorExpression acc( + std::make_unique("my_var"), std::move(idx)); + EXPECT_TRUE(td()->DetermineResultType(&acc)); + ASSERT_NE(acc.result_type(), nullptr); + ASSERT_TRUE(acc.result_type()->IsVector()); + EXPECT_EQ(acc.result_type()->AsVector()->size(), 3); +} + +TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Matrix_BothDimensions) { + ast::type::I32Type i32; + ast::type::F32Type f32; + ast::type::MatrixType mat(&f32, 3, 2); + + auto idx1 = std::make_unique( + std::make_unique(&i32, 2)); + auto idx2 = std::make_unique( + std::make_unique(&i32, 1)); + + ast::Module m; + auto var = + std::make_unique("my_var", ast::StorageClass::kNone, &mat); + m.AddGlobalVariable(std::move(var)); + + // Register the global + EXPECT_TRUE(td()->Determine(&m)); + + ast::ArrayAccessorExpression acc( + std::make_unique( + std::make_unique("my_var"), + std::move(idx1)), + std::move(idx2)); + + EXPECT_TRUE(td()->DetermineResultType(&acc)); + ASSERT_NE(acc.result_type(), nullptr); + EXPECT_TRUE(acc.result_type()->IsF32()); +} + +TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Vector) { + ast::type::I32Type i32; + ast::type::F32Type f32; + ast::type::VectorType vec(&f32, 3); + + auto idx = std::make_unique( + std::make_unique(&i32, 2)); + + ast::Module m; + auto var = + std::make_unique("my_var", ast::StorageClass::kNone, &vec); + m.AddGlobalVariable(std::move(var)); + + // Register the global + EXPECT_TRUE(td()->Determine(&m)); + + ast::ArrayAccessorExpression acc( + std::make_unique("my_var"), std::move(idx)); + EXPECT_TRUE(td()->DetermineResultType(&acc)); + ASSERT_NE(acc.result_type(), nullptr); + EXPECT_TRUE(acc.result_type()->IsF32()); +} + TEST_F(TypeDeterminerTest, Expr_Constructor_Scalar) { ast::type::F32Type f32; ast::ScalarConstructorExpression s(