diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 580c171402..268b037ea6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -580,6 +580,7 @@ if(${TINT_BUILD_TESTS}) resolver/entry_point_validation_test.cc resolver/function_validation_test.cc resolver/host_shareable_validation_test.cc + resolver/inferred_type_test.cc resolver/intrinsic_test.cc resolver/intrinsic_validation_test.cc resolver/is_host_shareable_test.cc diff --git a/src/ast/module_test.cc b/src/ast/module_test.cc index e53b9d890a..7007b4bb6b 100644 --- a/src/ast/module_test.cc +++ b/src/ast/module_test.cc @@ -55,15 +55,6 @@ TEST_F(ModuleTest, Assert_Null_GlobalVariable) { "internal compiler error"); } -TEST_F(ModuleTest, Assert_Invalid_GlobalVariable) { - EXPECT_FATAL_FAILURE( - { - ProgramBuilder builder; - builder.Global("var", nullptr, StorageClass::kInput); - }, - "internal compiler error"); -} - TEST_F(ModuleTest, Assert_Null_ConstructedType) { EXPECT_FATAL_FAILURE( { diff --git a/src/ast/variable.cc b/src/ast/variable.cc index 974607c6a3..d1f339585e 100644 --- a/src/ast/variable.cc +++ b/src/ast/variable.cc @@ -40,8 +40,6 @@ Variable::Variable(ProgramID program_id, declared_storage_class_(declared_storage_class) { TINT_ASSERT(symbol_.IsValid()); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(symbol_, program_id); - // no type means we must have a constructor to infer it - TINT_ASSERT(type_ || constructor); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(constructor, program_id); } diff --git a/src/ast/variable_test.cc b/src/ast/variable_test.cc index 9967a20b69..5f7ce60ad2 100644 --- a/src/ast/variable_test.cc +++ b/src/ast/variable_test.cc @@ -71,15 +71,6 @@ TEST_F(VariableTest, Assert_MissingSymbol) { "internal compiler error"); } -TEST_F(VariableTest, Assert_Null_Type) { - EXPECT_FATAL_FAILURE( - { - ProgramBuilder b; - b.Var("x", nullptr, StorageClass::kNone); - }, - "internal compiler error"); -} - TEST_F(VariableTest, Assert_DifferentProgramID_Symbol) { EXPECT_FATAL_FAILURE( { diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc index 224d2280ff..67bd0a365c 100644 --- a/src/reader/wgsl/parser_impl.cc +++ b/src/reader/wgsl/parser_impl.cc @@ -496,7 +496,7 @@ Maybe ParserImpl::global_constant_decl( const char* use = "let declaration"; - auto decl = expect_variable_ident_decl(use); + auto decl = expect_variable_ident_decl(use, /* allow_inferred = */ true); if (decl.errored) return Failure::kErrored; @@ -520,7 +520,7 @@ Maybe ParserImpl::global_constant_decl( // variable_decl // : VAR variable_storage_decoration? variable_ident_decl -Maybe ParserImpl::variable_decl() { +Maybe ParserImpl::variable_decl(bool allow_inferred) { if (!match(Token::Type::kVar)) return Failure::kNoMatch; @@ -544,7 +544,8 @@ Maybe ParserImpl::variable_decl() { } } - auto decl = expect_variable_ident_decl("variable declaration"); + auto decl = + expect_variable_ident_decl("variable declaration", allow_inferred); if (decl.errored) return Failure::kErrored; @@ -898,11 +899,16 @@ Expect ParserImpl::expect_image_storage_type( // variable_ident_decl // : IDENT COLON variable_decoration_list* type_decl Expect ParserImpl::expect_variable_ident_decl( - const std::string& use) { + const std::string& use, + bool allow_inferred) { auto ident = expect_ident(use); if (ident.errored) return Failure::kErrored; + if (allow_inferred && !peek().Is(Token::Type::kColon)) { + return TypedIdentifier{nullptr, ident.value, ident.source}; + } + if (!expect(use, Token::Type::kColon)) return Failure::kErrored; @@ -1689,7 +1695,8 @@ Maybe ParserImpl::return_stmt() { // | CONST variable_ident_decl EQUAL logical_or_expression Maybe ParserImpl::variable_stmt() { if (match(Token::Type::kLet)) { - auto decl = expect_variable_ident_decl("let declaration"); + auto decl = expect_variable_ident_decl("let declaration", + /*allow_inferred = */ true); if (decl.errored) return Failure::kErrored; @@ -1714,7 +1721,7 @@ Maybe ParserImpl::variable_stmt() { return create(decl->source, var); } - auto decl = variable_decl(); + auto decl = variable_decl(/*allow_inferred = */ true); if (decl.errored) return Failure::kErrored; if (!decl.matched) diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h index 1fa4f31c08..5a583597d8 100644 --- a/src/reader/wgsl/parser_impl.h +++ b/src/reader/wgsl/parser_impl.h @@ -214,8 +214,8 @@ class ParserImpl { /// Destructor ~TypedIdentifier(); - /// Parsed type. - ast::Type* type; + /// Parsed type. May be nullptr for inferred types. + ast::Type* type = nullptr; /// Parsed identifier. std::string name; /// Source to the identifier. @@ -387,13 +387,19 @@ class ParserImpl { /// @param decos the list of decorations for the constant declaration. Maybe global_constant_decl(ast::DecorationList& decos); /// 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 variable_decl(); + Maybe variable_decl(bool allow_inferred = false); /// 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 expect_variable_ident_decl(const std::string& use); + Expect expect_variable_ident_decl( + const std::string& use, + bool allow_inferred = false); /// Parses a `variable_storage_decoration` grammar element /// @returns the storage class or StorageClass::kNone if none matched Maybe variable_storage_decoration(); diff --git a/src/reader/wgsl/parser_impl_global_constant_decl_test.cc b/src/reader/wgsl/parser_impl_global_constant_decl_test.cc index 992883eb57..8892df7b8b 100644 --- a/src/reader/wgsl/parser_impl_global_constant_decl_test.cc +++ b/src/reader/wgsl/parser_impl_global_constant_decl_test.cc @@ -48,6 +48,33 @@ TEST_F(ParserImplTest, GlobalConstantDecl) { ast::HasDecoration(e.value->decorations())); } +TEST_F(ParserImplTest, GlobalConstantDecl_Inferred) { + auto p = parser("let a = 1."); + auto decos = p->decoration_list(); + EXPECT_FALSE(decos.errored); + EXPECT_FALSE(decos.matched); + auto e = p->global_constant_decl(decos.value); + EXPECT_FALSE(p->has_error()) << p->error(); + EXPECT_TRUE(e.matched); + EXPECT_FALSE(e.errored); + ASSERT_NE(e.value, nullptr); + + EXPECT_TRUE(e->is_const()); + EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a")); + EXPECT_EQ(e->type(), nullptr); + + EXPECT_EQ(e->source().range.begin.line, 1u); + EXPECT_EQ(e->source().range.begin.column, 5u); + EXPECT_EQ(e->source().range.end.line, 1u); + EXPECT_EQ(e->source().range.end.column, 6u); + + ASSERT_NE(e->constructor(), nullptr); + EXPECT_TRUE(e->constructor()->Is()); + + EXPECT_FALSE( + ast::HasDecoration(e.value->decorations())); +} + TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) { auto p = parser("let a : invalid = 1."); auto decos = p->decoration_list(); diff --git a/src/reader/wgsl/parser_impl_global_decl_test.cc b/src/reader/wgsl/parser_impl_global_decl_test.cc index 79e81a32d9..d9421db4d5 100644 --- a/src/reader/wgsl/parser_impl_global_decl_test.cc +++ b/src/reader/wgsl/parser_impl_global_decl_test.cc @@ -37,6 +37,13 @@ TEST_F(ParserImplTest, GlobalDecl_GlobalVariable) { EXPECT_EQ(v->symbol(), program.Symbols().Get("a")); } +TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_Inferred_Invalid) { + auto p = parser("var a = vec2(1, 2);"); + p->expect_global_decl(); + ASSERT_TRUE(p->has_error()); + EXPECT_EQ(p->error(), "1:16: expected ':' for variable declaration"); +} + TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_Invalid) { auto p = parser("var a : vec2;"); p->expect_global_decl(); diff --git a/src/reader/wgsl/parser_impl_variable_decl_test.cc b/src/reader/wgsl/parser_impl_variable_decl_test.cc index bb5a6597dd..367b3d483e 100644 --- a/src/reader/wgsl/parser_impl_variable_decl_test.cc +++ b/src/reader/wgsl/parser_impl_variable_decl_test.cc @@ -33,6 +33,18 @@ TEST_F(ParserImplTest, VariableDecl_Parses) { EXPECT_EQ(v->type->source().range, (Source::Range{{1u, 14u}, {1u, 17u}})); } +TEST_F(ParserImplTest, VariableDecl_Inferred_Parses) { + auto p = parser("var my_var = 1.0"); + auto v = p->variable_decl(/*allow_inferred = */ true); + EXPECT_FALSE(p->has_error()); + EXPECT_TRUE(v.matched); + EXPECT_FALSE(v.errored); + EXPECT_EQ(v->name, "my_var"); + EXPECT_EQ(v->type, nullptr); + + EXPECT_EQ(v->source.range, (Source::Range{{1u, 5u}, {1u, 11u}})); +} + TEST_F(ParserImplTest, VariableDecl_MissingVar) { auto p = parser("my_var : f32"); auto v = p->variable_decl(); diff --git a/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc b/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc index 696991daab..35cd4190d4 100644 --- a/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc +++ b/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc @@ -33,6 +33,17 @@ TEST_F(ParserImplTest, VariableIdentDecl_Parses) { EXPECT_EQ(decl->type->source().range, (Source::Range{{1u, 10u}, {1u, 13u}})); } +TEST_F(ParserImplTest, VariableIdentDecl_Inferred_Parses) { + 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(); + ASSERT_FALSE(decl.errored); + ASSERT_EQ(decl->name, "my_var"); + ASSERT_EQ(decl->type, nullptr); + + EXPECT_EQ(decl->source.range, (Source::Range{{1u, 1u}, {1u, 7u}})); +} + TEST_F(ParserImplTest, VariableIdentDecl_MissingIdent) { auto p = parser(": f32"); auto decl = p->expect_variable_ident_decl("test"); diff --git a/src/resolver/inferred_type_test.cc b/src/resolver/inferred_type_test.cc new file mode 100644 index 0000000000..caceb4321f --- /dev/null +++ b/src/resolver/inferred_type_test.cc @@ -0,0 +1,165 @@ +// Copyright 2021 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/ast/struct_block_decoration.h" +#include "src/resolver/resolver.h" +#include "src/resolver/resolver_test_helper.h" + +#include "gmock/gmock.h" + +namespace tint { +namespace resolver { +namespace { + +// Helpers and typedefs +using i32 = ProgramBuilder::i32; +using u32 = ProgramBuilder::u32; +using f32 = ProgramBuilder::f32; + +struct ResolverInferredTypeTest : public resolver::TestHelper, + public testing::Test {}; + +struct Params { + create_ast_type_func_ptr create_type; + create_sem_type_func_ptr create_expected_type; +}; + +Params all_cases[] = { + {ast_bool, sem_bool}, + {ast_u32, sem_u32}, + {ast_i32, sem_i32}, + {ast_f32, sem_f32}, + {ast_vec3, sem_vec3}, + {ast_vec3, sem_vec3}, + {ast_vec3, sem_vec3}, + {ast_vec3, sem_vec3}, + {ast_mat3x3, sem_mat3x3}, + {ast_mat3x3, sem_mat3x3}, + {ast_mat3x3, sem_mat3x3}, + + {ast_alias, sem_bool}, + {ast_alias, sem_u32}, + {ast_alias, sem_i32}, + {ast_alias, sem_f32}, + {ast_alias>, sem_vec3}, + {ast_alias>, sem_vec3}, + {ast_alias>, sem_vec3}, + {ast_alias>, sem_vec3}, + {ast_alias>, sem_mat3x3}, + {ast_alias>, sem_mat3x3}, + {ast_alias>, sem_mat3x3}, +}; + +using ResolverInferredTypeParamTest = ResolverTestWithParam; + +TEST_P(ResolverInferredTypeParamTest, GlobalLet_Pass) { + auto& params = GetParam(); + + auto* type = params.create_type(ty); + auto* expected_type = params.create_expected_type(ty); + + // let a = ; + auto* ctor_expr = ConstructValueFilledWith(type); + auto* var = GlobalConst("a", nullptr, ctor_expr); + WrapInFunction(); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + EXPECT_EQ(TypeOf(var), expected_type); +} + +TEST_P(ResolverInferredTypeParamTest, GlobalVar_Fail) { + auto& params = GetParam(); + + auto* type = params.create_type(ty); + + // var a = ; + auto* ctor_expr = ConstructValueFilledWith(type); + Global(Source{{12, 34}}, "a", nullptr, ast::StorageClass::kPrivate, + ctor_expr); + WrapInFunction(); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: global var declaration must specify a type"); +} + +TEST_P(ResolverInferredTypeParamTest, LocalLet_Pass) { + auto& params = GetParam(); + + auto* type = params.create_type(ty); + auto* expected_type = params.create_expected_type(ty); + + // let a = ; + auto* ctor_expr = ConstructValueFilledWith(type); + auto* var = Const("a", nullptr, ctor_expr); + WrapInFunction(var); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + EXPECT_EQ(TypeOf(var), expected_type); +} + +TEST_P(ResolverInferredTypeParamTest, LocalVar_Pass) { + auto& params = GetParam(); + + auto* type = params.create_type(ty); + auto* expected_type = params.create_expected_type(ty); + + // var a = ; + auto* ctor_expr = ConstructValueFilledWith(type); + auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr); + WrapInFunction(var); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + EXPECT_EQ(TypeOf(var)->UnwrapRef(), expected_type); +} + +INSTANTIATE_TEST_SUITE_P(ResolverTest, + ResolverInferredTypeParamTest, + testing::ValuesIn(all_cases)); + +TEST_F(ResolverInferredTypeTest, InferArray_Pass) { + auto* type = ty.array(ty.u32(), 10); + auto* expected_type = + create(create(), 10, 4, 4 * 10, 4, true); + + auto* ctor_expr = Construct(type); + auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr); + WrapInFunction(var); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + EXPECT_EQ(TypeOf(var)->UnwrapRef(), expected_type); +} + +TEST_F(ResolverInferredTypeTest, InferStruct_Pass) { + auto* member = Member("x", ty.i32()); + auto* type = Structure("S", {member}, {create()}); + + auto* expected_type = + create(type, + sem::StructMemberList{create( + member, create(), 0, 0, 0, 4)}, + 0, 4, 4); + + auto* ctor_expr = Construct(type); + + auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr); + WrapInFunction(var); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + EXPECT_EQ(TypeOf(var)->UnwrapRef(), expected_type); +} + +} // namespace +} // namespace resolver +} // namespace tint diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc index 7b59942345..9f81e32c4c 100644 --- a/src/resolver/resolver.cc +++ b/src/resolver/resolver.cc @@ -417,6 +417,12 @@ Resolver::VariableInfo* Resolver::Variable(ast::Variable* var, // If the variable has no declared type, infer it from the RHS if (!storage_type) { + if (!var->is_const() && kind == VariableKind::kGlobal) { + diagnostics_.add_error("global var declaration must specify a type", + var->source()); + return nullptr; + } + type_name = rhs_type_name; storage_type = rhs_type->UnwrapRef(); // Implicit load of RHS } diff --git a/test/var/inferred/function-let.wgsl b/test/var/inferred/function-let.wgsl new file mode 100644 index 0000000000..15fc9fafcd --- /dev/null +++ b/test/var/inferred/function-let.wgsl @@ -0,0 +1,39 @@ +struct MyStruct { + f1 : f32; +}; + +type MyArray = array; + +fn ret_i32() -> i32 { return 1; } +fn ret_u32() -> u32 { return 1u; } +fn ret_f32() -> f32 { return 1.0; } +fn ret_MyStruct() -> MyStruct { return MyStruct(); } +fn ret_MyArray() -> MyArray { return MyArray(); } + +// Local lets +fn let_decls() { + let v1 = 1; + let v2 = 1u; + let v3 = 1.0; + + let v4 = vec3(1, 1, 1); + let v5 = vec3(1u, 1u, 1u); + let v6 = vec3(1.0, 1.0, 1.0); + + let v7 = mat3x3(v6, v6, v6); + + let v8 = MyStruct(1.0); + let v9 = MyArray(); + + let v10 = ret_i32(); + let v11 = ret_u32(); + let v12 = ret_f32(); + let v13 = ret_MyStruct(); + let v14 = ret_MyStruct(); + let v15 = ret_MyArray(); +} + +[[stage(fragment)]] +fn main() -> [[location(0)]] vec4 { + return vec4(0.0,0.0,0.0,0.0); +} diff --git a/test/var/inferred/function-let.wgsl.expected.hlsl b/test/var/inferred/function-let.wgsl.expected.hlsl new file mode 100644 index 0000000000..8f0accb927 --- /dev/null +++ b/test/var/inferred/function-let.wgsl.expected.hlsl @@ -0,0 +1,63 @@ +SKIP: FAILED + + + +Validation Failure: +struct MyStruct { + float f1; +}; +struct tint_symbol { + float4 value : SV_Target0; +}; + +int ret_i32() { + return 1; +} + +uint ret_u32() { + return 1u; +} + +float ret_f32() { + return 1.0f; +} + +MyStruct ret_MyStruct() { + const MyStruct tint_symbol_1 = {0.0f}; + return tint_symbol_1; +} + +float[10] ret_MyArray() { + const float tint_symbol_2[10] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; + return tint_symbol_2; +} + +void let_decls() { + const int v1 = 1; + const uint v2 = 1u; + const float v3 = 1.0f; + const int3 v4 = int3(1, 1, 1); + const uint3 v5 = uint3(1u, 1u, 1u); + const float3 v6 = float3(1.0f, 1.0f, 1.0f); + const float3x3 v7 = float3x3(v6, v6, v6); + const MyStruct v8 = {1.0f}; + const float v9[10] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; + const int v10 = ret_i32(); + const uint v11 = ret_u32(); + const float v12 = ret_f32(); + const MyStruct v13 = ret_MyStruct(); + const MyStruct v14 = ret_MyStruct(); + const float v15[10] = ret_MyArray(); +} + +tint_symbol main() { + const tint_symbol tint_symbol_3 = {float4(0.0f, 0.0f, 0.0f, 0.0f)}; + return tint_symbol_3; +} + + +C:\src\temp\ut9k.0:25:24: error: brackets are not allowed here; to declare an array, place the brackets after the name +float[10] ret_MyArray() { + ~~~~ ^ + [10] + diff --git a/test/var/inferred/function-let.wgsl.expected.msl b/test/var/inferred/function-let.wgsl.expected.msl new file mode 100644 index 0000000000..a4595d89dd --- /dev/null +++ b/test/var/inferred/function-let.wgsl.expected.msl @@ -0,0 +1,58 @@ +#include + +using namespace metal; +struct MyStruct { + float f1; +}; +struct tint_symbol_1 { + float4 value [[color(0)]]; +}; +struct tint_array_wrapper_0 { + float array[10]; +}; + +int ret_i32() { + return 1; +} + +uint ret_u32() { + return 1u; +} + +float ret_f32() { + return 1.0f; +} + +MyStruct ret_MyStruct() { + MyStruct const tint_symbol_2 = {}; + return tint_symbol_2; +} + +tint_array_wrapper_0 ret_MyArray() { + tint_array_wrapper_0 const tint_symbol_3 = {}; + return tint_symbol_3; +} + +void let_decls() { + int const v1 = 1; + uint const v2 = 1u; + float const v3 = 1.0f; + int3 const v4 = int3(1, 1, 1); + uint3 const v5 = uint3(1u, 1u, 1u); + float3 const v6 = float3(1.0f, 1.0f, 1.0f); + float3x3 const v7 = float3x3(v6, v6, v6); + MyStruct const v8 = {.f1=1.0f}; + tint_array_wrapper_0 const v9 = {}; + int const v10 = ret_i32(); + uint const v11 = ret_u32(); + float const v12 = ret_f32(); + MyStruct const v13 = ret_MyStruct(); + MyStruct const v14 = ret_MyStruct(); + tint_array_wrapper_0 const v15 = ret_MyArray(); +} + +fragment tint_symbol_1 tint_symbol() { + tint_symbol_1 const tint_symbol_4 = {.value=float4(0.0f, 0.0f, 0.0f, 0.0f)}; + return tint_symbol_4; +} + diff --git a/test/var/inferred/function-let.wgsl.expected.spvasm b/test/var/inferred/function-let.wgsl.expected.spvasm new file mode 100644 index 0000000000..4b590e86e9 --- /dev/null +++ b/test/var/inferred/function-let.wgsl.expected.spvasm @@ -0,0 +1,99 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 59 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %tint_symbol_1 + OpExecutionMode %main OriginUpperLeft + OpName %tint_symbol_1 "tint_symbol_1" + OpName %ret_i32 "ret_i32" + OpName %ret_u32 "ret_u32" + OpName %ret_f32 "ret_f32" + OpName %MyStruct "MyStruct" + OpMemberName %MyStruct 0 "f1" + OpName %ret_MyStruct "ret_MyStruct" + OpName %ret_MyArray "ret_MyArray" + OpName %let_decls "let_decls" + OpName %tint_symbol_2 "tint_symbol_2" + OpName %tint_symbol "tint_symbol" + OpName %main "main" + OpDecorate %tint_symbol_1 Location 0 + OpMemberDecorate %MyStruct 0 Offset 0 + OpDecorate %_arr_float_uint_10 ArrayStride 4 + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %5 = OpConstantNull %v4float +%tint_symbol_1 = OpVariable %_ptr_Output_v4float Output %5 + %int = OpTypeInt 32 1 + %6 = OpTypeFunction %int + %int_1 = OpConstant %int 1 + %uint = OpTypeInt 32 0 + %11 = OpTypeFunction %uint + %uint_1 = OpConstant %uint 1 + %16 = OpTypeFunction %float + %float_1 = OpConstant %float 1 + %MyStruct = OpTypeStruct %float + %20 = OpTypeFunction %MyStruct + %24 = OpConstantNull %MyStruct + %uint_10 = OpConstant %uint 10 +%_arr_float_uint_10 = OpTypeArray %float %uint_10 + %25 = OpTypeFunction %_arr_float_uint_10 + %30 = OpConstantNull %_arr_float_uint_10 + %void = OpTypeVoid + %31 = OpTypeFunction %void + %v3int = OpTypeVector %int 3 + %36 = OpConstantComposite %v3int %int_1 %int_1 %int_1 + %v3uint = OpTypeVector %uint 3 + %38 = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1 + %v3float = OpTypeVector %float 3 + %40 = OpConstantComposite %v3float %float_1 %float_1 %float_1 +%mat3v3float = OpTypeMatrix %v3float 3 + %43 = OpConstantComposite %MyStruct %float_1 + %50 = OpTypeFunction %void %v4float + %float_0 = OpConstant %float 0 + %58 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 + %ret_i32 = OpFunction %int None %6 + %9 = OpLabel + OpReturnValue %int_1 + OpFunctionEnd + %ret_u32 = OpFunction %uint None %11 + %14 = OpLabel + OpReturnValue %uint_1 + OpFunctionEnd + %ret_f32 = OpFunction %float None %16 + %18 = OpLabel + OpReturnValue %float_1 + OpFunctionEnd +%ret_MyStruct = OpFunction %MyStruct None %20 + %23 = OpLabel + OpReturnValue %24 + OpFunctionEnd +%ret_MyArray = OpFunction %_arr_float_uint_10 None %25 + %29 = OpLabel + OpReturnValue %30 + OpFunctionEnd + %let_decls = OpFunction %void None %31 + %34 = OpLabel + %42 = OpCompositeConstruct %mat3v3float %40 %40 %40 + %44 = OpFunctionCall %int %ret_i32 + %45 = OpFunctionCall %uint %ret_u32 + %46 = OpFunctionCall %float %ret_f32 + %47 = OpFunctionCall %MyStruct %ret_MyStruct + %48 = OpFunctionCall %MyStruct %ret_MyStruct + %49 = OpFunctionCall %_arr_float_uint_10 %ret_MyArray + OpReturn + OpFunctionEnd +%tint_symbol_2 = OpFunction %void None %50 +%tint_symbol = OpFunctionParameter %v4float + %53 = OpLabel + OpStore %tint_symbol_1 %tint_symbol + OpReturn + OpFunctionEnd + %main = OpFunction %void None %31 + %55 = OpLabel + %56 = OpFunctionCall %void %tint_symbol_2 %58 + OpReturn + OpFunctionEnd diff --git a/test/var/inferred/function-let.wgsl.expected.wgsl b/test/var/inferred/function-let.wgsl.expected.wgsl new file mode 100644 index 0000000000..03d68ef1f5 --- /dev/null +++ b/test/var/inferred/function-let.wgsl.expected.wgsl @@ -0,0 +1,48 @@ +struct MyStruct { + f1 : f32; +}; + +type MyArray = array; + +fn ret_i32() -> i32 { + return 1; +} + +fn ret_u32() -> u32 { + return 1u; +} + +fn ret_f32() -> f32 { + return 1.0; +} + +fn ret_MyStruct() -> MyStruct { + return MyStruct(); +} + +fn ret_MyArray() -> MyArray { + return MyArray(); +} + +fn let_decls() { + let v1 = 1; + let v2 = 1u; + let v3 = 1.0; + let v4 = vec3(1, 1, 1); + let v5 = vec3(1u, 1u, 1u); + let v6 = vec3(1.0, 1.0, 1.0); + let v7 = mat3x3(v6, v6, v6); + let v8 = MyStruct(1.0); + let v9 = MyArray(); + let v10 = ret_i32(); + let v11 = ret_u32(); + let v12 = ret_f32(); + let v13 = ret_MyStruct(); + let v14 = ret_MyStruct(); + let v15 = ret_MyArray(); +} + +[[stage(fragment)]] +fn main() -> [[location(0)]] vec4 { + return vec4(0.0, 0.0, 0.0, 0.0); +} diff --git a/test/var/inferred/function-var.wgsl b/test/var/inferred/function-var.wgsl new file mode 100644 index 0000000000..0d39fe044f --- /dev/null +++ b/test/var/inferred/function-var.wgsl @@ -0,0 +1,39 @@ +struct MyStruct { + f1 : f32; +}; + +type MyArray = array; + +fn ret_i32() -> i32 { return 1; } +fn ret_u32() -> u32 { return 1u; } +fn ret_f32() -> f32 { return 1.0; } +fn ret_MyStruct() -> MyStruct { return MyStruct(); } +fn ret_MyArray() -> MyArray { return MyArray(); } + +// Local variables +fn var_decls() { + var v1 = 1; + var v2 = 1u; + var v3 = 1.0; + + var v4 = vec3(1, 1, 1); + var v5 = vec3(1u, 1u, 1u); + var v6 = vec3(1.0, 1.0, 1.0); + + var v7 = mat3x3(v6, v6, v6); + + var v8 = MyStruct(1.0); + var v9 = MyArray(); + + var v10 = ret_i32(); + var v11 = ret_u32(); + var v12 = ret_f32(); + var v13 = ret_MyStruct(); + var v14 = ret_MyStruct(); + var v15 = ret_MyArray(); +} + +[[stage(fragment)]] +fn main() -> [[location(0)]] vec4 { + return vec4(0.0,0.0,0.0,0.0); +} diff --git a/test/var/inferred/function-var.wgsl.expected.hlsl b/test/var/inferred/function-var.wgsl.expected.hlsl new file mode 100644 index 0000000000..253e39d1d1 --- /dev/null +++ b/test/var/inferred/function-var.wgsl.expected.hlsl @@ -0,0 +1,63 @@ +SKIP: FAILED + + + +Validation Failure: +struct MyStruct { + float f1; +}; +struct tint_symbol { + float4 value : SV_Target0; +}; + +int ret_i32() { + return 1; +} + +uint ret_u32() { + return 1u; +} + +float ret_f32() { + return 1.0f; +} + +MyStruct ret_MyStruct() { + const MyStruct tint_symbol_1 = {0.0f}; + return tint_symbol_1; +} + +float[10] ret_MyArray() { + const float tint_symbol_2[10] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; + return tint_symbol_2; +} + +void var_decls() { + int v1 = 1; + uint v2 = 1u; + float v3 = 1.0f; + int3 v4 = int3(1, 1, 1); + uint3 v5 = uint3(1u, 1u, 1u); + float3 v6 = float3(1.0f, 1.0f, 1.0f); + float3x3 v7 = float3x3(v6, v6, v6); + MyStruct v8 = {1.0f}; + float v9[10] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; + int v10 = ret_i32(); + uint v11 = ret_u32(); + float v12 = ret_f32(); + MyStruct v13 = ret_MyStruct(); + MyStruct v14 = ret_MyStruct(); + float v15[10] = ret_MyArray(); +} + +tint_symbol main() { + const tint_symbol tint_symbol_3 = {float4(0.0f, 0.0f, 0.0f, 0.0f)}; + return tint_symbol_3; +} + + +C:\src\temp\u1efk.0:25:24: error: brackets are not allowed here; to declare an array, place the brackets after the name +float[10] ret_MyArray() { + ~~~~ ^ + [10] + diff --git a/test/var/inferred/function-var.wgsl.expected.msl b/test/var/inferred/function-var.wgsl.expected.msl new file mode 100644 index 0000000000..66122e768b --- /dev/null +++ b/test/var/inferred/function-var.wgsl.expected.msl @@ -0,0 +1,58 @@ +#include + +using namespace metal; +struct MyStruct { + float f1; +}; +struct tint_symbol_1 { + float4 value [[color(0)]]; +}; +struct tint_array_wrapper_0 { + float array[10]; +}; + +int ret_i32() { + return 1; +} + +uint ret_u32() { + return 1u; +} + +float ret_f32() { + return 1.0f; +} + +MyStruct ret_MyStruct() { + MyStruct const tint_symbol_2 = {}; + return tint_symbol_2; +} + +tint_array_wrapper_0 ret_MyArray() { + tint_array_wrapper_0 const tint_symbol_3 = {}; + return tint_symbol_3; +} + +void var_decls() { + int v1 = 1; + uint v2 = 1u; + float v3 = 1.0f; + int3 v4 = int3(1, 1, 1); + uint3 v5 = uint3(1u, 1u, 1u); + float3 v6 = float3(1.0f, 1.0f, 1.0f); + float3x3 v7 = float3x3(v6, v6, v6); + MyStruct v8 = {.f1=1.0f}; + tint_array_wrapper_0 v9 = {}; + int v10 = ret_i32(); + uint v11 = ret_u32(); + float v12 = ret_f32(); + MyStruct v13 = ret_MyStruct(); + MyStruct v14 = ret_MyStruct(); + tint_array_wrapper_0 v15 = ret_MyArray(); +} + +fragment tint_symbol_1 tint_symbol() { + tint_symbol_1 const tint_symbol_4 = {.value=float4(0.0f, 0.0f, 0.0f, 0.0f)}; + return tint_symbol_4; +} + diff --git a/test/var/inferred/function-var.wgsl.expected.spvasm b/test/var/inferred/function-var.wgsl.expected.spvasm new file mode 100644 index 0000000000..94534db572 --- /dev/null +++ b/test/var/inferred/function-var.wgsl.expected.spvasm @@ -0,0 +1,163 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 93 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %tint_symbol_1 + OpExecutionMode %main OriginUpperLeft + OpName %tint_symbol_1 "tint_symbol_1" + OpName %ret_i32 "ret_i32" + OpName %ret_u32 "ret_u32" + OpName %ret_f32 "ret_f32" + OpName %MyStruct "MyStruct" + OpMemberName %MyStruct 0 "f1" + OpName %ret_MyStruct "ret_MyStruct" + OpName %ret_MyArray "ret_MyArray" + OpName %var_decls "var_decls" + OpName %v1 "v1" + OpName %v2 "v2" + OpName %v3 "v3" + OpName %v4 "v4" + OpName %v5 "v5" + OpName %v6 "v6" + 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 %tint_symbol_2 "tint_symbol_2" + OpName %tint_symbol "tint_symbol" + OpName %main "main" + OpDecorate %tint_symbol_1 Location 0 + OpMemberDecorate %MyStruct 0 Offset 0 + OpDecorate %_arr_float_uint_10 ArrayStride 4 + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %5 = OpConstantNull %v4float +%tint_symbol_1 = OpVariable %_ptr_Output_v4float Output %5 + %int = OpTypeInt 32 1 + %6 = OpTypeFunction %int + %int_1 = OpConstant %int 1 + %uint = OpTypeInt 32 0 + %11 = OpTypeFunction %uint + %uint_1 = OpConstant %uint 1 + %16 = OpTypeFunction %float + %float_1 = OpConstant %float 1 + %MyStruct = OpTypeStruct %float + %20 = OpTypeFunction %MyStruct + %24 = OpConstantNull %MyStruct + %uint_10 = OpConstant %uint 10 +%_arr_float_uint_10 = OpTypeArray %float %uint_10 + %25 = OpTypeFunction %_arr_float_uint_10 + %30 = OpConstantNull %_arr_float_uint_10 + %void = OpTypeVoid + %31 = OpTypeFunction %void +%_ptr_Function_int = OpTypePointer Function %int + %37 = OpConstantNull %int +%_ptr_Function_uint = OpTypePointer Function %uint + %40 = OpConstantNull %uint +%_ptr_Function_float = OpTypePointer Function %float + %43 = OpConstantNull %float + %v3int = OpTypeVector %int 3 + %45 = OpConstantComposite %v3int %int_1 %int_1 %int_1 +%_ptr_Function_v3int = OpTypePointer Function %v3int + %48 = OpConstantNull %v3int + %v3uint = OpTypeVector %uint 3 + %50 = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1 +%_ptr_Function_v3uint = OpTypePointer Function %v3uint + %53 = OpConstantNull %v3uint + %v3float = OpTypeVector %float 3 + %55 = OpConstantComposite %v3float %float_1 %float_1 %float_1 +%_ptr_Function_v3float = OpTypePointer Function %v3float + %58 = OpConstantNull %v3float +%mat3v3float = OpTypeMatrix %v3float 3 +%_ptr_Function_mat3v3float = OpTypePointer Function %mat3v3float + %66 = OpConstantNull %mat3v3float + %67 = OpConstantComposite %MyStruct %float_1 +%_ptr_Function_MyStruct = OpTypePointer Function %MyStruct +%_ptr_Function__arr_float_uint_10 = OpTypePointer Function %_arr_float_uint_10 + %84 = OpTypeFunction %void %v4float + %float_0 = OpConstant %float 0 + %92 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 + %ret_i32 = OpFunction %int None %6 + %9 = OpLabel + OpReturnValue %int_1 + OpFunctionEnd + %ret_u32 = OpFunction %uint None %11 + %14 = OpLabel + OpReturnValue %uint_1 + OpFunctionEnd + %ret_f32 = OpFunction %float None %16 + %18 = OpLabel + OpReturnValue %float_1 + OpFunctionEnd +%ret_MyStruct = OpFunction %MyStruct None %20 + %23 = OpLabel + OpReturnValue %24 + OpFunctionEnd +%ret_MyArray = OpFunction %_arr_float_uint_10 None %25 + %29 = OpLabel + OpReturnValue %30 + OpFunctionEnd + %var_decls = OpFunction %void None %31 + %34 = OpLabel + %v1 = OpVariable %_ptr_Function_int Function %37 + %v2 = OpVariable %_ptr_Function_uint Function %40 + %v3 = OpVariable %_ptr_Function_float Function %43 + %v4 = OpVariable %_ptr_Function_v3int Function %48 + %v5 = OpVariable %_ptr_Function_v3uint Function %53 + %v6 = OpVariable %_ptr_Function_v3float Function %58 + %v7 = OpVariable %_ptr_Function_mat3v3float Function %66 + %v8 = OpVariable %_ptr_Function_MyStruct Function %24 + %v9 = OpVariable %_ptr_Function__arr_float_uint_10 Function %30 + %v10 = OpVariable %_ptr_Function_int Function %37 + %v11 = OpVariable %_ptr_Function_uint Function %40 + %v12 = OpVariable %_ptr_Function_float Function %43 + %v13 = OpVariable %_ptr_Function_MyStruct Function %24 + %v14 = OpVariable %_ptr_Function_MyStruct Function %24 + %v15 = OpVariable %_ptr_Function__arr_float_uint_10 Function %30 + OpStore %v1 %int_1 + OpStore %v2 %uint_1 + OpStore %v3 %float_1 + OpStore %v4 %45 + OpStore %v5 %50 + OpStore %v6 %55 + %60 = OpLoad %v3float %v6 + %61 = OpLoad %v3float %v6 + %62 = OpLoad %v3float %v6 + %63 = OpCompositeConstruct %mat3v3float %60 %61 %62 + OpStore %v7 %63 + OpStore %v8 %67 + OpStore %v9 %30 + %72 = OpFunctionCall %int %ret_i32 + OpStore %v10 %72 + %74 = OpFunctionCall %uint %ret_u32 + OpStore %v11 %74 + %76 = OpFunctionCall %float %ret_f32 + OpStore %v12 %76 + %78 = OpFunctionCall %MyStruct %ret_MyStruct + OpStore %v13 %78 + %80 = OpFunctionCall %MyStruct %ret_MyStruct + OpStore %v14 %80 + %82 = OpFunctionCall %_arr_float_uint_10 %ret_MyArray + OpStore %v15 %82 + OpReturn + OpFunctionEnd +%tint_symbol_2 = OpFunction %void None %84 +%tint_symbol = OpFunctionParameter %v4float + %87 = OpLabel + OpStore %tint_symbol_1 %tint_symbol + OpReturn + OpFunctionEnd + %main = OpFunction %void None %31 + %89 = OpLabel + %90 = OpFunctionCall %void %tint_symbol_2 %92 + OpReturn + OpFunctionEnd diff --git a/test/var/inferred/function-var.wgsl.expected.wgsl b/test/var/inferred/function-var.wgsl.expected.wgsl new file mode 100644 index 0000000000..46141083e5 --- /dev/null +++ b/test/var/inferred/function-var.wgsl.expected.wgsl @@ -0,0 +1,48 @@ +struct MyStruct { + f1 : f32; +}; + +type MyArray = array; + +fn ret_i32() -> i32 { + return 1; +} + +fn ret_u32() -> u32 { + return 1u; +} + +fn ret_f32() -> f32 { + return 1.0; +} + +fn ret_MyStruct() -> MyStruct { + return MyStruct(); +} + +fn ret_MyArray() -> MyArray { + return MyArray(); +} + +fn var_decls() { + var v1 = 1; + var v2 = 1u; + var v3 = 1.0; + var v4 = vec3(1, 1, 1); + var v5 = vec3(1u, 1u, 1u); + var v6 = vec3(1.0, 1.0, 1.0); + var v7 = mat3x3(v6, v6, v6); + var v8 = MyStruct(1.0); + var v9 = MyArray(); + var v10 = ret_i32(); + var v11 = ret_u32(); + var v12 = ret_f32(); + var v13 = ret_MyStruct(); + var v14 = ret_MyStruct(); + var v15 = ret_MyArray(); +} + +[[stage(fragment)]] +fn main() -> [[location(0)]] vec4 { + return vec4(0.0, 0.0, 0.0, 0.0); +} diff --git a/test/var/inferred/global-let.wgsl b/test/var/inferred/global-let.wgsl new file mode 100644 index 0000000000..7928f9b96d --- /dev/null +++ b/test/var/inferred/global-let.wgsl @@ -0,0 +1,24 @@ +struct MyStruct { + f1 : f32; +}; + +type MyArray = array; + +// Global lets +let v1 = 1; +let v2 = 1u; +let v3 = 1.0; + +let v4 = vec3(1, 1, 1); +let v5 = vec3(1u, 1u, 1u); +let v6 = vec3(1.0, 1.0, 1.0); + +let v7 = mat3x3(vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0)); + +let v8 = MyStruct(); +let v9 = MyArray(); + +[[stage(fragment)]] +fn main() -> [[location(0)]] vec4 { + return vec4(0.0,0.0,0.0,0.0); +} diff --git a/test/var/inferred/global-let.wgsl.expected.hlsl b/test/var/inferred/global-let.wgsl.expected.hlsl new file mode 100644 index 0000000000..182e4b02e1 --- /dev/null +++ b/test/var/inferred/global-let.wgsl.expected.hlsl @@ -0,0 +1,21 @@ +struct MyStruct { + float f1; +}; +struct tint_symbol { + float4 value : SV_Target0; +}; + +static const int v1 = 1; +static const uint v2 = 1u; +static const float v3 = 1.0f; +static const int3 v4 = int3(1, 1, 1); +static const uint3 v5 = uint3(1u, 1u, 1u); +static const float3 v6 = float3(1.0f, 1.0f, 1.0f); +static const float3x3 v7 = float3x3(float3(1.0f, 1.0f, 1.0f), float3(1.0f, 1.0f, 1.0f), float3(1.0f, 1.0f, 1.0f)); +static const MyStruct v8 = {0.0f}; +static const float v9[10] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; +tint_symbol main() { + const tint_symbol tint_symbol_1 = {float4(0.0f, 0.0f, 0.0f, 0.0f)}; + return tint_symbol_1; +} + diff --git a/test/var/inferred/global-let.wgsl.expected.msl b/test/var/inferred/global-let.wgsl.expected.msl new file mode 100644 index 0000000000..65f9d52504 --- /dev/null +++ b/test/var/inferred/global-let.wgsl.expected.msl @@ -0,0 +1,27 @@ +#include + +using namespace metal; +struct MyStruct { + float f1; +}; +struct tint_symbol_1 { + float4 value [[color(0)]]; +}; +struct tint_array_wrapper_0 { + float array[10]; +}; + +constant int v1 = 1; +constant uint v2 = 1u; +constant float v3 = 1.0f; +constant int3 v4 = int3(1, 1, 1); +constant uint3 v5 = uint3(1u, 1u, 1u); +constant float3 v6 = float3(1.0f, 1.0f, 1.0f); +constant float3x3 v7 = float3x3(float3(1.0f, 1.0f, 1.0f), float3(1.0f, 1.0f, 1.0f), float3(1.0f, 1.0f, 1.0f)); +constant MyStruct v8 = {}; +constant tint_array_wrapper_0 v9 = {}; +fragment tint_symbol_1 tint_symbol() { + tint_symbol_1 const tint_symbol_2 = {.value=float4(0.0f, 0.0f, 0.0f, 0.0f)}; + return tint_symbol_2; +} + diff --git a/test/var/inferred/global-let.wgsl.expected.spvasm b/test/var/inferred/global-let.wgsl.expected.spvasm new file mode 100644 index 0000000000..ecf6016fb3 --- /dev/null +++ b/test/var/inferred/global-let.wgsl.expected.spvasm @@ -0,0 +1,66 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 35 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %tint_symbol_1 + OpExecutionMode %main OriginUpperLeft + OpName %v1 "v1" + OpName %v2 "v2" + OpName %v3 "v3" + OpName %v4 "v4" + OpName %v5 "v5" + OpName %v6 "v6" + OpName %v7 "v7" + OpName %MyStruct "MyStruct" + OpMemberName %MyStruct 0 "f1" + OpName %v8 "v8" + OpName %v9 "v9" + OpName %tint_symbol_1 "tint_symbol_1" + OpName %tint_symbol_2 "tint_symbol_2" + OpName %tint_symbol "tint_symbol" + OpName %main "main" + OpMemberDecorate %MyStruct 0 Offset 0 + OpDecorate %_arr_float_uint_10 ArrayStride 4 + OpDecorate %tint_symbol_1 Location 0 + %int = OpTypeInt 32 1 + %v1 = OpConstant %int 1 + %uint = OpTypeInt 32 0 + %v2 = OpConstant %uint 1 + %float = OpTypeFloat 32 + %v3 = OpConstant %float 1 + %v3int = OpTypeVector %int 3 + %v4 = OpConstantComposite %v3int %v1 %v1 %v1 + %v3uint = OpTypeVector %uint 3 + %v5 = OpConstantComposite %v3uint %v2 %v2 %v2 + %v3float = OpTypeVector %float 3 + %v6 = OpConstantComposite %v3float %v3 %v3 %v3 +%mat3v3float = OpTypeMatrix %v3float 3 + %v7 = OpConstantComposite %mat3v3float %v6 %v6 %v6 + %MyStruct = OpTypeStruct %float + %v8 = OpConstantNull %MyStruct + %uint_10 = OpConstant %uint 10 +%_arr_float_uint_10 = OpTypeArray %float %uint_10 + %v9 = OpConstantNull %_arr_float_uint_10 + %v4float = OpTypeVector %float 4 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %23 = OpConstantNull %v4float +%tint_symbol_1 = OpVariable %_ptr_Output_v4float Output %23 + %void = OpTypeVoid + %24 = OpTypeFunction %void %v4float + %29 = OpTypeFunction %void + %float_0 = OpConstant %float 0 + %34 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 +%tint_symbol_2 = OpFunction %void None %24 +%tint_symbol = OpFunctionParameter %v4float + %28 = OpLabel + OpStore %tint_symbol_1 %tint_symbol + OpReturn + OpFunctionEnd + %main = OpFunction %void None %29 + %31 = OpLabel + %32 = OpFunctionCall %void %tint_symbol_2 %34 + OpReturn + OpFunctionEnd diff --git a/test/var/inferred/global-let.wgsl.expected.wgsl b/test/var/inferred/global-let.wgsl.expected.wgsl new file mode 100644 index 0000000000..126f25c373 --- /dev/null +++ b/test/var/inferred/global-let.wgsl.expected.wgsl @@ -0,0 +1,28 @@ +struct MyStruct { + f1 : f32; +}; + +type MyArray = array; + +let v1 = 1; + +let v2 = 1u; + +let v3 = 1.0; + +let v4 = vec3(1, 1, 1); + +let v5 = vec3(1u, 1u, 1u); + +let v6 = vec3(1.0, 1.0, 1.0); + +let v7 = mat3x3(vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0)); + +let v8 = MyStruct(); + +let v9 = MyArray(); + +[[stage(fragment)]] +fn main() -> [[location(0)]] vec4 { + return vec4(0.0, 0.0, 0.0, 0.0); +}