IntrinsicTable: De-duplicate returned Intrinsics

Much like sem::Type, it greatly simplifies downstream logic if we can compare sem::Intrinsic pointers to know if they refer to the same intrinsic overload.

Change-Id: If236247cd3979bbde821d9294f304ab85ba4938e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/58061
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
Ben Clayton
2021-07-15 20:34:21 +00:00
committed by Ben Clayton
parent e54e26d7e8
commit b478f97975
18 changed files with 410 additions and 15 deletions

View File

@@ -26,6 +26,8 @@ CallTarget::CallTarget(sem::Type* return_type, const ParameterList& parameters)
TINT_ASSERT(Semantic, return_type);
}
CallTarget::CallTarget(const CallTarget&) = default;
CallTarget::~CallTarget() = default;
int IndexOf(const ParameterList& parameters, ParameterUsage usage) {

View File

@@ -20,6 +20,7 @@
#include "src/sem/node.h"
#include "src/sem/parameter_usage.h"
#include "src/sem/sampler_type.h"
#include "src/utils/hash.h"
namespace tint {
@@ -37,11 +38,16 @@ struct Parameter {
std::ostream& operator<<(std::ostream& out, Parameter parameter);
/// Comparison operator for Parameters
/// Equality operator for Parameters
static inline bool operator==(const Parameter& a, const Parameter& b) {
return a.type == b.type && a.usage == b.usage;
}
/// Inequality operator for Parameters
static inline bool operator!=(const Parameter& a, const Parameter& b) {
return !(a == b);
}
/// ParameterList is a list of Parameter
using ParameterList = std::vector<Parameter>;
@@ -59,6 +65,9 @@ class CallTarget : public Castable<CallTarget, Node> {
/// @param parameters the parameters for the call target
CallTarget(sem::Type* return_type, const ParameterList& parameters);
/// Copy constructor
CallTarget(const CallTarget&);
/// @return the return type of the call target
sem::Type* ReturnType() const { return return_type_; }
@@ -76,4 +85,19 @@ class CallTarget : public Castable<CallTarget, Node> {
} // namespace sem
} // namespace tint
namespace std {
/// Custom std::hash specialization for tint::sem::Parameter
template <>
class hash<tint::sem::Parameter> {
public:
/// @param p the tint::sem::Parameter to create a hash for
/// @return the hash value
inline std::size_t operator()(const tint::sem::Parameter& p) const {
return tint::utils::Hash(p.type, p.usage);
}
};
} // namespace std
#endif // SRC_SEM_CALL_TARGET_H_

View File

@@ -111,6 +111,8 @@ Intrinsic::Intrinsic(IntrinsicType type,
supported_stages_(supported_stages),
is_deprecated_(is_deprecated) {}
Intrinsic::Intrinsic(const Intrinsic&) = default;
Intrinsic::~Intrinsic() = default;
bool Intrinsic::IsCoarseDerivative() const {
@@ -153,5 +155,25 @@ bool Intrinsic::IsAtomic() const {
return IsAtomicIntrinsic(type_);
}
bool operator==(const Intrinsic& a, const Intrinsic& b) {
static_assert(sizeof(Intrinsic(IntrinsicType::kNone, nullptr, ParameterList{},
PipelineStageSet{}, false)) > 0,
"don't forget to update the comparison below if you change the "
"constructor of Intrinsic!");
if (a.Type() != b.Type() || a.SupportedStages() != b.SupportedStages() ||
a.ReturnType() != b.ReturnType() ||
a.IsDeprecated() != b.IsDeprecated() ||
a.Parameters().size() != b.Parameters().size()) {
return false;
}
for (size_t i = 0; i < a.Parameters().size(); i++) {
if (a.Parameters()[i] != b.Parameters()[i]) {
return false;
}
}
return true;
}
} // namespace sem
} // namespace tint

View File

@@ -20,6 +20,7 @@
#include "src/sem/call_target.h"
#include "src/sem/intrinsic_type.h"
#include "src/sem/pipeline_stage_set.h"
#include "src/utils/hash.h"
namespace tint {
namespace sem {
@@ -91,6 +92,9 @@ class Intrinsic : public Castable<Intrinsic, CallTarget> {
PipelineStageSet supported_stages,
bool is_deprecated);
/// Copy constructor
Intrinsic(const Intrinsic&);
/// Destructor
~Intrinsic() override;
@@ -147,7 +151,31 @@ class Intrinsic : public Castable<Intrinsic, CallTarget> {
/// matches the name in the WGSL spec.
std::ostream& operator<<(std::ostream& out, IntrinsicType i);
/// Equality operator for Intrinsics
bool operator==(const Intrinsic& a, const Intrinsic& b);
/// Inequality operator for Intrinsics
static inline bool operator!=(const Intrinsic& a, const Intrinsic& b) {
return !(a == b);
}
} // namespace sem
} // namespace tint
namespace std {
/// Custom std::hash specialization for tint::sem::Intrinsic
template <>
class hash<tint::sem::Intrinsic> {
public:
/// @param i the Intrinsic to create a hash for
/// @return the hash value
inline std::size_t operator()(const tint::sem::Intrinsic& i) const {
return tint::utils::Hash(i.Type(), i.SupportedStages(), i.ReturnType(),
i.Parameters(), i.IsDeprecated());
}
};
} // namespace std
#endif // SRC_SEM_INTRINSIC_H_