Resolver: compute canonical types and store them as semantic::Variable::Type

We define the canonical type as a type stripped of all aliases. For
example, Canonical(alias<alias<vec3<alias<f32>>>>) is vec3<f32>. This
change adds Resolver::Canonical(Type*) which caches and returns the
resulting canonical type. We use this throughout the Resolver instead of
UnwrapAliasIfNeeded(), and we store the result in semantic::Variable,
returned from it's Type() member function.

Also:

* Wrote unit tests for Resolver::Canonical()

* Added semantic::Variable::DeclaredType() as a convenience to
retrieve the AST variable's type.

* Updated post-resolve code (transforms) to make use of Type and
DeclaredType appropriately, removing unnecessary calls to
UnwrapAliasIfNeeded.

* Added IntrinsicTableTest.MatchWithNestedAliasUnwrapping to ensure we
don't need to pass canonical parameter types for instrinsic table
lookups.

* ProgramBuilder: added vecN and matMxN overloads that take a Type* arg
to create them with alias types.

Bug: tint:705
Change-Id: I58a3b62538356b8dad2b1161a19b38bcefdd5d62
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/47360
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
Antonio Maiorano
2021-04-13 13:32:33 +00:00
committed by Commit Bot service account
parent 2f25ecf8ba
commit 2543686412
14 changed files with 269 additions and 76 deletions

View File

