tint: Add builtin type aliases (vec3f, etc)

Fixed: tint:1772
Change-Id: I4bed36ded91ca5288875ed6ea819ff4bbb432186
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/112340
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
Ben Clayton 2022-12-01 13:41:56 +00:00 committed by Dawn LUCI CQ
parent 5798f2d021
commit d5d207ba9f
74 changed files with 943 additions and 18 deletions

View File

@ -408,6 +408,8 @@ libtint_source_set("libtint_core_all_src") {
"resolver/resolver.h", "resolver/resolver.h",
"resolver/sem_helper.cc", "resolver/sem_helper.cc",
"resolver/sem_helper.h", "resolver/sem_helper.h",
"resolver/type_alias.cc",
"resolver/type_alias.h",
"resolver/uniformity.cc", "resolver/uniformity.cc",
"resolver/uniformity.h", "resolver/uniformity.h",
"resolver/validator.cc", "resolver/validator.cc",

View File

@ -542,6 +542,7 @@ tint_generated(ast/extension BENCH TEST)
tint_generated(ast/interpolate_attribute BENCH TEST) tint_generated(ast/interpolate_attribute BENCH TEST)
tint_generated(ast/texel_format BENCH TEST) tint_generated(ast/texel_format BENCH TEST)
tint_generated(resolver/init_conv_intrinsic) tint_generated(resolver/init_conv_intrinsic)
tint_generated(resolver/type_alias BENCH TEST)
tint_generated(sem/builtin_type) tint_generated(sem/builtin_type)
tint_generated(sem/parameter_usage) tint_generated(sem/parameter_usage)

View File

@ -111,6 +111,22 @@ enum interpolation_sampling {
sample sample
} }
// https://www.w3.org/TR/WGSL/#vector-types
enum type_alias {
vec2f
vec2h
vec2i
vec2u
vec3f
vec3h
vec3i
vec3u
vec4f
vec4h
vec4i
vec4u
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// WGSL primitive types // // WGSL primitive types //
// Types may be decorated with @precedence(N) to prioritize which type // // Types may be decorated with @precedence(N) to prioritize which type //

View File

@ -66,6 +66,7 @@
#include "src/tint/ast/void.h" #include "src/tint/ast/void.h"
#include "src/tint/ast/while_statement.h" #include "src/tint/ast/while_statement.h"
#include "src/tint/ast/workgroup_attribute.h" #include "src/tint/ast/workgroup_attribute.h"
#include "src/tint/resolver/type_alias.h"
#include "src/tint/scope_stack.h" #include "src/tint/scope_stack.h"
#include "src/tint/sem/builtin.h" #include "src/tint/sem/builtin.h"
#include "src/tint/symbol_table.h" #include "src/tint/symbol_table.h"
@ -481,9 +482,14 @@ class DependencyScanner {
graph_.resolved_symbols.Add(from, resolved); graph_.resolved_symbols.Add(from, resolved);
} }
/// @returns true if `name` is the name of a builtin function /// @returns true if `name` is the name of a builtin function, or builtin type alias
bool IsBuiltin(Symbol name) const { bool IsBuiltin(Symbol name) const {
return sem::ParseBuiltinType(symbols_.NameFor(name)) != sem::BuiltinType::kNone; auto s = symbols_.NameFor(name);
if (sem::ParseBuiltinType(s) != sem::BuiltinType::kNone ||
ParseTypeAlias(s) != TypeAlias::kUndefined) {
return true;
}
return false;
} }
/// Appends an error to the diagnostics that the given symbol cannot be /// Appends an error to the diagnostics that the given symbol cannot be

View File

