tint: fix intrinsic table lookup of mixed const and non-const with non-matching arg element types
Bug: tint:1581 Change-Id: I7676ec6857c5fd790cb9c5644bfe674a603113ab Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/104545 Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
2e25382707
commit
fc7994ba4c
|
@ -27,6 +27,7 @@
|
|||
#include "src/tint/sem/atomic.h"
|
||||
#include "src/tint/sem/depth_multisampled_texture.h"
|
||||
#include "src/tint/sem/depth_texture.h"
|
||||
#include "src/tint/sem/evaluation_stage.h"
|
||||
#include "src/tint/sem/external_texture.h"
|
||||
#include "src/tint/sem/multisampled_texture.h"
|
||||
#include "src/tint/sem/pipeline_stage_set.h"
|
||||
|
@ -195,8 +196,14 @@ class MatchState {
|
|||
TemplateState& t,
|
||||
const Matchers& m,
|
||||
const OverloadInfo* o,
|
||||
MatcherIndex const* matcher_indices)
|
||||
: builder(b), templates(t), matchers(m), overload(o), matcher_indices_(matcher_indices) {}
|
||||
MatcherIndex const* matcher_indices,
|
||||
sem::EvaluationStage s)
|
||||
: builder(b),
|
||||
templates(t),
|
||||
matchers(m),
|
||||
overload(o),
|
||||
earliest_eval_stage(s),
|
||||
matcher_indices_(matcher_indices) {}
|
||||
|
||||
/// The program builder
|
||||
ProgramBuilder& builder;
|
||||
|
@ -206,6 +213,8 @@ class MatchState {
|
|||
Matchers const& matchers;
|
||||
/// The current overload being evaluated
|
||||
OverloadInfo const* overload;
|
||||
/// The earliest evaluation stage of the builtin call
|
||||
sem::EvaluationStage earliest_eval_stage;
|
||||
|
||||
/// Type uses the next TypeMatcher from the matcher indices to match the type
|
||||
/// `ty`. If the type matches, the canonical expected type is returned. If the
|
||||
|
@ -340,7 +349,7 @@ enum class OverloadFlag {
|
|||
// An enum set of OverloadFlag, used by OperatorInfo
|
||||
using OverloadFlags = utils::EnumSet<OverloadFlag>;
|
||||
|
||||
bool match_bool(const sem::Type* ty) {
|
||||
bool match_bool(MatchState&, const sem::Type* ty) {
|
||||
return ty->IsAnyOf<Any, sem::Bool>();
|
||||
}
|
||||
|
||||
|
@ -348,16 +357,18 @@ const sem::AbstractFloat* build_fa(MatchState& state) {
|
|||
return state.builder.create<sem::AbstractFloat>();
|
||||
}
|
||||
|
||||
bool match_fa(const sem::Type* ty) {
|
||||
return ty->IsAnyOf<Any, sem::AbstractNumeric>();
|
||||
bool match_fa(MatchState& state, const sem::Type* ty) {
|
||||
return (state.earliest_eval_stage == sem::EvaluationStage::kConstant) &&
|
||||
ty->IsAnyOf<Any, sem::AbstractNumeric>();
|
||||
}
|
||||
|
||||
const sem::AbstractInt* build_ia(MatchState& state) {
|
||||
return state.builder.create<sem::AbstractInt>();
|
||||
}
|
||||
|
||||
bool match_ia(const sem::Type* ty) {
|
||||
return ty->IsAnyOf<Any, sem::AbstractInt>();
|
||||
bool match_ia(MatchState& state, const sem::Type* ty) {
|
||||
return (state.earliest_eval_stage == sem::EvaluationStage::kConstant) &&
|
||||
ty->IsAnyOf<Any, sem::AbstractInt>();
|
||||
}
|
||||
|
||||
const sem::Bool* build_bool(MatchState& state) {
|
||||
|
@ -368,7 +379,7 @@ const sem::F16* build_f16(MatchState& state) {
|
|||
return state.builder.create<sem::F16>();
|
||||
}
|
||||
|
||||
bool match_f16(const sem::Type* ty) {
|
||||
bool match_f16(MatchState&, const sem::Type* ty) {
|
||||
return ty->IsAnyOf<Any, sem::F16, sem::AbstractNumeric>();
|
||||
}
|
||||
|
||||
|
@ -376,7 +387,7 @@ const sem::F32* build_f32(MatchState& state) {
|
|||
return state.builder.create<sem::F32>();
|
||||
}
|
||||
|
||||
bool match_f32(const sem::Type* ty) {
|
||||
bool match_f32(MatchState&, const sem::Type* ty) {
|
||||
return ty->IsAnyOf<Any, sem::F32, sem::AbstractNumeric>();
|
||||
}
|
||||
|
||||
|
@ -384,7 +395,7 @@ const sem::I32* build_i32(MatchState& state) {
|
|||
return state.builder.create<sem::I32>();
|
||||
}
|
||||
|
||||
bool match_i32(const sem::Type* ty) {
|
||||
bool match_i32(MatchState&, const sem::Type* ty) {
|
||||
return ty->IsAnyOf<Any, sem::I32, sem::AbstractInt>();
|
||||
}
|
||||
|
||||
|
@ -392,11 +403,11 @@ const sem::U32* build_u32(MatchState& state) {
|
|||
return state.builder.create<sem::U32>();
|
||||
}
|
||||
|
||||
bool match_u32(const sem::Type* ty) {
|
||||
bool match_u32(MatchState&, const sem::Type* ty) {
|
||||
return ty->IsAnyOf<Any, sem::U32, sem::AbstractInt>();
|
||||
}
|
||||
|
||||
bool match_vec(const sem::Type* ty, Number& N, const sem::Type*& T) {
|
||||
bool match_vec(MatchState&, const sem::Type* ty, Number& N, const sem::Type*& T) {
|
||||
if (ty->Is<Any>()) {
|
||||
N = Number::any;
|
||||
T = ty;
|
||||
|
@ -412,7 +423,7 @@ bool match_vec(const sem::Type* ty, Number& N, const sem::Type*& T) {
|
|||
}
|
||||
|
||||
template <uint32_t N>
|
||||
bool match_vec(const sem::Type* ty, const sem::Type*& T) {
|
||||
bool match_vec(MatchState&, const sem::Type* ty, const sem::Type*& T) {
|
||||
if (ty->Is<Any>()) {
|
||||
T = ty;
|
||||
return true;
|
||||
|
@ -444,7 +455,7 @@ constexpr auto build_vec2 = build_vec<2>;
|
|||
constexpr auto build_vec3 = build_vec<3>;
|
||||
constexpr auto build_vec4 = build_vec<4>;
|
||||
|
||||
bool match_mat(const sem::Type* ty, Number& M, Number& N, const sem::Type*& T) {
|
||||
bool match_mat(MatchState&, const sem::Type* ty, Number& M, Number& N, const sem::Type*& T) {
|
||||
if (ty->Is<Any>()) {
|
||||
M = Number::any;
|
||||
N = Number::any;
|
||||
|
@ -461,7 +472,7 @@ bool match_mat(const sem::Type* ty, Number& M, Number& N, const sem::Type*& T) {
|
|||
}
|
||||
|
||||
template <uint32_t C, uint32_t R>
|
||||
bool match_mat(const sem::Type* ty, const sem::Type*& T) {
|
||||
bool match_mat(MatchState&, const sem::Type* ty, const sem::Type*& T) {
|
||||
if (ty->Is<Any>()) {
|
||||
T = ty;
|
||||
return true;
|
||||
|
@ -506,7 +517,7 @@ constexpr auto match_mat4x2 = match_mat<4, 2>;
|
|||
constexpr auto match_mat4x3 = match_mat<4, 3>;
|
||||
constexpr auto match_mat4x4 = match_mat<4, 4>;
|
||||
|
||||
bool match_array(const sem::Type* ty, const sem::Type*& T) {
|
||||
bool match_array(MatchState&, const sem::Type* ty, const sem::Type*& T) {
|
||||
if (ty->Is<Any>()) {
|
||||
T = ty;
|
||||
return true;
|
||||
|
@ -530,7 +541,7 @@ const sem::Array* build_array(MatchState& state, const sem::Type* el) {
|
|||
/* stride_implicit */ 0u);
|
||||
}
|
||||
|
||||
bool match_ptr(const sem::Type* ty, Number& S, const sem::Type*& T, Number& A) {
|
||||
bool match_ptr(MatchState&, const sem::Type* ty, Number& S, const sem::Type*& T, Number& A) {
|
||||
if (ty->Is<Any>()) {
|
||||
S = Number::any;
|
||||
T = ty;
|
||||
|
@ -552,7 +563,7 @@ const sem::Pointer* build_ptr(MatchState& state, Number S, const sem::Type* T, N
|
|||
static_cast<ast::Access>(A.Value()));
|
||||
}
|
||||
|
||||
bool match_atomic(const sem::Type* ty, const sem::Type*& T) {
|
||||
bool match_atomic(MatchState&, const sem::Type* ty, const sem::Type*& T) {
|
||||
if (ty->Is<Any>()) {
|
||||
T = ty;
|
||||
return true;
|
||||
|
@ -569,7 +580,7 @@ const sem::Atomic* build_atomic(MatchState& state, const sem::Type* T) {
|
|||
return state.builder.create<sem::Atomic>(T);
|
||||
}
|
||||
|
||||
bool match_sampler(const sem::Type* ty) {
|
||||
bool match_sampler(MatchState&, const sem::Type* ty) {
|
||||
if (ty->Is<Any>()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -580,7 +591,7 @@ const sem::Sampler* build_sampler(MatchState& state) {
|
|||
return state.builder.create<sem::Sampler>(ast::SamplerKind::kSampler);
|
||||
}
|
||||
|
||||
bool match_sampler_comparison(const sem::Type* ty) {
|
||||
bool match_sampler_comparison(MatchState&, const sem::Type* ty) {
|
||||
if (ty->Is<Any>()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -592,7 +603,10 @@ const sem::Sampler* build_sampler_comparison(MatchState& state) {
|
|||
return state.builder.create<sem::Sampler>(ast::SamplerKind::kComparisonSampler);
|
||||
}
|
||||
|
||||
bool match_texture(const sem::Type* ty, ast::TextureDimension dim, const sem::Type*& T) {
|
||||
bool match_texture(MatchState&,
|
||||
const sem::Type* ty,
|
||||
ast::TextureDimension dim,
|
||||
const sem::Type*& T) {
|
||||
if (ty->Is<Any>()) {
|
||||
T = ty;
|
||||
return true;
|
||||
|
@ -609,8 +623,9 @@ bool match_texture(const sem::Type* ty, ast::TextureDimension dim, const sem::Ty
|
|||
#define JOIN(a, b) a##b
|
||||
|
||||
#define DECLARE_SAMPLED_TEXTURE(suffix, dim) \
|
||||
bool JOIN(match_texture_, suffix)(const sem::Type* ty, const sem::Type*& T) { \
|
||||
return match_texture(ty, dim, T); \
|
||||
bool JOIN(match_texture_, suffix)(MatchState & state, const sem::Type* ty, \
|
||||
const sem::Type*& T) { \
|
||||
return match_texture(state, ty, dim, T); \
|
||||
} \
|
||||
const sem::SampledTexture* JOIN(build_texture_, suffix)(MatchState & state, \
|
||||
const sem::Type* T) { \
|
||||
|
@ -625,7 +640,8 @@ DECLARE_SAMPLED_TEXTURE(cube, ast::TextureDimension::kCube)
|
|||
DECLARE_SAMPLED_TEXTURE(cube_array, ast::TextureDimension::kCubeArray)
|
||||
#undef DECLARE_SAMPLED_TEXTURE
|
||||
|
||||
bool match_texture_multisampled(const sem::Type* ty,
|
||||
bool match_texture_multisampled(MatchState&,
|
||||
const sem::Type* ty,
|
||||
ast::TextureDimension dim,
|
||||
const sem::Type*& T) {
|
||||
if (ty->Is<Any>()) {
|
||||
|
@ -641,31 +657,32 @@ bool match_texture_multisampled(const sem::Type* ty,
|
|||
return false;
|
||||
}
|
||||
|
||||
#define DECLARE_MULTISAMPLED_TEXTURE(suffix, dim) \
|
||||
bool JOIN(match_texture_multisampled_, suffix)(const sem::Type* ty, const sem::Type*& T) { \
|
||||
return match_texture_multisampled(ty, dim, T); \
|
||||
} \
|
||||
const sem::MultisampledTexture* JOIN(build_texture_multisampled_, suffix)( \
|
||||
MatchState & state, const sem::Type* T) { \
|
||||
return state.builder.create<sem::MultisampledTexture>(dim, T); \
|
||||
#define DECLARE_MULTISAMPLED_TEXTURE(suffix, dim) \
|
||||
bool JOIN(match_texture_multisampled_, suffix)(MatchState & state, const sem::Type* ty, \
|
||||
const sem::Type*& T) { \
|
||||
return match_texture_multisampled(state, ty, dim, T); \
|
||||
} \
|
||||
const sem::MultisampledTexture* JOIN(build_texture_multisampled_, suffix)( \
|
||||
MatchState & state, const sem::Type* T) { \
|
||||
return state.builder.create<sem::MultisampledTexture>(dim, T); \
|
||||
}
|
||||
|
||||
DECLARE_MULTISAMPLED_TEXTURE(2d, ast::TextureDimension::k2d)
|
||||
#undef DECLARE_MULTISAMPLED_TEXTURE
|
||||
|
||||
bool match_texture_depth(const sem::Type* ty, ast::TextureDimension dim) {
|
||||
bool match_texture_depth(MatchState&, const sem::Type* ty, ast::TextureDimension dim) {
|
||||
if (ty->Is<Any>()) {
|
||||
return true;
|
||||
}
|
||||
return ty->Is([&](const sem::DepthTexture* t) { return t->dim() == dim; });
|
||||
}
|
||||
|
||||
#define DECLARE_DEPTH_TEXTURE(suffix, dim) \
|
||||
bool JOIN(match_texture_depth_, suffix)(const sem::Type* ty) { \
|
||||
return match_texture_depth(ty, dim); \
|
||||
} \
|
||||
const sem::DepthTexture* JOIN(build_texture_depth_, suffix)(MatchState & state) { \
|
||||
return state.builder.create<sem::DepthTexture>(dim); \
|
||||
#define DECLARE_DEPTH_TEXTURE(suffix, dim) \
|
||||
bool JOIN(match_texture_depth_, suffix)(MatchState & state, const sem::Type* ty) { \
|
||||
return match_texture_depth(state, ty, dim); \
|
||||
} \
|
||||
const sem::DepthTexture* JOIN(build_texture_depth_, suffix)(MatchState & state) { \
|
||||
return state.builder.create<sem::DepthTexture>(dim); \
|
||||
}
|
||||
|
||||
DECLARE_DEPTH_TEXTURE(2d, ast::TextureDimension::k2d)
|
||||
|
@ -674,7 +691,7 @@ DECLARE_DEPTH_TEXTURE(cube, ast::TextureDimension::kCube)
|
|||
DECLARE_DEPTH_TEXTURE(cube_array, ast::TextureDimension::kCubeArray)
|
||||
#undef DECLARE_DEPTH_TEXTURE
|
||||
|
||||
bool match_texture_depth_multisampled_2d(const sem::Type* ty) {
|
||||
bool match_texture_depth_multisampled_2d(MatchState&, const sem::Type* ty) {
|
||||
if (ty->Is<Any>()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -687,7 +704,11 @@ sem::DepthMultisampledTexture* build_texture_depth_multisampled_2d(MatchState& s
|
|||
return state.builder.create<sem::DepthMultisampledTexture>(ast::TextureDimension::k2d);
|
||||
}
|
||||
|
||||
bool match_texture_storage(const sem::Type* ty, ast::TextureDimension dim, Number& F, Number& A) {
|
||||
bool match_texture_storage(MatchState&,
|
||||
const sem::Type* ty,
|
||||
ast::TextureDimension dim,
|
||||
Number& F,
|
||||
Number& A) {
|
||||
if (ty->Is<Any>()) {
|
||||
F = Number::any;
|
||||
A = Number::any;
|
||||
|
@ -704,8 +725,9 @@ bool match_texture_storage(const sem::Type* ty, ast::TextureDimension dim, Numbe
|
|||
}
|
||||
|
||||
#define DECLARE_STORAGE_TEXTURE(suffix, dim) \
|
||||
bool JOIN(match_texture_storage_, suffix)(const sem::Type* ty, Number& F, Number& A) { \
|
||||
return match_texture_storage(ty, dim, F, A); \
|
||||
bool JOIN(match_texture_storage_, suffix)(MatchState & state, const sem::Type* ty, Number& F, \
|
||||
Number& A) { \
|
||||
return match_texture_storage(state, ty, dim, F, A); \
|
||||
} \
|
||||
const sem::StorageTexture* JOIN(build_texture_storage_, suffix)(MatchState & state, Number F, \
|
||||
Number A) { \
|
||||
|
@ -721,7 +743,7 @@ DECLARE_STORAGE_TEXTURE(2d_array, ast::TextureDimension::k2dArray)
|
|||
DECLARE_STORAGE_TEXTURE(3d, ast::TextureDimension::k3d)
|
||||
#undef DECLARE_STORAGE_TEXTURE
|
||||
|
||||
bool match_texture_external(const sem::Type* ty) {
|
||||
bool match_texture_external(MatchState&, const sem::Type* ty) {
|
||||
return ty->IsAnyOf<Any, sem::ExternalTexture>();
|
||||
}
|
||||
|
||||
|
@ -732,14 +754,14 @@ const sem::ExternalTexture* build_texture_external(MatchState& state) {
|
|||
// Builtin types starting with a _ prefix cannot be declared in WGSL, so they
|
||||
// can only be used as return types. Because of this, they must only match Any,
|
||||
// which is used as the return type matcher.
|
||||
bool match_modf_result(const sem::Type* ty, const sem::Type*& T) {
|
||||
bool match_modf_result(MatchState&, const sem::Type* ty, const sem::Type*& T) {
|
||||
if (!ty->Is<Any>()) {
|
||||
return false;
|
||||
}
|
||||
T = ty;
|
||||
return true;
|
||||
}
|
||||
bool match_modf_result_vec(const sem::Type* ty, Number& N, const sem::Type*& T) {
|
||||
bool match_modf_result_vec(MatchState&, const sem::Type* ty, Number& N, const sem::Type*& T) {
|
||||
if (!ty->Is<Any>()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -747,14 +769,14 @@ bool match_modf_result_vec(const sem::Type* ty, Number& N, const sem::Type*& T)
|
|||
T = ty;
|
||||
return true;
|
||||
}
|
||||
bool match_frexp_result(const sem::Type* ty, const sem::Type*& T) {
|
||||
bool match_frexp_result(MatchState&, const sem::Type* ty, const sem::Type*& T) {
|
||||
if (!ty->Is<Any>()) {
|
||||
return false;
|
||||
}
|
||||
T = ty;
|
||||
return true;
|
||||
}
|
||||
bool match_frexp_result_vec(const sem::Type* ty, Number& N, const sem::Type*& T) {
|
||||
bool match_frexp_result_vec(MatchState&, const sem::Type* ty, Number& N, const sem::Type*& T) {
|
||||
if (!ty->Is<Any>()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -763,7 +785,7 @@ bool match_frexp_result_vec(const sem::Type* ty, Number& N, const sem::Type*& T)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool match_atomic_compare_exchange_result(const sem::Type* ty, const sem::Type*& T) {
|
||||
bool match_atomic_compare_exchange_result(MatchState&, const sem::Type* ty, const sem::Type*& T) {
|
||||
if (ty->Is<Any>()) {
|
||||
T = ty;
|
||||
return true;
|
||||
|
@ -970,6 +992,7 @@ class Impl : public IntrinsicTable {
|
|||
|
||||
Builtin Lookup(sem::BuiltinType builtin_type,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
sem::EvaluationStage earliest_eval_stage,
|
||||
const Source& source) override;
|
||||
|
||||
UnaryOperator Lookup(ast::UnaryOp op, const sem::Type* arg, const Source& source) override;
|
||||
|
@ -1028,6 +1051,7 @@ class Impl : public IntrinsicTable {
|
|||
IntrinsicPrototype MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
||||
const char* intrinsic_name,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
sem::EvaluationStage earliest_eval_stage,
|
||||
TemplateState templates,
|
||||
OnNoMatch on_no_match) const;
|
||||
|
||||
|
@ -1040,6 +1064,7 @@ class Impl : public IntrinsicTable {
|
|||
/// @returns the evaluated Candidate information.
|
||||
Candidate ScoreOverload(const OverloadInfo* overload,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
sem::EvaluationStage earliest_eval_stage,
|
||||
TemplateState templates) const;
|
||||
|
||||
/// Performs overload resolution given the list of candidates, by ranking the conversions of
|
||||
|
@ -1063,7 +1088,8 @@ class Impl : public IntrinsicTable {
|
|||
/// @param matcher_indices pointer to a list of matcher indices
|
||||
MatchState Match(TemplateState& templates,
|
||||
const OverloadInfo* overload,
|
||||
MatcherIndex const* matcher_indices) const;
|
||||
MatcherIndex const* matcher_indices,
|
||||
sem::EvaluationStage earliest_eval_stage) const;
|
||||
|
||||
// Prints the overload for emitting diagnostics
|
||||
void PrintOverload(std::ostream& ss,
|
||||
|
@ -1129,6 +1155,7 @@ Impl::Impl(ProgramBuilder& b) : builder(b) {}
|
|||
|
||||
Impl::Builtin Impl::Lookup(sem::BuiltinType builtin_type,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
sem::EvaluationStage earliest_eval_stage,
|
||||
const Source& source) {
|
||||
const char* intrinsic_name = sem::str(builtin_type);
|
||||
|
||||
|
@ -1147,7 +1174,7 @@ Impl::Builtin Impl::Lookup(sem::BuiltinType builtin_type,
|
|||
|
||||
// Resolve the intrinsic overload
|
||||
auto match = MatchIntrinsic(kBuiltins[static_cast<size_t>(builtin_type)], intrinsic_name, args,
|
||||
TemplateState{}, on_no_match);
|
||||
earliest_eval_stage, TemplateState{}, on_no_match);
|
||||
if (!match.overload) {
|
||||
return {};
|
||||
}
|
||||
|
@ -1213,7 +1240,7 @@ IntrinsicTable::UnaryOperator Impl::Lookup(ast::UnaryOp op,
|
|||
|
||||
// Resolve the intrinsic overload
|
||||
auto match = MatchIntrinsic(kUnaryOperators[intrinsic_index], intrinsic_name, args,
|
||||
TemplateState{}, on_no_match);
|
||||
sem::EvaluationStage::kConstant, TemplateState{}, on_no_match);
|
||||
if (!match.overload) {
|
||||
return {};
|
||||
}
|
||||
|
@ -1290,7 +1317,7 @@ IntrinsicTable::BinaryOperator Impl::Lookup(ast::BinaryOp op,
|
|||
|
||||
// Resolve the intrinsic overload
|
||||
auto match = MatchIntrinsic(kBinaryOperators[intrinsic_index], intrinsic_name, args,
|
||||
TemplateState{}, on_no_match);
|
||||
sem::EvaluationStage::kConstant, TemplateState{}, on_no_match);
|
||||
if (!match.overload) {
|
||||
return {};
|
||||
}
|
||||
|
@ -1345,7 +1372,7 @@ IntrinsicTable::CtorOrConv Impl::Lookup(CtorConvIntrinsic type,
|
|||
|
||||
// Resolve the intrinsic overload
|
||||
auto match = MatchIntrinsic(kConstructorsAndConverters[static_cast<size_t>(type)], name, args,
|
||||
templates, on_no_match);
|
||||
sem::EvaluationStage::kConstant, templates, on_no_match);
|
||||
if (!match.overload) {
|
||||
return {};
|
||||
}
|
||||
|
@ -1383,6 +1410,7 @@ IntrinsicTable::CtorOrConv Impl::Lookup(CtorConvIntrinsic type,
|
|||
IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
||||
const char* intrinsic_name,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
sem::EvaluationStage earliest_eval_stage,
|
||||
TemplateState templates,
|
||||
OnNoMatch on_no_match) const {
|
||||
size_t num_matched = 0;
|
||||
|
@ -1391,7 +1419,8 @@ IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
|||
candidates.Reserve(intrinsic.num_overloads);
|
||||
for (size_t overload_idx = 0; overload_idx < static_cast<size_t>(intrinsic.num_overloads);
|
||||
overload_idx++) {
|
||||
auto candidate = ScoreOverload(&intrinsic.overloads[overload_idx], args, templates);
|
||||
auto candidate =
|
||||
ScoreOverload(&intrinsic.overloads[overload_idx], args, earliest_eval_stage, templates);
|
||||
if (candidate.score == 0) {
|
||||
match_idx = overload_idx;
|
||||
num_matched++;
|
||||
|
@ -1423,7 +1452,8 @@ IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
|||
const sem::Type* return_type = nullptr;
|
||||
if (auto* indices = match.overload->return_matcher_indices) {
|
||||
Any any;
|
||||
return_type = Match(match.templates, match.overload, indices).Type(&any);
|
||||
return_type =
|
||||
Match(match.templates, match.overload, indices, earliest_eval_stage).Type(&any);
|
||||
if (!return_type) {
|
||||
TINT_ICE(Resolver, builder.Diagnostics()) << "MatchState.Match() returned null";
|
||||
return {};
|
||||
|
@ -1437,6 +1467,7 @@ IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
|||
|
||||
Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
sem::EvaluationStage earliest_eval_stage,
|
||||
TemplateState templates) const {
|
||||
// Penalty weights for overload mismatching.
|
||||
// This scoring is used to order the suggested overloads in diagnostic on overload mismatch, and
|
||||
|
@ -1469,7 +1500,7 @@ Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
|||
for (size_t p = 0; p < num_params; p++) {
|
||||
auto& parameter = overload->parameters[p];
|
||||
auto* indices = parameter.matcher_indices;
|
||||
if (!Match(templates, overload, indices).Type(args[p]->UnwrapRef())) {
|
||||
if (!Match(templates, overload, indices, earliest_eval_stage).Type(args[p]->UnwrapRef())) {
|
||||
score += kMismatchedParamTypePenalty;
|
||||
}
|
||||
}
|
||||
|
@ -1485,7 +1516,8 @@ Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
|||
auto* matcher_index = &overload->template_types[ot].matcher_index;
|
||||
if (*matcher_index != kNoMatcher) {
|
||||
if (auto* template_type = templates.Type(ot)) {
|
||||
if (auto* ty = Match(templates, overload, matcher_index).Type(template_type)) {
|
||||
if (auto* ty = Match(templates, overload, matcher_index, earliest_eval_stage)
|
||||
.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);
|
||||
|
@ -1507,7 +1539,9 @@ Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
|||
if (*matcher_index != kNoMatcher) {
|
||||
auto template_num = templates.Num(on);
|
||||
if (!template_num.IsValid() ||
|
||||
!Match(templates, overload, matcher_index).Num(template_num).IsValid()) {
|
||||
!Match(templates, overload, matcher_index, earliest_eval_stage)
|
||||
.Num(template_num)
|
||||
.IsValid()) {
|
||||
score += kMismatchedTemplateNumberPenalty;
|
||||
}
|
||||
}
|
||||
|
@ -1521,7 +1555,8 @@ Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
|||
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());
|
||||
auto* ty =
|
||||
Match(templates, overload, indices, earliest_eval_stage).Type(args[p]->UnwrapRef());
|
||||
parameters.Emplace(ty, parameter.usage);
|
||||
}
|
||||
}
|
||||
|
@ -1596,8 +1631,9 @@ Impl::Candidate Impl::ResolveCandidate(Impl::Candidates&& candidates,
|
|||
|
||||
MatchState Impl::Match(TemplateState& templates,
|
||||
const OverloadInfo* overload,
|
||||
MatcherIndex const* matcher_indices) const {
|
||||
return MatchState(builder, templates, matchers, overload, matcher_indices);
|
||||
MatcherIndex const* matcher_indices,
|
||||
sem::EvaluationStage earliest_eval_stage) const {
|
||||
return MatchState(builder, templates, matchers, overload, matcher_indices, earliest_eval_stage);
|
||||
}
|
||||
|
||||
void Impl::PrintOverload(std::ostream& ss,
|
||||
|
@ -1605,6 +1641,8 @@ void Impl::PrintOverload(std::ostream& ss,
|
|||
const char* intrinsic_name) const {
|
||||
TemplateState templates;
|
||||
|
||||
auto earliest_eval_stage = sem::EvaluationStage::kConstant;
|
||||
|
||||
ss << intrinsic_name << "(";
|
||||
for (size_t p = 0; p < overload->num_parameters; p++) {
|
||||
auto& parameter = overload->parameters[p];
|
||||
|
@ -1615,13 +1653,13 @@ void Impl::PrintOverload(std::ostream& ss,
|
|||
ss << sem::str(parameter.usage) << ": ";
|
||||
}
|
||||
auto* indices = parameter.matcher_indices;
|
||||
ss << Match(templates, overload, indices).TypeName();
|
||||
ss << Match(templates, overload, indices, earliest_eval_stage).TypeName();
|
||||
}
|
||||
ss << ")";
|
||||
if (overload->return_matcher_indices) {
|
||||
ss << " -> ";
|
||||
auto* indices = overload->return_matcher_indices;
|
||||
ss << Match(templates, overload, indices).TypeName();
|
||||
ss << Match(templates, overload, indices, earliest_eval_stage).TypeName();
|
||||
}
|
||||
|
||||
bool first = true;
|
||||
|
@ -1635,7 +1673,7 @@ void Impl::PrintOverload(std::ostream& ss,
|
|||
separator();
|
||||
ss << template_type.name;
|
||||
auto* index = &template_type.matcher_index;
|
||||
ss << " is " << Match(templates, overload, index).TypeName();
|
||||
ss << " is " << Match(templates, overload, index, earliest_eval_stage).TypeName();
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < overload->num_template_numbers; i++) {
|
||||
|
@ -1644,7 +1682,7 @@ void Impl::PrintOverload(std::ostream& ss,
|
|||
separator();
|
||||
ss << template_number.name;
|
||||
auto* index = &template_number.matcher_index;
|
||||
ss << " is " << Match(templates, overload, index).NumName();
|
||||
ss << " is " << Match(templates, overload, index, earliest_eval_stage).NumName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,10 +84,17 @@ class IntrinsicTable {
|
|||
/// if the builtin was not found.
|
||||
/// @param type the builtin type
|
||||
/// @param args the argument types passed to the builtin function
|
||||
/// @param earliest_eval_stage the the earliest evaluation stage that a call to
|
||||
/// the builtin can be made. This can alter the overloads considered.
|
||||
/// For example, if the earliest evaluation stage is
|
||||
/// `sem::EvaluationStage::kRuntime`, then only concrete argument types
|
||||
/// will be considered, as all abstract-numerics will have been materialized
|
||||
/// after shader creation time (sem::EvaluationStage::kConstant).
|
||||
/// @param source the source of the builtin call
|
||||
/// @return the semantic builtin if found, otherwise nullptr
|
||||
virtual Builtin Lookup(sem::BuiltinType type,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
sem::EvaluationStage earliest_eval_stage,
|
||||
const Source& source) = 0;
|
||||
|
||||
/// Lookup looks for the unary op overload with the given signature, raising an error
|
||||
|
|
|
@ -38,7 +38,7 @@ class Bool : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* Bool::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_bool(ty)) {
|
||||
if (!match_bool(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_bool(state);
|
||||
|
@ -64,7 +64,7 @@ class Ia : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* Ia::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_ia(ty)) {
|
||||
if (!match_ia(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_ia(state);
|
||||
|
@ -92,7 +92,7 @@ class Fa : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* Fa::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_fa(ty)) {
|
||||
if (!match_fa(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_fa(state);
|
||||
|
@ -120,7 +120,7 @@ class I32 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* I32::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_i32(ty)) {
|
||||
if (!match_i32(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_i32(state);
|
||||
|
@ -146,7 +146,7 @@ class U32 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* U32::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_u32(ty)) {
|
||||
if (!match_u32(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_u32(state);
|
||||
|
@ -172,7 +172,7 @@ class F32 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* F32::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_f32(ty)) {
|
||||
if (!match_f32(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_f32(state);
|
||||
|
@ -198,7 +198,7 @@ class F16 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* F16::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_f16(ty)) {
|
||||
if (!match_f16(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_f16(state);
|
||||
|
@ -225,7 +225,7 @@ class Vec2 : public TypeMatcher {
|
|||
|
||||
const sem::Type* Vec2::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_vec2(ty, T)) {
|
||||
if (!match_vec2(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -257,7 +257,7 @@ class Vec3 : public TypeMatcher {
|
|||
|
||||
const sem::Type* Vec3::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_vec3(ty, T)) {
|
||||
if (!match_vec3(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -289,7 +289,7 @@ class Vec4 : public TypeMatcher {
|
|||
|
||||
const sem::Type* Vec4::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_vec4(ty, T)) {
|
||||
if (!match_vec4(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -321,7 +321,7 @@ class Mat2X2 : public TypeMatcher {
|
|||
|
||||
const sem::Type* Mat2X2::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_mat2x2(ty, T)) {
|
||||
if (!match_mat2x2(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -353,7 +353,7 @@ class Mat2X3 : public TypeMatcher {
|
|||
|
||||
const sem::Type* Mat2X3::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_mat2x3(ty, T)) {
|
||||
if (!match_mat2x3(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -385,7 +385,7 @@ class Mat2X4 : public TypeMatcher {
|
|||
|
||||
const sem::Type* Mat2X4::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_mat2x4(ty, T)) {
|
||||
if (!match_mat2x4(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -417,7 +417,7 @@ class Mat3X2 : public TypeMatcher {
|
|||
|
||||
const sem::Type* Mat3X2::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_mat3x2(ty, T)) {
|
||||
if (!match_mat3x2(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -449,7 +449,7 @@ class Mat3X3 : public TypeMatcher {
|
|||
|
||||
const sem::Type* Mat3X3::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_mat3x3(ty, T)) {
|
||||
if (!match_mat3x3(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -481,7 +481,7 @@ class Mat3X4 : public TypeMatcher {
|
|||
|
||||
const sem::Type* Mat3X4::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_mat3x4(ty, T)) {
|
||||
if (!match_mat3x4(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -513,7 +513,7 @@ class Mat4X2 : public TypeMatcher {
|
|||
|
||||
const sem::Type* Mat4X2::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_mat4x2(ty, T)) {
|
||||
if (!match_mat4x2(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -545,7 +545,7 @@ class Mat4X3 : public TypeMatcher {
|
|||
|
||||
const sem::Type* Mat4X3::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_mat4x3(ty, T)) {
|
||||
if (!match_mat4x3(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -577,7 +577,7 @@ class Mat4X4 : public TypeMatcher {
|
|||
|
||||
const sem::Type* Mat4X4::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_mat4x4(ty, T)) {
|
||||
if (!match_mat4x4(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -610,7 +610,7 @@ class Vec : public TypeMatcher {
|
|||
const sem::Type* Vec::Match(MatchState& state, const sem::Type* ty) const {
|
||||
Number N = Number::invalid;
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_vec(ty, N, T)) {
|
||||
if (!match_vec(state, ty, N, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
N = state.Num(N);
|
||||
|
@ -651,7 +651,7 @@ const sem::Type* Mat::Match(MatchState& state, const sem::Type* ty) const {
|
|||
Number N = Number::invalid;
|
||||
Number M = Number::invalid;
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_mat(ty, N, M, T)) {
|
||||
if (!match_mat(state, ty, N, M, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
N = state.Num(N);
|
||||
|
@ -697,7 +697,7 @@ const sem::Type* Ptr::Match(MatchState& state, const sem::Type* ty) const {
|
|||
Number S = Number::invalid;
|
||||
const sem::Type* T = nullptr;
|
||||
Number A = Number::invalid;
|
||||
if (!match_ptr(ty, S, T, A)) {
|
||||
if (!match_ptr(state, ty, S, T, A)) {
|
||||
return nullptr;
|
||||
}
|
||||
S = state.Num(S);
|
||||
|
@ -739,7 +739,7 @@ class Atomic : public TypeMatcher {
|
|||
|
||||
const sem::Type* Atomic::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_atomic(ty, T)) {
|
||||
if (!match_atomic(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -771,7 +771,7 @@ class Array : public TypeMatcher {
|
|||
|
||||
const sem::Type* Array::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_array(ty, T)) {
|
||||
if (!match_array(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -802,7 +802,7 @@ class Sampler : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* Sampler::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_sampler(ty)) {
|
||||
if (!match_sampler(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_sampler(state);
|
||||
|
@ -828,7 +828,7 @@ class SamplerComparison : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* SamplerComparison::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_sampler_comparison(ty)) {
|
||||
if (!match_sampler_comparison(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_sampler_comparison(state);
|
||||
|
@ -855,7 +855,7 @@ class Texture1D : public TypeMatcher {
|
|||
|
||||
const sem::Type* Texture1D::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_texture_1d(ty, T)) {
|
||||
if (!match_texture_1d(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -887,7 +887,7 @@ class Texture2D : public TypeMatcher {
|
|||
|
||||
const sem::Type* Texture2D::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_texture_2d(ty, T)) {
|
||||
if (!match_texture_2d(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -919,7 +919,7 @@ class Texture2DArray : public TypeMatcher {
|
|||
|
||||
const sem::Type* Texture2DArray::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_texture_2d_array(ty, T)) {
|
||||
if (!match_texture_2d_array(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -951,7 +951,7 @@ class Texture3D : public TypeMatcher {
|
|||
|
||||
const sem::Type* Texture3D::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_texture_3d(ty, T)) {
|
||||
if (!match_texture_3d(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -983,7 +983,7 @@ class TextureCube : public TypeMatcher {
|
|||
|
||||
const sem::Type* TextureCube::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_texture_cube(ty, T)) {
|
||||
if (!match_texture_cube(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -1015,7 +1015,7 @@ class TextureCubeArray : public TypeMatcher {
|
|||
|
||||
const sem::Type* TextureCubeArray::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_texture_cube_array(ty, T)) {
|
||||
if (!match_texture_cube_array(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -1047,7 +1047,7 @@ class TextureMultisampled2D : public TypeMatcher {
|
|||
|
||||
const sem::Type* TextureMultisampled2D::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_texture_multisampled_2d(ty, T)) {
|
||||
if (!match_texture_multisampled_2d(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -1078,7 +1078,7 @@ class TextureDepth2D : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* TextureDepth2D::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_texture_depth_2d(ty)) {
|
||||
if (!match_texture_depth_2d(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_texture_depth_2d(state);
|
||||
|
@ -1104,7 +1104,7 @@ class TextureDepth2DArray : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* TextureDepth2DArray::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_texture_depth_2d_array(ty)) {
|
||||
if (!match_texture_depth_2d_array(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_texture_depth_2d_array(state);
|
||||
|
@ -1130,7 +1130,7 @@ class TextureDepthCube : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* TextureDepthCube::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_texture_depth_cube(ty)) {
|
||||
if (!match_texture_depth_cube(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_texture_depth_cube(state);
|
||||
|
@ -1156,7 +1156,7 @@ class TextureDepthCubeArray : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* TextureDepthCubeArray::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_texture_depth_cube_array(ty)) {
|
||||
if (!match_texture_depth_cube_array(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_texture_depth_cube_array(state);
|
||||
|
@ -1182,7 +1182,7 @@ class TextureDepthMultisampled2D : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* TextureDepthMultisampled2D::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_texture_depth_multisampled_2d(ty)) {
|
||||
if (!match_texture_depth_multisampled_2d(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_texture_depth_multisampled_2d(state);
|
||||
|
@ -1210,7 +1210,7 @@ class TextureStorage1D : public TypeMatcher {
|
|||
const sem::Type* TextureStorage1D::Match(MatchState& state, const sem::Type* ty) const {
|
||||
Number F = Number::invalid;
|
||||
Number A = Number::invalid;
|
||||
if (!match_texture_storage_1d(ty, F, A)) {
|
||||
if (!match_texture_storage_1d(state, ty, F, A)) {
|
||||
return nullptr;
|
||||
}
|
||||
F = state.Num(F);
|
||||
|
@ -1248,7 +1248,7 @@ class TextureStorage2D : public TypeMatcher {
|
|||
const sem::Type* TextureStorage2D::Match(MatchState& state, const sem::Type* ty) const {
|
||||
Number F = Number::invalid;
|
||||
Number A = Number::invalid;
|
||||
if (!match_texture_storage_2d(ty, F, A)) {
|
||||
if (!match_texture_storage_2d(state, ty, F, A)) {
|
||||
return nullptr;
|
||||
}
|
||||
F = state.Num(F);
|
||||
|
@ -1286,7 +1286,7 @@ class TextureStorage2DArray : public TypeMatcher {
|
|||
const sem::Type* TextureStorage2DArray::Match(MatchState& state, const sem::Type* ty) const {
|
||||
Number F = Number::invalid;
|
||||
Number A = Number::invalid;
|
||||
if (!match_texture_storage_2d_array(ty, F, A)) {
|
||||
if (!match_texture_storage_2d_array(state, ty, F, A)) {
|
||||
return nullptr;
|
||||
}
|
||||
F = state.Num(F);
|
||||
|
@ -1324,7 +1324,7 @@ class TextureStorage3D : public TypeMatcher {
|
|||
const sem::Type* TextureStorage3D::Match(MatchState& state, const sem::Type* ty) const {
|
||||
Number F = Number::invalid;
|
||||
Number A = Number::invalid;
|
||||
if (!match_texture_storage_3d(ty, F, A)) {
|
||||
if (!match_texture_storage_3d(state, ty, F, A)) {
|
||||
return nullptr;
|
||||
}
|
||||
F = state.Num(F);
|
||||
|
@ -1360,7 +1360,7 @@ class TextureExternal : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* TextureExternal::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (!match_texture_external(ty)) {
|
||||
if (!match_texture_external(state, ty)) {
|
||||
return nullptr;
|
||||
}
|
||||
return build_texture_external(state);
|
||||
|
@ -1387,7 +1387,7 @@ class ModfResult : public TypeMatcher {
|
|||
|
||||
const sem::Type* ModfResult::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_modf_result(ty, T)) {
|
||||
if (!match_modf_result(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -1422,7 +1422,7 @@ class ModfResultVec : public TypeMatcher {
|
|||
const sem::Type* ModfResultVec::Match(MatchState& state, const sem::Type* ty) const {
|
||||
Number N = Number::invalid;
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_modf_result_vec(ty, N, T)) {
|
||||
if (!match_modf_result_vec(state, ty, N, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
N = state.Num(N);
|
||||
|
@ -1461,7 +1461,7 @@ class FrexpResult : public TypeMatcher {
|
|||
|
||||
const sem::Type* FrexpResult::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_frexp_result(ty, T)) {
|
||||
if (!match_frexp_result(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -1496,7 +1496,7 @@ class FrexpResultVec : public TypeMatcher {
|
|||
const sem::Type* FrexpResultVec::Match(MatchState& state, const sem::Type* ty) const {
|
||||
Number N = Number::invalid;
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_frexp_result_vec(ty, N, T)) {
|
||||
if (!match_frexp_result_vec(state, ty, N, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
N = state.Num(N);
|
||||
|
@ -1535,7 +1535,7 @@ class AtomicCompareExchangeResult : public TypeMatcher {
|
|||
|
||||
const sem::Type* AtomicCompareExchangeResult::Match(MatchState& state, const sem::Type* ty) const {
|
||||
const sem::Type* T = nullptr;
|
||||
if (!match_atomic_compare_exchange_result(ty, T)) {
|
||||
if (!match_atomic_compare_exchange_result(state, ty, T)) {
|
||||
return nullptr;
|
||||
}
|
||||
T = state.Type(T);
|
||||
|
@ -1567,25 +1567,25 @@ class AbstractOrScalar : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* AbstractOrScalar::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_ia(ty)) {
|
||||
if (match_ia(state, ty)) {
|
||||
return build_ia(state);
|
||||
}
|
||||
if (match_fa(ty)) {
|
||||
if (match_fa(state, ty)) {
|
||||
return build_fa(state);
|
||||
}
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_u32(ty)) {
|
||||
if (match_u32(state, ty)) {
|
||||
return build_u32(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
if (match_f16(ty)) {
|
||||
if (match_f16(state, ty)) {
|
||||
return build_f16(state);
|
||||
}
|
||||
if (match_bool(ty)) {
|
||||
if (match_bool(state, ty)) {
|
||||
return build_bool(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -1616,19 +1616,19 @@ class Scalar : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* Scalar::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_u32(ty)) {
|
||||
if (match_u32(state, ty)) {
|
||||
return build_u32(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
if (match_f16(ty)) {
|
||||
if (match_f16(state, ty)) {
|
||||
return build_f16(state);
|
||||
}
|
||||
if (match_bool(ty)) {
|
||||
if (match_bool(state, ty)) {
|
||||
return build_bool(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -1659,16 +1659,16 @@ class ScalarNoF32 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* ScalarNoF32::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_u32(ty)) {
|
||||
if (match_u32(state, ty)) {
|
||||
return build_u32(state);
|
||||
}
|
||||
if (match_f16(ty)) {
|
||||
if (match_f16(state, ty)) {
|
||||
return build_f16(state);
|
||||
}
|
||||
if (match_bool(ty)) {
|
||||
if (match_bool(state, ty)) {
|
||||
return build_bool(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -1699,16 +1699,16 @@ class ScalarNoF16 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* ScalarNoF16::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_u32(ty)) {
|
||||
if (match_u32(state, ty)) {
|
||||
return build_u32(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
if (match_bool(ty)) {
|
||||
if (match_bool(state, ty)) {
|
||||
return build_bool(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -1739,16 +1739,16 @@ class ScalarNoI32 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* ScalarNoI32::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_u32(ty)) {
|
||||
if (match_u32(state, ty)) {
|
||||
return build_u32(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
if (match_f16(ty)) {
|
||||
if (match_f16(state, ty)) {
|
||||
return build_f16(state);
|
||||
}
|
||||
if (match_bool(ty)) {
|
||||
if (match_bool(state, ty)) {
|
||||
return build_bool(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -1779,16 +1779,16 @@ class ScalarNoU32 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* ScalarNoU32::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
if (match_f16(ty)) {
|
||||
if (match_f16(state, ty)) {
|
||||
return build_f16(state);
|
||||
}
|
||||
if (match_bool(ty)) {
|
||||
if (match_bool(state, ty)) {
|
||||
return build_bool(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -1819,16 +1819,16 @@ class ScalarNoBool : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* ScalarNoBool::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_u32(ty)) {
|
||||
if (match_u32(state, ty)) {
|
||||
return build_u32(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
if (match_f16(ty)) {
|
||||
if (match_f16(state, ty)) {
|
||||
return build_f16(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -1859,22 +1859,22 @@ class FiaFiu32F16 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* FiaFiu32F16::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_ia(ty)) {
|
||||
if (match_ia(state, ty)) {
|
||||
return build_ia(state);
|
||||
}
|
||||
if (match_fa(ty)) {
|
||||
if (match_fa(state, ty)) {
|
||||
return build_fa(state);
|
||||
}
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_u32(ty)) {
|
||||
if (match_u32(state, ty)) {
|
||||
return build_u32(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
if (match_f16(ty)) {
|
||||
if (match_f16(state, ty)) {
|
||||
return build_f16(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -1905,19 +1905,19 @@ class FiaFi32F16 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* FiaFi32F16::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_ia(ty)) {
|
||||
if (match_ia(state, ty)) {
|
||||
return build_ia(state);
|
||||
}
|
||||
if (match_fa(ty)) {
|
||||
if (match_fa(state, ty)) {
|
||||
return build_fa(state);
|
||||
}
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
if (match_f16(ty)) {
|
||||
if (match_f16(state, ty)) {
|
||||
return build_f16(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -1948,19 +1948,19 @@ class FiaFiu32 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* FiaFiu32::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_ia(ty)) {
|
||||
if (match_ia(state, ty)) {
|
||||
return build_ia(state);
|
||||
}
|
||||
if (match_fa(ty)) {
|
||||
if (match_fa(state, ty)) {
|
||||
return build_fa(state);
|
||||
}
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_u32(ty)) {
|
||||
if (match_u32(state, ty)) {
|
||||
return build_u32(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -1991,10 +1991,10 @@ class FaF32 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* FaF32::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_fa(ty)) {
|
||||
if (match_fa(state, ty)) {
|
||||
return build_fa(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -2025,13 +2025,13 @@ class FaF32F16 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* FaF32F16::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_fa(ty)) {
|
||||
if (match_fa(state, ty)) {
|
||||
return build_fa(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
if (match_f16(ty)) {
|
||||
if (match_f16(state, ty)) {
|
||||
return build_f16(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -2062,13 +2062,13 @@ class IaIu32 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* IaIu32::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_ia(ty)) {
|
||||
if (match_ia(state, ty)) {
|
||||
return build_ia(state);
|
||||
}
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_u32(ty)) {
|
||||
if (match_u32(state, ty)) {
|
||||
return build_u32(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -2099,16 +2099,16 @@ class Fiu32F16 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* Fiu32F16::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_u32(ty)) {
|
||||
if (match_u32(state, ty)) {
|
||||
return build_u32(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
if (match_f16(ty)) {
|
||||
if (match_f16(state, ty)) {
|
||||
return build_f16(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -2139,13 +2139,13 @@ class Fiu32 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* Fiu32::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_u32(ty)) {
|
||||
if (match_u32(state, ty)) {
|
||||
return build_u32(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -2176,13 +2176,13 @@ class Fi32F16 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* Fi32F16::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
if (match_f16(ty)) {
|
||||
if (match_f16(state, ty)) {
|
||||
return build_f16(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -2213,10 +2213,10 @@ class Fi32 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* Fi32::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -2247,10 +2247,10 @@ class F32F16 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* F32F16::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_f32(ty)) {
|
||||
if (match_f32(state, ty)) {
|
||||
return build_f32(state);
|
||||
}
|
||||
if (match_f16(ty)) {
|
||||
if (match_f16(state, ty)) {
|
||||
return build_f16(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -2281,10 +2281,10 @@ class Iu32 : public TypeMatcher {
|
|||
};
|
||||
|
||||
const sem::Type* Iu32::Match(MatchState& state, const sem::Type* ty) const {
|
||||
if (match_i32(ty)) {
|
||||
if (match_i32(state, ty)) {
|
||||
return build_i32(state);
|
||||
}
|
||||
if (match_u32(ty)) {
|
||||
if (match_u32(state, ty)) {
|
||||
return build_u32(state);
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
@ -201,7 +201,7 @@ const sem::Type* {{$class}}::Match(MatchState& state, const sem::Type* ty) const
|
|||
{{- range .TemplateParams }}
|
||||
{{- template "DeclareLocalTemplateParam" . }}
|
||||
{{- end }}
|
||||
if (!match_{{TrimLeft .Name "_"}}(ty{{range .TemplateParams}}, {{.GetName}}{{end}})) {
|
||||
if (!match_{{TrimLeft .Name "_"}}(state, ty{{range .TemplateParams}}, {{.GetName}}{{end}})) {
|
||||
return nullptr;
|
||||
}
|
||||
{{- range .TemplateParams }}
|
||||
|
@ -254,7 +254,7 @@ class {{$class}} : public TypeMatcher {
|
|||
|
||||
const sem::Type* {{$class}}::Match(MatchState& state, const sem::Type* ty) const {
|
||||
{{- range .PrecedenceSortedTypes }}
|
||||
if (match_{{.Name}}(ty)) {
|
||||
if (match_{{.Name}}(state, ty)) {
|
||||
return build_{{.Name}}(state);
|
||||
}
|
||||
{{- end }}
|
||||
|
|
|
@ -53,7 +53,8 @@ class IntrinsicTableTest : public testing::Test, public ProgramBuilder {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MatchF32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kCos, utils::Vector{f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kCos, utils::Vector{f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kCos);
|
||||
|
@ -64,7 +65,8 @@ TEST_F(IntrinsicTableTest, MatchF32) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MismatchF32) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto result = table->Lookup(BuiltinType::kCos, utils::Vector{i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kCos, utils::Vector{i32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -73,7 +75,8 @@ TEST_F(IntrinsicTableTest, MatchU32) {
|
|||
auto* f32 = create<sem::F32>();
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto* vec2_f32 = create<sem::Vector>(f32, 2u);
|
||||
auto result = table->Lookup(BuiltinType::kUnpack2x16float, utils::Vector{u32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kUnpack2x16float, utils::Vector{u32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kUnpack2x16float);
|
||||
|
@ -84,7 +87,8 @@ TEST_F(IntrinsicTableTest, MatchU32) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MismatchU32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kUnpack2x16float, utils::Vector{f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kUnpack2x16float, utils::Vector{f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -94,7 +98,8 @@ TEST_F(IntrinsicTableTest, MatchI32) {
|
|||
auto* i32 = create<sem::I32>();
|
||||
auto* vec4_f32 = create<sem::Vector>(f32, 4u);
|
||||
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k1d, f32);
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, i32, i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, i32, i32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
|
||||
|
@ -111,14 +116,16 @@ TEST_F(IntrinsicTableTest, MatchI32) {
|
|||
TEST_F(IntrinsicTableTest, MismatchI32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k1d, f32);
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchIU32AsI32) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto result = table->Lookup(BuiltinType::kCountOneBits, utils::Vector{i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kCountOneBits, utils::Vector{i32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kCountOneBits);
|
||||
|
@ -129,7 +136,8 @@ TEST_F(IntrinsicTableTest, MatchIU32AsI32) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MatchIU32AsU32) {
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto result = table->Lookup(BuiltinType::kCountOneBits, utils::Vector{u32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kCountOneBits, utils::Vector{u32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kCountOneBits);
|
||||
|
@ -140,14 +148,16 @@ TEST_F(IntrinsicTableTest, MatchIU32AsU32) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MismatchIU32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kCountOneBits, utils::Vector{f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kCountOneBits, utils::Vector{f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchFIU32AsI32) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{i32, i32, i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{i32, i32, i32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
|
||||
|
@ -160,7 +170,8 @@ TEST_F(IntrinsicTableTest, MatchFIU32AsI32) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MatchFIU32AsU32) {
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{u32, u32, u32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{u32, u32, u32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
|
||||
|
@ -173,7 +184,8 @@ TEST_F(IntrinsicTableTest, MatchFIU32AsU32) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MatchFIU32AsF32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{f32, f32, f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{f32, f32, f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
|
||||
|
@ -186,7 +198,8 @@ TEST_F(IntrinsicTableTest, MatchFIU32AsF32) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MismatchFIU32) {
|
||||
auto* bool_ = create<sem::Bool>();
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{bool_, bool_, bool_}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{bool_, bool_, bool_},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -194,7 +207,8 @@ TEST_F(IntrinsicTableTest, MismatchFIU32) {
|
|||
TEST_F(IntrinsicTableTest, MatchBool) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* bool_ = create<sem::Bool>();
|
||||
auto result = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, bool_}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, bool_},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kSelect);
|
||||
|
@ -207,7 +221,8 @@ TEST_F(IntrinsicTableTest, MatchBool) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MismatchBool) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -217,7 +232,8 @@ TEST_F(IntrinsicTableTest, MatchPointer) {
|
|||
auto* atomicI32 = create<sem::Atomic>(i32);
|
||||
auto* ptr =
|
||||
create<sem::Pointer>(atomicI32, ast::AddressSpace::kWorkgroup, ast::Access::kReadWrite);
|
||||
auto result = table->Lookup(BuiltinType::kAtomicLoad, utils::Vector{ptr}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kAtomicLoad, utils::Vector{ptr},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kAtomicLoad);
|
||||
|
@ -229,7 +245,8 @@ TEST_F(IntrinsicTableTest, MatchPointer) {
|
|||
TEST_F(IntrinsicTableTest, MismatchPointer) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* atomicI32 = create<sem::Atomic>(i32);
|
||||
auto result = table->Lookup(BuiltinType::kAtomicLoad, utils::Vector{atomicI32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kAtomicLoad, utils::Vector{atomicI32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -237,7 +254,8 @@ TEST_F(IntrinsicTableTest, MismatchPointer) {
|
|||
TEST_F(IntrinsicTableTest, MatchArray) {
|
||||
auto* arr = create<sem::Array>(create<sem::U32>(), sem::RuntimeArrayCount{}, 4u, 4u, 4u, 4u);
|
||||
auto* arr_ptr = create<sem::Pointer>(arr, ast::AddressSpace::kStorage, ast::Access::kReadWrite);
|
||||
auto result = table->Lookup(BuiltinType::kArrayLength, utils::Vector{arr_ptr}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kArrayLength, utils::Vector{arr_ptr},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kArrayLength);
|
||||
|
@ -250,7 +268,8 @@ TEST_F(IntrinsicTableTest, MatchArray) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MismatchArray) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kArrayLength, utils::Vector{f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kArrayLength, utils::Vector{f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -261,8 +280,8 @@ TEST_F(IntrinsicTableTest, MatchSampler) {
|
|||
auto* vec4_f32 = create<sem::Vector>(f32, 4u);
|
||||
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
|
||||
auto* sampler = create<sem::Sampler>(ast::SamplerKind::kSampler);
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureSample, utils::Vector{tex, sampler, vec2_f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureSample, utils::Vector{tex, sampler, vec2_f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureSample);
|
||||
|
@ -280,8 +299,8 @@ TEST_F(IntrinsicTableTest, MismatchSampler) {
|
|||
auto* f32 = create<sem::F32>();
|
||||
auto* vec2_f32 = create<sem::Vector>(f32, 2u);
|
||||
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureSample, utils::Vector{tex, f32, vec2_f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureSample, utils::Vector{tex, f32, vec2_f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -292,8 +311,8 @@ TEST_F(IntrinsicTableTest, MatchSampledTexture) {
|
|||
auto* vec2_i32 = create<sem::Vector>(i32, 2u);
|
||||
auto* vec4_f32 = create<sem::Vector>(f32, 4u);
|
||||
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
|
||||
|
@ -313,8 +332,8 @@ TEST_F(IntrinsicTableTest, MatchMultisampledTexture) {
|
|||
auto* vec2_i32 = create<sem::Vector>(i32, 2u);
|
||||
auto* vec4_f32 = create<sem::Vector>(f32, 4u);
|
||||
auto* tex = create<sem::MultisampledTexture>(ast::TextureDimension::k2d, f32);
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
|
||||
|
@ -333,8 +352,8 @@ TEST_F(IntrinsicTableTest, MatchDepthTexture) {
|
|||
auto* i32 = create<sem::I32>();
|
||||
auto* vec2_i32 = create<sem::Vector>(i32, 2u);
|
||||
auto* tex = create<sem::DepthTexture>(ast::TextureDimension::k2d);
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
|
||||
|
@ -353,8 +372,8 @@ TEST_F(IntrinsicTableTest, MatchDepthMultisampledTexture) {
|
|||
auto* i32 = create<sem::I32>();
|
||||
auto* vec2_i32 = create<sem::Vector>(i32, 2u);
|
||||
auto* tex = create<sem::DepthMultisampledTexture>(ast::TextureDimension::k2d);
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
|
||||
|
@ -374,7 +393,8 @@ TEST_F(IntrinsicTableTest, MatchExternalTexture) {
|
|||
auto* vec2_i32 = create<sem::Vector>(i32, 2u);
|
||||
auto* vec4_f32 = create<sem::Vector>(f32, 4u);
|
||||
auto* tex = create<sem::ExternalTexture>();
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
|
||||
|
@ -395,8 +415,8 @@ TEST_F(IntrinsicTableTest, MatchWOStorageTexture) {
|
|||
auto* tex = create<sem::StorageTexture>(ast::TextureDimension::k2d, ast::TexelFormat::kR32Float,
|
||||
ast::Access::kWrite, subtype);
|
||||
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureStore, utils::Vector{tex, vec2_i32, vec4_f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureStore, utils::Vector{tex, vec2_i32, vec4_f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureStore);
|
||||
|
@ -414,7 +434,8 @@ TEST_F(IntrinsicTableTest, MismatchTexture) {
|
|||
auto* f32 = create<sem::F32>();
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* vec2_i32 = create<sem::Vector>(i32, 2u);
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{f32, vec2_i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{f32, vec2_i32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -426,7 +447,7 @@ TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) {
|
|||
utils::Vector{
|
||||
create<sem::Reference>(f32, ast::AddressSpace::kFunction, ast::Access::kReadWrite),
|
||||
},
|
||||
Source{});
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kCos);
|
||||
|
@ -437,7 +458,8 @@ TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MatchTemplateType) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{f32, f32, f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{f32, f32, f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
|
||||
|
@ -450,7 +472,8 @@ TEST_F(IntrinsicTableTest, MatchTemplateType) {
|
|||
TEST_F(IntrinsicTableTest, MismatchTemplateType) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{f32, u32, f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{f32, u32, f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -458,8 +481,8 @@ TEST_F(IntrinsicTableTest, MismatchTemplateType) {
|
|||
TEST_F(IntrinsicTableTest, MatchOpenSizeVector) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* vec2_f32 = create<sem::Vector>(f32, 2u);
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kClamp, utils::Vector{vec2_f32, vec2_f32, vec2_f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{vec2_f32, vec2_f32, vec2_f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
|
||||
|
@ -474,8 +497,8 @@ TEST_F(IntrinsicTableTest, MismatchOpenSizeVector) {
|
|||
auto* f32 = create<sem::F32>();
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto* vec2_f32 = create<sem::Vector>(f32, 2u);
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kClamp, utils::Vector{vec2_f32, u32, vec2_f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{vec2_f32, u32, vec2_f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -484,7 +507,8 @@ TEST_F(IntrinsicTableTest, MatchOpenSizeMatrix) {
|
|||
auto* f32 = create<sem::F32>();
|
||||
auto* vec3_f32 = create<sem::Vector>(f32, 3u);
|
||||
auto* mat3_f32 = create<sem::Matrix>(vec3_f32, 3u);
|
||||
auto result = table->Lookup(BuiltinType::kDeterminant, utils::Vector{mat3_f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kDeterminant, utils::Vector{mat3_f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kDeterminant);
|
||||
|
@ -497,16 +521,50 @@ TEST_F(IntrinsicTableTest, MismatchOpenSizeMatrix) {
|
|||
auto* f32 = create<sem::F32>();
|
||||
auto* vec2_f32 = create<sem::Vector>(f32, 2u);
|
||||
auto* mat3x2_f32 = create<sem::Matrix>(vec2_f32, 3u);
|
||||
auto result = table->Lookup(BuiltinType::kDeterminant, utils::Vector{mat3x2_f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kDeterminant, utils::Vector{mat3x2_f32},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
// TODO(amaiorano): Enable this test when constexpr `select` is implemented.
|
||||
TEST_F(IntrinsicTableTest, DISABLED_MatchDifferentArgsElementType_ConstantEval) {
|
||||
auto* af = create<sem::AbstractFloat>();
|
||||
auto* bool_ = create<sem::Bool>();
|
||||
auto result = table->Lookup(BuiltinType::kSelect, utils::Vector{af, af, bool_},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kSelect);
|
||||
EXPECT_EQ(result.sem->ReturnType(), af);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), af);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), af);
|
||||
EXPECT_EQ(result.sem->Parameters()[2]->Type(), bool_);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchDifferentArgsElementType_RuntimeEval) {
|
||||
auto* af = create<sem::AbstractFloat>();
|
||||
auto* bool_ref = create<sem::Reference>(create<sem::Bool>(), ast::AddressSpace::kFunction,
|
||||
ast::Access::kReadWrite);
|
||||
auto result = table->Lookup(BuiltinType::kSelect, utils::Vector{af, af, bool_ref},
|
||||
sem::EvaluationStage::kRuntime, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kSelect);
|
||||
EXPECT_TRUE(result.sem->ReturnType()->Is<sem::F32>());
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_TRUE(result.sem->Parameters()[0]->Type()->Is<sem::F32>());
|
||||
EXPECT_TRUE(result.sem->Parameters()[1]->Type()->Is<sem::F32>());
|
||||
EXPECT_TRUE(result.sem->Parameters()[2]->Type()->Is<sem::Bool>());
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, OverloadOrderByNumberOfParameters) {
|
||||
// None of the arguments match, so expect the overloads with 2 parameters to
|
||||
// come first
|
||||
auto* bool_ = create<sem::Bool>();
|
||||
table->Lookup(BuiltinType::kTextureDimensions, utils::Vector{bool_, bool_}, Source{});
|
||||
table->Lookup(BuiltinType::kTextureDimensions, utils::Vector{bool_, bool_},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(Diagnostics().str(),
|
||||
R"(error: no matching call to textureDimensions(bool, bool)
|
||||
|
||||
|
@ -544,7 +602,8 @@ TEST_F(IntrinsicTableTest, OverloadOrderByNumberOfParameters) {
|
|||
TEST_F(IntrinsicTableTest, OverloadOrderByMatchingParameter) {
|
||||
auto* tex = create<sem::DepthTexture>(ast::TextureDimension::k2d);
|
||||
auto* bool_ = create<sem::Bool>();
|
||||
table->Lookup(BuiltinType::kTextureDimensions, utils::Vector{tex, bool_}, Source{});
|
||||
table->Lookup(BuiltinType::kTextureDimensions, utils::Vector{tex, bool_},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(Diagnostics().str(),
|
||||
R"(error: no matching call to textureDimensions(texture_depth_2d, bool)
|
||||
|
||||
|
@ -583,15 +642,17 @@ TEST_F(IntrinsicTableTest, SameOverloadReturnsSameBuiltinPointer) {
|
|||
auto* f32 = create<sem::F32>();
|
||||
auto* vec2_f32 = create<sem::Vector>(create<sem::F32>(), 2u);
|
||||
auto* bool_ = create<sem::Bool>();
|
||||
auto a = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, bool_}, Source{});
|
||||
auto a = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, bool_},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(a.sem, nullptr) << Diagnostics().str();
|
||||
|
||||
auto b = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, bool_}, Source{});
|
||||
auto b = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, bool_},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(b.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
|
||||
auto c =
|
||||
table->Lookup(BuiltinType::kSelect, utils::Vector{vec2_f32, vec2_f32, bool_}, Source{});
|
||||
auto c = table->Lookup(BuiltinType::kSelect, utils::Vector{vec2_f32, vec2_f32, bool_},
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_NE(c.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
|
||||
|
@ -827,7 +888,8 @@ TEST_F(IntrinsicTableTest, Err257Arguments) { // crbug.com/1323605
|
|||
auto* f32 = create<sem::F32>();
|
||||
utils::Vector<const sem::Type*, 0> arg_tys;
|
||||
arg_tys.Resize(257, f32);
|
||||
auto result = table->Lookup(BuiltinType::kAbs, std::move(arg_tys), Source{});
|
||||
auto result = table->Lookup(BuiltinType::kAbs, std::move(arg_tys),
|
||||
sem::EvaluationStage::kConstant, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -1064,7 +1126,7 @@ TEST_P(IntrinsicTableAbstractTernaryTest, MatchClamp) {
|
|||
auto* arg_b = GetParam().arg_b(*this);
|
||||
auto* arg_c = GetParam().arg_c(*this);
|
||||
auto builtin = table->Lookup(sem::BuiltinType::kClamp, utils::Vector{arg_a, arg_b, arg_c},
|
||||
Source{{12, 34}});
|
||||
sem::EvaluationStage::kConstant, Source{{12, 34}});
|
||||
|
||||
bool matched = builtin.sem != nullptr;
|
||||
bool expected_match = GetParam().expected_match;
|
||||
|
@ -1295,8 +1357,8 @@ TEST_P(IntrinsicTableAbstractTernaryTest_NonConstEval, MatchMix) {
|
|||
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::kMix, utils::Vector{arg_a, arg_b, arg_c}, Source{{12, 34}});
|
||||
auto builtin = table->Lookup(sem::BuiltinType::kMix, utils::Vector{arg_a, arg_b, arg_c},
|
||||
sem::EvaluationStage::kConstant, Source{{12, 34}});
|
||||
|
||||
bool matched = builtin.sem != nullptr;
|
||||
bool expected_match = GetParam().expected_match;
|
||||
|
|
|
@ -1999,10 +1999,15 @@ template <size_t N>
|
|||
sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
||||
sem::BuiltinType builtin_type,
|
||||
utils::Vector<const sem::Expression*, N>& args) {
|
||||
auto arg_stage = sem::EvaluationStage::kConstant;
|
||||
for (auto* arg : args) {
|
||||
arg_stage = sem::EarliestStage(arg_stage, arg->Stage());
|
||||
}
|
||||
|
||||
IntrinsicTable::Builtin builtin;
|
||||
{
|
||||
auto arg_tys = utils::Transform(args, [](auto* arg) { return arg->Type(); });
|
||||
builtin = intrinsic_table_->Lookup(builtin_type, arg_tys, expr->source);
|
||||
builtin = intrinsic_table_->Lookup(builtin_type, arg_tys, arg_stage, expr->source);
|
||||
if (!builtin.sem) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2016,19 +2021,8 @@ sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
|||
AddWarning("use of deprecated builtin", expr->source);
|
||||
}
|
||||
|
||||
auto stage = builtin.sem->Stage();
|
||||
if (stage == sem::EvaluationStage::kConstant) { // <-- Optimization
|
||||
// If the builtin is not annotated with @const, then it can only be evaluated
|
||||
// at runtime, in which case there's no point checking the evaluation stage of the
|
||||
// arguments.
|
||||
|
||||
// The builtin is @const annotated. Check all arguments are also constant.
|
||||
for (auto* arg : args) {
|
||||
stage = sem::EarliestStage(stage, arg->Stage());
|
||||
}
|
||||
}
|
||||
|
||||
// If the builtin is @const, and all arguments have constant values, evaluate the builtin now.
|
||||
auto stage = sem::EarliestStage(arg_stage, builtin.sem->Stage());
|
||||
const sem::Constant* value = nullptr;
|
||||
if (stage == sem::EvaluationStage::kConstant) {
|
||||
auto const_args = ConvertArguments(args, builtin.sem);
|
||||
|
|
Loading…
Reference in New Issue