mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-09 08:03:31 +00:00
CloneContext: Move hot code out of template members
This is causing code bloat. Move common code out to a single method that's implemented in the .cc file. Saves about 10k from the all-features-enabled Release build of tint for x64. Bug: tint:1226 Change-Id: I80b76e69521c3cc890c74b4bc73a68f1c9bdd3df Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/66446 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: David Neto <dneto@google.com> Reviewed-by: Antonio Maiorano <amaiorano@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
d1ee47a1cd
commit
a095b26d17
@ -69,6 +69,42 @@ ast::FunctionList CloneContext::Clone(const ast::FunctionList& v) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tint::Cloneable* CloneContext::CloneCloneable(Cloneable* object) {
|
||||||
|
// If the input is nullptr, there's nothing to clone - just return nullptr.
|
||||||
|
if (object == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Was Replace() called for this object?
|
||||||
|
auto it = replacements_.find(object);
|
||||||
|
if (it != replacements_.end()) {
|
||||||
|
return it->second();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to clone using the registered replacer functions.
|
||||||
|
auto& typeinfo = object->TypeInfo();
|
||||||
|
for (auto& transform : transforms_) {
|
||||||
|
if (typeinfo.Is(*transform.typeinfo)) {
|
||||||
|
if (auto* transformed = transform.function(object)) {
|
||||||
|
return transformed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No transform for this type, or the transform returned nullptr.
|
||||||
|
// Clone with T::Clone().
|
||||||
|
return object->Clone(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CloneContext::CheckedCastFailure(Cloneable* got,
|
||||||
|
const TypeInfo& expected) {
|
||||||
|
TINT_ICE(Clone, Diagnostics())
|
||||||
|
<< "Cloned object was not of the expected type\n"
|
||||||
|
<< "got: " << got->TypeInfo().name << "\n"
|
||||||
|
<< "expected: " << expected.name;
|
||||||
|
}
|
||||||
|
|
||||||
diag::List& CloneContext::Diagnostics() const {
|
diag::List& CloneContext::Diagnostics() const {
|
||||||
return dst->Diagnostics();
|
return dst->Diagnostics();
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "src/castable.h"
|
#include "src/castable.h"
|
||||||
#include "src/debug.h"
|
#include "src/debug.h"
|
||||||
|
#include "src/program_id.h"
|
||||||
#include "src/symbol.h"
|
#include "src/symbol.h"
|
||||||
#include "src/traits.h"
|
#include "src/traits.h"
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ class Node;
|
|||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
|
||||||
ProgramID ProgramIDOf(const Program*);
|
ProgramID ProgramIDOf(const Program*);
|
||||||
ProgramID ProgramIDOf(const ast::Node*);
|
ProgramID ProgramIDOf(const ProgramBuilder*);
|
||||||
|
|
||||||
/// Cloneable is the base class for all objects that can be cloned
|
/// Cloneable is the base class for all objects that can be cloned
|
||||||
class Cloneable : public Castable<Cloneable> {
|
class Cloneable : public Castable<Cloneable> {
|
||||||
@ -93,50 +94,19 @@ class CloneContext {
|
|||||||
/// If the CloneContext is cloning from a Program to a ProgramBuilder, then
|
/// If the CloneContext is cloning from a Program to a ProgramBuilder, then
|
||||||
/// the Node or sem::Type `a` must be owned by the Program #src.
|
/// the Node or sem::Type `a` must be owned by the Program #src.
|
||||||
///
|
///
|
||||||
/// @param a the `Node` or `sem::Type` to clone
|
/// @param object the type deriving from Cloneable to clone
|
||||||
/// @return the cloned node
|
/// @return the cloned node
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T* Clone(T* a) {
|
T* Clone(T* object) {
|
||||||
// If the input is nullptr, there's nothing to clone - just return nullptr.
|
|
||||||
if (a == nullptr) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (src) {
|
if (src) {
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, a);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, object);
|
||||||
}
|
}
|
||||||
|
if (auto* cloned = CloneCloneable(object)) {
|
||||||
// Was Replace() called for this object?
|
auto* out = CheckedCast<T>(cloned);
|
||||||
auto it = replacements_.find(a);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, out);
|
||||||
if (it != replacements_.end()) {
|
return out;
|
||||||
auto* replacement = it->second();
|
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, replacement);
|
|
||||||
return CheckedCast<T>(replacement);
|
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
Cloneable* cloned = nullptr;
|
|
||||||
|
|
||||||
// Attempt to clone using the registered replacer functions.
|
|
||||||
auto& typeinfo = a->TypeInfo();
|
|
||||||
for (auto& transform : transforms_) {
|
|
||||||
if (!typeinfo.Is(*transform.typeinfo)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cloned = transform.function(a);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cloned) {
|
|
||||||
// No transform for this type, or the transform returned nullptr.
|
|
||||||
// Clone with T::Clone().
|
|
||||||
cloned = a->Clone(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* out = CheckedCast<T>(cloned);
|
|
||||||
|
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, out);
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clones the Node or sem::Type `a` into the ProgramBuilder #dst if `a` is
|
/// Clones the Node or sem::Type `a` into the ProgramBuilder #dst if `a` is
|
||||||
@ -148,7 +118,7 @@ class CloneContext {
|
|||||||
/// If the CloneContext is cloning from a Program to a ProgramBuilder, then
|
/// If the CloneContext is cloning from a Program to a ProgramBuilder, then
|
||||||
/// the Node or sem::Type `a` must be owned by the Program #src.
|
/// the Node or sem::Type `a` must be owned by the Program #src.
|
||||||
///
|
///
|
||||||
/// @param a the `Node` or `sem::Type` to clone
|
/// @param a the type deriving from Cloneable to clone
|
||||||
/// @return the cloned node
|
/// @return the cloned node
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T* CloneWithoutTransform(T* a) {
|
T* CloneWithoutTransform(T* a) {
|
||||||
@ -519,20 +489,25 @@ class CloneContext {
|
|||||||
if (TO* cast = obj->template As<TO>()) {
|
if (TO* cast = obj->template As<TO>()) {
|
||||||
return cast;
|
return cast;
|
||||||
}
|
}
|
||||||
TINT_ICE(Clone, Diagnostics())
|
CheckedCastFailure(obj, TypeInfo::Of<TO>());
|
||||||
<< "Cloned object was not of the expected type\n"
|
|
||||||
<< "got: " << obj->TypeInfo().name << "\n"
|
|
||||||
<< "expected: " << TypeInfo::Of<TO>().name;
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clones a Cloneable object, using any replacements or transforms that have
|
||||||
|
/// been configured.
|
||||||
|
tint::Cloneable* CloneCloneable(Cloneable* object);
|
||||||
|
|
||||||
|
/// Adds an error diagnostic to Diagnostics() that the cloned object was not
|
||||||
|
/// of the expected type.
|
||||||
|
void CheckedCastFailure(Cloneable* got, const TypeInfo& expected);
|
||||||
|
|
||||||
/// @returns the diagnostic list of #dst
|
/// @returns the diagnostic list of #dst
|
||||||
diag::List& Diagnostics() const;
|
diag::List& Diagnostics() const;
|
||||||
|
|
||||||
/// A vector of Cloneable*
|
/// A vector of Cloneable*
|
||||||
using CloneableList = std::vector<Cloneable*>;
|
using CloneableList = std::vector<Cloneable*>;
|
||||||
|
|
||||||
// Transformations to be applied to a list (vector)
|
/// Transformations to be applied to a list (vector)
|
||||||
struct ListTransforms {
|
struct ListTransforms {
|
||||||
/// Constructor
|
/// Constructor
|
||||||
ListTransforms();
|
ListTransforms();
|
||||||
|
@ -844,7 +844,7 @@ TEST_F(CloneContextTest, ProgramIDs_Clone_ObjectNotOwnedBySrc) {
|
|||||||
Allocator allocator;
|
Allocator allocator;
|
||||||
ctx.Clone(allocator.Create<ProgramNode>(ProgramID::New(), dst.ID()));
|
ctx.Clone(allocator.Create<ProgramNode>(ProgramID::New(), dst.ID()));
|
||||||
},
|
},
|
||||||
R"(internal compiler error: TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, a))");
|
R"(internal compiler error: TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, object))");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CloneContextTest, ProgramIDs_Clone_ObjectNotOwnedByDst) {
|
TEST_F(CloneContextTest, ProgramIDs_Clone_ObjectNotOwnedByDst) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user