[tint][core] Don't create throw-away StructMembers
When constructing a builtin-struct check whether the builtin has been created already before building a new struct (just to drop it).
Bug: tint:2129
Change-Id: Ic76718dc4efd41167e832767225f5280f491c5d9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/171805
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/core/type/builtin_structs.cc b/src/tint/lang/core/type/builtin_structs.cc
index 8f319d5..31af873 100644
--- a/src/tint/lang/core/type/builtin_structs.cc
+++ b/src/tint/lang/core/type/builtin_structs.cc
@@ -70,7 +70,11 @@
Struct* CreateModfResult(Manager& types, SymbolTable& symbols, const Type* ty) {
auto build = [&](core::BuiltinType name, const Type* t) {
- return types.Struct(symbols.Register(tint::ToString(name)),
+ auto symbol = symbols.Register(tint::ToString(name));
+ if (auto* existing = types.Find<type::Struct>(symbol)) {
+ return existing;
+ }
+ return types.Struct(symbol,
{{symbols.Register("fract"), t}, {symbols.Register("whole"), t}});
};
return Switch(
@@ -127,9 +131,12 @@
Struct* CreateFrexpResult(Manager& types, SymbolTable& symbols, const Type* ty) {
auto build = [&](core::BuiltinType name, const Type* fract_ty, const Type* exp_ty) {
+ auto symbol = symbols.Register(tint::ToString(name));
+ if (auto* existing = types.Find<type::Struct>(symbol)) {
+ return existing;
+ }
return types.Struct(
- symbols.Register(tint::ToString(name)),
- {{symbols.Register("fract"), fract_ty}, {symbols.Register("exp"), exp_ty}});
+ symbol, {{symbols.Register("fract"), fract_ty}, {symbols.Register("exp"), exp_ty}});
};
return Switch(
ty, //
@@ -172,11 +179,14 @@
Struct* CreateAtomicCompareExchangeResult(Manager& types, SymbolTable& symbols, const Type* ty) {
auto build = [&](core::BuiltinType name) {
- return types.Struct(symbols.Register(tint::ToString(name)),
- {
- {symbols.Register("old_value"), ty},
- {symbols.Register("exchanged"), types.bool_()},
- });
+ auto symbol = symbols.Register(tint::ToString(name));
+ if (auto* existing = types.Find<type::Struct>(symbol)) {
+ return existing;
+ }
+ return types.Struct(symbol, {
+ {symbols.Register("old_value"), ty},
+ {symbols.Register("exchanged"), types.bool_()},
+ });
};
return Switch(
ty, //
diff --git a/src/tint/lang/core/type/manager.cc b/src/tint/lang/core/type/manager.cc
index ff70390..f158770 100644
--- a/src/tint/lang/core/type/manager.cc
+++ b/src/tint/lang/core/type/manager.cc
@@ -42,6 +42,7 @@
#include "src/tint/lang/core/type/u32.h"
#include "src/tint/lang/core/type/vector.h"
#include "src/tint/lang/core/type/void.h"
+#include "src/tint/utils/macros/compiler.h"
namespace tint::core::type {
@@ -198,6 +199,11 @@
}
core::type::Struct* Manager::Struct(Symbol name, VectorRef<const StructMember*> members) {
+ if (auto* existing = Find<type::Struct>(name); TINT_UNLIKELY(existing)) {
+ TINT_ICE() << "attempting to construct two structs named " << name.NameView();
+ return existing;
+ }
+
uint32_t max_align = 0u;
for (const auto& m : members) {
max_align = std::max(max_align, m->Align());
@@ -208,6 +214,11 @@
}
core::type::Struct* Manager::Struct(Symbol name, VectorRef<StructMemberDesc> md) {
+ if (auto* existing = Find<type::Struct>(name); TINT_UNLIKELY(existing)) {
+ TINT_ICE() << "attempting to construct two structs named " << name.NameView();
+ return existing;
+ }
+
tint::Vector<const StructMember*, 4> members;
uint32_t current_size = 0u;
uint32_t max_align = 0u;
diff --git a/src/tint/lang/core/type/manager.h b/src/tint/lang/core/type/manager.h
index 6c12a6c..f02290b 100644
--- a/src/tint/lang/core/type/manager.h
+++ b/src/tint/lang/core/type/manager.h
@@ -475,18 +475,21 @@
/// Create a new structure declaration.
/// @param name the name of the structure
/// @param members the list of structure members
+ /// @note a structure must not already exist with the same name
/// @returns the structure type
core::type::Struct* Struct(Symbol name, VectorRef<const StructMember*> members);
/// Create a new structure declaration.
/// @param name the name of the structure
/// @param members the list of structure member descriptors
+ /// @note a structure must not already exist with the same name
/// @returns the structure type
core::type::Struct* Struct(Symbol name, VectorRef<StructMemberDesc> members);
/// Create a new structure declaration.
/// @param name the name of the structure
/// @param members the list of structure member descriptors
+ /// @note a structure must not already exist with the same name
/// @returns the structure type
core::type::Struct* Struct(Symbol name, std::initializer_list<StructMemberDesc> members) {
return Struct(name, tint::Vector<StructMemberDesc, 4>(members));
diff --git a/src/tint/lang/core/type/struct.cc b/src/tint/lang/core/type/struct.cc
index c916e4b..ff08e35 100644
--- a/src/tint/lang/core/type/struct.cc
+++ b/src/tint/lang/core/type/struct.cc
@@ -43,8 +43,8 @@
namespace tint::core::type {
namespace {
-core::type::Flags FlagsFrom(VectorRef<const StructMember*> members) {
- core::type::Flags flags{
+Flags FlagsFrom(VectorRef<const StructMember*> members) {
+ Flags flags{
Flag::kConstructable,
Flag::kCreationFixedFootprint,
Flag::kFixedFootprint,
@@ -65,6 +65,14 @@
} // namespace
+Struct::Struct(Symbol name)
+ : Base(Hash(tint::TypeInfo::Of<Struct>().full_hashcode, name), type::Flags{}),
+ name_(name),
+ members_{},
+ align_(0),
+ size_(0),
+ size_no_padding_(0) {}
+
Struct::Struct(Symbol name,
VectorRef<const StructMember*> members,
uint32_t align,
diff --git a/src/tint/lang/core/type/struct.h b/src/tint/lang/core/type/struct.h
index 228c8b8..eec7dab 100644
--- a/src/tint/lang/core/type/struct.h
+++ b/src/tint/lang/core/type/struct.h
@@ -72,6 +72,12 @@
class Struct : public Castable<Struct, Type> {
public:
/// Constructor
+ /// Note: this constructs an empty structure, which should only be used find a struct with the
+ /// same name in a type::Manager.
+ /// @param name the name of the structure
+ explicit Struct(Symbol name);
+
+ /// Constructor
/// @param name the name of the structure
/// @param members the structure members
/// @param align the byte alignment of the structure