sem::Type: Replace GetDefaultAlignAndSize() with Size() and Align()
This is a cleaner API, and the implementation doesn't have to know a bunch of information about all the derived types.
Change-Id: I96bebcb9f3ceda86fa34bd8e70961dee63fd7e13
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/59301
Commit-Queue: Ben Clayton <bclayton@google.com>
Auto-Submit: Ben Clayton <bclayton@google.com>
Kokoro: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc
index dd2bdb2..84a1eee 100644
--- a/src/inspector/inspector.cc
+++ b/src/inspector/inspector.cc
@@ -546,9 +546,9 @@
auto* func_sem = program_->Sem().Get(func);
for (const sem::Variable* var : func_sem->ReferencedModuleVariables()) {
if (var->StorageClass() == ast::StorageClass::kWorkgroup) {
- uint32_t align = 0;
- uint32_t size = 0;
- var->Type()->UnwrapRef()->GetDefaultAlignAndSize(align, size);
+ auto* ty = var->Type()->UnwrapRef();
+ uint32_t align = ty->Align();
+ uint32_t size = ty->Size();
// This essentially matches std430 layout rules from GLSL, which are in
// turn specified as an upper bound for Vulkan layout sizing. Since D3D
diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc
index 93012fd..f7bb4e4 100644
--- a/src/resolver/resolver.cc
+++ b/src/resolver/resolver.cc
@@ -693,9 +693,7 @@
};
auto required_alignment_of = [&](const sem::Type* ty) {
- uint32_t actual_align = 0;
- uint32_t actual_size = 0;
- ty->GetDefaultAlignAndSize(actual_align, actual_size);
+ uint32_t actual_align = ty->Align();
uint32_t required_align = actual_align;
if (is_uniform_struct_or_array(ty)) {
required_align = utils::RoundUp(16u, actual_align);
@@ -3813,9 +3811,8 @@
return nullptr;
}
- uint32_t el_align = 0;
- uint32_t el_size = 0;
- el_ty->GetDefaultAlignAndSize(el_align, el_size);
+ uint32_t el_align = el_ty->Align();
+ uint32_t el_size = el_ty->Size();
if (!ValidateNoDuplicateDecorations(arr->decorations())) {
return nullptr;
@@ -4035,9 +4032,8 @@
}
uint32_t offset = struct_size;
- uint32_t align = 0;
- uint32_t size = 0;
- type->GetDefaultAlignAndSize(align, size);
+ uint32_t align = type->Align();
+ uint32_t size = type->Size();
if (!ValidateNoDuplicateDecorations(member->decorations())) {
return nullptr;
diff --git a/src/sem/array.cc b/src/sem/array.cc
index 8e3a734..a5757be 100644
--- a/src/sem/array.cc
+++ b/src/sem/array.cc
@@ -68,5 +68,13 @@
return out.str();
}
+uint32_t Array::Align() const {
+ return align_;
+}
+
+uint32_t Array::Size() const {
+ return size_;
+}
+
} // namespace sem
} // namespace tint
diff --git a/src/sem/array.h b/src/sem/array.h
index 592c538..8ae7a97 100644
--- a/src/sem/array.h
+++ b/src/sem/array.h
@@ -62,12 +62,12 @@
/// @returns the byte alignment of the array
/// @note this may differ from the alignment of a structure member of this
/// array type, if the member is annotated with the `[[align(n)]]` decoration.
- uint32_t Align() const { return align_; }
+ uint32_t Align() const override;
/// @returns the byte size of the array
/// @note this may differ from the size of a structure member of this array
/// type, if the member is annotated with the `[[size(n)]]` decoration.
- uint32_t SizeInBytes() const { return size_; }
+ uint32_t Size() const override;
/// @returns the number of bytes from the start of one element of the
/// array to the start of the next element
diff --git a/src/sem/atomic_type.cc b/src/sem/atomic_type.cc
index 4444768..18fc5d2 100644
--- a/src/sem/atomic_type.cc
+++ b/src/sem/atomic_type.cc
@@ -38,6 +38,14 @@
return out.str();
}
+uint32_t Atomic::Size() const {
+ return subtype_->Size();
+}
+
+uint32_t Atomic::Align() const {
+ return subtype_->Align();
+}
+
Atomic::Atomic(Atomic&&) = default;
Atomic::~Atomic() = default;
diff --git a/src/sem/atomic_type.h b/src/sem/atomic_type.h
index 8c4a4ff..c284d1d 100644
--- a/src/sem/atomic_type.h
+++ b/src/sem/atomic_type.h
@@ -44,6 +44,12 @@
/// declared in WGSL.
std::string FriendlyName(const SymbolTable& symbols) const override;
+ /// @returns the size in bytes of the type.
+ uint32_t Size() const override;
+
+ /// @returns the alignment in bytes of the type.
+ uint32_t Align() const override;
+
private:
sem::Type const* const subtype_;
};
diff --git a/src/sem/bool_type.cc b/src/sem/bool_type.cc
index aec4f6b..eeb3100 100644
--- a/src/sem/bool_type.cc
+++ b/src/sem/bool_type.cc
@@ -39,5 +39,13 @@
return true;
}
+uint32_t Bool::Size() const {
+ return 4;
+}
+
+uint32_t Bool::Align() const {
+ return 4;
+}
+
} // namespace sem
} // namespace tint
diff --git a/src/sem/bool_type.h b/src/sem/bool_type.h
index b9fa24d..c143989 100644
--- a/src/sem/bool_type.h
+++ b/src/sem/bool_type.h
@@ -48,6 +48,16 @@
/// @returns true if constructible as per
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
bool IsConstructible() const override;
+
+ /// @returns the size in bytes of the type.
+ /// @note: booleans are not host-sharable, but still may exist in workgroup
+ /// storage.
+ uint32_t Size() const override;
+
+ /// @returns the alignment in bytes of the type.
+ /// @note: booleans are not host-sharable, but still may exist in workgroup
+ /// storage.
+ uint32_t Align() const override;
};
} // namespace sem
diff --git a/src/sem/f32_type.cc b/src/sem/f32_type.cc
index 49d8666..3935fe3a 100644
--- a/src/sem/f32_type.cc
+++ b/src/sem/f32_type.cc
@@ -39,5 +39,13 @@
return true;
}
+uint32_t F32::Size() const {
+ return 4;
+}
+
+uint32_t F32::Align() const {
+ return 4;
+}
+
} // namespace sem
} // namespace tint
diff --git a/src/sem/f32_type.h b/src/sem/f32_type.h
index 2d35982..16fe521 100644
--- a/src/sem/f32_type.h
+++ b/src/sem/f32_type.h
@@ -42,6 +42,12 @@
/// @returns true if constructible as per
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
bool IsConstructible() const override;
+
+ /// @returns the size in bytes of the type.
+ uint32_t Size() const override;
+
+ /// @returns the alignment in bytes of the type.
+ uint32_t Align() const override;
};
} // namespace sem
diff --git a/src/sem/i32_type.cc b/src/sem/i32_type.cc
index 0b24e87..daacf27 100644
--- a/src/sem/i32_type.cc
+++ b/src/sem/i32_type.cc
@@ -39,5 +39,13 @@
return true;
}
+uint32_t I32::Size() const {
+ return 4;
+}
+
+uint32_t I32::Align() const {
+ return 4;
+}
+
} // namespace sem
} // namespace tint
diff --git a/src/sem/i32_type.h b/src/sem/i32_type.h
index 4621306..6818559 100644
--- a/src/sem/i32_type.h
+++ b/src/sem/i32_type.h
@@ -42,6 +42,12 @@
/// @returns true if constructible as per
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
bool IsConstructible() const override;
+
+ /// @returns the size in bytes of the type.
+ uint32_t Size() const override;
+
+ /// @returns the alignment in bytes of the type.
+ uint32_t Align() const override;
};
} // namespace sem
diff --git a/src/sem/matrix_type.cc b/src/sem/matrix_type.cc
index f9fed56..34de689 100644
--- a/src/sem/matrix_type.cc
+++ b/src/sem/matrix_type.cc
@@ -53,5 +53,17 @@
return true;
}
+uint32_t Matrix::Size() const {
+ return column_type_->Align() * columns();
+}
+
+uint32_t Matrix::Align() const {
+ return column_type_->Align();
+}
+
+uint32_t Matrix::ColumnStride() const {
+ return column_type_->Align();
+}
+
} // namespace sem
} // namespace tint
diff --git a/src/sem/matrix_type.h b/src/sem/matrix_type.h
index d3724fa..9c69b79 100644
--- a/src/sem/matrix_type.h
+++ b/src/sem/matrix_type.h
@@ -58,6 +58,16 @@
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
bool IsConstructible() const override;
+ /// @returns the size in bytes of the type. This may include tail padding.
+ uint32_t Size() const override;
+
+ /// @returns the alignment in bytes of the type. This may include tail
+ /// padding.
+ uint32_t Align() const override;
+
+ /// @returns the number of bytes between columns of the matrix
+ uint32_t ColumnStride() const;
+
private:
Type* const subtype_;
Vector* const column_type_;
diff --git a/src/sem/sem_array_test.cc b/src/sem/sem_array_test.cc
index 30c6fca..04207b6 100644
--- a/src/sem/sem_array_test.cc
+++ b/src/sem/sem_array_test.cc
@@ -27,7 +27,7 @@
EXPECT_EQ(arr->ElemType(), &u32);
EXPECT_EQ(arr->Count(), 2u);
EXPECT_EQ(arr->Align(), 4u);
- EXPECT_EQ(arr->SizeInBytes(), 8u);
+ EXPECT_EQ(arr->Size(), 8u);
EXPECT_EQ(arr->Stride(), 32u);
EXPECT_EQ(arr->ImplicitStride(), 16u);
EXPECT_FALSE(arr->IsStrideImplicit());
@@ -40,7 +40,7 @@
EXPECT_EQ(arr->ElemType(), &u32);
EXPECT_EQ(arr->Count(), 0u);
EXPECT_EQ(arr->Align(), 4u);
- EXPECT_EQ(arr->SizeInBytes(), 8u);
+ EXPECT_EQ(arr->Size(), 8u);
EXPECT_EQ(arr->Stride(), 32u);
EXPECT_EQ(arr->ImplicitStride(), 32u);
EXPECT_TRUE(arr->IsStrideImplicit());
diff --git a/src/sem/struct.cc b/src/sem/struct.cc
index 317402e..210a70e 100644
--- a/src/sem/struct.cc
+++ b/src/sem/struct.cc
@@ -60,6 +60,14 @@
return declaration_->type_name();
}
+uint32_t Struct::Align() const {
+ return align_;
+}
+
+uint32_t Struct::Size() const {
+ return size_;
+}
+
std::string Struct::FriendlyName(const SymbolTable& symbols) const {
return symbols.NameFor(declaration_->name());
}
diff --git a/src/sem/struct.h b/src/sem/struct.h
index e4595c9..b5357cb 100644
--- a/src/sem/struct.h
+++ b/src/sem/struct.h
@@ -86,13 +86,13 @@
/// @note this may differ from the alignment of a structure member of this
/// structure type, if the member is annotated with the `[[align(n)]]`
/// decoration.
- uint32_t Align() const { return align_; }
+ uint32_t Align() const override;
/// @returns the byte size of the structure
/// @note this may differ from the size of a structure member of this
/// structure type, if the member is annotated with the `[[size(n)]]`
/// decoration.
- uint32_t Size() const { return size_; }
+ uint32_t Size() const override;
/// @returns the byte size of the members without the end of structure
/// alignment padding
diff --git a/src/sem/type.cc b/src/sem/type.cc
index 16555f9..5f547a2 100644
--- a/src/sem/type.cc
+++ b/src/sem/type.cc
@@ -14,9 +14,6 @@
#include "src/sem/type.h"
-#include "src/debug.h"
-#include "src/sem/array.h"
-#include "src/sem/atomic_type.h"
#include "src/sem/bool_type.h"
#include "src/sem/f32_type.h"
#include "src/sem/i32_type.h"
@@ -24,7 +21,6 @@
#include "src/sem/pointer_type.h"
#include "src/sem/reference_type.h"
#include "src/sem/sampler_type.h"
-#include "src/sem/struct.h"
#include "src/sem/texture_type.h"
#include "src/sem/u32_type.h"
#include "src/sem/vector_type.h"
@@ -56,59 +52,12 @@
return type;
}
-void Type::GetDefaultAlignAndSize(uint32_t& align, uint32_t& size) const {
- TINT_ASSERT(Semantic, !As<Reference>());
- TINT_ASSERT(Semantic, !As<Pointer>());
+uint32_t Type::Size() const {
+ return 0;
+}
- static constexpr uint32_t vector_size[] = {
- /* padding */ 0,
- /* padding */ 0,
- /*vec2*/ 8,
- /*vec3*/ 12,
- /*vec4*/ 16,
- };
- static constexpr uint32_t vector_align[] = {
- /* padding */ 0,
- /* padding */ 0,
- /*vec2*/ 8,
- /*vec3*/ 16,
- /*vec4*/ 16,
- };
-
- if (is_scalar()) {
- // Note: Also captures booleans, but these are not host-shareable.
- align = 4;
- size = 4;
- return;
- }
- if (auto* vec = As<Vector>()) {
- TINT_ASSERT(Semantic, vec->Width() >= 2 && vec->Width() <= 4);
- align = vector_align[vec->Width()];
- size = vector_size[vec->Width()];
- return;
- }
- if (auto* mat = As<Matrix>()) {
- TINT_ASSERT(Semantic, mat->columns() >= 2 && mat->columns() <= 4);
- TINT_ASSERT(Semantic, mat->rows() >= 2 && mat->rows() <= 4);
- align = vector_align[mat->rows()];
- size = vector_align[mat->rows()] * mat->columns();
- return;
- }
- if (auto* s = As<Struct>()) {
- align = s->Align();
- size = s->Size();
- return;
- }
- if (auto* a = As<Array>()) {
- align = a->Align();
- size = a->SizeInBytes();
- return;
- }
- if (auto* a = As<Atomic>()) {
- return a->Type()->GetDefaultAlignAndSize(align, size);
- }
-
- TINT_ASSERT(Semantic, false);
+uint32_t Type::Align() const {
+ return 0;
}
bool Type::IsConstructible() const {
diff --git a/src/sem/type.h b/src/sem/type.h
index 81a11d9..d38b5ef 100644
--- a/src/sem/type.h
+++ b/src/sem/type.h
@@ -52,9 +52,14 @@
/// @returns the inner type if this is a reference, `this` otherwise
const Type* UnwrapRef() const;
- /// @param align the output default alignment in bytes for this type.
- /// @param size the output default size in bytes for this type.
- void GetDefaultAlignAndSize(uint32_t& align, uint32_t& size) const;
+ /// @returns the size in bytes of the type. This may include tail padding.
+ /// @note opaque types will return a size of 0.
+ virtual uint32_t Size() const;
+
+ /// @returns the alignment in bytes of the type. This may include tail
+ /// padding.
+ /// @note opaque types will return a size of 0.
+ virtual uint32_t Align() const;
/// @returns true if constructible as per
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
diff --git a/src/sem/u32_type.cc b/src/sem/u32_type.cc
index dbc42b0..6383814 100644
--- a/src/sem/u32_type.cc
+++ b/src/sem/u32_type.cc
@@ -39,5 +39,13 @@
return true;
}
+uint32_t U32::Size() const {
+ return 4;
+}
+
+uint32_t U32::Align() const {
+ return 4;
+}
+
} // namespace sem
} // namespace tint
diff --git a/src/sem/u32_type.h b/src/sem/u32_type.h
index cf68da6..8d4bb06 100644
--- a/src/sem/u32_type.h
+++ b/src/sem/u32_type.h
@@ -42,6 +42,12 @@
/// @returns true if constructible as per
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
bool IsConstructible() const override;
+
+ /// @returns the size in bytes of the type.
+ uint32_t Size() const override;
+
+ /// @returns the alignment in bytes of the type.
+ uint32_t Align() const override;
};
} // namespace sem
diff --git a/src/sem/vector_type.cc b/src/sem/vector_type.cc
index 1a44a52..20faa13 100644
--- a/src/sem/vector_type.cc
+++ b/src/sem/vector_type.cc
@@ -45,5 +45,37 @@
return true;
}
+uint32_t Vector::Size() const {
+ return SizeOf(width_);
+}
+
+uint32_t Vector::Align() const {
+ return AlignOf(width_);
+}
+
+uint32_t Vector::SizeOf(uint32_t width) {
+ switch (width) {
+ case 2:
+ return 8;
+ case 3:
+ return 12;
+ case 4:
+ return 16;
+ }
+ return 0; // Unreachable
+}
+
+uint32_t Vector::AlignOf(uint32_t width) {
+ switch (width) {
+ case 2:
+ return 8;
+ case 3:
+ return 16;
+ case 4:
+ return 16;
+ }
+ return 0; // Unreachable
+}
+
} // namespace sem
} // namespace tint
diff --git a/src/sem/vector_type.h b/src/sem/vector_type.h
index 5697386..91633a7 100644
--- a/src/sem/vector_type.h
+++ b/src/sem/vector_type.h
@@ -39,9 +39,6 @@
/// @returns the name for th type
std::string type_name() const override;
- /// @returns the width of the vector
- uint32_t Width() const { return width_; }
-
/// @param symbols the program's symbol table
/// @returns the name for this type that closely resembles how it would be
/// declared in WGSL.
@@ -51,6 +48,24 @@
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
bool IsConstructible() const override;
+ /// @returns the number of elements in the vector
+ uint32_t Width() const { return width_; }
+
+ /// @returns the size in bytes of the type. This may include tail padding.
+ uint32_t Size() const override;
+
+ /// @returns the alignment in bytes of the type. This may include tail
+ /// padding.
+ uint32_t Align() const override;
+
+ /// @param width the width of the vector
+ /// @returns the size in bytes of a vector of the given width.
+ static uint32_t SizeOf(uint32_t width);
+
+ /// @param width the width of the vector
+ /// @returns the alignment in bytes of a vector of the given width.
+ static uint32_t AlignOf(uint32_t width);
+
private:
Type const* const subtype_;
uint32_t const width_;
diff --git a/src/transform/decompose_memory_access.cc b/src/transform/decompose_memory_access.cc
index 65bfec1..8f94f18 100644
--- a/src/transform/decompose_memory_access.cc
+++ b/src/transform/decompose_memory_access.cc
@@ -127,17 +127,6 @@
};
};
-/// @returns the size in bytes of a scalar
-uint32_t ScalarSize(const sem::Type*) {
- // TODO(bclayton): Assumes 32-bit elements
- return 4;
-}
-
-/// @returns the number of bytes between columns of the given matrix
-uint32_t MatrixColumnStride(const sem::Matrix* mat) {
- return ScalarSize(mat->type()) * ((mat->rows() == 2) ? 2 : 4);
-}
-
bool IntrinsicDataTypeFor(const sem::Type* ty,
DecomposeMemoryAccess::Intrinsic::DataType& out) {
if (ty->Is<sem::I32>()) {
@@ -525,7 +514,7 @@
auto* vec_ty = mat_ty->ColumnType();
Symbol load = LoadFunc(buf_ty, vec_ty, var_user);
for (uint32_t i = 0; i < mat_ty->columns(); i++) {
- auto* offset = b.Add("offset", i * MatrixColumnStride(mat_ty));
+ auto* offset = b.Add("offset", i * mat_ty->ColumnStride());
values.emplace_back(b.Call(load, "buffer", offset));
}
} else if (auto* str = el_ty->As<sem::Struct>()) {
@@ -624,7 +613,7 @@
auto* vec_ty = mat_ty->ColumnType();
Symbol store = StoreFunc(buf_ty, vec_ty, var_user);
for (uint32_t i = 0; i < mat_ty->columns(); i++) {
- auto* offset = b.Add("offset", i * MatrixColumnStride(mat_ty));
+ auto* offset = b.Add("offset", i * mat_ty->ColumnStride());
auto* access = b.IndexAccessor("value", i);
auto* call = b.Call(store, "buffer", offset, access);
body.emplace_back(b.create<ast::CallStatement>(call));
@@ -845,7 +834,7 @@
if (auto access = state.TakeAccess(accessor->structure())) {
auto* vec_ty = access.type->As<sem::Vector>();
auto* offset =
- state.Mul(ScalarSize(vec_ty->type()), swizzle->Indices()[0]);
+ state.Mul(vec_ty->type()->Size(), swizzle->Indices()[0]);
state.AddAccess(accessor, {
access.var,
state.Add(access.offset, offset),
@@ -882,7 +871,7 @@
}
if (auto* vec_ty = access.type->As<sem::Vector>()) {
auto* offset =
- state.Mul(ScalarSize(vec_ty->type()), accessor->idx_expr());
+ state.Mul(vec_ty->type()->Size(), accessor->idx_expr());
state.AddAccess(accessor, {
access.var,
state.Add(access.offset, offset),
@@ -892,7 +881,7 @@
}
if (auto* mat_ty = access.type->As<sem::Matrix>()) {
auto* offset =
- state.Mul(MatrixColumnStride(mat_ty), accessor->idx_expr());
+ state.Mul(mat_ty->ColumnStride(), accessor->idx_expr());
state.AddAccess(accessor, {
access.var,
state.Add(access.offset, offset),
diff --git a/src/transform/zero_init_workgroup_memory.cc b/src/transform/zero_init_workgroup_memory.cc
index bc820fa..f866298 100644
--- a/src/transform/zero_init_workgroup_memory.cc
+++ b/src/transform/zero_init_workgroup_memory.cc
@@ -130,7 +130,7 @@
// we need to return true for these arrays.
// See https://github.com/gpuweb/gpuweb/pull/1792
return (cfg.init_arrays_with_loop_size_threshold != 0) &&
- (array->SizeInBytes() >= cfg.init_arrays_with_loop_size_threshold);
+ (array->Size() >= cfg.init_arrays_with_loop_size_threshold);
}
};
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index e853aee..e3ed808 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -2970,21 +2970,21 @@
} else if (type->Is<sem::U32>()) {
out << "uint";
} else if (auto* vec = type->As<sem::Vector>()) {
- auto size = vec->Width();
- if (vec->type()->Is<sem::F32>() && size >= 1 && size <= 4) {
- out << "float" << size;
- } else if (vec->type()->Is<sem::I32>() && size >= 1 && size <= 4) {
- out << "int" << size;
- } else if (vec->type()->Is<sem::U32>() && size >= 1 && size <= 4) {
- out << "uint" << size;
- } else if (vec->type()->Is<sem::Bool>() && size >= 1 && size <= 4) {
- out << "bool" << size;
+ auto width = vec->Width();
+ if (vec->type()->Is<sem::F32>() && width >= 1 && width <= 4) {
+ out << "float" << width;
+ } else if (vec->type()->Is<sem::I32>() && width >= 1 && width <= 4) {
+ out << "int" << width;
+ } else if (vec->type()->Is<sem::U32>() && width >= 1 && width <= 4) {
+ out << "uint" << width;
+ } else if (vec->type()->Is<sem::Bool>() && width >= 1 && width <= 4) {
+ out << "bool" << width;
} else {
out << "vector<";
if (!EmitType(out, vec->type(), storage_class, access, "")) {
return false;
}
- out << ", " << size << ">";
+ out << ", " << width << ">";
}
} else if (auto* atomic = type->As<sem::Atomic>()) {
if (!EmitType(out, atomic->Type(), storage_class, access, name)) {