@ -51,6 +51,7 @@
#include "src/tint/ast/vector.h" #include "src/tint/ast/vector.h"
#include "src/tint/ast/while_statement.h" #include "src/tint/ast/while_statement.h"
#include "src/tint/ast/workgroup_attribute.h" #include "src/tint/ast/workgroup_attribute.h"
#include "src/tint/resolver/type_alias.h"
#include "src/tint/resolver/uniformity.h" #include "src/tint/resolver/uniformity.h"
#include "src/tint/sem/abstract_float.h" #include "src/tint/sem/abstract_float.h"
#include "src/tint/sem/abstract_int.h" #include "src/tint/sem/abstract_int.h"
@ -329,13 +330,16 @@ sem::Type* Resolver::Type(const ast::Type* ty) {
AddNote("'" + name + "' declared here", func->Declaration()->source); AddNote("'" + name + "' declared here", func->Declaration()->source);
return nullptr; return nullptr;
}, },
[&](Default) { [&](Default) -> sem::Type* {
if (auto* tn = ty->As<ast::TypeName>()) { if (auto* tn = ty->As<ast::TypeName>()) {
if (IsBuiltin(tn->name)) { if (IsBuiltin(tn->name)) {
auto name = builder_->Symbols().NameFor(tn->name); auto name = builder_->Symbols().NameFor(tn->name);
AddError("cannot use builtin '" + name + "' as type", ty->source); AddError("cannot use builtin '" + name + "' as type", ty->source);
return nullptr; return nullptr;
} }
if (auto* t = BuiltinTypeAlias(tn->name)) {
return t;
}
} }
TINT_UNREACHABLE(Resolver, diagnostics_) TINT_UNREACHABLE(Resolver, diagnostics_)
<< "Unhandled resolved type '" << "Unhandled resolved type '"
@ -2228,11 +2232,13 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
}, },
[&](Default) -> sem::Call* { [&](Default) -> sem::Call* {
auto name = builder_->Symbols().NameFor(ident->symbol); auto name = builder_->Symbols().NameFor(ident->symbol);
auto builtin_type = sem::ParseBuiltinType(name); if (auto* alias = BuiltinTypeAlias(ident->symbol)) {
if (builtin_type != sem::BuiltinType::kNone) { return ty_init_or_conv(alias);
}
if (auto builtin_type = sem::ParseBuiltinType(name);
builtin_type != sem::BuiltinType::kNone) {
return BuiltinCall(expr, builtin_type, args); return BuiltinCall(expr, builtin_type, args);
} }
TINT_ICE(Resolver, diagnostics_) TINT_ICE(Resolver, diagnostics_)
<< expr->source << " unhandled CallExpression target:\n" << expr->source << " unhandled CallExpression target:\n"
<< "resolved: " << (resolved ? resolved->TypeInfo().name : "<null>") << "\n" << "resolved: " << (resolved ? resolved->TypeInfo().name : "<null>") << "\n"
@ -2328,6 +2334,40 @@ sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
return call; return call;
} }
sem::Type* Resolver::BuiltinTypeAlias(Symbol sym) const {
auto name = builder_->Symbols().NameFor(sym);
auto& b = *builder_;
switch (ParseTypeAlias(name)) {
case TypeAlias::kVec2F:
return b.create<sem::Vector>(b.create<sem::F32>(), 2u);
case TypeAlias::kVec3F:
return b.create<sem::Vector>(b.create<sem::F32>(), 3u);
case TypeAlias::kVec4F:
return b.create<sem::Vector>(b.create<sem::F32>(), 4u);
case TypeAlias::kVec2H:
return b.create<sem::Vector>(b.create<sem::F16>(), 2u);
case TypeAlias::kVec3H:
return b.create<sem::Vector>(b.create<sem::F16>(), 3u);
case TypeAlias::kVec4H:
return b.create<sem::Vector>(b.create<sem::F16>(), 4u);
case TypeAlias::kVec2I:
return b.create<sem::Vector>(b.create<sem::I32>(), 2u);
case TypeAlias::kVec3I:
return b.create<sem::Vector>(b.create<sem::I32>(), 3u);
case TypeAlias::kVec4I:
return b.create<sem::Vector>(b.create<sem::I32>(), 4u);
case TypeAlias::kVec2U:
return b.create<sem::Vector>(b.create<sem::U32>(), 2u);
case TypeAlias::kVec3U:
return b.create<sem::Vector>(b.create<sem::U32>(), 3u);
case TypeAlias::kVec4U:
return b.create<sem::Vector>(b.create<sem::U32>(), 4u);
case TypeAlias::kUndefined:
break;
}
return nullptr;
}
void Resolver::CollectTextureSamplerPairs(const sem::Builtin* builtin, void Resolver::CollectTextureSamplerPairs(const sem::Builtin* builtin,
utils::VectorRef<const sem::Expression*> args) const { utils::VectorRef<const sem::Expression*> args) const {
// Collect a texture/sampler pair for this builtin. // Collect a texture/sampler pair for this builtin.
@ -2550,7 +2590,7 @@ sem::Expression* Resolver::Identifier(const ast::IdentifierExpression* expr) {
return nullptr; return nullptr;
} }
if (resolved->Is<sem::Type>()) { if (resolved->Is<sem::Type>() || BuiltinTypeAlias(symbol)) {
AddError("missing '(' for type initializer or cast", expr->source.End()); AddError("missing '(' for type initializer or cast", expr->source.End());
return nullptr; return nullptr;
} }

View File

@ -384,6 +384,7 @@ class Resolver {
/// Set the shadowing information on variable declarations. /// Set the shadowing information on variable declarations.
/// @note this method must only be called after all semantic nodes are built. /// @note this method must only be called after all semantic nodes are built.
void SetShadows(); void SetShadows();
/// StatementScope() does the following: /// StatementScope() does the following:
/// * Creates the AST -> SEM mapping. /// * Creates the AST -> SEM mapping.
/// * Assigns `sem` to #current_statement_ /// * Assigns `sem` to #current_statement_
@ -415,6 +416,9 @@ class Resolver {
/// @returns true if the symbol is the name of a builtin function. /// @returns true if the symbol is the name of a builtin function.
bool IsBuiltin(Symbol) const; bool IsBuiltin(Symbol) const;
/// @returns the builtin type alias for the given symbol
sem::Type* BuiltinTypeAlias(Symbol) const;
// ArrayInitializerSig represents a unique array initializer signature. // ArrayInitializerSig represents a unique array initializer signature.
// It is a tuple of the array type, number of arguments provided and earliest evaluation stage. // It is a tuple of the array type, number of arguments provided and earliest evaluation stage.
using ArrayInitializerSig = using ArrayInitializerSig =

View File

@ -0,0 +1,102 @@
// Copyright 2022 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.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen
// using the template:
// src/tint/resolver/type_alias.cc.tmpl
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
#include "src/tint/resolver/type_alias.h"
namespace tint::resolver {
/// ParseTypeAlias parses a TypeAlias from a string.
/// @param str the string to parse
/// @returns the parsed enum, or TypeAlias::kUndefined if the string could not be parsed.
TypeAlias ParseTypeAlias(std::string_view str) {
if (str == "vec2f") {
return TypeAlias::kVec2F;
}
if (str == "vec2h") {
return TypeAlias::kVec2H;
}
if (str == "vec2i") {
return TypeAlias::kVec2I;
}
if (str == "vec2u") {
return TypeAlias::kVec2U;
}
if (str == "vec3f") {
return TypeAlias::kVec3F;
}
if (str == "vec3h") {
return TypeAlias::kVec3H;
}
if (str == "vec3i") {
return TypeAlias::kVec3I;
}
if (str == "vec3u") {
return TypeAlias::kVec3U;
}
if (str == "vec4f") {
return TypeAlias::kVec4F;
}
if (str == "vec4h") {
return TypeAlias::kVec4H;
}
if (str == "vec4i") {
return TypeAlias::kVec4I;
}
if (str == "vec4u") {
return TypeAlias::kVec4U;
}
return TypeAlias::kUndefined;
}
std::ostream& operator<<(std::ostream& out, TypeAlias value) {
switch (value) {
case TypeAlias::kUndefined:
return out << "undefined";
case TypeAlias::kVec2F:
return out << "vec2f";
case TypeAlias::kVec2H:
return out << "vec2h";
case TypeAlias::kVec2I:
return out << "vec2i";
case TypeAlias::kVec2U:
return out << "vec2u";
case TypeAlias::kVec3F:
return out << "vec3f";
case TypeAlias::kVec3H:
return out << "vec3h";
case TypeAlias::kVec3I:
return out << "vec3i";
case TypeAlias::kVec3U:
return out << "vec3u";
case TypeAlias::kVec4F:
return out << "vec4f";
case TypeAlias::kVec4H:
return out << "vec4h";
case TypeAlias::kVec4I:
return out << "vec4i";
case TypeAlias::kVec4U:
return out << "vec4u";
}
return out << "<unknown>";
}
} // namespace tint::resolver

View File

@ -0,0 +1,25 @@
{{- /*
--------------------------------------------------------------------------------
Template file for use with tools/src/cmd/gen to generate type_alias.cc
To update the generated file, run:
./tools/run gen
See:
* tools/src/cmd/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax
--------------------------------------------------------------------------------
*/ -}}
{{- Import "src/tint/templates/enums.tmpl.inc" -}}
{{- $enum := (Sem.Enum "type_alias") -}}
#include "src/tint/resolver/type_alias.h"
namespace tint::resolver {
{{ Eval "ParseEnum" $enum}}
{{ Eval "EnumOStream" $enum}}
} // namespace tint::resolver

View File

@ -0,0 +1,64 @@
// Copyright 2022 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.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen
// using the template:
// src/tint/resolver/type_alias.h.tmpl
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
#ifndef SRC_TINT_RESOLVER_TYPE_ALIAS_H_
#define SRC_TINT_RESOLVER_TYPE_ALIAS_H_
#include <ostream>
namespace tint::resolver {
/// An enumerator of builtin type aliases.
enum class TypeAlias {
kUndefined,
kVec2F,
kVec2H,
kVec2I,
kVec2U,
kVec3F,
kVec3H,
kVec3I,
kVec3U,
kVec4F,
kVec4H,
kVec4I,
kVec4U,
};
/// @param out the std::ostream to write to
/// @param value the TypeAlias
/// @returns `out` so calls can be chained
std::ostream& operator<<(std::ostream& out, TypeAlias value);
/// ParseTypeAlias parses a TypeAlias from a string.
/// @param str the string to parse
/// @returns the parsed enum, or TypeAlias::kUndefined if the string could not be parsed.
TypeAlias ParseTypeAlias(std::string_view str);
constexpr const char* kTypeAliasStrings[] = {
"vec2f", "vec2h", "vec2i", "vec2u", "vec3f", "vec3h",
"vec3i", "vec3u", "vec4f", "vec4h", "vec4i", "vec4u",
};
} // namespace tint::resolver
#endif // SRC_TINT_RESOLVER_TYPE_ALIAS_H_

View File

@ -0,0 +1,29 @@
{{- /*
--------------------------------------------------------------------------------
Template file for use with tools/src/cmd/gen to generate type_alias.h
To update the generated file, run:
./tools/run gen
See:
* tools/src/cmd/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax
--------------------------------------------------------------------------------
*/ -}}
{{- Import "src/tint/templates/enums.tmpl.inc" -}}
{{- $enum := (Sem.Enum "type_alias") -}}
#ifndef SRC_TINT_RESOLVER_TYPE_ALIAS_H_
#define SRC_TINT_RESOLVER_TYPE_ALIAS_H_
#include <ostream>
namespace tint::resolver {
/// An enumerator of builtin type aliases.
{{ Eval "DeclareEnum" $enum}}
} // namespace tint::resolver
#endif // SRC_TINT_RESOLVER_TYPE_ALIAS_H_

View File

@ -0,0 +1,57 @@
// Copyright 2022 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.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen
// using the template:
// src/tint/resolver/type_alias_bench.cc.tmpl
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
#include "src/tint/resolver/type_alias.h"
#include <array>
#include "benchmark/benchmark.h"
namespace tint::resolver {
namespace {
void TypeAliasParser(::benchmark::State& state) {
std::array kStrings{
"veccf", "32", "vVc2f", "vec2f", "vec21", "qqeJf", "vecll7f", "veqH2pp",
"vh", "Gebh", "vec2h", "vevi2h", "ve8WWh", "Mxxc2", "vgg2i", "V2X",
"vec23", "vec2i", "vec2E", "TTeP2i", "vxxcdd", "v44c2u", "veVVSSu", "22RRu",
"vec2u", "vF2u", "vecu", "ROOHVu", "ecyf", "n77rrlcGf", "vec340", "vec3f",
"oof", "vezz", "1ipp3f", "XXec3h", "ve9IInn5h", "HHreSSaYh", "vec3h", "kk3",
"jgRR", "veb", "vjc3i", "vc3i", "vcq", "vec3i", "Nec3i", "vcvv",
"ve3QQ", "vrcf", "vecju", "NNew23", "vec3u", "ve3u", "vrrc3u", "Gec3u",
"veFF4f", "vE", "verrf", "vec4f", "vef", "veJJD", "v4", "e4k",
"vech", "Jech", "vec4h", "ec4h", "_KKttcH", "vexxh", "__qcF", "vc4qq",
"33e64i", "vec4i", "6QQott4i", "v6c4i", "zzc4O6", "vyyc4u", "vcZZ", "ecWq4u",
"vec4u", "vOO4u", "oYe4", "v4",
};
for (auto _ : state) {
for (auto& str : kStrings) {
auto result = ParseTypeAlias(str);
benchmark::DoNotOptimize(result);
}
}
}
BENCHMARK(TypeAliasParser);
} // namespace
} // namespace tint::resolver

View File

@ -0,0 +1,29 @@
{{- /*
--------------------------------------------------------------------------------
Template file for use with tools/src/cmd/gen to generate type_alias_bench.cc
To update the generated file, run:
./tools/run gen
See:
* tools/src/cmd/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax
--------------------------------------------------------------------------------
*/ -}}
{{- Import "src/tint/templates/enums.tmpl.inc" -}}
{{- $enum := (Sem.Enum "type_alias") -}}
#include "src/tint/resolver/type_alias.h"
#include <array>
#include "benchmark/benchmark.h"
namespace tint::resolver {
namespace {
{{ Eval "BenchmarkParseEnum" $enum }}
} // namespace
} // namespace tint::resolver

View File

@ -0,0 +1,97 @@
// Copyright 2022 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.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen
// using the template:
// src/tint/resolver/type_alias_test.cc.tmpl
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
#include "src/tint/resolver/type_alias.h"
#include <string>
#include "gtest/gtest.h"
#include "src/tint/utils/string.h"
namespace tint::resolver {
namespace {
namespace parse_print_tests {
struct Case {
const char* string;
TypeAlias value;
};
inline std::ostream& operator<<(std::ostream& out, Case c) {
return out << "'" << std::string(c.string) << "'";
}
static constexpr Case kValidCases[] = {
{"vec2f", TypeAlias::kVec2F}, {"vec2h", TypeAlias::kVec2H}, {"vec2i", TypeAlias::kVec2I},
{"vec2u", TypeAlias::kVec2U}, {"vec3f", TypeAlias::kVec3F}, {"vec3h", TypeAlias::kVec3H},
{"vec3i", TypeAlias::kVec3I}, {"vec3u", TypeAlias::kVec3U}, {"vec4f", TypeAlias::kVec4F},
{"vec4h", TypeAlias::kVec4H}, {"vec4i", TypeAlias::kVec4I}, {"vec4u", TypeAlias::kVec4U},
};
static constexpr Case kInvalidCases[] = {
{"veccf", TypeAlias::kUndefined}, {"32", TypeAlias::kUndefined},
{"vVc2f", TypeAlias::kUndefined}, {"vec21", TypeAlias::kUndefined},
{"qqeJh", TypeAlias::kUndefined}, {"vecll7h", TypeAlias::kUndefined},
{"veqH2pp", TypeAlias::kUndefined}, {"vi", TypeAlias::kUndefined},
{"Gebi", TypeAlias::kUndefined}, {"vevi2u", TypeAlias::kUndefined},
{"ve8WWu", TypeAlias::kUndefined}, {"Mxxc2", TypeAlias::kUndefined},
{"vgg3f", TypeAlias::kUndefined}, {"V3X", TypeAlias::kUndefined},
{"vec33", TypeAlias::kUndefined}, {"vec3E", TypeAlias::kUndefined},
{"TTeP3h", TypeAlias::kUndefined}, {"vxxcdd", TypeAlias::kUndefined},
{"v44c3i", TypeAlias::kUndefined}, {"veVVSSi", TypeAlias::kUndefined},
{"22RRi", TypeAlias::kUndefined}, {"vF3u", TypeAlias::kUndefined},
{"vecu", TypeAlias::kUndefined}, {"ROOHVu", TypeAlias::kUndefined},
{"ecyf", TypeAlias::kUndefined}, {"n77rrlcGf", TypeAlias::kUndefined},
{"vec440", TypeAlias::kUndefined}, {"ooh", TypeAlias::kUndefined},
{"vezz", TypeAlias::kUndefined}, {"1ipp4h", TypeAlias::kUndefined},
{"XXec4i", TypeAlias::kUndefined}, {"ve9IInn5i", TypeAlias::kUndefined},
{"HHreSSaYi", TypeAlias::kUndefined}, {"kk4", TypeAlias::kUndefined},
{"jgRR", TypeAlias::kUndefined}, {"veb", TypeAlias::kUndefined},
};
using TypeAliasParseTest = testing::TestWithParam<Case>;
TEST_P(TypeAliasParseTest, Parse) {
const char* string = GetParam().string;
TypeAlias expect = GetParam().value;
EXPECT_EQ(expect, ParseTypeAlias(string));
}
INSTANTIATE_TEST_SUITE_P(ValidCases, TypeAliasParseTest, testing::ValuesIn(kValidCases));
INSTANTIATE_TEST_SUITE_P(InvalidCases, TypeAliasParseTest, testing::ValuesIn(kInvalidCases));
using TypeAliasPrintTest = testing::TestWithParam<Case>;
TEST_P(TypeAliasPrintTest, Print) {
TypeAlias value = GetParam().value;
const char* expect = GetParam().string;
EXPECT_EQ(expect, utils::ToString(value));
}
INSTANTIATE_TEST_SUITE_P(ValidCases, TypeAliasPrintTest, testing::ValuesIn(kValidCases));
} // namespace parse_print_tests
} // namespace
} // namespace tint::resolver

View File

@ -0,0 +1,31 @@
{{- /*
--------------------------------------------------------------------------------
Template file for use with tools/src/cmd/gen to generate type_alias_test.cc
To update the generated file, run:
./tools/run gen
See:
* tools/src/cmd/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax
--------------------------------------------------------------------------------
*/ -}}
{{- Import "src/tint/templates/enums.tmpl.inc" -}}
{{- $enum := (Sem.Enum "type_alias") -}}
#include "src/tint/resolver/type_alias.h"
#include <string>
#include "gtest/gtest.h"
#include "src/tint/utils/string.h"
namespace tint::resolver {
namespace {
{{ Eval "TestParsePrintEnum" $enum}}
} // namespace
} // namespace tint::resolver

View File

@ -1395,5 +1395,56 @@ INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
ParamsFor<array<2, f32>>(2))); ParamsFor<array<2, f32>>(2)));
} // namespace VectorTests } // namespace VectorTests
namespace BuiltinTypeAliasTests {
struct Params {
const char* alias;
builder::ast_type_func_ptr type;
};
template <typename T>
constexpr Params Case(const char* alias) {
return Params{alias, DataType<T>::AST};
}
using BuiltinTypeAliasTest = ResolverTestWithParam<Params>;
TEST_P(BuiltinTypeAliasTest, CheckEquivalent) {
// var aliased : vecTN;
// var explicit : vecN<T>;
// explicit = aliased;
auto& params = GetParam();
Enable(ast::Extension::kF16);
WrapInFunction(Decl(Var("aliased", ty.type_name(params.alias))),
Decl(Var("explicit", params.type(*this))), //
Assign("explicit", "aliased"));
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_P(BuiltinTypeAliasTest, Construct) {
// var v : vecN<T> = vecTN();
auto& params = GetParam();
Enable(ast::Extension::kF16);
WrapInFunction(Decl(Var("v", params.type(*this), Construct(ty.type_name(params.alias)))));
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
BuiltinTypeAliasTest,
testing::Values(Case<vec2<f32>>("vec2f"),
Case<vec3<f32>>("vec3f"),
Case<vec4<f32>>("vec4f"),
Case<vec2<f16>>("vec2h"),
Case<vec3<f16>>("vec3h"),
Case<vec4<f16>>("vec4h"),
Case<vec2<i32>>("vec2i"),
Case<vec3<i32>>("vec3i"),
Case<vec4<i32>>("vec4i"),
Case<vec2<u32>>("vec2u"),
Case<vec3<u32>>("vec3u"),
Case<vec4<u32>>("vec4u")));
} // namespace BuiltinTypeAliasTests
} // namespace } // namespace
} // namespace tint::resolver } // namespace tint::resolver

