tint: Fix Renamer transform with type short-names

Fixed: tint:1783
Change-Id: I0ffd5860405651f15961dc8fe753eeac6edc8434
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/113441
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
Ben Clayton
2022-12-08 20:45:54 +00:00
committed by Dawn LUCI CQ
parent 384e2bee88
commit 06c1af47bd
38 changed files with 964 additions and 35 deletions

View File

@@ -21,7 +21,10 @@
#include "src/tint/program_builder.h"
#include "src/tint/sem/call.h"
#include "src/tint/sem/member_accessor_expression.h"
#include "src/tint/sem/type_conversion.h"
#include "src/tint/sem/type_initializer.h"
#include "src/tint/text/unicode.h"
#include "src/tint/type/short_name.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::Renamer);
TINT_INSTANTIATE_TYPEINFO(tint::transform::Renamer::Data);
@@ -1258,27 +1261,63 @@ Transform::ApplyResult Renamer::Apply(const Program* src,
ProgramBuilder b;
CloneContext ctx{&b, src, /* auto_clone_symbols */ false};
// Swizzles, builtin calls and builtin structure members need to keep their
// symbols preserved.
utils::Hashset<const ast::IdentifierExpression*, 8> preserve;
for (auto* node : src->ASTNodes().Objects()) {
if (auto* member = node->As<ast::MemberAccessorExpression>()) {
auto* sem = src->Sem().Get(member);
if (sem->Is<sem::Swizzle>()) {
preserve.Add(member->member);
} else if (auto* str_expr = src->Sem().Get(member->structure)) {
if (auto* ty = str_expr->Type()->UnwrapRef()->As<sem::Struct>()) {
if (ty->Declaration() == nullptr) { // Builtin structure
preserve.Add(member->member);
}
// Identifiers that need to keep their symbols preserved.
utils::Hashset<const ast::IdentifierExpression*, 8> preserved_identifiers;
// Type names that need to keep their symbols preserved.
utils::Hashset<const ast::TypeName*, 8> preserved_type_names;
auto is_type_short_name = [&](const Symbol& symbol) {
auto name = src->Symbols().NameFor(symbol);
if (type::ParseShortName(name) != type::ShortName::kUndefined) {
// Identifier *looks* like a builtin short-name, but check the using actually
// shadowing a short-name with a type alias.
for (auto* decl : src->AST().TypeDecls()) {
if (decl->name == symbol) {
return false;
}
}
} else if (auto* call = node->As<ast::CallExpression>()) {
auto* sem = src->Sem().Get(call)->UnwrapMaterialize()->As<sem::Call>();
if (sem->Target()->Is<sem::Builtin>()) {
preserve.Add(call->target.name);
}
return true;
}
return false;
};
for (auto* node : src->ASTNodes().Objects()) {
Switch(
node,
[&](const ast::MemberAccessorExpression* accessor) {
auto* sem = src->Sem().Get(accessor);
if (sem->Is<sem::Swizzle>()) {
preserved_identifiers.Add(accessor->member);
} else if (auto* str_expr = src->Sem().Get(accessor->structure)) {
if (auto* ty = str_expr->Type()->UnwrapRef()->As<sem::Struct>()) {
if (ty->Declaration() == nullptr) { // Builtin structure
preserved_identifiers.Add(accessor->member);
}
}
}
},
[&](const ast::CallExpression* call) {
if (auto* ident = call->target.name) {
Switch(
src->Sem().Get(call)->UnwrapMaterialize()->As<sem::Call>()->Target(),
[&](const sem::Builtin*) { preserved_identifiers.Add(ident); },
[&](const sem::TypeConversion*) {
if (is_type_short_name(ident->symbol)) {
preserved_identifiers.Add(ident);
}
},
[&](const sem::TypeInitializer*) {
if (is_type_short_name(ident->symbol)) {
preserved_identifiers.Add(ident);
}
});
}
},
[&](const ast::TypeName* type_name) {
if (is_type_short_name(type_name->name)) {
preserved_type_names.Add(type_name);
}
});
}
Data::Remappings remappings;
@@ -1335,7 +1374,7 @@ Transform::ApplyResult Renamer::Apply(const Program* src,
});
ctx.ReplaceAll([&](const ast::IdentifierExpression* ident) -> const ast::IdentifierExpression* {
if (preserve.Contains(ident)) {
if (preserved_identifiers.Contains(ident)) {
auto sym_in = ident->symbol;
auto str = src->Symbols().NameFor(sym_in);
auto sym_out = b.Symbols().Register(str);
@@ -1344,6 +1383,16 @@ Transform::ApplyResult Renamer::Apply(const Program* src,
return nullptr; // Clone ident. Uses the symbol remapping above.
});
ctx.ReplaceAll([&](const ast::TypeName* type_name) -> const ast::TypeName* {
if (preserved_type_names.Contains(type_name)) {
auto sym_in = type_name->name;
auto str = src->Symbols().NameFor(sym_in);
auto sym_out = b.Symbols().Register(str);
return ctx.dst->create<ast::TypeName>(ctx.Clone(type_name->source), sym_out);
}
return nullptr; // Clone ident. Uses the symbol remapping above.
});
ctx.Clone(); // Must come before the std::move()
outputs.Add<Data>(std::move(remappings));

View File

@@ -18,6 +18,7 @@
#include "gmock/gmock.h"
#include "src/tint/transform/test_helper.h"
#include "src/tint/type/short_name.h"
namespace tint::transform {
namespace {
@@ -1457,5 +1458,219 @@ INSTANTIATE_TEST_SUITE_P(
// "while" // WGSL reserved keyword
kUnicodeIdentifier));
const char* ExpandShortName(std::string_view name) {
if (name == "vec2f") {
return "vec2<f32>";
}
if (name == "vec2h") {
return "vec2<f16>";
}
if (name == "vec2i") {
return "vec2<i32>";
}
if (name == "vec2u") {
return "vec2<u32>";
}
if (name == "vec3f") {
return "vec3<f32>";
}
if (name == "vec3h") {
return "vec3<f16>";
}
if (name == "vec3i") {
return "vec3<i32>";
}
if (name == "vec3u") {
return "vec3<u32>";
}
if (name == "vec4f") {
return "vec4<f32>";
}
if (name == "vec4h") {
return "vec4<f16>";
}
if (name == "vec4i") {
return "vec4<i32>";
}
if (name == "vec4u") {
return "vec4<u32>";
}
ADD_FAILURE() << "unhandled type short-name: " << name;
return "<invalid>";
}
using RenamerTypeShortNamesTest = TransformTestWithParam<const char*>;
TEST_P(RenamerTypeShortNamesTest, PreserveTypeUsage) {
auto expand = [&](const char* source) {
auto out = utils::ReplaceAll(source, "$name", GetParam());
out = utils::ReplaceAll(out, "$type", ExpandShortName(GetParam()));
return out;
};
auto src = expand(R"(
enable f16;
fn x(v : $name) -> $name {
const a : $name = $name();
let b : $name = a;
var c : $name = b;
return c;
}
struct y {
a : $name,
}
)");
auto expect = expand(R"(
enable f16;
fn tint_symbol(tint_symbol_1 : $name) -> $name {
const tint_symbol_2 : $name = $name();
let tint_symbol_3 : $name = tint_symbol_2;
var tint_symbol_4 : $name = tint_symbol_3;
return tint_symbol_4;
}
struct tint_symbol_5 {
tint_symbol_2 : $name,
}
)");
auto got = Run<Renamer>(src);
EXPECT_EQ(expect, str(got));
}
TEST_P(RenamerTypeShortNamesTest, PreserveTypeInitializer) {
auto expand = [&](const char* source) {
auto out = utils::ReplaceAll(source, "$name", GetParam());
out = utils::ReplaceAll(out, "$type", ExpandShortName(GetParam()));
return out;
};
auto src = expand(R"(
enable f16;
@fragment
fn f() {
var v : $type = $name();
}
)");
auto expect = expand(R"(
enable f16;
@fragment
fn tint_symbol() {
var tint_symbol_1 : $type = $name();
}
)");
auto got = Run<Renamer>(src);
EXPECT_EQ(expect, str(got));
}
TEST_P(RenamerTypeShortNamesTest, PreserveTypeConversion) {
auto expand = [&](const char* source) {
auto out = utils::ReplaceAll(source, "$name", GetParam());
out = utils::ReplaceAll(out, "$type", ExpandShortName(GetParam()));
return out;
};
auto src = expand(R"(
enable f16;
@fragment
fn f() {
var v : $type = $name($type());
}
)");
auto expect = expand(R"(
enable f16;
@fragment
fn tint_symbol() {
var tint_symbol_1 : $type = $name($type());
}
)");
auto got = Run<Renamer>(src);
EXPECT_EQ(expect, str(got));
}
TEST_P(RenamerTypeShortNamesTest, RenameShadowedByAlias) {
auto expand = [&](const char* source) {
auto out = utils::ReplaceAll(source, "$name", GetParam());
out = utils::ReplaceAll(out, "$type", ExpandShortName(GetParam()));
return out;
};
auto src = expand(R"(
type $name = i32;
@fragment
fn f() {
var v : i32 = $name();
}
)");
auto expect = expand(R"(
type tint_symbol = i32;
@fragment
fn tint_symbol_1() {
var tint_symbol_2 : i32 = tint_symbol();
}
)");
auto got = Run<Renamer>(src);
EXPECT_EQ(expect, str(got));
}
TEST_P(RenamerTypeShortNamesTest, RenameShadowedByStruct) {
auto expand = [&](const char* source) {
auto out = utils::ReplaceAll(source, "$name", GetParam());
out = utils::ReplaceAll(out, "$type", ExpandShortName(GetParam()));
return out;
};
auto src = expand(R"(
struct $name {
i : i32,
}
@fragment
fn f() {
var a = $name();
var b = a.i;
}
)");
auto expect = expand(R"(
struct tint_symbol {
tint_symbol_1 : i32,
}
@fragment
fn tint_symbol_2() {
var tint_symbol_3 = tint_symbol();
var tint_symbol_4 = tint_symbol_3.tint_symbol_1;
}
)");
auto got = Run<Renamer>(src);
EXPECT_EQ(expect, str(got));
}
INSTANTIATE_TEST_SUITE_P(RenamerTypeShortNamesTest,
RenamerTypeShortNamesTest,
testing::ValuesIn(type::kShortNameStrings));
} // namespace
} // namespace tint::transform