mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-16 00:17:03 +00:00
ast: Remove TypeConstructorExpression
Add a new 'Target' to the ast::CallExpression, which can be either an Identifier or Type. The Identifier may resolve to a Type, if the Type is a structure or alias. The Resolver now resolves the CallExpression target to one of the following sem::CallTargets: * sem::Function * sem::Intrinsic * sem::TypeConstructor * sem::TypeCast This change will allow us to remove the type tracking logic from the WGSL parser, which is required for out-of-order module scope declarations. Bug: tint:888 Bug: tint:1266 Change-Id: I696f117115a50981fd5c102a0d7764641bb755dd Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/68525 Reviewed-by: David Neto <dneto@google.com> Reviewed-by: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -78,7 +78,7 @@ void ExternalTextureTransform::Run(CloneContext& ctx,
|
||||
// Replace the call with another that has the same parameters in
|
||||
// addition to a level parameter (always zero for external
|
||||
// textures).
|
||||
auto* exp = ctx.Clone(call_expr->func);
|
||||
auto* exp = ctx.Clone(call_expr->target.name);
|
||||
auto* externalTextureParam = ctx.Clone(call_expr->args[0]);
|
||||
|
||||
ast::ExpressionList params;
|
||||
|
||||
@@ -19,7 +19,10 @@
|
||||
#include <vector>
|
||||
|
||||
#include "src/program_builder.h"
|
||||
#include "src/sem/call.h"
|
||||
#include "src/sem/expression.h"
|
||||
#include "src/sem/type_constructor.h"
|
||||
#include "src/sem/type_conversion.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::transform::FoldConstants);
|
||||
|
||||
@@ -32,26 +35,25 @@ FoldConstants::~FoldConstants() = default;
|
||||
|
||||
void FoldConstants::Run(CloneContext& ctx, const DataMap&, DataMap&) {
|
||||
ctx.ReplaceAll([&](const ast::Expression* expr) -> const ast::Expression* {
|
||||
auto* sem = ctx.src->Sem().Get(expr);
|
||||
if (!sem) {
|
||||
auto* call = ctx.src->Sem().Get<sem::Call>(expr);
|
||||
if (!call) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto value = sem->ConstantValue();
|
||||
auto value = call->ConstantValue();
|
||||
if (!value.IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* ty = sem->Type();
|
||||
auto* ty = call->Type();
|
||||
|
||||
auto* ctor = expr->As<ast::TypeConstructorExpression>();
|
||||
if (!ctor) {
|
||||
if (!call->Target()->IsAnyOf<sem::TypeConversion, sem::TypeConstructor>()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If original ctor expression had no init values, don't replace the
|
||||
// expression
|
||||
if (ctor->values.size() == 0) {
|
||||
if (call->Arguments().empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -68,7 +70,7 @@ void FoldConstants::Run(CloneContext& ctx, const DataMap&, DataMap&) {
|
||||
// create it with 3. So what we do is construct with vec_size args,
|
||||
// except if the original vector was single-value initialized, in
|
||||
// which case, we only construct with one arg again.
|
||||
uint32_t ctor_size = (ctor->values.size() == 1) ? 1 : vec_size;
|
||||
uint32_t ctor_size = (call->Arguments().size() == 1) ? 1 : vec_size;
|
||||
|
||||
ast::ExpressionList ctors;
|
||||
for (uint32_t i = 0; i < ctor_size; ++i) {
|
||||
|
||||
@@ -307,7 +307,8 @@ struct ModuleScopeVarToEntryPointParam::State {
|
||||
|
||||
// Pass the variables as pointers to any functions that need them.
|
||||
for (auto* call : calls_to_replace[func_ast]) {
|
||||
auto* target = ctx.src->AST().Functions().Find(call->func->symbol);
|
||||
auto* target =
|
||||
ctx.src->AST().Functions().Find(call->target.name->symbol);
|
||||
auto* target_sem = ctx.src->Sem().Get(target);
|
||||
|
||||
// Add new arguments for any variables that are needed by the callee.
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
|
||||
#include "src/program_builder.h"
|
||||
#include "src/sem/array.h"
|
||||
#include "src/sem/call.h"
|
||||
#include "src/sem/expression.h"
|
||||
#include "src/sem/type_constructor.h"
|
||||
#include "src/utils/get_or_create.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::transform::PadArrayElements);
|
||||
@@ -131,26 +133,29 @@ void PadArrayElements::Run(CloneContext& ctx, const DataMap&, DataMap&) {
|
||||
|
||||
// Fix up array constructors so `A(1,2)` becomes
|
||||
// `A(padded(1), padded(2))`
|
||||
ctx.ReplaceAll([&](const ast::TypeConstructorExpression* ctor)
|
||||
-> const ast::Expression* {
|
||||
if (auto* array =
|
||||
tint::As<sem::Array>(sem.Get(ctor)->Type()->UnwrapRef())) {
|
||||
if (auto p = pad(array)) {
|
||||
auto* arr_ty = p();
|
||||
auto el_typename = arr_ty->type->As<ast::TypeName>()->name;
|
||||
ctx.ReplaceAll(
|
||||
[&](const ast::CallExpression* expr) -> const ast::Expression* {
|
||||
auto* call = sem.Get(expr);
|
||||
if (auto* ctor = call->Target()->As<sem::TypeConstructor>()) {
|
||||
if (auto* array = ctor->ReturnType()->As<sem::Array>()) {
|
||||
if (auto p = pad(array)) {
|
||||
auto* arr_ty = p();
|
||||
auto el_typename = arr_ty->type->As<ast::TypeName>()->name;
|
||||
|
||||
ast::ExpressionList args;
|
||||
args.reserve(ctor->values.size());
|
||||
for (auto* arg : ctor->values) {
|
||||
args.emplace_back(ctx.dst->Construct(
|
||||
ctx.dst->create<ast::TypeName>(el_typename), ctx.Clone(arg)));
|
||||
ast::ExpressionList args;
|
||||
args.reserve(call->Arguments().size());
|
||||
for (auto* arg : call->Arguments()) {
|
||||
auto* val = ctx.Clone(arg->Declaration());
|
||||
args.emplace_back(ctx.dst->Construct(
|
||||
ctx.dst->create<ast::TypeName>(el_typename), val));
|
||||
}
|
||||
|
||||
return ctx.dst->Construct(arr_ty, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ctx.dst->Construct(arr_ty, args);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
ctx.Clone();
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
|
||||
#include "src/program_builder.h"
|
||||
#include "src/sem/block_statement.h"
|
||||
#include "src/sem/call.h"
|
||||
#include "src/sem/expression.h"
|
||||
#include "src/sem/statement.h"
|
||||
#include "src/sem/type_constructor.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::transform::PromoteInitializersToConstVar);
|
||||
|
||||
@@ -50,14 +52,12 @@ void PromoteInitializersToConstVar::Run(CloneContext& ctx,
|
||||
// pointer can be passed to the parent's constructor.
|
||||
|
||||
for (auto* src_node : ctx.src->ASTNodes().Objects()) {
|
||||
if (auto* src_init = src_node->As<ast::TypeConstructorExpression>()) {
|
||||
auto* src_sem_expr = ctx.src->Sem().Get(src_init);
|
||||
if (!src_sem_expr) {
|
||||
TINT_ICE(Transform, ctx.dst->Diagnostics())
|
||||
<< "ast::TypeConstructorExpression has no semantic expression node";
|
||||
if (auto* src_init = src_node->As<ast::CallExpression>()) {
|
||||
auto* call = ctx.src->Sem().Get(src_init);
|
||||
if (!call->Target()->Is<sem::TypeConstructor>()) {
|
||||
continue;
|
||||
}
|
||||
auto* src_sem_stmt = src_sem_expr->Stmt();
|
||||
auto* src_sem_stmt = call->Stmt();
|
||||
if (!src_sem_stmt) {
|
||||
// Expression is outside of a statement. This usually means the
|
||||
// expression is part of a global (module-scope) constant declaration.
|
||||
@@ -76,12 +76,12 @@ void PromoteInitializersToConstVar::Run(CloneContext& ctx,
|
||||
}
|
||||
}
|
||||
|
||||
auto* src_ty = src_sem_expr->Type();
|
||||
auto* src_ty = call->Type();
|
||||
if (src_ty->IsAnyOf<sem::Array, sem::Struct>()) {
|
||||
// Create a new symbol for the constant
|
||||
auto dst_symbol = ctx.dst->Sym();
|
||||
// Clone the type
|
||||
auto* dst_ty = ctx.Clone(src_init->type);
|
||||
auto* dst_ty = CreateASTTypeFor(ctx, call->Type());
|
||||
// Clone the initializer
|
||||
auto* dst_init = ctx.Clone(src_init);
|
||||
// Construct the constant that holds the hoisted initializer
|
||||
|
||||
@@ -30,7 +30,7 @@ fn main() {
|
||||
var f1 : f32 = 2.0;
|
||||
var f2 : f32 = 3.0;
|
||||
var f3 : f32 = 4.0;
|
||||
var i : f32 = array<f32, 4>(f0, f1, f2, f3)[2];
|
||||
var i : f32 = array<f32, 4u>(f0, f1, f2, f3)[2];
|
||||
}
|
||||
)";
|
||||
|
||||
@@ -41,7 +41,7 @@ fn main() {
|
||||
var f1 : f32 = 2.0;
|
||||
var f2 : f32 = 3.0;
|
||||
var f3 : f32 = 4.0;
|
||||
let tint_symbol : array<f32, 4> = array<f32, 4>(f0, f1, f2, f3);
|
||||
let tint_symbol : array<f32, 4u> = array<f32, 4u>(f0, f1, f2, f3);
|
||||
var i : f32 = tint_symbol[2];
|
||||
}
|
||||
)";
|
||||
@@ -88,16 +88,16 @@ TEST_F(PromoteInitializersToConstVarTest, ArrayInArrayArray) {
|
||||
auto* src = R"(
|
||||
[[stage(compute), workgroup_size(1)]]
|
||||
fn main() {
|
||||
var i : f32 = array<array<f32, 2>, 2>(array<f32, 2>(1.0, 2.0), array<f32, 2>(3.0, 4.0))[0][1];
|
||||
var i : f32 = array<array<f32, 2u>, 2u>(array<f32, 2u>(1.0, 2.0), array<f32, 2u>(3.0, 4.0))[0][1];
|
||||
}
|
||||
)";
|
||||
|
||||
auto* expect = R"(
|
||||
[[stage(compute), workgroup_size(1)]]
|
||||
fn main() {
|
||||
let tint_symbol : array<f32, 2> = array<f32, 2>(1.0, 2.0);
|
||||
let tint_symbol_1 : array<f32, 2> = array<f32, 2>(3.0, 4.0);
|
||||
let tint_symbol_2 : array<array<f32, 2>, 2> = array<array<f32, 2>, 2>(tint_symbol, tint_symbol_1);
|
||||
let tint_symbol : array<f32, 2u> = array<f32, 2u>(1.0, 2.0);
|
||||
let tint_symbol_1 : array<f32, 2u> = array<f32, 2u>(3.0, 4.0);
|
||||
let tint_symbol_2 : array<array<f32, 2u>, 2u> = array<array<f32, 2u>, 2u>(tint_symbol, tint_symbol_1);
|
||||
var i : f32 = tint_symbol_2[0][1];
|
||||
}
|
||||
)";
|
||||
@@ -165,12 +165,12 @@ struct S1 {
|
||||
};
|
||||
|
||||
struct S2 {
|
||||
a : array<S1, 3>;
|
||||
a : array<S1, 3u>;
|
||||
};
|
||||
|
||||
[[stage(compute), workgroup_size(1)]]
|
||||
fn main() {
|
||||
var x : i32 = S2(array<S1, 3>(S1(1), S1(2), S1(3))).a[1].a;
|
||||
var x : i32 = S2(array<S1, 3u>(S1(1), S1(2), S1(3))).a[1].a;
|
||||
}
|
||||
)";
|
||||
|
||||
@@ -180,7 +180,7 @@ struct S1 {
|
||||
};
|
||||
|
||||
struct S2 {
|
||||
a : array<S1, 3>;
|
||||
a : array<S1, 3u>;
|
||||
};
|
||||
|
||||
[[stage(compute), workgroup_size(1)]]
|
||||
@@ -188,7 +188,7 @@ fn main() {
|
||||
let tint_symbol : S1 = S1(1);
|
||||
let tint_symbol_1 : S1 = S1(2);
|
||||
let tint_symbol_2 : S1 = S1(3);
|
||||
let tint_symbol_3 : array<S1, 3> = array<S1, 3>(tint_symbol, tint_symbol_1, tint_symbol_2);
|
||||
let tint_symbol_3 : array<S1, 3u> = array<S1, 3u>(tint_symbol, tint_symbol_1, tint_symbol_2);
|
||||
let tint_symbol_4 : S2 = S2(tint_symbol_3);
|
||||
var x : i32 = tint_symbol_4.a[1].a;
|
||||
}
|
||||
@@ -209,11 +209,11 @@ struct S {
|
||||
|
||||
[[stage(compute), workgroup_size(1)]]
|
||||
fn main() {
|
||||
var local_arr : array<f32, 4> = array<f32, 4>(0.0, 1.0, 2.0, 3.0);
|
||||
var local_arr : array<f32, 4u> = array<f32, 4u>(0.0, 1.0, 2.0, 3.0);
|
||||
var local_str : S = S(1, 2.0, 3);
|
||||
}
|
||||
|
||||
let module_arr : array<f32, 4> = array<f32, 4>(0.0, 1.0, 2.0, 3.0);
|
||||
let module_arr : array<f32, 4u> = array<f32, 4u>(0.0, 1.0, 2.0, 3.0);
|
||||
|
||||
let module_str : S = S(1, 2.0, 3);
|
||||
)";
|
||||
|
||||
@@ -1285,7 +1285,7 @@ Output Renamer::Run(const Program* in, const DataMap& inputs) {
|
||||
continue;
|
||||
}
|
||||
if (sem->Target()->Is<sem::Intrinsic>()) {
|
||||
preserve.emplace(call->func);
|
||||
preserve.emplace(call->target.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
#include <utility>
|
||||
|
||||
#include "src/program_builder.h"
|
||||
#include "src/sem/call.h"
|
||||
#include "src/sem/expression.h"
|
||||
#include "src/sem/type_constructor.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::transform::VectorizeScalarMatrixConstructors);
|
||||
|
||||
@@ -33,38 +35,44 @@ VectorizeScalarMatrixConstructors::~VectorizeScalarMatrixConstructors() =
|
||||
void VectorizeScalarMatrixConstructors::Run(CloneContext& ctx,
|
||||
const DataMap&,
|
||||
DataMap&) {
|
||||
ctx.ReplaceAll([&](const ast::TypeConstructorExpression* constructor)
|
||||
-> const ast::TypeConstructorExpression* {
|
||||
// Check if this is a matrix constructor with scalar arguments.
|
||||
auto* mat_type = ctx.src->Sem().Get(constructor->type)->As<sem::Matrix>();
|
||||
if (!mat_type) {
|
||||
return nullptr;
|
||||
}
|
||||
if (constructor->values.size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!ctx.src->Sem().Get(constructor->values[0])->Type()->is_scalar()) {
|
||||
return nullptr;
|
||||
}
|
||||
ctx.ReplaceAll(
|
||||
[&](const ast::CallExpression* expr) -> const ast::CallExpression* {
|
||||
auto* call = ctx.src->Sem().Get(expr);
|
||||
auto* ty_ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
if (!ty_ctor) {
|
||||
return nullptr;
|
||||
}
|
||||
// Check if this is a matrix constructor with scalar arguments.
|
||||
auto* mat_type = call->Type()->As<sem::Matrix>();
|
||||
if (!mat_type) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Build a list of vector expressions for each column.
|
||||
ast::ExpressionList columns;
|
||||
for (uint32_t c = 0; c < mat_type->columns(); c++) {
|
||||
// Build a list of scalar expressions for each value in the column.
|
||||
ast::ExpressionList row_values;
|
||||
for (uint32_t r = 0; r < mat_type->rows(); r++) {
|
||||
row_values.push_back(
|
||||
ctx.Clone(constructor->values[c * mat_type->rows() + r]));
|
||||
}
|
||||
auto& args = call->Arguments();
|
||||
if (args.size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!args[0]->Type()->is_scalar()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Construct the column vector.
|
||||
auto* col = ctx.dst->vec(CreateASTTypeFor(ctx, mat_type->type()),
|
||||
mat_type->rows(), row_values);
|
||||
columns.push_back(col);
|
||||
}
|
||||
// Build a list of vector expressions for each column.
|
||||
ast::ExpressionList columns;
|
||||
for (uint32_t c = 0; c < mat_type->columns(); c++) {
|
||||
// Build a list of scalar expressions for each value in the column.
|
||||
ast::ExpressionList row_values;
|
||||
for (uint32_t r = 0; r < mat_type->rows(); r++) {
|
||||
row_values.push_back(
|
||||
ctx.Clone(args[c * mat_type->rows() + r]->Declaration()));
|
||||
}
|
||||
|
||||
return ctx.dst->Construct(CreateASTTypeFor(ctx, mat_type), columns);
|
||||
});
|
||||
// Construct the column vector.
|
||||
auto* col = ctx.dst->vec(CreateASTTypeFor(ctx, mat_type->type()),
|
||||
mat_type->rows(), row_values);
|
||||
columns.push_back(col);
|
||||
}
|
||||
return ctx.dst->Construct(CreateASTTypeFor(ctx, mat_type), columns);
|
||||
});
|
||||
|
||||
ctx.Clone();
|
||||
}
|
||||
|
||||
@@ -715,8 +715,8 @@ struct State {
|
||||
LoadPrimitive(array_base, primitive_offset, buffer, base_format));
|
||||
}
|
||||
|
||||
return ctx.dst->Construct(
|
||||
ctx.dst->create<ast::Vector>(base_type, count), std::move(expr_list));
|
||||
return ctx.dst->Construct(ctx.dst->create<ast::Vector>(base_type, count),
|
||||
std::move(expr_list));
|
||||
}
|
||||
|
||||
/// Process a non-struct entry point parameter.
|
||||
|
||||
@@ -18,8 +18,11 @@
|
||||
|
||||
#include "src/program_builder.h"
|
||||
#include "src/sem/array.h"
|
||||
#include "src/sem/call.h"
|
||||
#include "src/sem/expression.h"
|
||||
#include "src/sem/type_constructor.h"
|
||||
#include "src/utils/get_or_create.h"
|
||||
#include "src/utils/transform.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::transform::WrapArraysInStructs);
|
||||
|
||||
@@ -74,21 +77,28 @@ void WrapArraysInStructs::Run(CloneContext& ctx, const DataMap&, DataMap&) {
|
||||
});
|
||||
|
||||
// Fix up array constructors so `A(1,2)` becomes `tint_array_wrapper(A(1,2))`
|
||||
ctx.ReplaceAll([&](const ast::TypeConstructorExpression* ctor)
|
||||
-> const ast::Expression* {
|
||||
if (auto* array =
|
||||
::tint::As<sem::Array>(sem.Get(ctor)->Type()->UnwrapRef())) {
|
||||
if (auto w = wrapper(array)) {
|
||||
// Wrap the array type constructor with another constructor for
|
||||
// the wrapper
|
||||
auto* wrapped_array_ty = ctx.Clone(ctor->type);
|
||||
auto* array_ty = w.array_type(ctx);
|
||||
auto* arr_ctor = ctx.dst->Construct(array_ty, ctx.Clone(ctor->values));
|
||||
return ctx.dst->Construct(wrapped_array_ty, arr_ctor);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
ctx.ReplaceAll(
|
||||
[&](const ast::CallExpression* expr) -> const ast::Expression* {
|
||||
if (auto* call = sem.Get(expr)) {
|
||||
if (auto* ctor = call->Target()->As<sem::TypeConstructor>()) {
|
||||
if (auto* array = ctor->ReturnType()->As<sem::Array>()) {
|
||||
if (auto w = wrapper(array)) {
|
||||
// Wrap the array type constructor with another constructor for
|
||||
// the wrapper
|
||||
auto* wrapped_array_ty = ctx.dst->ty.type_name(w.wrapper_name);
|
||||
auto* array_ty = w.array_type(ctx);
|
||||
auto args = utils::Transform(
|
||||
call->Arguments(), [&](const tint::sem::Expression* s) {
|
||||
return ctx.Clone(s->Declaration());
|
||||
});
|
||||
auto* arr_ctor = ctx.dst->Construct(array_ty, args);
|
||||
return ctx.dst->Construct(wrapped_array_ty, arr_ctor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
ctx.Clone();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user