View File

@ -16,10 +16,10 @@
#define SRC_TINT_RESOLVER_UNIFORMITY_H_ #define SRC_TINT_RESOLVER_UNIFORMITY_H_
// Forward declarations. // Forward declarations.
namespace tint { namespace tint::resolver {
namespace resolver {
struct DependencyGraph; struct DependencyGraph;
} // namespace resolver } // namespace tint::resolver
namespace tint {
class ProgramBuilder; class ProgramBuilder;
} // namespace tint } // namespace tint

View File

@ -0,0 +1,10 @@
type a = vec3f;
fn f() {
{
const vec3f = 1;
const b = vec3f;
}
const c = a();
const d = vec3f();
}

View File

@ -0,0 +1,10 @@
type a = vec3f;
fn f() {
{
const vec3f = 1;
const b = vec3f;
}
const c = a();
const d = vec3f();
}

View File

@ -0,0 +1,10 @@
type a = vec3f;
fn f() {
{
let vec3f = 1;
let b = vec3f;
}
let c = a();
let d = vec3f();
}

View File

@ -0,0 +1,13 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
void f() {
{
const int vec3f = 1;
const int b = vec3f;
}
const float3 c = (0.0f).xxx;
const float3 d = (0.0f).xxx;
}

View File

@ -0,0 +1,13 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
void f() {
{
const int vec3f = 1;
const int b = vec3f;
}
const float3 c = (0.0f).xxx;
const float3 d = (0.0f).xxx;
}

View File

@ -0,0 +1,15 @@
#version 310 es
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void unused_entry_point() {
return;
}
void f() {
{
int vec3f = 1;
int b = vec3f;
}
vec3 c = vec3(0.0f);
vec3 d = vec3(0.0f);
}

View File

@ -0,0 +1,12 @@
#include <metal_stdlib>
using namespace metal;
void f() {
{
int const vec3f = 1;
int const b = vec3f;
}
float3 const c = float3(0.0f);
float3 const d = float3(0.0f);
}

View File

@ -0,0 +1,26 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 12
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %unused_entry_point "unused_entry_point"
OpName %f "f"
%void = OpTypeVoid
%1 = OpTypeFunction %void
%int = OpTypeInt 32 1
%int_1 = OpConstant %int 1
%float = OpTypeFloat 32
%v3float = OpTypeVector %float 3
%11 = OpConstantNull %v3float
%unused_entry_point = OpFunction %void None %1
%4 = OpLabel
OpReturn
OpFunctionEnd
%f = OpFunction %void None %1
%6 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,10 @@
type a = vec3f;
fn f() {
{
let vec3f = 1;
let b = vec3f;
}
let c = a();
let d = vec3f();
}

View File

@ -0,0 +1,3 @@
fn f(vec3f : vec3f) {
let b = vec3f;
}

View File

@ -0,0 +1,8 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
void f(float3 vec3f) {
const float3 b = vec3f;
}

View File

@ -0,0 +1,8 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
void f(float3 vec3f) {
const float3 b = vec3f;
}

View File

@ -0,0 +1,10 @@
#version 310 es
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void unused_entry_point() {
return;
}
void f(vec3 vec3f) {
vec3 b = vec3f;
}

View File

@ -0,0 +1,7 @@
#include <metal_stdlib>
using namespace metal;
void f(float3 vec3f) {
float3 const b = vec3f;
}

View File

@ -0,0 +1,26 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 11
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %unused_entry_point "unused_entry_point"
OpName %f "f"
OpName %vec3f "vec3f"
%void = OpTypeVoid
%1 = OpTypeFunction %void
%float = OpTypeFloat 32
%v3float = OpTypeVector %float 3
%5 = OpTypeFunction %void %v3float
%unused_entry_point = OpFunction %void None %1
%4 = OpLabel
OpReturn
OpFunctionEnd
%f = OpFunction %void None %5
%vec3f = OpFunctionParameter %v3float
%10 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,3 @@
fn f(vec3f : vec3f) {
let b = vec3f;
}

View File

@ -0,0 +1,10 @@
type a = vec3f;
fn f() {
{
var vec3f = 1;
var b = vec3f;
}
var c = a();
var d = vec3f();
}

View File

@ -0,0 +1,13 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
void f() {
{
int vec3f = 1;
int b = vec3f;
}
float3 c = (0.0f).xxx;
float3 d = (0.0f).xxx;
}

View File

@ -0,0 +1,13 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
void f() {
{
int vec3f = 1;
int b = vec3f;
}
float3 c = (0.0f).xxx;
float3 d = (0.0f).xxx;
}

View File

@ -0,0 +1,15 @@
#version 310 es
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void unused_entry_point() {
return;
}
void f() {
{
int vec3f = 1;
int b = vec3f;
}
vec3 c = vec3(0.0f);
vec3 d = vec3(0.0f);
}

View File

@ -0,0 +1,12 @@
#include <metal_stdlib>
using namespace metal;
void f() {
{
int vec3f = 1;
int b = vec3f;
}
float3 c = float3(0.0f);
float3 d = float3(0.0f);
}

View File

@ -0,0 +1,42 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 20
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %unused_entry_point "unused_entry_point"
OpName %f "f"
OpName %vec3f "vec3f"
OpName %b "b"
OpName %c "c"
OpName %d "d"
%void = OpTypeVoid
%1 = OpTypeFunction %void
%int = OpTypeInt 32 1
%int_1 = OpConstant %int 1
%_ptr_Function_int = OpTypePointer Function %int
%11 = OpConstantNull %int
%float = OpTypeFloat 32
%v3float = OpTypeVector %float 3
%16 = OpConstantNull %v3float
%_ptr_Function_v3float = OpTypePointer Function %v3float
%unused_entry_point = OpFunction %void None %1
%4 = OpLabel
OpReturn
OpFunctionEnd
%f = OpFunction %void None %1
%6 = OpLabel
%vec3f = OpVariable %_ptr_Function_int Function %11
%b = OpVariable %_ptr_Function_int Function %11
%c = OpVariable %_ptr_Function_v3float Function %16
%d = OpVariable %_ptr_Function_v3float Function %16
OpStore %vec3f %int_1
%12 = OpLoad %int %vec3f
OpStore %b %12
OpStore %c %16
OpStore %d %16
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,10 @@
type a = vec3f;
fn f() {
{
var vec3f = 1;
var b = vec3f;
}
var c = a();
var d = vec3f();
}

View File

@ -0,0 +1,9 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
void f() {
{
}
}

View File

@ -0,0 +1,9 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
void f() {
{
}
}

View File

@ -0,0 +1,11 @@
#version 310 es
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void unused_entry_point() {
return;
}
void f() {
{
}
}

View File

@ -0,0 +1,8 @@
#include <metal_stdlib>
using namespace metal;
void f() {
{
}
}

View File

@ -0,0 +1,21 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 7
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %unused_entry_point "unused_entry_point"
OpName %f "f"
%void = OpTypeVoid
%1 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %1
%4 = OpLabel
OpReturn
OpFunctionEnd
%f = OpFunction %void None %1
%6 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -93,15 +93,26 @@ func (l *lexer) lex() error {
case l.match("/", tok.Divide): case l.match("/", tok.Divide):
case l.match(".", tok.Dot): case l.match(".", tok.Dot):
case l.match("->", tok.Arrow): case l.match("->", tok.Arrow):
case l.match("fn", tok.Function):
case l.match("op", tok.Operator):
case l.match("enum", tok.Enum):
case l.match("type", tok.Type):
case l.match("init", tok.Initializer):
case l.match("conv", tok.Converter):
case l.match("match", tok.Match):
case unicode.IsLetter(l.peek(0)) || l.peek(0) == '_': case unicode.IsLetter(l.peek(0)) || l.peek(0) == '_':
l.tok(l.count(alphaNumericOrUnderscore), tok.Identifier) n := l.count(alphaNumericOrUnderscore)
switch string(l.runes[:n]) {
case "fn":
l.tok(n, tok.Function)
case "op":
l.tok(n, tok.Operator)
case "enum":
l.tok(n, tok.Enum)
case "type":
l.tok(n, tok.Type)
case "init":
l.tok(n, tok.Initializer)
case "conv":
l.tok(n, tok.Converter)
case "match":
l.tok(n, tok.Match)
default:
l.tok(n, tok.Identifier)
}
case unicode.IsNumber(l.peek(0)) || l.peek(0) == '-': case unicode.IsNumber(l.peek(0)) || l.peek(0) == '-':
isFloat := false isFloat := false
isNegative := false isNegative := false

View File

@ -84,6 +84,9 @@ func TestLexTokens(t *testing.T) {
{"op", []tok.Token{{Kind: tok.Operator, Runes: []rune("op"), Source: tok.Source{ {"op", []tok.Token{{Kind: tok.Operator, Runes: []rune("op"), Source: tok.Source{
S: loc(1, 1, 0), E: loc(1, 3, 2), S: loc(1, 1, 0), E: loc(1, 3, 2),
}}}}, }}}},
{"operation", []tok.Token{{Kind: tok.Identifier, Runes: []rune("operation"), Source: tok.Source{
S: loc(1, 1, 0), E: loc(1, 10, 9),
}}}},
{"type", []tok.Token{{Kind: tok.Type, Runes: []rune("type"), Source: tok.Source{ {"type", []tok.Token{{Kind: tok.Type, Runes: []rune("type"), Source: tok.Source{
S: loc(1, 1, 0), E: loc(1, 5, 4), S: loc(1, 1, 0), E: loc(1, 5, 4),
}}}}, }}}},