tint/reader: Allow module-scope 'var' type inferencing
Fixed: tint:1584
Change-Id: I193ad2c00faa4ae2001d981bb38a55d4d6a4c269
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/94687
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
diff --git a/docs/tint/origin-trial-changes.md b/docs/tint/origin-trial-changes.md
index 6d04c01..3736506 100644
--- a/docs/tint/origin-trial-changes.md
+++ b/docs/tint/origin-trial-changes.md
@@ -2,6 +2,10 @@
## Changes for M105
+### New features
+
+* Module-scope `var<private>` can now infer the storage type, like function-scope `var`. [tint:1584](crbug.com/tint/1584)
+
### Breaking changes
* The `smoothStep()` builtin has been removed (use `smoothstep` instead). [tint:1483](crbug.com/tint/1483)
diff --git a/src/tint/reader/wgsl/parser_impl.cc b/src/tint/reader/wgsl/parser_impl.cc
index c39df85..35360e4 100644
--- a/src/tint/reader/wgsl/parser_impl.cc
+++ b/src/tint/reader/wgsl/parser_impl.cc
@@ -641,7 +641,7 @@
// variable_decl
// : VAR variable_qualifier? variable_ident_decl
-Maybe<ParserImpl::VarDeclInfo> ParserImpl::variable_decl(bool allow_inferred) {
+Maybe<ParserImpl::VarDeclInfo> ParserImpl::variable_decl() {
Source source;
if (!match(Token::Type::kVar, &source)) {
return Failure::kNoMatch;
@@ -656,7 +656,8 @@
vq = explicit_vq.value;
}
- auto decl = expect_variable_ident_decl("variable declaration", allow_inferred);
+ auto decl = expect_variable_ident_decl("variable declaration",
+ /*allow_inferred = */ true);
if (decl.errored) {
return Failure::kErrored;
}
@@ -1379,7 +1380,8 @@
return Failure::kErrored;
}
- auto decl = expect_variable_ident_decl("struct member");
+ auto decl = expect_variable_ident_decl("struct member",
+ /*allow_inferred = */ false);
if (decl.errored) {
return Failure::kErrored;
}
@@ -1515,7 +1517,8 @@
Expect<ast::Parameter*> ParserImpl::expect_param() {
auto attrs = attribute_list();
- auto decl = expect_variable_ident_decl("parameter");
+ auto decl = expect_variable_ident_decl("parameter",
+ /*allow_inferred = */ false);
if (decl.errored) {
return Failure::kErrored;
}
@@ -1798,7 +1801,7 @@
// | variable_decl EQUAL logical_or_expression
// | CONST variable_ident_decl EQUAL logical_or_expression
Maybe<const ast::VariableDeclStatement*> ParserImpl::variable_stmt() {
- if (const_enabled && match(Token::Type::kConst)) {
+ if (match(Token::Type::kConst)) {
auto decl = expect_variable_ident_decl("'const' declaration",
/*allow_inferred = */ true);
if (decl.errored) {
@@ -1854,7 +1857,7 @@
return create<ast::VariableDeclStatement>(decl->source, let);
}
- auto decl = variable_decl(/*allow_inferred = */ true);
+ auto decl = variable_decl();
if (decl.errored) {
return Failure::kErrored;
}
diff --git a/src/tint/reader/wgsl/parser_impl.h b/src/tint/reader/wgsl/parser_impl.h
index 73c5829..4ae4eef 100644
--- a/src/tint/reader/wgsl/parser_impl.h
+++ b/src/tint/reader/wgsl/parser_impl.h
@@ -393,18 +393,15 @@
/// @param attrs the list of attributes for the constant declaration.
Maybe<const ast::Variable*> global_constant_decl(ast::AttributeList& attrs);
/// Parses a `variable_decl` grammar element
- /// @param allow_inferred if true, do not fail if variable decl does not
- /// specify type
/// @returns the parsed variable declaration info
- Maybe<VarDeclInfo> variable_decl(bool allow_inferred = false);
+ Maybe<VarDeclInfo> variable_decl();
/// Parses a `variable_ident_decl` grammar element, erroring on parse
/// failure.
/// @param use a description of what was being parsed if an error was raised.
/// @param allow_inferred if true, do not fail if variable decl does not
/// specify type
/// @returns the identifier and type parsed or empty otherwise
- Expect<TypedIdentifier> expect_variable_ident_decl(std::string_view use,
- bool allow_inferred = false);
+ Expect<TypedIdentifier> expect_variable_ident_decl(std::string_view use, bool allow_inferred);
/// Parses a `variable_qualifier` grammar element
/// @returns the variable qualifier information
Maybe<VariableQualifier> variable_qualifier();
diff --git a/src/tint/reader/wgsl/parser_impl_global_decl_test.cc b/src/tint/reader/wgsl/parser_impl_global_decl_test.cc
index a09486d..3b48b5a 100644
--- a/src/tint/reader/wgsl/parser_impl_global_decl_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_global_decl_test.cc
@@ -33,13 +33,20 @@
auto* v = program.AST().GlobalVariables()[0];
EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
+ EXPECT_TRUE(Is<ast::Vector>(v->type));
}
-TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_Inferred_Invalid) {
+TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_Inferred) {
auto p = parser("var<private> a = vec2<i32>(1, 2);");
p->global_decl();
- ASSERT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:16: expected ':' for variable declaration");
+ ASSERT_FALSE(p->has_error()) << p->error();
+
+ auto program = p->program();
+ ASSERT_EQ(program.AST().GlobalVariables().size(), 1u);
+
+ auto* v = program.AST().GlobalVariables()[0];
+ EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
+ EXPECT_EQ(v->type, nullptr);
}
TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_MissingSemicolon) {
diff --git a/src/tint/reader/wgsl/parser_impl_variable_decl_test.cc b/src/tint/reader/wgsl/parser_impl_variable_decl_test.cc
index 70ec394..39f8b24 100644
--- a/src/tint/reader/wgsl/parser_impl_variable_decl_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_variable_decl_test.cc
@@ -51,7 +51,7 @@
TEST_F(ParserImplTest, VariableDecl_Inferred_Parses) {
auto p = parser("var my_var = 1.0");
- auto v = p->variable_decl(/*allow_inferred = */ true);
+ auto v = p->variable_decl();
EXPECT_FALSE(p->has_error());
EXPECT_TRUE(v.matched);
EXPECT_FALSE(v.errored);
@@ -72,15 +72,6 @@
ASSERT_TRUE(t.IsIdentifier());
}
-TEST_F(ParserImplTest, VariableDecl_InvalidIdentDecl) {
- auto p = parser("var my_var f32");
- auto v = p->variable_decl();
- EXPECT_FALSE(v.matched);
- EXPECT_TRUE(v.errored);
- EXPECT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:12: expected ':' for variable declaration");
-}
-
TEST_F(ParserImplTest, VariableDecl_WithStorageClass) {
auto p = parser("var<private> my_var : f32");
auto v = p->variable_decl();
diff --git a/src/tint/reader/wgsl/parser_impl_variable_ident_decl_test.cc b/src/tint/reader/wgsl/parser_impl_variable_ident_decl_test.cc
index 3ffb29e..a811a82 100644
--- a/src/tint/reader/wgsl/parser_impl_variable_ident_decl_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_variable_ident_decl_test.cc
@@ -19,7 +19,7 @@
TEST_F(ParserImplTest, VariableIdentDecl_Parses) {
auto p = parser("my_var : f32");
- auto decl = p->expect_variable_ident_decl("test");
+ auto decl = p->expect_variable_ident_decl("test", /*allow_inferred = */ false);
ASSERT_FALSE(p->has_error()) << p->error();
ASSERT_FALSE(decl.errored);
ASSERT_EQ(decl->name, "my_var");
@@ -30,7 +30,27 @@
EXPECT_EQ(decl->type->source.range, (Source::Range{{1u, 10u}, {1u, 13u}}));
}
-TEST_F(ParserImplTest, VariableIdentDecl_Inferred_Parses) {
+TEST_F(ParserImplTest, VariableIdentDecl_Parses_AllowInferredType) {
+ auto p = parser("my_var : f32");
+ auto decl = p->expect_variable_ident_decl("test", /*allow_inferred = */ true);
+ ASSERT_FALSE(p->has_error()) << p->error();
+ ASSERT_FALSE(decl.errored);
+ ASSERT_EQ(decl->name, "my_var");
+ ASSERT_NE(decl->type, nullptr);
+ ASSERT_TRUE(decl->type->Is<ast::F32>());
+
+ EXPECT_EQ(decl->source.range, (Source::Range{{1u, 1u}, {1u, 7u}}));
+ EXPECT_EQ(decl->type->source.range, (Source::Range{{1u, 10u}, {1u, 13u}}));
+}
+
+TEST_F(ParserImplTest, VariableIdentDecl_Inferred_Parse_Failure) {
+ auto p = parser("my_var = 1.0");
+ auto decl = p->expect_variable_ident_decl("test", /*allow_inferred = */ false);
+ ASSERT_TRUE(p->has_error());
+ ASSERT_EQ(p->error(), "1:8: expected ':' for test");
+}
+
+TEST_F(ParserImplTest, VariableIdentDecl_Inferred_Parses_AllowInferredType) {
auto p = parser("my_var = 1.0");
auto decl = p->expect_variable_ident_decl("test", /*allow_inferred = */ true);
ASSERT_FALSE(p->has_error()) << p->error();
@@ -43,23 +63,31 @@
TEST_F(ParserImplTest, VariableIdentDecl_MissingIdent) {
auto p = parser(": f32");
- auto decl = p->expect_variable_ident_decl("test");
+ auto decl = p->expect_variable_ident_decl("test", /*allow_inferred = */ false);
ASSERT_TRUE(p->has_error());
ASSERT_TRUE(decl.errored);
ASSERT_EQ(p->error(), "1:1: expected identifier for test");
}
-TEST_F(ParserImplTest, VariableIdentDecl_MissingColon) {
- auto p = parser("my_var f32");
- auto decl = p->expect_variable_ident_decl("test");
+TEST_F(ParserImplTest, VariableIdentDecl_MissingIdent_AllowInferredType) {
+ auto p = parser(": f32");
+ auto decl = p->expect_variable_ident_decl("test", /*allow_inferred = */ true);
ASSERT_TRUE(p->has_error());
ASSERT_TRUE(decl.errored);
- ASSERT_EQ(p->error(), "1:8: expected ':' for test");
+ ASSERT_EQ(p->error(), "1:1: expected identifier for test");
}
TEST_F(ParserImplTest, VariableIdentDecl_MissingType) {
auto p = parser("my_var :");
- auto decl = p->expect_variable_ident_decl("test");
+ auto decl = p->expect_variable_ident_decl("test", /*allow_inferred = */ false);
+ ASSERT_TRUE(p->has_error());
+ ASSERT_TRUE(decl.errored);
+ ASSERT_EQ(p->error(), "1:9: invalid type for test");
+}
+
+TEST_F(ParserImplTest, VariableIdentDecl_MissingType_AllowInferredType) {
+ auto p = parser("my_var :");
+ auto decl = p->expect_variable_ident_decl("test", /*allow_inferred = */ true);
ASSERT_TRUE(p->has_error());
ASSERT_TRUE(decl.errored);
ASSERT_EQ(p->error(), "1:9: invalid type for test");
@@ -67,7 +95,15 @@
TEST_F(ParserImplTest, VariableIdentDecl_InvalidIdent) {
auto p = parser("123 : f32");
- auto decl = p->expect_variable_ident_decl("test");
+ auto decl = p->expect_variable_ident_decl("test", /*allow_inferred = */ false);
+ ASSERT_TRUE(p->has_error());
+ ASSERT_TRUE(decl.errored);
+ ASSERT_EQ(p->error(), "1:1: expected identifier for test");
+}
+
+TEST_F(ParserImplTest, VariableIdentDecl_InvalidIdent_AllowInferredType) {
+ auto p = parser("123 : f32");
+ auto decl = p->expect_variable_ident_decl("test", /*allow_inferred = */ true);
ASSERT_TRUE(p->has_error());
ASSERT_TRUE(decl.errored);
ASSERT_EQ(p->error(), "1:1: expected identifier for test");
diff --git a/test/tint/var/inferred/global.wgsl b/test/tint/var/inferred/global.wgsl
new file mode 100644
index 0000000..7ddb3e0
--- /dev/null
+++ b/test/tint/var/inferred/global.wgsl
@@ -0,0 +1,46 @@
+struct MyStruct {
+ f1 : f32,
+};
+
+type MyArray = array<f32, 10>;
+
+var<private> v1 = 1;
+var<private> v2 = 1u;
+var<private> v3 = 1.0;
+
+var<private> v4 = vec3<i32>(1, 1, 1);
+var<private> v5 = vec3<u32>(1u, 2u, 3u);
+var<private> v6 = vec3<f32>(1.0, 2.0, 3.0);
+
+var<private> v7 = MyStruct(1.0);
+var<private> v8 = MyArray();
+
+var<private> v9 = i32();
+var<private> v10 = u32();
+var<private> v11 = f32();
+var<private> v12 = MyStruct();
+var<private> v13 = MyStruct();
+var<private> v14 = MyArray();
+
+var<private> v15 = vec3(1, 2, 3);
+var<private> v16 = vec3(1.0, 2.0, 3.0);
+
+@compute @workgroup_size(1)
+fn f() {
+ let l1 = v1;
+ let l2 = v2;
+ let l3 = v3;
+ let l4 = v4;
+ let l5 = v5;
+ let l6 = v6;
+ let l7 = v7;
+ let l8 = v8;
+ let l9 = v9;
+ let l10 = v10;
+ let l11 = v11;
+ let l12 = v12;
+ let l13 = v13;
+ let l14 = v14;
+ let l15 = v15;
+ let l16 = v16;
+}
diff --git a/test/tint/var/inferred/global.wgsl.expected.glsl b/test/tint/var/inferred/global.wgsl.expected.glsl
new file mode 100644
index 0000000..0c7fe37
--- /dev/null
+++ b/test/tint/var/inferred/global.wgsl.expected.glsl
@@ -0,0 +1,46 @@
+#version 310 es
+
+struct MyStruct {
+ float f1;
+};
+
+int v1 = 1;
+uint v2 = 1u;
+float v3 = 1.0f;
+ivec3 v4 = ivec3(1);
+uvec3 v5 = uvec3(1u, 2u, 3u);
+vec3 v6 = vec3(1.0f, 2.0f, 3.0f);
+MyStruct v7 = MyStruct(1.0f);
+float v8[10] = float[10](0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+int v9 = 0;
+uint v10 = 0u;
+float v11 = 0.0f;
+MyStruct v12 = MyStruct(0.0f);
+MyStruct v13 = MyStruct(0.0f);
+float v14[10] = float[10](0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+ivec3 v15 = ivec3(1, 2, 3);
+vec3 v16 = vec3(1.0f, 2.0f, 3.0f);
+void f() {
+ int l1 = v1;
+ uint l2 = v2;
+ float l3 = v3;
+ ivec3 l4 = v4;
+ uvec3 l5 = v5;
+ vec3 l6 = v6;
+ MyStruct l7 = v7;
+ float l8[10] = v8;
+ int l9 = v9;
+ uint l10 = v10;
+ float l11 = v11;
+ MyStruct l12 = v12;
+ MyStruct l13 = v13;
+ float l14[10] = v14;
+ ivec3 l15 = v15;
+ vec3 l16 = v16;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ f();
+ return;
+}
diff --git a/test/tint/var/inferred/global.wgsl.expected.hlsl b/test/tint/var/inferred/global.wgsl.expected.hlsl
new file mode 100644
index 0000000..09a7a21
--- /dev/null
+++ b/test/tint/var/inferred/global.wgsl.expected.hlsl
@@ -0,0 +1,41 @@
+struct MyStruct {
+ float f1;
+};
+
+static int v1 = 1;
+static uint v2 = 1u;
+static float v3 = 1.0f;
+static int3 v4 = (1).xxx;
+static uint3 v5 = uint3(1u, 2u, 3u);
+static float3 v6 = float3(1.0f, 2.0f, 3.0f);
+static MyStruct v7 = {1.0f};
+static float v8[10] = (float[10])0;
+static int v9 = 0;
+static uint v10 = 0u;
+static float v11 = 0.0f;
+static MyStruct v12 = (MyStruct)0;
+static MyStruct v13 = (MyStruct)0;
+static float v14[10] = (float[10])0;
+static int3 v15 = int3(1, 2, 3);
+static float3 v16 = float3(1.0f, 2.0f, 3.0f);
+
+[numthreads(1, 1, 1)]
+void f() {
+ const int l1 = v1;
+ const uint l2 = v2;
+ const float l3 = v3;
+ const int3 l4 = v4;
+ const uint3 l5 = v5;
+ const float3 l6 = v6;
+ const MyStruct l7 = v7;
+ const float l8[10] = v8;
+ const int l9 = v9;
+ const uint l10 = v10;
+ const float l11 = v11;
+ const MyStruct l12 = v12;
+ const MyStruct l13 = v13;
+ const float l14[10] = v14;
+ const int3 l15 = v15;
+ const float3 l16 = v16;
+ return;
+}
diff --git a/test/tint/var/inferred/global.wgsl.expected.msl b/test/tint/var/inferred/global.wgsl.expected.msl
new file mode 100644
index 0000000..50c5a7e
--- /dev/null
+++ b/test/tint/var/inferred/global.wgsl.expected.msl
@@ -0,0 +1,56 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+ const constant T& operator[](size_t i) const constant { return elements[i]; }
+ device T& operator[](size_t i) device { return elements[i]; }
+ const device T& operator[](size_t i) const device { return elements[i]; }
+ thread T& operator[](size_t i) thread { return elements[i]; }
+ const thread T& operator[](size_t i) const thread { return elements[i]; }
+ threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+ const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+ T elements[N];
+};
+
+struct MyStruct {
+ float f1;
+};
+
+kernel void f() {
+ thread int tint_symbol = 1;
+ thread uint tint_symbol_1 = 1u;
+ thread float tint_symbol_2 = 1.0f;
+ thread int3 tint_symbol_3 = int3(1);
+ thread uint3 tint_symbol_4 = uint3(1u, 2u, 3u);
+ thread float3 tint_symbol_5 = float3(1.0f, 2.0f, 3.0f);
+ thread MyStruct tint_symbol_6 = {.f1=1.0f};
+ thread tint_array<float, 10> tint_symbol_7 = tint_array<float, 10>{};
+ thread int tint_symbol_8 = 0;
+ thread uint tint_symbol_9 = 0u;
+ thread float tint_symbol_10 = 0.0f;
+ thread MyStruct tint_symbol_11 = {};
+ thread MyStruct tint_symbol_12 = {};
+ thread tint_array<float, 10> tint_symbol_13 = tint_array<float, 10>{};
+ thread int3 tint_symbol_14 = int3(1, 2, 3);
+ thread float3 tint_symbol_15 = float3(1.0f, 2.0f, 3.0f);
+ int const l1 = tint_symbol;
+ uint const l2 = tint_symbol_1;
+ float const l3 = tint_symbol_2;
+ int3 const l4 = tint_symbol_3;
+ uint3 const l5 = tint_symbol_4;
+ float3 const l6 = tint_symbol_5;
+ MyStruct const l7 = tint_symbol_6;
+ tint_array<float, 10> const l8 = tint_symbol_7;
+ int const l9 = tint_symbol_8;
+ uint const l10 = tint_symbol_9;
+ float const l11 = tint_symbol_10;
+ MyStruct const l12 = tint_symbol_11;
+ MyStruct const l13 = tint_symbol_12;
+ tint_array<float, 10> const l14 = tint_symbol_13;
+ int3 const l15 = tint_symbol_14;
+ float3 const l16 = tint_symbol_15;
+ return;
+}
+
diff --git a/test/tint/var/inferred/global.wgsl.expected.spvasm b/test/tint/var/inferred/global.wgsl.expected.spvasm
new file mode 100644
index 0000000..e4bae60
--- /dev/null
+++ b/test/tint/var/inferred/global.wgsl.expected.spvasm
@@ -0,0 +1,104 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 73
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %f "f"
+ OpExecutionMode %f LocalSize 1 1 1
+ OpName %v1 "v1"
+ OpName %v2 "v2"
+ OpName %v3 "v3"
+ OpName %v4 "v4"
+ OpName %v5 "v5"
+ OpName %v6 "v6"
+ OpName %MyStruct "MyStruct"
+ OpMemberName %MyStruct 0 "f1"
+ OpName %v7 "v7"
+ OpName %v8 "v8"
+ OpName %v9 "v9"
+ OpName %v10 "v10"
+ OpName %v11 "v11"
+ OpName %v12 "v12"
+ OpName %v13 "v13"
+ OpName %v14 "v14"
+ OpName %v15 "v15"
+ OpName %v16 "v16"
+ OpName %f "f"
+ OpMemberDecorate %MyStruct 0 Offset 0
+ OpDecorate %_arr_float_uint_10 ArrayStride 4
+ %int = OpTypeInt 32 1
+ %int_1 = OpConstant %int 1
+%_ptr_Private_int = OpTypePointer Private %int
+ %v1 = OpVariable %_ptr_Private_int Private %int_1
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %v2 = OpVariable %_ptr_Private_uint Private %uint_1
+ %float = OpTypeFloat 32
+ %float_1 = OpConstant %float 1
+%_ptr_Private_float = OpTypePointer Private %float
+ %v3 = OpVariable %_ptr_Private_float Private %float_1
+ %v3int = OpTypeVector %int 3
+ %14 = OpConstantComposite %v3int %int_1 %int_1 %int_1
+%_ptr_Private_v3int = OpTypePointer Private %v3int
+ %v4 = OpVariable %_ptr_Private_v3int Private %14
+ %v3uint = OpTypeVector %uint 3
+ %uint_2 = OpConstant %uint 2
+ %uint_3 = OpConstant %uint 3
+ %20 = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3
+%_ptr_Private_v3uint = OpTypePointer Private %v3uint
+ %v5 = OpVariable %_ptr_Private_v3uint Private %20
+ %v3float = OpTypeVector %float 3
+ %float_2 = OpConstant %float 2
+ %float_3 = OpConstant %float 3
+ %26 = OpConstantComposite %v3float %float_1 %float_2 %float_3
+%_ptr_Private_v3float = OpTypePointer Private %v3float
+ %v6 = OpVariable %_ptr_Private_v3float Private %26
+ %MyStruct = OpTypeStruct %float
+ %30 = OpConstantComposite %MyStruct %float_1
+%_ptr_Private_MyStruct = OpTypePointer Private %MyStruct
+ %v7 = OpVariable %_ptr_Private_MyStruct Private %30
+ %uint_10 = OpConstant %uint 10
+%_arr_float_uint_10 = OpTypeArray %float %uint_10
+ %35 = OpConstantNull %_arr_float_uint_10
+%_ptr_Private__arr_float_uint_10 = OpTypePointer Private %_arr_float_uint_10
+ %v8 = OpVariable %_ptr_Private__arr_float_uint_10 Private %35
+ %38 = OpConstantNull %int
+ %v9 = OpVariable %_ptr_Private_int Private %38
+ %40 = OpConstantNull %uint
+ %v10 = OpVariable %_ptr_Private_uint Private %40
+ %42 = OpConstantNull %float
+ %v11 = OpVariable %_ptr_Private_float Private %42
+ %44 = OpConstantNull %MyStruct
+ %v12 = OpVariable %_ptr_Private_MyStruct Private %44
+ %v13 = OpVariable %_ptr_Private_MyStruct Private %44
+ %v14 = OpVariable %_ptr_Private__arr_float_uint_10 Private %35
+ %int_2 = OpConstant %int 2
+ %int_3 = OpConstant %int 3
+ %50 = OpConstantComposite %v3int %int_1 %int_2 %int_3
+ %v15 = OpVariable %_ptr_Private_v3int Private %50
+ %v16 = OpVariable %_ptr_Private_v3float Private %26
+ %void = OpTypeVoid
+ %53 = OpTypeFunction %void
+ %f = OpFunction %void None %53
+ %56 = OpLabel
+ %57 = OpLoad %int %v1
+ %58 = OpLoad %uint %v2
+ %59 = OpLoad %float %v3
+ %60 = OpLoad %v3int %v4
+ %61 = OpLoad %v3uint %v5
+ %62 = OpLoad %v3float %v6
+ %63 = OpLoad %MyStruct %v7
+ %64 = OpLoad %_arr_float_uint_10 %v8
+ %65 = OpLoad %int %v9
+ %66 = OpLoad %uint %v10
+ %67 = OpLoad %float %v11
+ %68 = OpLoad %MyStruct %v12
+ %69 = OpLoad %MyStruct %v13
+ %70 = OpLoad %_arr_float_uint_10 %v14
+ %71 = OpLoad %v3int %v15
+ %72 = OpLoad %v3float %v16
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/var/inferred/global.wgsl.expected.wgsl b/test/tint/var/inferred/global.wgsl.expected.wgsl
new file mode 100644
index 0000000..bc7132f
--- /dev/null
+++ b/test/tint/var/inferred/global.wgsl.expected.wgsl
@@ -0,0 +1,57 @@
+struct MyStruct {
+ f1 : f32,
+}
+
+type MyArray = array<f32, 10>;
+
+var<private> v1 = 1;
+
+var<private> v2 = 1u;
+
+var<private> v3 = 1.0;
+
+var<private> v4 = vec3<i32>(1, 1, 1);
+
+var<private> v5 = vec3<u32>(1u, 2u, 3u);
+
+var<private> v6 = vec3<f32>(1.0, 2.0, 3.0);
+
+var<private> v7 = MyStruct(1.0);
+
+var<private> v8 = MyArray();
+
+var<private> v9 = i32();
+
+var<private> v10 = u32();
+
+var<private> v11 = f32();
+
+var<private> v12 = MyStruct();
+
+var<private> v13 = MyStruct();
+
+var<private> v14 = MyArray();
+
+var<private> v15 = vec3(1, 2, 3);
+
+var<private> v16 = vec3(1.0, 2.0, 3.0);
+
+@compute @workgroup_size(1)
+fn f() {
+ let l1 = v1;
+ let l2 = v2;
+ let l3 = v3;
+ let l4 = v4;
+ let l5 = v5;
+ let l6 = v6;
+ let l7 = v7;
+ let l8 = v8;
+ let l9 = v9;
+ let l10 = v10;
+ let l11 = v11;
+ let l12 = v12;
+ let l13 = v13;
+ let l14 = v14;
+ let l15 = v15;
+ let l16 = v16;
+}