[tint] Resolve @row_major attributes

Check that they are only applied to matrices.

Bug: 364267168
Change-Id: I7d61bf5767bcd85dfccc0c618599e1b38d4ba2eb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/207416
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/tint/lang/wgsl/ast/builder.h b/src/tint/lang/wgsl/ast/builder.h
index cf09f0a..279deca 100644
--- a/src/tint/lang/wgsl/ast/builder.h
+++ b/src/tint/lang/wgsl/ast/builder.h
@@ -84,6 +84,7 @@
 #include "src/tint/lang/wgsl/ast/phony_expression.h"
 #include "src/tint/lang/wgsl/ast/requires.h"
 #include "src/tint/lang/wgsl/ast/return_statement.h"
+#include "src/tint/lang/wgsl/ast/row_major_attribute.h"
 #include "src/tint/lang/wgsl/ast/stage_attribute.h"
 #include "src/tint/lang/wgsl/ast/stride_attribute.h"
 #include "src/tint/lang/wgsl/ast/struct.h"
@@ -3331,6 +3332,17 @@
                                                Expr(std::forward<EXPR_Z>(z)));
     }
 
+    /// Creates an ast::RowMajorAttribute
+    /// @param source the source information
+    /// @returns the row-major attribute pointer
+    const ast::RowMajorAttribute* RowMajor(const Source& source) {
+        return create<ast::RowMajorAttribute>(source);
+    }
+
+    /// Creates an ast::RowMajorAttribute
+    /// @returns the row-major attribute pointer
+    const ast::RowMajorAttribute* RowMajor() { return create<ast::RowMajorAttribute>(source_); }
+
     /// Creates an ast::DisableValidationAttribute
     /// @param validation the validation to disable
     /// @returns the disable validation attribute pointer
diff --git a/src/tint/lang/wgsl/resolver/attribute_validation_test.cc b/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
index ef6cac9..da07571 100644
--- a/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
@@ -2932,6 +2932,36 @@
 }  // namespace
 }  // namespace InternalAttributeDeps
 
+namespace RowMajorAttributeTests {
+
+using RowMajorAttributeTest = ResolverTest;
+
+TEST_F(RowMajorAttributeTest, StructMember_Matrix) {
+    Structure("S", Vector{
+                       Member(Source{{12, 34}}, "m", ty.mat3x4<f32>(), Vector{RowMajor()}),
+                   });
+
+    EXPECT_TRUE(r()->Resolve()) << r()->error();
+}
+
+TEST_F(RowMajorAttributeTest, StructMember_NonMatrix) {
+    Structure("S", Vector{
+                       Member(Source{{12, 34}}, "f", ty.vec4<f32>(), Vector{RowMajor()}),
+                   });
+
+    EXPECT_FALSE(r()->Resolve());
+    EXPECT_EQ(r()->error(), R"(error: '@row_major' can only be applied to matrices)");
+}
+
+TEST_F(RowMajorAttributeTest, Variable) {
+    GlobalVar(Source{{12, 34}}, "v", ty.mat3x4<f32>(), Vector{RowMajor()});
+
+    EXPECT_FALSE(r()->Resolve());
+    EXPECT_EQ(r()->error(), R"(error: '@row_major' is not valid for module-scope 'var')");
+}
+
+}  // namespace RowMajorAttributeTests
+
 }  // namespace tint::resolver
 
 TINT_INSTANTIATE_TYPEINFO(tint::resolver::InternalAttributeDeps::TestAttribute);
diff --git a/src/tint/lang/wgsl/resolver/dependency_graph.cc b/src/tint/lang/wgsl/resolver/dependency_graph.cc
index 0817005..b39a4a7 100644
--- a/src/tint/lang/wgsl/resolver/dependency_graph.cc
+++ b/src/tint/lang/wgsl/resolver/dependency_graph.cc
@@ -62,6 +62,7 @@
 #include "src/tint/lang/wgsl/ast/must_use_attribute.h"
 #include "src/tint/lang/wgsl/ast/override.h"
 #include "src/tint/lang/wgsl/ast/return_statement.h"
+#include "src/tint/lang/wgsl/ast/row_major_attribute.h"
 #include "src/tint/lang/wgsl/ast/stage_attribute.h"
 #include "src/tint/lang/wgsl/ast/stride_attribute.h"
 #include "src/tint/lang/wgsl/ast/struct.h"
@@ -397,7 +398,8 @@
             [&](Default) {
                 if (!attr->IsAnyOf<ast::BuiltinAttribute, ast::DiagnosticAttribute,
                                    ast::InterpolateAttribute, ast::InvariantAttribute,
-                                   ast::MustUseAttribute, ast::StageAttribute, ast::StrideAttribute,
+                                   ast::MustUseAttribute, ast::RowMajorAttribute,
+                                   ast::StageAttribute, ast::StrideAttribute,
                                    ast::StructMemberOffsetAttribute>()) {
                     TINT_ICE() << "unhandled attribute type: " << attr->TypeInfo().name;
                 }
diff --git a/src/tint/lang/wgsl/resolver/resolver.cc b/src/tint/lang/wgsl/resolver/resolver.cc
index 91258cb..5ae1676 100644
--- a/src/tint/lang/wgsl/resolver/resolver.cc
+++ b/src/tint/lang/wgsl/resolver/resolver.cc
@@ -71,6 +71,7 @@
 #include "src/tint/lang/wgsl/ast/interpolate_attribute.h"
 #include "src/tint/lang/wgsl/ast/loop_statement.h"
 #include "src/tint/lang/wgsl/ast/return_statement.h"
+#include "src/tint/lang/wgsl/ast/row_major_attribute.h"
 #include "src/tint/lang/wgsl/ast/switch_statement.h"
 #include "src/tint/lang/wgsl/ast/traverse_expressions.h"
 #include "src/tint/lang/wgsl/ast/unary_op_expression.h"
@@ -4537,6 +4538,14 @@
                     attributes.invariant = true;
                     return true;
                 },
+                [&](const ast::RowMajorAttribute* attr) {
+                    if (!type->Is<core::type::Matrix>()) {
+                        AddError(attr->source)
+                            << style::Attribute("@row_major") << " can only be applied to matrices";
+                        return false;
+                    }
+                    return true;
+                },
                 [&](const ast::StrideAttribute* attr) {
                     if (validator_.IsValidationEnabled(
                             member->attributes, ast::DisabledValidation::kIgnoreStrideAttribute)) {