Implement type inference
Bug: tint:672 Change-Id: I3f586ee867f75427c4e8c309f72fb468643c23c0 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/53182 Reviewed-by: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
parent
7697c31e84
commit
9834fefa7f
|
@ -580,6 +580,7 @@ if(${TINT_BUILD_TESTS})
|
||||||
resolver/entry_point_validation_test.cc
|
resolver/entry_point_validation_test.cc
|
||||||
resolver/function_validation_test.cc
|
resolver/function_validation_test.cc
|
||||||
resolver/host_shareable_validation_test.cc
|
resolver/host_shareable_validation_test.cc
|
||||||
|
resolver/inferred_type_test.cc
|
||||||
resolver/intrinsic_test.cc
|
resolver/intrinsic_test.cc
|
||||||
resolver/intrinsic_validation_test.cc
|
resolver/intrinsic_validation_test.cc
|
||||||
resolver/is_host_shareable_test.cc
|
resolver/is_host_shareable_test.cc
|
||||||
|
|
|
@ -55,15 +55,6 @@ TEST_F(ModuleTest, Assert_Null_GlobalVariable) {
|
||||||
"internal compiler error");
|
"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) {
|
TEST_F(ModuleTest, Assert_Null_ConstructedType) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,8 +40,6 @@ Variable::Variable(ProgramID program_id,
|
||||||
declared_storage_class_(declared_storage_class) {
|
declared_storage_class_(declared_storage_class) {
|
||||||
TINT_ASSERT(symbol_.IsValid());
|
TINT_ASSERT(symbol_.IsValid());
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(symbol_, program_id);
|
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);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(constructor, program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,15 +71,6 @@ TEST_F(VariableTest, Assert_MissingSymbol) {
|
||||||
"internal compiler error");
|
"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) {
|
TEST_F(VariableTest, Assert_DifferentProgramID_Symbol) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
|
|
|
@ -496,7 +496,7 @@ Maybe<ast::Variable*> ParserImpl::global_constant_decl(
|
||||||
|
|
||||||
const char* use = "let declaration";
|
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)
|
if (decl.errored)
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
|
|
||||||
|
@ -520,7 +520,7 @@ Maybe<ast::Variable*> ParserImpl::global_constant_decl(
|
||||||
|
|
||||||
// variable_decl
|
// variable_decl
|
||||||
// : VAR variable_storage_decoration? variable_ident_decl
|
// : VAR variable_storage_decoration? variable_ident_decl
|
||||||
Maybe<ParserImpl::VarDeclInfo> ParserImpl::variable_decl() {
|
Maybe<ParserImpl::VarDeclInfo> ParserImpl::variable_decl(bool allow_inferred) {
|
||||||
if (!match(Token::Type::kVar))
|
if (!match(Token::Type::kVar))
|
||||||
return Failure::kNoMatch;
|
return Failure::kNoMatch;
|
||||||
|
|
||||||
|
@ -544,7 +544,8 @@ Maybe<ParserImpl::VarDeclInfo> ParserImpl::variable_decl() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto decl = expect_variable_ident_decl("variable declaration");
|
auto decl =
|
||||||
|
expect_variable_ident_decl("variable declaration", allow_inferred);
|
||||||
if (decl.errored)
|
if (decl.errored)
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
|
|
||||||
|
@ -898,11 +899,16 @@ Expect<ast::ImageFormat> ParserImpl::expect_image_storage_type(
|
||||||
// variable_ident_decl
|
// variable_ident_decl
|
||||||
// : IDENT COLON variable_decoration_list* type_decl
|
// : IDENT COLON variable_decoration_list* type_decl
|
||||||
Expect<ParserImpl::TypedIdentifier> ParserImpl::expect_variable_ident_decl(
|
Expect<ParserImpl::TypedIdentifier> ParserImpl::expect_variable_ident_decl(
|
||||||
const std::string& use) {
|
const std::string& use,
|
||||||
|
bool allow_inferred) {
|
||||||
auto ident = expect_ident(use);
|
auto ident = expect_ident(use);
|
||||||
if (ident.errored)
|
if (ident.errored)
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
|
|
||||||
|
if (allow_inferred && !peek().Is(Token::Type::kColon)) {
|
||||||
|
return TypedIdentifier{nullptr, ident.value, ident.source};
|
||||||
|
}
|
||||||
|
|
||||||
if (!expect(use, Token::Type::kColon))
|
if (!expect(use, Token::Type::kColon))
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
|
|
||||||
|
@ -1689,7 +1695,8 @@ Maybe<ast::ReturnStatement*> ParserImpl::return_stmt() {
|
||||||
// | CONST variable_ident_decl EQUAL logical_or_expression
|
// | CONST variable_ident_decl EQUAL logical_or_expression
|
||||||
Maybe<ast::VariableDeclStatement*> ParserImpl::variable_stmt() {
|
Maybe<ast::VariableDeclStatement*> ParserImpl::variable_stmt() {
|
||||||
if (match(Token::Type::kLet)) {
|
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)
|
if (decl.errored)
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
|
|
||||||
|
@ -1714,7 +1721,7 @@ Maybe<ast::VariableDeclStatement*> ParserImpl::variable_stmt() {
|
||||||
return create<ast::VariableDeclStatement>(decl->source, var);
|
return create<ast::VariableDeclStatement>(decl->source, var);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto decl = variable_decl();
|
auto decl = variable_decl(/*allow_inferred = */ true);
|
||||||
if (decl.errored)
|
if (decl.errored)
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
if (!decl.matched)
|
if (!decl.matched)
|
||||||
|
|
|
@ -214,8 +214,8 @@ class ParserImpl {
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~TypedIdentifier();
|
~TypedIdentifier();
|
||||||
|
|
||||||
/// Parsed type.
|
/// Parsed type. May be nullptr for inferred types.
|
||||||
ast::Type* type;
|
ast::Type* type = nullptr;
|
||||||
/// Parsed identifier.
|
/// Parsed identifier.
|
||||||
std::string name;
|
std::string name;
|
||||||
/// Source to the identifier.
|
/// Source to the identifier.
|
||||||
|
@ -387,13 +387,19 @@ class ParserImpl {
|
||||||
/// @param decos the list of decorations for the constant declaration.
|
/// @param decos the list of decorations for the constant declaration.
|
||||||
Maybe<ast::Variable*> global_constant_decl(ast::DecorationList& decos);
|
Maybe<ast::Variable*> global_constant_decl(ast::DecorationList& decos);
|
||||||
/// Parses a `variable_decl` grammar element
|
/// 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
|
/// @returns the parsed variable declaration info
|
||||||
Maybe<VarDeclInfo> variable_decl();
|
Maybe<VarDeclInfo> variable_decl(bool allow_inferred = false);
|
||||||
/// Parses a `variable_ident_decl` grammar element, erroring on parse
|
/// Parses a `variable_ident_decl` grammar element, erroring on parse
|
||||||
/// failure.
|
/// failure.
|
||||||
/// @param use a description of what was being parsed if an error was raised.
|
/// @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
|
/// @returns the identifier and type parsed or empty otherwise
|
||||||
Expect<TypedIdentifier> expect_variable_ident_decl(const std::string& use);
|
Expect<TypedIdentifier> expect_variable_ident_decl(
|
||||||
|
const std::string& use,
|
||||||
|
bool allow_inferred = false);
|
||||||
/// Parses a `variable_storage_decoration` grammar element
|
/// Parses a `variable_storage_decoration` grammar element
|
||||||
/// @returns the storage class or StorageClass::kNone if none matched
|
/// @returns the storage class or StorageClass::kNone if none matched
|
||||||
Maybe<ast::StorageClass> variable_storage_decoration();
|
Maybe<ast::StorageClass> variable_storage_decoration();
|
||||||
|
|
|
@ -48,6 +48,33 @@ TEST_F(ParserImplTest, GlobalConstantDecl) {
|
||||||
ast::HasDecoration<ast::OverrideDecoration>(e.value->decorations()));
|
ast::HasDecoration<ast::OverrideDecoration>(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<ast::ConstructorExpression>());
|
||||||
|
|
||||||
|
EXPECT_FALSE(
|
||||||
|
ast::HasDecoration<ast::OverrideDecoration>(e.value->decorations()));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) {
|
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) {
|
||||||
auto p = parser("let a : invalid = 1.");
|
auto p = parser("let a : invalid = 1.");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
|
|
|
@ -37,6 +37,13 @@ TEST_F(ParserImplTest, GlobalDecl_GlobalVariable) {
|
||||||
EXPECT_EQ(v->symbol(), program.Symbols().Get("a"));
|
EXPECT_EQ(v->symbol(), program.Symbols().Get("a"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_Inferred_Invalid) {
|
||||||
|
auto p = parser("var<private> a = vec2<i32>(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) {
|
TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_Invalid) {
|
||||||
auto p = parser("var<private> a : vec2<invalid>;");
|
auto p = parser("var<private> a : vec2<invalid>;");
|
||||||
p->expect_global_decl();
|
p->expect_global_decl();
|
||||||
|
|
|
@ -33,6 +33,18 @@ TEST_F(ParserImplTest, VariableDecl_Parses) {
|
||||||
EXPECT_EQ(v->type->source().range, (Source::Range{{1u, 14u}, {1u, 17u}}));
|
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) {
|
TEST_F(ParserImplTest, VariableDecl_MissingVar) {
|
||||||
auto p = parser("my_var : f32");
|
auto p = parser("my_var : f32");
|
||||||
auto v = p->variable_decl();
|
auto v = p->variable_decl();
|
||||||
|
|
|
@ -33,6 +33,17 @@ TEST_F(ParserImplTest, VariableIdentDecl_Parses) {
|
||||||
EXPECT_EQ(decl->type->source().range, (Source::Range{{1u, 10u}, {1u, 13u}}));
|
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) {
|
TEST_F(ParserImplTest, VariableIdentDecl_MissingIdent) {
|
||||||
auto p = parser(": f32");
|
auto p = parser(": f32");
|
||||||
auto decl = p->expect_variable_ident_decl("test");
|
auto decl = p->expect_variable_ident_decl("test");
|
||||||
|
|
|
@ -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<bool>, sem_vec3<sem_bool>},
|
||||||
|
{ast_vec3<i32>, sem_vec3<sem_i32>},
|
||||||
|
{ast_vec3<u32>, sem_vec3<sem_u32>},
|
||||||
|
{ast_vec3<f32>, sem_vec3<sem_f32>},
|
||||||
|
{ast_mat3x3<i32>, sem_mat3x3<sem_i32>},
|
||||||
|
{ast_mat3x3<u32>, sem_mat3x3<sem_u32>},
|
||||||
|
{ast_mat3x3<f32>, sem_mat3x3<sem_f32>},
|
||||||
|
|
||||||
|
{ast_alias<ast_bool>, sem_bool},
|
||||||
|
{ast_alias<ast_u32>, sem_u32},
|
||||||
|
{ast_alias<ast_i32>, sem_i32},
|
||||||
|
{ast_alias<ast_f32>, sem_f32},
|
||||||
|
{ast_alias<ast_vec3<bool>>, sem_vec3<sem_bool>},
|
||||||
|
{ast_alias<ast_vec3<i32>>, sem_vec3<sem_i32>},
|
||||||
|
{ast_alias<ast_vec3<u32>>, sem_vec3<sem_u32>},
|
||||||
|
{ast_alias<ast_vec3<f32>>, sem_vec3<sem_f32>},
|
||||||
|
{ast_alias<ast_mat3x3<i32>>, sem_mat3x3<sem_i32>},
|
||||||
|
{ast_alias<ast_mat3x3<u32>>, sem_mat3x3<sem_u32>},
|
||||||
|
{ast_alias<ast_mat3x3<f32>>, sem_mat3x3<sem_f32>},
|
||||||
|
};
|
||||||
|
|
||||||
|
using ResolverInferredTypeParamTest = ResolverTestWithParam<Params>;
|
||||||
|
|
||||||
|
TEST_P(ResolverInferredTypeParamTest, GlobalLet_Pass) {
|
||||||
|
auto& params = GetParam();
|
||||||
|
|
||||||
|
auto* type = params.create_type(ty);
|
||||||
|
auto* expected_type = params.create_expected_type(ty);
|
||||||
|
|
||||||
|
// let a = <type constructor>;
|
||||||
|
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 = <type constructor>;
|
||||||
|
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 = <type constructor>;
|
||||||
|
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 = <type constructor>;
|
||||||
|
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<sem::Array>(create<sem::U32>(), 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<ast::StructBlockDecoration>()});
|
||||||
|
|
||||||
|
auto* expected_type =
|
||||||
|
create<sem::Struct>(type,
|
||||||
|
sem::StructMemberList{create<sem::StructMember>(
|
||||||
|
member, create<sem::I32>(), 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
|
|
@ -417,6 +417,12 @@ Resolver::VariableInfo* Resolver::Variable(ast::Variable* var,
|
||||||
|
|
||||||
// If the variable has no declared type, infer it from the RHS
|
// If the variable has no declared type, infer it from the RHS
|
||||||
if (!storage_type) {
|
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;
|
type_name = rhs_type_name;
|
||||||
storage_type = rhs_type->UnwrapRef(); // Implicit load of RHS
|
storage_type = rhs_type->UnwrapRef(); // Implicit load of RHS
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
struct MyStruct {
|
||||||
|
f1 : f32;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MyArray = array<f32, 10>;
|
||||||
|
|
||||||
|
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<i32>(1, 1, 1);
|
||||||
|
let v5 = vec3<u32>(1u, 1u, 1u);
|
||||||
|
let v6 = vec3<f32>(1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
let v7 = mat3x3<f32>(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<f32> {
|
||||||
|
return vec4<f32>(0.0,0.0,0.0,0.0);
|
||||||
|
}
|
|
@ -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]
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -0,0 +1,48 @@
|
||||||
|
struct MyStruct {
|
||||||
|
f1 : f32;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MyArray = array<f32, 10>;
|
||||||
|
|
||||||
|
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<i32>(1, 1, 1);
|
||||||
|
let v5 = vec3<u32>(1u, 1u, 1u);
|
||||||
|
let v6 = vec3<f32>(1.0, 1.0, 1.0);
|
||||||
|
let v7 = mat3x3<f32>(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<f32> {
|
||||||
|
return vec4<f32>(0.0, 0.0, 0.0, 0.0);
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
struct MyStruct {
|
||||||
|
f1 : f32;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MyArray = array<f32, 10>;
|
||||||
|
|
||||||
|
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<i32>(1, 1, 1);
|
||||||
|
var v5 = vec3<u32>(1u, 1u, 1u);
|
||||||
|
var v6 = vec3<f32>(1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
var v7 = mat3x3<f32>(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<f32> {
|
||||||
|
return vec4<f32>(0.0,0.0,0.0,0.0);
|
||||||
|
}
|
|
@ -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]
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -0,0 +1,48 @@
|
||||||
|
struct MyStruct {
|
||||||
|
f1 : f32;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MyArray = array<f32, 10>;
|
||||||
|
|
||||||
|
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<i32>(1, 1, 1);
|
||||||
|
var v5 = vec3<u32>(1u, 1u, 1u);
|
||||||
|
var v6 = vec3<f32>(1.0, 1.0, 1.0);
|
||||||
|
var v7 = mat3x3<f32>(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<f32> {
|
||||||
|
return vec4<f32>(0.0, 0.0, 0.0, 0.0);
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
struct MyStruct {
|
||||||
|
f1 : f32;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MyArray = array<f32, 10>;
|
||||||
|
|
||||||
|
// Global lets
|
||||||
|
let v1 = 1;
|
||||||
|
let v2 = 1u;
|
||||||
|
let v3 = 1.0;
|
||||||
|
|
||||||
|
let v4 = vec3<i32>(1, 1, 1);
|
||||||
|
let v5 = vec3<u32>(1u, 1u, 1u);
|
||||||
|
let v6 = vec3<f32>(1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
let v7 = mat3x3<f32>(vec3<f32>(1.0, 1.0, 1.0), vec3<f32>(1.0, 1.0, 1.0), vec3<f32>(1.0, 1.0, 1.0));
|
||||||
|
|
||||||
|
let v8 = MyStruct();
|
||||||
|
let v9 = MyArray();
|
||||||
|
|
||||||
|
[[stage(fragment)]]
|
||||||
|
fn main() -> [[location(0)]] vec4<f32> {
|
||||||
|
return vec4<f32>(0.0,0.0,0.0,0.0);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -0,0 +1,28 @@
|
||||||
|
struct MyStruct {
|
||||||
|
f1 : f32;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MyArray = array<f32, 10>;
|
||||||
|
|
||||||
|
let v1 = 1;
|
||||||
|
|
||||||
|
let v2 = 1u;
|
||||||
|
|
||||||
|
let v3 = 1.0;
|
||||||
|
|
||||||
|
let v4 = vec3<i32>(1, 1, 1);
|
||||||
|
|
||||||
|
let v5 = vec3<u32>(1u, 1u, 1u);
|
||||||
|
|
||||||
|
let v6 = vec3<f32>(1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
let v7 = mat3x3<f32>(vec3<f32>(1.0, 1.0, 1.0), vec3<f32>(1.0, 1.0, 1.0), vec3<f32>(1.0, 1.0, 1.0));
|
||||||
|
|
||||||
|
let v8 = MyStruct();
|
||||||
|
|
||||||
|
let v9 = MyArray();
|
||||||
|
|
||||||
|
[[stage(fragment)]]
|
||||||
|
fn main() -> [[location(0)]] vec4<f32> {
|
||||||
|
return vec4<f32>(0.0, 0.0, 0.0, 0.0);
|
||||||
|
}
|
Loading…
Reference in New Issue