mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-17 17:05:31 +00:00
Implement Pointers and References
This change implements pointers and references as described by the WGSL specification change in https://github.com/gpuweb/gpuweb/pull/1569. reader/spirv: * Now emits address-of `&expr` and indirection `*expr` operators as needed. * As an identifier may now resolve to a pointer or reference type depending on whether the declaration is a `var`, `let` or parameter, `Function::identifier_values_` has been changed from an ID set to an ID -> Type* map. resolver: * Now correctly resolves all expressions to either a value type, reference type or pointer type. * Validates pointer / reference rules on assignment, `var` and `let` construction, and usage. * Handles the address-of and indirection operators. * No longer does any implicit loads of pointer types. * Storage class validation is still TODO (crbug.com/tint/809) writer/spirv: * Correctly handles variables and expressions of pointer and reference types, emitting OpLoads where necessary. test: * Lots of new test cases Fixed: tint:727 Change-Id: I77d3281590e35e5a3122f5b74cdeb71a6fe51f74 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/50740 Commit-Queue: Ben Clayton <bclayton@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
committed by
Commit Bot service account
parent
d1232670ae
commit
9b54a2e53c
@@ -113,7 +113,7 @@ Output BindingRemapper::Run(const Program* in, const DataMap& datamap) {
|
||||
auto ac_it = remappings->access_controls.find(from);
|
||||
if (ac_it != remappings->access_controls.end()) {
|
||||
ast::AccessControl::Access ac = ac_it->second;
|
||||
auto* ty = in->Sem().Get(var)->Type();
|
||||
auto* ty = in->Sem().Get(var)->Type()->UnwrapRef();
|
||||
ast::Type* inner_ty = CreateASTTypeFor(&ctx, ty);
|
||||
auto* new_ty = ctx.dst->create<ast::AccessControl>(ac, inner_ty);
|
||||
auto* new_var = ctx.dst->create<ast::Variable>(
|
||||
|
||||
@@ -41,7 +41,7 @@ ast::ArrayAccessorExpression* BoundArrayAccessors::Transform(
|
||||
CloneContext* ctx) {
|
||||
auto& diags = ctx->dst->Diagnostics();
|
||||
|
||||
auto* ret_type = ctx->src->Sem().Get(expr->array())->Type()->UnwrapAll();
|
||||
auto* ret_type = ctx->src->Sem().Get(expr->array())->Type()->UnwrapRef();
|
||||
if (!ret_type->Is<sem::Array>() && !ret_type->Is<sem::Matrix>() &&
|
||||
!ret_type->Is<sem::Vector>()) {
|
||||
return nullptr;
|
||||
|
||||
@@ -29,7 +29,7 @@ var<private> a : array<f32, 3>;
|
||||
let c : u32 = 1u;
|
||||
|
||||
fn f() {
|
||||
let b : ptr<private, f32> = a[c];
|
||||
let b : f32 = a[c];
|
||||
}
|
||||
)";
|
||||
|
||||
@@ -39,7 +39,7 @@ var<private> a : array<f32, 3>;
|
||||
let c : u32 = 1u;
|
||||
|
||||
fn f() {
|
||||
let b : ptr<private, f32> = a[min(u32(c), 2u)];
|
||||
let b : f32 = a[min(u32(c), 2u)];
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ Output CalculateArrayLength::Run(const Program* in, const DataMap&) {
|
||||
auto* storage_buffer_expr = accessor->structure();
|
||||
auto* storage_buffer_sem = sem.Get(storage_buffer_expr);
|
||||
auto* storage_buffer_type =
|
||||
storage_buffer_sem->Type()->UnwrapAll()->As<sem::Struct>();
|
||||
storage_buffer_sem->Type()->UnwrapRef()->As<sem::Struct>();
|
||||
|
||||
// Generate BufferSizeIntrinsic for this storage type if we haven't
|
||||
// already
|
||||
|
||||
@@ -115,7 +115,7 @@ Output CanonicalizeEntryPointIO::Run(const Program* in, const DataMap&) {
|
||||
// Pull out all struct members and build initializer list.
|
||||
std::vector<Symbol> member_names;
|
||||
for (auto* member : str->Members()) {
|
||||
if (member->Type()->UnwrapAll()->Is<sem::Struct>()) {
|
||||
if (member->Type()->Is<sem::Struct>()) {
|
||||
TINT_ICE(ctx.dst->Diagnostics()) << "nested pipeline IO struct";
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ Output CanonicalizeEntryPointIO::Run(const Program* in, const DataMap&) {
|
||||
if (auto* str = ret_type->As<sem::Struct>()) {
|
||||
// Rebuild struct with only the entry point IO attributes.
|
||||
for (auto* member : str->Members()) {
|
||||
if (member->Type()->UnwrapAll()->Is<sem::Struct>()) {
|
||||
if (member->Type()->Is<sem::Struct>()) {
|
||||
TINT_ICE(ctx.dst->Diagnostics()) << "nested pipeline IO struct";
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "src/sem/array.h"
|
||||
#include "src/sem/call.h"
|
||||
#include "src/sem/member_accessor_expression.h"
|
||||
#include "src/sem/reference_type.h"
|
||||
#include "src/sem/struct.h"
|
||||
#include "src/sem/variable.h"
|
||||
#include "src/utils/get_or_create.h"
|
||||
@@ -56,7 +57,7 @@ struct OffsetExpr : Offset {
|
||||
explicit OffsetExpr(ast::Expression* e) : expr(e) {}
|
||||
|
||||
ast::Expression* Build(CloneContext& ctx) override {
|
||||
auto* type = ctx.src->Sem().Get(expr)->Type()->UnwrapAll();
|
||||
auto* type = ctx.src->Sem().Get(expr)->Type()->UnwrapRef();
|
||||
auto* res = ctx.Clone(expr);
|
||||
if (!type->Is<sem::U32>()) {
|
||||
res = ctx.dst->Construct<ProgramBuilder::u32>(res);
|
||||
@@ -333,8 +334,8 @@ void InsertGlobal(CloneContext& ctx,
|
||||
/// @returns the unwrapped, user-declared constructed type of ty.
|
||||
const ast::NamedType* ConstructedTypeOf(const sem::Type* ty) {
|
||||
while (true) {
|
||||
if (auto* ptr = ty->As<sem::Pointer>()) {
|
||||
ty = ptr->StoreType();
|
||||
if (auto* ref = ty->As<sem::Reference>()) {
|
||||
ty = ref->StoreType();
|
||||
continue;
|
||||
}
|
||||
if (auto* str = ty->As<sem::Struct>()) {
|
||||
@@ -466,14 +467,14 @@ struct DecomposeStorageAccess::State {
|
||||
for (auto* member : str->Members()) {
|
||||
auto* offset = ctx.dst->Add("offset", member->Offset());
|
||||
Symbol load = LoadFunc(ctx, insert_after, buf_ty,
|
||||
member->Type()->UnwrapAll(), var_user);
|
||||
member->Type()->UnwrapRef(), var_user);
|
||||
values.emplace_back(ctx.dst->Call(load, "buffer", offset));
|
||||
}
|
||||
} else if (auto* arr = el_ty->As<sem::Array>()) {
|
||||
for (uint32_t i = 0; i < arr->Count(); i++) {
|
||||
auto* offset = ctx.dst->Add("offset", arr->Stride() * i);
|
||||
Symbol load = LoadFunc(ctx, insert_after, buf_ty,
|
||||
arr->ElemType()->UnwrapAll(), var_user);
|
||||
arr->ElemType()->UnwrapRef(), var_user);
|
||||
values.emplace_back(ctx.dst->Call(load, "buffer", offset));
|
||||
}
|
||||
}
|
||||
@@ -546,7 +547,7 @@ struct DecomposeStorageAccess::State {
|
||||
auto* access = ctx.dst->MemberAccessor(
|
||||
"value", ctx.Clone(member->Declaration()->symbol()));
|
||||
Symbol store = StoreFunc(ctx, insert_after, buf_ty,
|
||||
member->Type()->UnwrapAll(), var_user);
|
||||
member->Type()->UnwrapRef(), var_user);
|
||||
auto* call = ctx.dst->Call(store, "buffer", offset, access);
|
||||
body.emplace_back(ctx.dst->create<ast::CallStatement>(call));
|
||||
}
|
||||
@@ -555,7 +556,7 @@ struct DecomposeStorageAccess::State {
|
||||
auto* offset = ctx.dst->Add("offset", arr->Stride() * i);
|
||||
auto* access = ctx.dst->IndexAccessor("value", ctx.dst->Expr(i));
|
||||
Symbol store = StoreFunc(ctx, insert_after, buf_ty,
|
||||
arr->ElemType()->UnwrapAll(), var_user);
|
||||
arr->ElemType()->UnwrapRef(), var_user);
|
||||
auto* call = ctx.dst->Call(store, "buffer", offset, access);
|
||||
body.emplace_back(ctx.dst->create<ast::CallStatement>(call));
|
||||
}
|
||||
@@ -661,7 +662,7 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
|
||||
state.AddAccess(ident, {
|
||||
var,
|
||||
ToOffset(0u),
|
||||
var->Type()->UnwrapAll(),
|
||||
var->Type()->UnwrapRef(),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -681,7 +682,7 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
|
||||
accessor, {
|
||||
access.var,
|
||||
Add(std::move(access.offset), std::move(offset)),
|
||||
vec_ty->type()->UnwrapAll(),
|
||||
vec_ty->type()->UnwrapRef(),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -694,7 +695,7 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
|
||||
{
|
||||
access.var,
|
||||
Add(std::move(access.offset), std::move(offset)),
|
||||
member->Type()->UnwrapAll(),
|
||||
member->Type()->UnwrapRef(),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -710,7 +711,7 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
|
||||
{
|
||||
access.var,
|
||||
Add(std::move(access.offset), std::move(offset)),
|
||||
arr->ElemType()->UnwrapAll(),
|
||||
arr->ElemType()->UnwrapRef(),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
@@ -720,7 +721,7 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
|
||||
{
|
||||
access.var,
|
||||
Add(std::move(access.offset), std::move(offset)),
|
||||
vec_ty->type()->UnwrapAll(),
|
||||
vec_ty->type()->UnwrapRef(),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
@@ -770,8 +771,8 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
|
||||
|
||||
auto* buf = access.var->Declaration();
|
||||
auto* offset = access.offset->Build(ctx);
|
||||
auto* buf_ty = access.var->Type()->UnwrapPtr();
|
||||
auto* el_ty = access.type->UnwrapAll();
|
||||
auto* buf_ty = access.var->Type()->UnwrapRef();
|
||||
auto* el_ty = access.type->UnwrapRef();
|
||||
auto* insert_after = ConstructedTypeOf(access.var->Type());
|
||||
Symbol func = state.LoadFunc(ctx, insert_after, buf_ty, el_ty,
|
||||
access.var->As<sem::VariableUser>());
|
||||
@@ -785,8 +786,8 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
|
||||
for (auto& store : state.stores) {
|
||||
auto* buf = store.target.var->Declaration();
|
||||
auto* offset = store.target.offset->Build(ctx);
|
||||
auto* buf_ty = store.target.var->Type()->UnwrapPtr();
|
||||
auto* el_ty = store.target.type->UnwrapAll();
|
||||
auto* buf_ty = store.target.var->Type()->UnwrapRef();
|
||||
auto* el_ty = store.target.type->UnwrapRef();
|
||||
auto* value = store.assignment->rhs();
|
||||
auto* insert_after = ConstructedTypeOf(store.target.var->Type());
|
||||
Symbol func = state.StoreFunc(ctx, insert_after, buf_ty, el_ty,
|
||||
|
||||
@@ -52,7 +52,10 @@ Output ExternalTextureTransform::Run(const Program* in, const DataMap&) {
|
||||
// if the first parameter is an external texture.
|
||||
if (auto* var =
|
||||
sem.Get(call_expr->params()[0])->As<sem::VariableUser>()) {
|
||||
if (var->Variable()->Type()->Is<sem::ExternalTexture>()) {
|
||||
if (var->Variable()
|
||||
->Type()
|
||||
->UnwrapRef()
|
||||
->Is<sem::ExternalTexture>()) {
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad &&
|
||||
call_expr->params().size() != 2) {
|
||||
TINT_ICE(ctx.dst->Diagnostics())
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "src/program_builder.h"
|
||||
#include "src/sem/reference_type.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::transform::Data);
|
||||
|
||||
@@ -107,6 +108,9 @@ ast::Type* Transform::CreateASTTypeFor(CloneContext* ctx, const sem::Type* ty) {
|
||||
return ctx->dst->create<ast::TypeName>(
|
||||
ctx->Clone(s->Declaration()->name()));
|
||||
}
|
||||
if (auto* s = ty->As<sem::Reference>()) {
|
||||
return CreateASTTypeFor(ctx, s->StoreType());
|
||||
}
|
||||
TINT_UNREACHABLE(ctx->dst->Diagnostics())
|
||||
<< "Unhandled type: " << ty->TypeInfo().name;
|
||||
return nullptr;
|
||||
|
||||
Reference in New Issue
Block a user