@@ -65,8 +65,7 @@ Transform::Output BindingRemapper::Run(const Program* in,
auto ac_it = remappings->access_controls.find(from);
if (ac_it != remappings->access_controls.end()) {
ast::AccessControl ac = ac_it->second;
auto* var_ty = in->Sem().Get(var)->Type();
auto* ty = var_ty->UnwrapAliasIfNeeded();
auto* ty = in->Sem().Get(var)->Type();
type::Type* inner_ty = nullptr;
if (auto* old_ac = ty->As<type::AccessControl>()) {
inner_ty = ctx.Clone(old_ac->type());

View File

@@ -72,11 +72,11 @@ Transform::Output CanonicalizeEntryPointIO::Run(const Program* in,
for (auto* param : func->params()) {
auto param_name = ctx.Clone(param->symbol());
auto* param_ty = ctx.src->Sem().Get(param)->Type();
auto* param_declared_ty = ctx.src->Sem().Get(param)->DeclaredType();
ast::Expression* func_const_initializer = nullptr;
if (auto* struct_ty =
param_ty->UnwrapAliasIfNeeded()->As<type::Struct>()) {
if (auto* struct_ty = param_ty->As<type::Struct>()) {
// Pull out all struct members and build initializer list.
ast::ExpressionList init_values;
for (auto* member : struct_ty->impl()->members()) {
@@ -97,7 +97,7 @@ Transform::Output CanonicalizeEntryPointIO::Run(const Program* in,
}
func_const_initializer =
ctx.dst->Construct(ctx.Clone(param_ty), init_values);
ctx.dst->Construct(ctx.Clone(param_declared_ty), init_values);
} else {
ast::DecorationList new_decorations = RemoveDecorations(
&ctx, param->decorations(), [](const ast::Decoration* deco) {
@@ -105,7 +105,7 @@ Transform::Output CanonicalizeEntryPointIO::Run(const Program* in,
ast::LocationDecoration>();
});
new_struct_members.push_back(ctx.dst->Member(
param_name, ctx.Clone(param_ty), new_decorations));
param_name, ctx.Clone(param_declared_ty), new_decorations));
func_const_initializer =
ctx.dst->MemberAccessor(new_struct_param_symbol, param_name);
}
@@ -117,8 +117,8 @@ Transform::Output CanonicalizeEntryPointIO::Run(const Program* in,
// Create a function-scope const to replace the parameter.
// Initialize it with the value extracted from the new struct parameter.
auto* func_const = ctx.dst->Const(param_name, ctx.Clone(param_ty),
func_const_initializer);
auto* func_const = ctx.dst->Const(
param_name, ctx.Clone(param_declared_ty), func_const_initializer);
ctx.InsertBefore(func->body()->statements(), *func->body()->begin(),
ctx.dst->WrapInStatement(func_const));

View File

@@ -141,7 +141,8 @@ void Spirv::HandleEntryPointIOTypes(CloneContext& ctx) const {
for (auto* param : func->params()) {
Symbol new_var = HoistToInputVariables(
ctx, func, ctx.src->Sem().Get(param)->Type(), param->decorations());
ctx, func, ctx.src->Sem().Get(param)->Type(),
ctx.src->Sem().Get(param)->DeclaredType(), param->decorations());
// Replace all uses of the function parameter with the new variable.
for (auto* user : ctx.src->Sem().Get(param)->Users()) {
@@ -153,9 +154,9 @@ void Spirv::HandleEntryPointIOTypes(CloneContext& ctx) const {
if (!func->return_type()->Is<type::Void>()) {
ast::StatementList stores;
auto store_value_symbol = ctx.dst->Symbols().New();
HoistToOutputVariables(ctx, func, func->return_type(),
func->return_type_decorations(), {},
store_value_symbol, stores);
HoistToOutputVariables(
ctx, func, func->return_type(), func->return_type(),
func->return_type_decorations(), {}, store_value_symbol, stores);
// Create a function that writes a return value to all output variables.
auto* store_value =
@@ -251,8 +252,9 @@ Symbol Spirv::HoistToInputVariables(
CloneContext& ctx,
const ast::Function* func,
type::Type* ty,
type::Type* declared_ty,
const ast::DecorationList& decorations) const {
if (!ty->UnwrapAliasIfNeeded()->Is<type::Struct>()) {
if (!ty->Is<type::Struct>()) {
// Base case: create a global variable and return.
ast::DecorationList new_decorations =
RemoveDecorations(&ctx, decorations, [](const ast::Decoration* deco) {
@@ -261,7 +263,7 @@ Symbol Spirv::HoistToInputVariables(
});
auto global_var_symbol = ctx.dst->Symbols().New();
auto* global_var =
ctx.dst->Var(global_var_symbol, ctx.Clone(ty),
ctx.dst->Var(global_var_symbol, ctx.Clone(declared_ty),
ast::StorageClass::kInput, nullptr, new_decorations);
ctx.InsertBefore(ctx.src->AST().GlobalDeclarations(), func, global_var);
return global_var_symbol;
@@ -269,10 +271,10 @@ Symbol Spirv::HoistToInputVariables(
// Recurse into struct members and build the initializer list.
ast::ExpressionList init_values;
auto* struct_ty = ty->UnwrapAliasIfNeeded()->As<type::Struct>();
auto* struct_ty = ty->As<type::Struct>();
for (auto* member : struct_ty->impl()->members()) {
auto member_var =
HoistToInputVariables(ctx, func, member->type(), member->decorations());
auto member_var = HoistToInputVariables(
ctx, func, member->type(), member->type(), member->decorations());
init_values.push_back(ctx.dst->Expr(member_var));
}
@@ -283,8 +285,9 @@ Symbol Spirv::HoistToInputVariables(
}
// Create a function-scope variable for the struct.
auto* initializer = ctx.dst->Construct(ctx.Clone(ty), init_values);
auto* func_var = ctx.dst->Const(func_var_symbol, ctx.Clone(ty), initializer);
auto* initializer = ctx.dst->Construct(ctx.Clone(declared_ty), init_values);
auto* func_var =
ctx.dst->Const(func_var_symbol, ctx.Clone(declared_ty), initializer);
ctx.InsertBefore(func->body()->statements(), *func->body()->begin(),
ctx.dst->WrapInStatement(func_var));
return func_var_symbol;
@@ -293,12 +296,13 @@ Symbol Spirv::HoistToInputVariables(
void Spirv::HoistToOutputVariables(CloneContext& ctx,
const ast::Function* func,
type::Type* ty,
type::Type* declared_ty,
const ast::DecorationList& decorations,
std::vector<Symbol> member_accesses,
Symbol store_value,
ast::StatementList& stores) const {
// Base case.
if (!ty->UnwrapAliasIfNeeded()->Is<type::Struct>()) {
if (!ty->Is<type::Struct>()) {
// Create a global variable.
ast::DecorationList new_decorations =
RemoveDecorations(&ctx, decorations, [](const ast::Decoration* deco) {
@@ -307,7 +311,7 @@ void Spirv::HoistToOutputVariables(CloneContext& ctx,
});
auto global_var_symbol = ctx.dst->Symbols().New();
auto* global_var =
ctx.dst->Var(global_var_symbol, ctx.Clone(ty),
ctx.dst->Var(global_var_symbol, ctx.Clone(declared_ty),
ast::StorageClass::kOutput, nullptr, new_decorations);
ctx.InsertBefore(ctx.src->AST().GlobalDeclarations(), func, global_var);
@@ -322,11 +326,12 @@ void Spirv::HoistToOutputVariables(CloneContext& ctx,
}
// Recurse into struct members.
auto* struct_ty = ty->UnwrapAliasIfNeeded()->As<type::Struct>();
auto* struct_ty = ty->As<type::Struct>();
for (auto* member : struct_ty->impl()->members()) {
member_accesses.push_back(ctx.Clone(member->symbol()));
HoistToOutputVariables(ctx, func, member->type(), member->decorations(),
member_accesses, store_value, stores);
HoistToOutputVariables(ctx, func, member->type(), member->type(),
member->decorations(), member_accesses, store_value,
stores);
member_accesses.pop_back();
}
}

View File

@@ -60,6 +60,7 @@ class Spirv : public Transform {
Symbol HoistToInputVariables(CloneContext& ctx,
const ast::Function* func,
type::Type* ty,
type::Type* declared_ty,
const ast::DecorationList& decorations) const;
/// Recursively create module-scope output variables for `ty` and build a list
@@ -73,6 +74,7 @@ class Spirv : public Transform {
void HoistToOutputVariables(CloneContext& ctx,
const ast::Function* func,
type::Type* ty,
type::Type* declared_ty,
const ast::DecorationList& decorations,
std::vector<Symbol> member_accesses,
Symbol store_value,