tint: Implement abstract-numeric overload resolution
Support overload resolution of abstract-numeric argument types, allowing them to implicitly convert down to concrete parameter types (and in the near future, abstract parameter types). Major kudos to cwallez for the suggested algorithm which is a minor adaption of what we had already. Bug: tint:1504 Change-Id: I85fa8e70ab0b6aa643caec4c51433f15784af55f Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/90522 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: David Neto <dneto@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
2e681052b3
commit
23696b1ba3
|
@ -384,6 +384,9 @@ libtint_source_set("libtint_core_all_src") {
|
|||
"resolver/validator.cc",
|
||||
"resolver/validator.h",
|
||||
"scope_stack.h",
|
||||
"sem/abstract_float.h",
|
||||
"sem/abstract_int.h",
|
||||
"sem/abstract_numeric.h",
|
||||
"sem/array.h",
|
||||
"sem/atomic.h",
|
||||
"sem/behavior.h",
|
||||
|
|
|
@ -199,14 +199,30 @@ match workgroup_or_storage: workgroup | storage
|
|||
// the same argument type. //
|
||||
// //
|
||||
// //
|
||||
// Matching algorithm: //
|
||||
// ------------------- //
|
||||
// Matching algorithm for a single overload: //
|
||||
// ----------------------------------------- //
|
||||
// //
|
||||
// The goal of matching is to compare a function call's arguments in the //
|
||||
// program source against a possibly-templated overload declaration, and //
|
||||
// determine if the call satisfies the form and type constraints of the //
|
||||
// overload. Currently it is impossible for a call to match more than one //
|
||||
// overload definition. In the event that more than one overload matches, an //
|
||||
// ICE will be raised. Note that Tint may need to support multiple-overload //
|
||||
// resolution in the future, depending on future overload definitions. //
|
||||
// //
|
||||
// Prior to matching an overload, all template types are undefined. //
|
||||
// //
|
||||
// Template types become defined on the first attempt to match an argument to //
|
||||
// that template type. Once template types are defined, they remain that type //
|
||||
// for the rest of the overload evaluation. //
|
||||
// Template types are first defined with the type of the leftmost argument //
|
||||
// that matches against that template type name. Subsequent arguments that //
|
||||
// attempt to match against the template type name will either reject the //
|
||||
// overload or refine the template, in one of 3 ways: //
|
||||
// (a) Fail to match, causing the overload to be immediately rejected. //
|
||||
// (b) Match the existing template type, either exactly or via implicit //
|
||||
// conversion, and overload resolution continues. //
|
||||
// (c) Match via implicit conversion of the currently defined template type //
|
||||
// to the argument type. In this situation, the template type is refined //
|
||||
// with the more constrained argument type, and overload resolution //
|
||||
// continues. //
|
||||
// //
|
||||
// To better understand, let's consider the following hypothetical overload //
|
||||
// declaration: //
|
||||
|
@ -228,17 +244,24 @@ match workgroup_or_storage: workgroup | storage
|
|||
// type of the first argument. //
|
||||
// There's no verification that the T type is a scalar at this stage. //
|
||||
// (2) The second parameter is then compared against the second argument. //
|
||||
// As the template type T is now defined the argument type is compared //
|
||||
// against the value of the defined type of T. If the types match, then //
|
||||
// the overload is still a candidate for matching, otherwise the //
|
||||
// overload is no longer considered. //
|
||||
// As the template type T is now defined the argument type is compared //
|
||||
// against the value of the defined type of T. Depending on the //
|
||||
// comparison of the argument type to the template type, either the //
|
||||
// actions of (a), (b) or (c) from above will occur. //
|
||||
// (3) If all the parameters matched, constraints on the template types //
|
||||
// need to be checked next. If the defined type does not match the //
|
||||
// 'match' constraint, then the overload is no longer considered. //
|
||||
// //
|
||||
// The algorithm for matching template numbers is almost identical to //
|
||||
// matching template types, except of course, they match against integer //
|
||||
// numbers or enumerators instead of types. //
|
||||
// This algorithm is less general than the overload resolution described in //
|
||||
// the WGSL spec. But it makes the same decisions because the overloads //
|
||||
// defined by WGSL are monotonic in the sense that once a template parameter //
|
||||
// has been refined, there is never a need to backtrack and un-refine it to //
|
||||
// match a later argument. //
|
||||
// //
|
||||
// The algorithm for matching template numbers is similar to matching //
|
||||
// template types, except numbers need to exactly match across all uses - //
|
||||
// there is no implicit conversion. Template numbers may match integer //
|
||||
// numbers or enumerators. //
|
||||
// //
|
||||
// //
|
||||
// * More examples: //
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
#include <utility>
|
||||
|
||||
#include "src/tint/program_builder.h"
|
||||
#include "src/tint/sem/abstract_float.h"
|
||||
#include "src/tint/sem/abstract_int.h"
|
||||
#include "src/tint/sem/abstract_numeric.h"
|
||||
#include "src/tint/sem/atomic.h"
|
||||
#include "src/tint/sem/depth_multisampled_texture.h"
|
||||
#include "src/tint/sem/depth_texture.h"
|
||||
|
@ -104,12 +107,33 @@ const Number Number::invalid{Number::kInvalid};
|
|||
/// Used by the MatchState.
|
||||
class TemplateState {
|
||||
public:
|
||||
/// If the type with index `idx` is undefined, then it is defined with type `ty` and Type()
|
||||
/// returns true. If the template type is defined, then `Type()` returns true iff it is equal to
|
||||
/// `ty`.
|
||||
bool Type(size_t idx, const sem::Type* ty) {
|
||||
/// If the template type with index `idx` is undefined, then it is defined with the `ty` and
|
||||
/// Type() returns `ty`.
|
||||
/// If the template type is defined, and `ty` can be converted to the template type then the
|
||||
/// template type is returned.
|
||||
/// If the template type is defined, and the template type can be converted to `ty`, then the
|
||||
/// template type is replaced with `ty`, and `ty` is returned.
|
||||
/// If none of the above applies, then `ty` is a type mismatch for the template type, and
|
||||
/// nullptr is returned.
|
||||
const sem::Type* Type(size_t idx, const sem::Type* ty) {
|
||||
auto res = types_.emplace(idx, ty);
|
||||
return res.second || res.first->second == ty;
|
||||
if (res.second) {
|
||||
return ty;
|
||||
}
|
||||
auto* existing = res.first->second;
|
||||
if (existing == ty) {
|
||||
return ty;
|
||||
}
|
||||
if (sem::Type::ConversionRank(ty, existing) != sem::Type::kNoConversion) {
|
||||
// ty can be converted to the existing type. Keep the existing type.
|
||||
return existing;
|
||||
}
|
||||
if (sem::Type::ConversionRank(existing, ty) != sem::Type::kNoConversion) {
|
||||
// template type can be converted to ty. Constrain the existing type.
|
||||
types_[idx] = ty;
|
||||
return ty;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// If the number with index `idx` is undefined, then it is defined with the number `number` and
|
||||
|
@ -126,6 +150,9 @@ class TemplateState {
|
|||
return (it != types_.end()) ? it->second : nullptr;
|
||||
}
|
||||
|
||||
/// SetType replaces the template type with index `idx` with type `ty`.
|
||||
void SetType(size_t idx, const sem::Type* ty) { types_[idx] = ty; }
|
||||
|
||||
/// Type returns the number type with index `idx`.
|
||||
Number Num(size_t idx) const {
|
||||
auto it = numbers_.find(idx);
|
||||
|
@ -197,7 +224,7 @@ class TypeMatcher {
|
|||
|
||||
/// Checks whether the given type matches the matcher rules, and returns the
|
||||
/// expected, canonicalized type on success.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
virtual const sem::Type* Match(MatchState& state, const sem::Type* type) const = 0;
|
||||
|
@ -226,8 +253,8 @@ class NumberMatcher {
|
|||
};
|
||||
|
||||
/// TemplateTypeMatcher is a Matcher for a template type.
|
||||
/// The TemplateTypeMatcher will initially match against any type (so long as it is
|
||||
/// consistent for all uses in the overload)
|
||||
/// The TemplateTypeMatcher will initially match against any type, and then will only be further
|
||||
/// constrained based on the conversion rules defined at https://www.w3.org/TR/WGSL/#conversion-rank
|
||||
class TemplateTypeMatcher : public TypeMatcher {
|
||||
public:
|
||||
/// Constructor
|
||||
|
@ -237,7 +264,10 @@ class TemplateTypeMatcher : public TypeMatcher {
|
|||
if (type->Is<Any>()) {
|
||||
return state.templates.Type(index_);
|
||||
}
|
||||
return state.templates.Type(index_, type) ? type : nullptr;
|
||||
if (auto* templates = state.templates.Type(index_, type)) {
|
||||
return templates;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string String(MatchState& state) const override;
|
||||
|
@ -305,7 +335,7 @@ const sem::F32* build_f32(MatchState& state) {
|
|||
}
|
||||
|
||||
bool match_f32(const sem::Type* ty) {
|
||||
return ty->IsAnyOf<Any, sem::F32>();
|
||||
return ty->IsAnyOf<Any, sem::F32, sem::AbstractNumeric>();
|
||||
}
|
||||
|
||||
const sem::I32* build_i32(MatchState& state) {
|
||||
|
@ -313,7 +343,7 @@ const sem::I32* build_i32(MatchState& state) {
|
|||
}
|
||||
|
||||
bool match_i32(const sem::Type* ty) {
|
||||
return ty->IsAnyOf<Any, sem::I32>();
|
||||
return ty->IsAnyOf<Any, sem::I32, sem::AbstractInt>();
|
||||
}
|
||||
|
||||
const sem::U32* build_u32(MatchState& state) {
|
||||
|
@ -321,7 +351,7 @@ const sem::U32* build_u32(MatchState& state) {
|
|||
}
|
||||
|
||||
bool match_u32(const sem::Type* ty) {
|
||||
return ty->IsAnyOf<Any, sem::U32>();
|
||||
return ty->IsAnyOf<Any, sem::U32, sem::AbstractInt>();
|
||||
}
|
||||
|
||||
bool match_vec(const sem::Type* ty, Number& N, const sem::Type*& T) {
|
||||
|
@ -1247,6 +1277,11 @@ IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
|||
case 1:
|
||||
break;
|
||||
default:
|
||||
// Note: Currently the intrinsic table does not contain any overloads which may result
|
||||
// in ambiguities, so here we call ErrMultipleOverloadsMatched() which will produce and
|
||||
// ICE. If we end up in the situation where this is unavoidable, we'll need to perform
|
||||
// further overload resolution as described in
|
||||
// https://www.w3.org/TR/WGSL/#overload-resolution-section.
|
||||
ErrMultipleOverloadsMatched(num_matched, intrinsic_name, args, templates, candidates);
|
||||
}
|
||||
|
||||
|
@ -1290,36 +1325,51 @@ Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
|||
std::min(num_parameters, num_arguments));
|
||||
}
|
||||
|
||||
std::vector<IntrinsicPrototype::Parameter> parameters;
|
||||
|
||||
// Invoke the matchers for each parameter <-> argument pair.
|
||||
// If any arguments cannot be matched, then `score` will be increased.
|
||||
// If the overload has any template types or numbers then these will be set based on the
|
||||
// argument types. Template types may be refined by constraining with later argument types. For
|
||||
// example calling `F<T>(T, T)` with the argument types (abstract-int, i32) will first set T to
|
||||
// abstract-int when matching the first argument, and then constrained down to i32 when matching
|
||||
// the second argument.
|
||||
// Note that inferred template types are not tested against their matchers at this point.
|
||||
auto num_params = std::min(num_parameters, num_arguments);
|
||||
for (size_t p = 0; p < num_params; p++) {
|
||||
auto& parameter = overload->parameters[p];
|
||||
auto* indices = parameter.matcher_indices;
|
||||
auto* type = Match(templates, overload, indices).Type(args[p]->UnwrapRef());
|
||||
if (type) {
|
||||
parameters.emplace_back(IntrinsicPrototype::Parameter{type, parameter.usage});
|
||||
} else {
|
||||
if (!Match(templates, overload, indices).Type(args[p]->UnwrapRef())) {
|
||||
score += kMismatchedParamTypePenalty;
|
||||
}
|
||||
}
|
||||
|
||||
if (score == 0) {
|
||||
// Check all constrained template types matched
|
||||
// Check all constrained template types matched their constraint matchers.
|
||||
// If the template type *does not* match any of the types in the constraint matcher, then
|
||||
// `score` is incremented. If the template type *does* match a type, then the template type
|
||||
// is replaced with the first matching type. The order of types in the template matcher is
|
||||
// important here, which can be controlled with the [[precedence(N)]] decorations on the
|
||||
// types in intrinsics.def.
|
||||
for (size_t ot = 0; ot < overload->num_template_types; ot++) {
|
||||
auto* matcher_index = &overload->template_types[ot].matcher_index;
|
||||
if (*matcher_index != kNoMatcher) {
|
||||
auto* template_type = templates.Type(ot);
|
||||
if (!template_type ||
|
||||
!Match(templates, overload, matcher_index).Type(template_type)) {
|
||||
score += kMismatchedTemplateTypePenalty;
|
||||
if (auto* template_type = templates.Type(ot)) {
|
||||
if (auto* ty = Match(templates, overload, matcher_index).Type(template_type)) {
|
||||
// Template type matched one of the types in the template type's matcher.
|
||||
// Replace the template type with this type.
|
||||
templates.SetType(ot, ty);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
score += kMismatchedTemplateTypePenalty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (score == 0) {
|
||||
// Check all constrained open numbers matched
|
||||
// Check all constrained open numbers matched.
|
||||
// Unlike template types, numbers are not constrained, so we're just checking that the
|
||||
// inferred number matches the constraints on the overload. Increments `score` if the
|
||||
// template numbers do not match their constraint matchers.
|
||||
for (size_t on = 0; on < overload->num_template_numbers; on++) {
|
||||
auto* matcher_index = &overload->template_numbers[on].matcher_index;
|
||||
if (*matcher_index != kNoMatcher) {
|
||||
|
@ -1332,6 +1382,18 @@ Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
|||
}
|
||||
}
|
||||
|
||||
// Now that all the template types have been finalized, we can construct the parameters.
|
||||
std::vector<IntrinsicPrototype::Parameter> parameters;
|
||||
if (score == 0) {
|
||||
parameters.reserve(num_params);
|
||||
for (size_t p = 0; p < num_params; p++) {
|
||||
auto& parameter = overload->parameters[p];
|
||||
auto* indices = parameter.matcher_indices;
|
||||
auto* ty = Match(templates, overload, indices).Type(args[p]->UnwrapRef());
|
||||
parameters.emplace_back(IntrinsicPrototype::Parameter{ty, parameter.usage});
|
||||
}
|
||||
}
|
||||
|
||||
return Candidate{overload, templates, parameters, score};
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
class Bool : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -56,7 +56,7 @@ std::string Bool::String(MatchState&) const {
|
|||
class I32 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -83,7 +83,7 @@ std::string I32::String(MatchState&) const {
|
|||
class U32 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -110,7 +110,7 @@ std::string U32::String(MatchState&) const {
|
|||
class F32 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -137,7 +137,7 @@ std::string F32::String(MatchState&) const {
|
|||
class Vec2 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -170,7 +170,7 @@ std::string Vec2::String(MatchState& state) const {
|
|||
class Vec3 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -203,7 +203,7 @@ std::string Vec3::String(MatchState& state) const {
|
|||
class Vec4 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -236,7 +236,7 @@ std::string Vec4::String(MatchState& state) const {
|
|||
class Mat2X2 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -269,7 +269,7 @@ std::string Mat2X2::String(MatchState& state) const {
|
|||
class Mat2X3 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -302,7 +302,7 @@ std::string Mat2X3::String(MatchState& state) const {
|
|||
class Mat2X4 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -335,7 +335,7 @@ std::string Mat2X4::String(MatchState& state) const {
|
|||
class Mat3X2 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -368,7 +368,7 @@ std::string Mat3X2::String(MatchState& state) const {
|
|||
class Mat3X3 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -401,7 +401,7 @@ std::string Mat3X3::String(MatchState& state) const {
|
|||
class Mat3X4 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -434,7 +434,7 @@ std::string Mat3X4::String(MatchState& state) const {
|
|||
class Mat4X2 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -467,7 +467,7 @@ std::string Mat4X2::String(MatchState& state) const {
|
|||
class Mat4X3 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -500,7 +500,7 @@ std::string Mat4X3::String(MatchState& state) const {
|
|||
class Mat4X4 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -533,7 +533,7 @@ std::string Mat4X4::String(MatchState& state) const {
|
|||
class Vec : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -574,7 +574,7 @@ std::string Vec::String(MatchState& state) const {
|
|||
class Mat : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -621,7 +621,7 @@ std::string Mat::String(MatchState& state) const {
|
|||
class Ptr : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -666,7 +666,7 @@ std::string Ptr::String(MatchState& state) const {
|
|||
class Atomic : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -699,7 +699,7 @@ std::string Atomic::String(MatchState& state) const {
|
|||
class Array : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -732,7 +732,7 @@ std::string Array::String(MatchState& state) const {
|
|||
class Sampler : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -759,7 +759,7 @@ std::string Sampler::String(MatchState&) const {
|
|||
class SamplerComparison : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -786,7 +786,7 @@ std::string SamplerComparison::String(MatchState&) const {
|
|||
class Texture1D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -819,7 +819,7 @@ std::string Texture1D::String(MatchState& state) const {
|
|||
class Texture2D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -852,7 +852,7 @@ std::string Texture2D::String(MatchState& state) const {
|
|||
class Texture2DArray : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -885,7 +885,7 @@ std::string Texture2DArray::String(MatchState& state) const {
|
|||
class Texture3D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -918,7 +918,7 @@ std::string Texture3D::String(MatchState& state) const {
|
|||
class TextureCube : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -951,7 +951,7 @@ std::string TextureCube::String(MatchState& state) const {
|
|||
class TextureCubeArray : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -984,7 +984,7 @@ std::string TextureCubeArray::String(MatchState& state) const {
|
|||
class TextureMultisampled2D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1017,7 +1017,7 @@ std::string TextureMultisampled2D::String(MatchState& state) const {
|
|||
class TextureDepth2D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1044,7 +1044,7 @@ std::string TextureDepth2D::String(MatchState&) const {
|
|||
class TextureDepth2DArray : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1071,7 +1071,7 @@ std::string TextureDepth2DArray::String(MatchState&) const {
|
|||
class TextureDepthCube : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1098,7 +1098,7 @@ std::string TextureDepthCube::String(MatchState&) const {
|
|||
class TextureDepthCubeArray : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1125,7 +1125,7 @@ std::string TextureDepthCubeArray::String(MatchState&) const {
|
|||
class TextureDepthMultisampled2D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1152,7 +1152,7 @@ std::string TextureDepthMultisampled2D::String(MatchState&) const {
|
|||
class TextureStorage1D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1191,7 +1191,7 @@ std::string TextureStorage1D::String(MatchState& state) const {
|
|||
class TextureStorage2D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1230,7 +1230,7 @@ std::string TextureStorage2D::String(MatchState& state) const {
|
|||
class TextureStorage2DArray : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1269,7 +1269,7 @@ std::string TextureStorage2DArray::String(MatchState& state) const {
|
|||
class TextureStorage3D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1308,7 +1308,7 @@ std::string TextureStorage3D::String(MatchState& state) const {
|
|||
class TextureExternal : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1335,7 +1335,7 @@ std::string TextureExternal::String(MatchState&) const {
|
|||
class ModfResult : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1362,7 +1362,7 @@ std::string ModfResult::String(MatchState&) const {
|
|||
class ModfResultVec : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1397,7 +1397,7 @@ std::string ModfResultVec::String(MatchState& state) const {
|
|||
class FrexpResult : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1424,7 +1424,7 @@ std::string FrexpResult::String(MatchState&) const {
|
|||
class FrexpResultVec : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1460,7 +1460,7 @@ class Fiu32 : public TypeMatcher {
|
|||
public:
|
||||
/// Checks whether the given type matches the matcher rules, and returns the
|
||||
/// expected, canonicalized type on success.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1494,7 +1494,7 @@ class Fi32 : public TypeMatcher {
|
|||
public:
|
||||
/// Checks whether the given type matches the matcher rules, and returns the
|
||||
/// expected, canonicalized type on success.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1525,7 +1525,7 @@ class Iu32 : public TypeMatcher {
|
|||
public:
|
||||
/// Checks whether the given type matches the matcher rules, and returns the
|
||||
/// expected, canonicalized type on success.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1556,7 +1556,7 @@ class Scalar : public TypeMatcher {
|
|||
public:
|
||||
/// Checks whether the given type matches the matcher rules, and returns the
|
||||
/// expected, canonicalized type on success.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1593,7 +1593,7 @@ class ScalarNoF32 : public TypeMatcher {
|
|||
public:
|
||||
/// Checks whether the given type matches the matcher rules, and returns the
|
||||
/// expected, canonicalized type on success.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1627,7 +1627,7 @@ class ScalarNoI32 : public TypeMatcher {
|
|||
public:
|
||||
/// Checks whether the given type matches the matcher rules, and returns the
|
||||
/// expected, canonicalized type on success.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1661,7 +1661,7 @@ class ScalarNoU32 : public TypeMatcher {
|
|||
public:
|
||||
/// Checks whether the given type matches the matcher rules, and returns the
|
||||
/// expected, canonicalized type on success.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1695,7 +1695,7 @@ class ScalarNoBool : public TypeMatcher {
|
|||
public:
|
||||
/// Checks whether the given type matches the matcher rules, and returns the
|
||||
/// expected, canonicalized type on success.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -1728,7 +1728,7 @@ std::string ScalarNoBool::String(MatchState&) const {
|
|||
class F32TexelFormat : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define template numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param number the enum value as a Number
|
||||
/// @return true if the enum value matches the set
|
||||
|
@ -1761,7 +1761,7 @@ std::string F32TexelFormat::String(MatchState&) const {
|
|||
class I32TexelFormat : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define template numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param number the enum value as a Number
|
||||
/// @return true if the enum value matches the set
|
||||
|
@ -1793,7 +1793,7 @@ std::string I32TexelFormat::String(MatchState&) const {
|
|||
class U32TexelFormat : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define template numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param number the enum value as a Number
|
||||
/// @return true if the enum value matches the set
|
||||
|
@ -1825,7 +1825,7 @@ std::string U32TexelFormat::String(MatchState&) const {
|
|||
class WriteOnly : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define template numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param number the enum value as a Number
|
||||
/// @return true if the enum value matches the set
|
||||
|
@ -1851,7 +1851,7 @@ std::string WriteOnly::String(MatchState&) const {
|
|||
class FunctionPrivateWorkgroup : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define template numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param number the enum value as a Number
|
||||
/// @return true if the enum value matches the set
|
||||
|
@ -1881,7 +1881,7 @@ std::string FunctionPrivateWorkgroup::String(MatchState&) const {
|
|||
class WorkgroupOrStorage : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define template numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param number the enum value as a Number
|
||||
/// @return true if the enum value matches the set
|
||||
|
@ -1909,7 +1909,7 @@ std::string WorkgroupOrStorage::String(MatchState&) const {
|
|||
class Storage : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define template numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param number the enum value as a Number
|
||||
/// @return true if the enum value matches the set
|
||||
|
@ -1934,7 +1934,7 @@ std::string Storage::String(MatchState&) const {
|
|||
class Write : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define template numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param number the enum value as a Number
|
||||
/// @return true if the enum value matches the set
|
||||
|
@ -1959,7 +1959,7 @@ std::string Write::String(MatchState&) const {
|
|||
class ReadWrite : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define template numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param number the enum value as a Number
|
||||
/// @return true if the enum value matches the set
|
||||
|
|
|
@ -180,7 +180,7 @@ constexpr IntrinsicInfo kConstructorsAndConverters[] = {
|
|||
class {{$class}} : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -236,7 +236,7 @@ class {{$class}} : public TypeMatcher {
|
|||
public:
|
||||
/// Checks whether the given type matches the matcher rules, and returns the
|
||||
/// expected, canonicalized type on success.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define and refine the template types and numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param type the type to match
|
||||
/// @returns the canonicalized type on match, otherwise nullptr
|
||||
|
@ -280,7 +280,7 @@ std::string {{$class}}::String(MatchState&) const {
|
|||
class {{$class}} : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
/// Match may define template types and numbers in state.
|
||||
/// Match may define template numbers in state.
|
||||
/// @param state the MatchState
|
||||
/// @param number the enum value as a Number
|
||||
/// @return true if the enum value matches the set
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/tint/program_builder.h"
|
||||
#include "src/tint/resolver/resolver_test_helper.h"
|
||||
#include "src/tint/sem/atomic.h"
|
||||
#include "src/tint/sem/depth_multisampled_texture.h"
|
||||
#include "src/tint/sem/depth_texture.h"
|
||||
|
@ -32,12 +33,27 @@
|
|||
namespace tint::resolver {
|
||||
namespace {
|
||||
|
||||
#define EXPECT_TYPE(GOT, EXPECT) \
|
||||
if ((GOT) != (EXPECT)) { \
|
||||
FAIL() << #GOT " != " #EXPECT "\n" \
|
||||
<< " " #GOT ": " << NameOf(GOT) << "\n" \
|
||||
<< " " #EXPECT ": " << NameOf(EXPECT); \
|
||||
} \
|
||||
do { \
|
||||
} while (false)
|
||||
|
||||
using ::testing::HasSubstr;
|
||||
|
||||
using BuiltinType = sem::BuiltinType;
|
||||
using Parameter = sem::Parameter;
|
||||
using ParameterUsage = sem::ParameterUsage;
|
||||
|
||||
using AFloatV = builder::vec<3, AFloat>;
|
||||
using AIntV = builder::vec<3, AInt>;
|
||||
using f32V = builder::vec<3, f32>;
|
||||
using i32V = builder::vec<3, i32>;
|
||||
using u32V = builder::vec<3, u32>;
|
||||
|
||||
class IntrinsicTableTest : public testing::Test, public ProgramBuilder {
|
||||
public:
|
||||
std::unique_ptr<IntrinsicTable> table = IntrinsicTable::Create(*this);
|
||||
|
@ -418,7 +434,7 @@ TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) {
|
|||
EXPECT_EQ(result->Parameters()[0]->Type(), f32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchOpenType) {
|
||||
TEST_F(IntrinsicTableTest, MatchTemplateType) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* result = table->Lookup(BuiltinType::kClamp, {f32, f32, f32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
|
@ -430,7 +446,7 @@ TEST_F(IntrinsicTableTest, MatchOpenType) {
|
|||
EXPECT_EQ(result->Parameters()[2]->Type(), f32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchOpenType) {
|
||||
TEST_F(IntrinsicTableTest, MismatchTemplateType) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto* result = table->Lookup(BuiltinType::kClamp, {f32, u32, f32}, Source{});
|
||||
|
@ -785,5 +801,461 @@ TEST_F(IntrinsicTableTest, Err257Arguments) { // crbug.com/1323605
|
|||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AbstractBinaryTests
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AbstractBinaryTests {
|
||||
|
||||
struct Case {
|
||||
template <typename RESULT,
|
||||
typename PARAM_LHS,
|
||||
typename PARAM_RHS,
|
||||
typename ARG_LHS,
|
||||
typename ARG_RHS>
|
||||
static Case Create(bool match = true) {
|
||||
return {
|
||||
match, //
|
||||
builder::DataType<RESULT>::Sem, //
|
||||
builder::DataType<PARAM_LHS>::Sem, //
|
||||
builder::DataType<PARAM_RHS>::Sem, //
|
||||
builder::DataType<ARG_LHS>::Sem, //
|
||||
builder::DataType<ARG_RHS>::Sem, //
|
||||
};
|
||||
}
|
||||
bool expected_match;
|
||||
builder::sem_type_func_ptr expected_result;
|
||||
builder::sem_type_func_ptr expected_param_lhs;
|
||||
builder::sem_type_func_ptr expected_param_rhs;
|
||||
builder::sem_type_func_ptr arg_lhs;
|
||||
builder::sem_type_func_ptr arg_rhs;
|
||||
};
|
||||
|
||||
class IntrinsicTableAbstractBinaryTest : public testing::TestWithParam<Case>,
|
||||
public ProgramBuilder {
|
||||
public:
|
||||
std::string NameOf(const sem::Type* type) {
|
||||
return type ? type->FriendlyName(Symbols()) : "<null>";
|
||||
}
|
||||
|
||||
std::unique_ptr<IntrinsicTable> table = IntrinsicTable::Create(*this);
|
||||
};
|
||||
|
||||
TEST_P(IntrinsicTableAbstractBinaryTest, MatchAdd) {
|
||||
auto* arg_lhs = GetParam().arg_lhs(*this);
|
||||
auto* arg_rhs = GetParam().arg_rhs(*this);
|
||||
auto result = table->Lookup(ast::BinaryOp::kAdd, arg_lhs, arg_rhs, Source{{12, 34}},
|
||||
/* is_compound */ false);
|
||||
|
||||
bool matched = result.result != nullptr;
|
||||
bool expected_match = GetParam().expected_match;
|
||||
EXPECT_EQ(matched, expected_match) << Diagnostics().str();
|
||||
|
||||
auto* expected_result = GetParam().expected_result(*this);
|
||||
EXPECT_TYPE(result.result, expected_result);
|
||||
|
||||
auto* expected_param_lhs = GetParam().expected_param_lhs(*this);
|
||||
EXPECT_TYPE(result.lhs, expected_param_lhs);
|
||||
|
||||
auto* expected_param_rhs = GetParam().expected_param_rhs(*this);
|
||||
EXPECT_TYPE(result.rhs, expected_param_rhs);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(AFloat_AInt,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<f32, f32, f32, AFloat, AFloat>(),
|
||||
Case::Create<f32, f32, f32, AFloat, AInt>(),
|
||||
Case::Create<f32, f32, f32, AInt, AFloat>(),
|
||||
Case::Create<i32, i32, i32, AInt, AInt>()
|
||||
)); // clang-format on
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(VecAFloat_VecAInt,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<f32V, f32V, f32V, AFloatV, AFloatV>(),
|
||||
Case::Create<f32V, f32V, f32V, AFloatV, AIntV>(),
|
||||
Case::Create<f32V, f32V, f32V, AIntV, AFloatV>(),
|
||||
Case::Create<i32V, i32V, i32V, AIntV, AIntV>()
|
||||
)); // clang-format on
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(AFloat_f32,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<f32, f32, f32, AFloat, f32>(),
|
||||
Case::Create<f32, f32, f32, f32, AFloat>()
|
||||
)); // clang-format on
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(VecAFloat_Vecf32,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<f32V, f32V, f32V, AFloatV, f32V>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, AFloatV>()
|
||||
)); // clang-format on
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AFloat_i32,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<void, void, void, AFloat, i32>(false),
|
||||
Case::Create<void, void, void, i32, AFloat>(false)
|
||||
)); // clang-format on
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
VecAFloat_Veci32,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<void, void, void, AFloatV, i32V>(false),
|
||||
Case::Create<void, void, void, i32V, AFloatV>(false)
|
||||
)); // clang-format on
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AFloat_u32,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<void, void, void, AFloat, u32>(false),
|
||||
Case::Create<void, void, void, u32, AFloat>(false)
|
||||
)); // clang-format on
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
VecAFloat_Vecu32,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<void, void, void, AFloatV, u32V>(false),
|
||||
Case::Create<void, void, void, u32V, AFloatV>(false)
|
||||
)); // clang-format on
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(AInt_f32,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<f32, f32, f32, AInt, f32>(),
|
||||
Case::Create<f32, f32, f32, f32, AInt>()
|
||||
)); // clang-format on
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(VecAInt_Vecf32,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<f32V, f32V, f32V, AIntV, f32V>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, AIntV>()
|
||||
)); // clang-format on
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(AInt_i32,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<i32, i32, i32, AInt, i32>(),
|
||||
Case::Create<i32, i32, i32, i32, AInt>()
|
||||
)); // clang-format on
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(VecAInt_Veci32,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<i32V, i32V, i32V, AIntV, i32V>(),
|
||||
Case::Create<i32V, i32V, i32V, i32V, AIntV>()
|
||||
)); // clang-format on
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(AInt_u32,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<u32, u32, u32, AInt, u32>(),
|
||||
Case::Create<u32, u32, u32, u32, AInt>()
|
||||
)); // clang-format on
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(VecAInt_Vecu32,
|
||||
IntrinsicTableAbstractBinaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param lhs | param rhs | arg lhs | arg rhs
|
||||
Case::Create<u32V, u32V, u32V, AIntV, u32V>(),
|
||||
Case::Create<u32V, u32V, u32V, u32V, AIntV>()
|
||||
)); // clang-format on
|
||||
|
||||
} // namespace AbstractBinaryTests
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AbstractTernaryTests
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AbstractTernaryTests {
|
||||
|
||||
struct Case {
|
||||
template <typename RESULT,
|
||||
typename PARAM_A,
|
||||
typename PARAM_B,
|
||||
typename PARAM_C,
|
||||
typename ARG_A,
|
||||
typename ARG_B,
|
||||
typename ARG_C>
|
||||
static Case Create(bool match = true) {
|
||||
return {
|
||||
match,
|
||||
builder::DataType<RESULT>::Sem, //
|
||||
builder::DataType<PARAM_A>::Sem, //
|
||||
builder::DataType<PARAM_B>::Sem, //
|
||||
builder::DataType<PARAM_C>::Sem, //
|
||||
builder::DataType<ARG_A>::Sem, //
|
||||
builder::DataType<ARG_B>::Sem, //
|
||||
builder::DataType<ARG_C>::Sem, //
|
||||
};
|
||||
}
|
||||
bool expected_match;
|
||||
builder::sem_type_func_ptr expected_result;
|
||||
builder::sem_type_func_ptr expected_param_a;
|
||||
builder::sem_type_func_ptr expected_param_b;
|
||||
builder::sem_type_func_ptr expected_param_c;
|
||||
builder::sem_type_func_ptr arg_a;
|
||||
builder::sem_type_func_ptr arg_b;
|
||||
builder::sem_type_func_ptr arg_c;
|
||||
};
|
||||
|
||||
class IntrinsicTableAbstractTernaryTest : public testing::TestWithParam<Case>,
|
||||
public ProgramBuilder {
|
||||
public:
|
||||
std::string NameOf(const sem::Type* type) {
|
||||
return type ? type->FriendlyName(Symbols()) : "<null>";
|
||||
}
|
||||
|
||||
std::unique_ptr<IntrinsicTable> table = IntrinsicTable::Create(*this);
|
||||
};
|
||||
|
||||
TEST_P(IntrinsicTableAbstractTernaryTest, MatchClamp) {
|
||||
auto* arg_a = GetParam().arg_a(*this);
|
||||
auto* arg_b = GetParam().arg_b(*this);
|
||||
auto* arg_c = GetParam().arg_c(*this);
|
||||
auto* builtin =
|
||||
table->Lookup(sem::BuiltinType::kClamp, {arg_a, arg_b, arg_c}, Source{{12, 34}});
|
||||
|
||||
bool matched = builtin != nullptr;
|
||||
bool expected_match = GetParam().expected_match;
|
||||
EXPECT_EQ(matched, expected_match) << Diagnostics().str();
|
||||
|
||||
auto* result = builtin ? builtin->ReturnType() : nullptr;
|
||||
auto* expected_result = GetParam().expected_result(*this);
|
||||
EXPECT_TYPE(result, expected_result);
|
||||
|
||||
auto* param_a = builtin ? builtin->Parameters()[0]->Type() : nullptr;
|
||||
auto* expected_param_a = GetParam().expected_param_a(*this);
|
||||
EXPECT_TYPE(param_a, expected_param_a);
|
||||
|
||||
auto* param_b = builtin ? builtin->Parameters()[1]->Type() : nullptr;
|
||||
auto* expected_param_b = GetParam().expected_param_b(*this);
|
||||
EXPECT_TYPE(param_b, expected_param_b);
|
||||
|
||||
auto* param_c = builtin ? builtin->Parameters()[2]->Type() : nullptr;
|
||||
auto* expected_param_c = GetParam().expected_param_c(*this);
|
||||
EXPECT_TYPE(param_c, expected_param_c);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AFloat_AInt,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<f32, f32, f32, f32, AFloat, AFloat, AFloat>(),
|
||||
Case::Create<f32, f32, f32, f32, AFloat, AFloat, AInt>(),
|
||||
Case::Create<f32, f32, f32, f32, AFloat, AInt, AFloat>(),
|
||||
Case::Create<f32, f32, f32, f32, AFloat, AInt, AInt>(),
|
||||
Case::Create<f32, f32, f32, f32, AInt, AFloat, AFloat>(),
|
||||
Case::Create<f32, f32, f32, f32, AInt, AFloat, AInt>(),
|
||||
Case::Create<f32, f32, f32, f32, AInt, AInt, AFloat>(),
|
||||
Case::Create<i32, i32, i32, i32, AInt, AInt, AInt>()
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
VecAFloat_VecAInt,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<f32V, f32V, f32V, f32V, AFloatV, AFloatV, AFloatV>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, AFloatV, AFloatV, AIntV>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, AFloatV, AIntV, AFloatV>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, AFloatV, AIntV, AIntV>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, AIntV, AFloatV, AFloatV>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, AIntV, AFloatV, AIntV>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, AIntV, AIntV, AFloatV>(),
|
||||
Case::Create<i32V, i32V, i32V, i32V, AIntV, AIntV, AIntV>()
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AFloat_f32,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<f32, f32, f32, f32, AFloat, AFloat, f32>(),
|
||||
Case::Create<f32, f32, f32, f32, AFloat, f32, AFloat>(),
|
||||
Case::Create<f32, f32, f32, f32, AFloat, f32, f32>(),
|
||||
Case::Create<f32, f32, f32, f32, f32, AFloat, AFloat>(),
|
||||
Case::Create<f32, f32, f32, f32, f32, AFloat, f32>(),
|
||||
Case::Create<f32, f32, f32, f32, f32, f32, AFloat>()
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
VecAFloat_Vecf32,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<f32V, f32V, f32V, f32V, AFloatV, AFloatV, f32V>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, AFloatV, f32V, AFloatV>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, AFloatV, f32V, f32V>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, f32V, AFloatV, AFloatV>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, f32V, AFloatV, f32V>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, f32V, f32V, AFloatV> ()
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AFloat_i32,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<void, void, void, void, AFloat, AFloat, i32>(false),
|
||||
Case::Create<void, void, void, void, AFloat, i32, AFloat>(false),
|
||||
Case::Create<void, void, void, void, AFloat, i32, i32>(false),
|
||||
Case::Create<void, void, void, void, i32, AFloat, AFloat>(false),
|
||||
Case::Create<void, void, void, void, i32, AFloat, i32>(false),
|
||||
Case::Create<void, void, void, void, i32, i32, AFloat>(false)
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
VecAFloat_Veci32,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<void, void, void, void, AFloatV, AFloatV, i32V>(false),
|
||||
Case::Create<void, void, void, void, AFloatV, i32V, AFloatV>(false),
|
||||
Case::Create<void, void, void, void, AFloatV, i32V, i32V>(false),
|
||||
Case::Create<void, void, void, void, i32V, AFloatV, AFloatV>(false),
|
||||
Case::Create<void, void, void, void, i32V, AFloatV, i32V>(false),
|
||||
Case::Create<void, void, void, void, i32V, i32V, AFloatV>(false)
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AFloat_u32,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<void, void, void, void, AFloat, AFloat, u32>(false),
|
||||
Case::Create<void, void, void, void, AFloat, u32, AFloat>(false),
|
||||
Case::Create<void, void, void, void, AFloat, u32, u32>(false),
|
||||
Case::Create<void, void, void, void, u32, AFloat, AFloat>(false),
|
||||
Case::Create<void, void, void, void, u32, AFloat, u32>(false),
|
||||
Case::Create<void, void, void, void, u32, u32, AFloat>(false)
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
VecAFloat_Vecu32,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<void, void, void, void, AFloatV, AFloatV, u32V>(false),
|
||||
Case::Create<void, void, void, void, AFloatV, u32V, AFloatV>(false),
|
||||
Case::Create<void, void, void, void, AFloatV, u32V, u32V>(false),
|
||||
Case::Create<void, void, void, void, u32V, AFloatV, AFloatV>(false),
|
||||
Case::Create<void, void, void, void, u32V, AFloatV, u32V>(false),
|
||||
Case::Create<void, void, void, void, u32V, u32V, AFloatV>(false)
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AInt_f32,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<f32, f32, f32, f32, AInt, AInt, f32>(),
|
||||
Case::Create<f32, f32, f32, f32, AInt, f32, AInt>(),
|
||||
Case::Create<f32, f32, f32, f32, AInt, f32, f32>(),
|
||||
Case::Create<f32, f32, f32, f32, f32, AInt, AInt>(),
|
||||
Case::Create<f32, f32, f32, f32, f32, AInt, f32>(),
|
||||
Case::Create<f32, f32, f32, f32, f32, f32, AInt>()
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
VecAInt_Vecf32,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<f32V, f32V, f32V, f32V, AIntV, AIntV, f32V>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, AIntV, f32V, AIntV>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, AIntV, f32V, f32V>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, f32V, AIntV, AIntV>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, f32V, AIntV, f32V>(),
|
||||
Case::Create<f32V, f32V, f32V, f32V, f32V, f32V, AIntV>()
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AInt_i32,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<i32, i32, i32, i32, AInt, AInt, i32>(),
|
||||
Case::Create<i32, i32, i32, i32, AInt, i32, AInt>(),
|
||||
Case::Create<i32, i32, i32, i32, AInt, i32, i32>(),
|
||||
Case::Create<i32, i32, i32, i32, i32, AInt, AInt>(),
|
||||
Case::Create<i32, i32, i32, i32, i32, AInt, i32>(),
|
||||
Case::Create<i32, i32, i32, i32, i32, i32, AInt>()
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
VecAInt_Veci32,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<i32V, i32V, i32V, i32V, AIntV, AIntV, i32V>(),
|
||||
Case::Create<i32V, i32V, i32V, i32V, AIntV, i32V, AIntV>(),
|
||||
Case::Create<i32V, i32V, i32V, i32V, AIntV, i32V, i32V>(),
|
||||
Case::Create<i32V, i32V, i32V, i32V, i32V, AIntV, AIntV>(),
|
||||
Case::Create<i32V, i32V, i32V, i32V, i32V, AIntV, i32V>(),
|
||||
Case::Create<i32V, i32V, i32V, i32V, i32V, i32V, AIntV>()
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AInt_u32,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<u32, u32, u32, u32, AInt, AInt, u32>(),
|
||||
Case::Create<u32, u32, u32, u32, AInt, u32, AInt>(),
|
||||
Case::Create<u32, u32, u32, u32, AInt, u32, u32>(),
|
||||
Case::Create<u32, u32, u32, u32, u32, AInt, AInt>(),
|
||||
Case::Create<u32, u32, u32, u32, u32, AInt, u32>(),
|
||||
Case::Create<u32, u32, u32, u32, u32, u32, AInt>()
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
VecAInt_Vecu32,
|
||||
IntrinsicTableAbstractTernaryTest,
|
||||
testing::Values( // clang-format off
|
||||
// result | param a | param b | param c | arg a | arg b | arg c
|
||||
Case::Create<u32V, u32V, u32V, u32V, AIntV, AIntV, u32V>(),
|
||||
Case::Create<u32V, u32V, u32V, u32V, AIntV, u32V, AIntV>(),
|
||||
Case::Create<u32V, u32V, u32V, u32V, AIntV, u32V, u32V>(),
|
||||
Case::Create<u32V, u32V, u32V, u32V, u32V, AIntV, AIntV>(),
|
||||
Case::Create<u32V, u32V, u32V, u32V, u32V, AIntV, u32V>(),
|
||||
Case::Create<u32V, u32V, u32V, u32V, u32V, u32V, AIntV>()
|
||||
// clang-format on
|
||||
));
|
||||
|
||||
} // namespace AbstractTernaryTests
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::resolver
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/tint/program_builder.h"
|
||||
#include "src/tint/resolver/resolver.h"
|
||||
#include "src/tint/sem/abstract_float.h"
|
||||
#include "src/tint/sem/abstract_int.h"
|
||||
#include "src/tint/sem/expression.h"
|
||||
#include "src/tint/sem/statement.h"
|
||||
#include "src/tint/sem/variable.h"
|
||||
|
@ -174,6 +176,15 @@ using sem_type_func_ptr = const sem::Type* (*)(ProgramBuilder& b);
|
|||
template <typename T>
|
||||
struct DataType {};
|
||||
|
||||
/// Helper that represents no-type. Returns nullptr for all static methods.
|
||||
template <>
|
||||
struct DataType<void> {
|
||||
/// @return nullptr
|
||||
static inline const ast::Type* AST(ProgramBuilder&) { return nullptr; }
|
||||
/// @return nullptr
|
||||
static inline const sem::Type* Sem(ProgramBuilder&) { return nullptr; }
|
||||
};
|
||||
|
||||
/// Helper for building bool types and expressions
|
||||
template <>
|
||||
struct DataType<bool> {
|
||||
|
@ -254,6 +265,40 @@ struct DataType<f32> {
|
|||
}
|
||||
};
|
||||
|
||||
/// Helper for building abstract float types and expressions
|
||||
template <>
|
||||
struct DataType<AFloat> {
|
||||
/// false as AFloat is not a composite type
|
||||
static constexpr bool is_composite = false;
|
||||
|
||||
/// @param b the ProgramBuilder
|
||||
/// @return the semantic abstract-float type
|
||||
static inline const sem::Type* Sem(ProgramBuilder& b) { return b.create<sem::AbstractFloat>(); }
|
||||
/// @param b the ProgramBuilder
|
||||
/// @param elem_value the abstract-float value
|
||||
/// @return a new AST abstract-float literal value expression
|
||||
static inline const ast::Expression* Expr(ProgramBuilder& b, AFloat elem_value) {
|
||||
return b.Expr(elem_value);
|
||||
}
|
||||
};
|
||||
|
||||
/// Helper for building abstract integer types and expressions
|
||||
template <>
|
||||
struct DataType<AInt> {
|
||||
/// false as AFloat is not a composite type
|
||||
static constexpr bool is_composite = false;
|
||||
|
||||
/// @param b the ProgramBuilder
|
||||
/// @return the semantic abstract-int type
|
||||
static inline const sem::Type* Sem(ProgramBuilder& b) { return b.create<sem::AbstractInt>(); }
|
||||
/// @param b the ProgramBuilder
|
||||
/// @param elem_value the abstract-int value
|
||||
/// @return a new AST abstract-int literal value expression
|
||||
static inline const ast::Expression* Expr(ProgramBuilder& b, AInt elem_value) {
|
||||
return b.Expr(elem_value);
|
||||
}
|
||||
};
|
||||
|
||||
/// Helper for building vector types and expressions
|
||||
template <uint32_t N, typename T>
|
||||
struct DataType<vec<N, T>> {
|
||||
|
|
Loading…
Reference in New Issue