tint/resolver: Use utils::Vector in a few places
Use the new vector type in some of the hot code paths of the resolver. Bug: tint:1613 Change-Id: Ie56d8c96f73c9112f37934ad67e588513aafb982 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/96282 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Antonio Maiorano <amaiorano@google.com> Reviewed-by: Dan Sinclair <dsinclair@chromium.org> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
4b3d53d141
commit
958a4642f1
|
@ -26,6 +26,7 @@
|
|||
#include "src/tint/ast/phony_expression.h"
|
||||
#include "src/tint/ast/unary_op_expression.h"
|
||||
#include "src/tint/utils/reverse.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
|
@ -67,35 +68,34 @@ bool TraverseExpressions(const ast::Expression* root, diag::List& diags, CALLBAC
|
|||
size_t depth;
|
||||
};
|
||||
|
||||
std::vector<Pending> to_visit{{root, 0}};
|
||||
utils::Vector<Pending, 64> to_visit{{root, 0}};
|
||||
|
||||
auto push_single = [&](const ast::Expression* expr, size_t depth) {
|
||||
to_visit.push_back({expr, depth});
|
||||
to_visit.Push({expr, depth});
|
||||
};
|
||||
auto push_pair = [&](const ast::Expression* left, const ast::Expression* right, size_t depth) {
|
||||
if (ORDER == TraverseOrder::LeftToRight) {
|
||||
to_visit.push_back({right, depth});
|
||||
to_visit.push_back({left, depth});
|
||||
to_visit.Push({right, depth});
|
||||
to_visit.Push({left, depth});
|
||||
} else {
|
||||
to_visit.push_back({left, depth});
|
||||
to_visit.push_back({right, depth});
|
||||
to_visit.Push({left, depth});
|
||||
to_visit.Push({right, depth});
|
||||
}
|
||||
};
|
||||
auto push_list = [&](const std::vector<const ast::Expression*>& exprs, size_t depth) {
|
||||
if (ORDER == TraverseOrder::LeftToRight) {
|
||||
for (auto* expr : utils::Reverse(exprs)) {
|
||||
to_visit.push_back({expr, depth});
|
||||
to_visit.Push({expr, depth});
|
||||
}
|
||||
} else {
|
||||
for (auto* expr : exprs) {
|
||||
to_visit.push_back({expr, depth});
|
||||
to_visit.Push({expr, depth});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
while (!to_visit.empty()) {
|
||||
auto p = to_visit.back();
|
||||
to_visit.pop_back();
|
||||
while (!to_visit.IsEmpty()) {
|
||||
auto p = to_visit.Pop();
|
||||
const ast::Expression* expr = p.expr;
|
||||
|
||||
if (auto* filtered = expr->template As<EXPR_TYPE>()) {
|
||||
|
|
|
@ -468,7 +468,7 @@ struct CastableCommonBaseImpl {};
|
|||
|
||||
/// Alias to typename CastableCommonBaseImpl<TYPES>::type
|
||||
template <typename... TYPES>
|
||||
using CastableCommonBase = typename detail::CastableCommonBaseImpl<TYPES...>::type;
|
||||
using CastableCommonBase = typename CastableCommonBaseImpl<TYPES...>::type;
|
||||
|
||||
/// CastableCommonBaseImpl template specialization for a single type
|
||||
template <typename T>
|
||||
|
|
|
@ -1593,7 +1593,8 @@ INSTANTIATE_TEST_SUITE_P(ResolverTest,
|
|||
ResolverBuiltinTest_Texture,
|
||||
testing::ValuesIn(ast::builtin::test::TextureOverloadCase::ValidCases()));
|
||||
|
||||
std::string to_str(const std::string& function, const sem::ParameterList& params) {
|
||||
std::string to_str(const std::string& function,
|
||||
utils::ConstVectorRef<const sem::Parameter*> params) {
|
||||
std::stringstream out;
|
||||
out << function << "(";
|
||||
bool first = true;
|
||||
|
|
|
@ -119,7 +119,7 @@ struct Constant : public sem::Constant {
|
|||
// Forward declaration
|
||||
const Constant* CreateComposite(ProgramBuilder& builder,
|
||||
const sem::Type* type,
|
||||
std::vector<const sem::Constant*> elements);
|
||||
utils::VectorRef<const sem::Constant*> elements);
|
||||
|
||||
/// Element holds a single scalar or abstract-numeric value.
|
||||
/// Element implements the Constant interface.
|
||||
|
@ -251,13 +251,16 @@ struct Splat : Constant {
|
|||
/// implementation. Use CreateComposite() to create the appropriate Constant type.
|
||||
/// Composite implements the Constant interface.
|
||||
struct Composite : Constant {
|
||||
Composite(const sem::Type* t, std::vector<const sem::Constant*> els, bool all_0, bool any_0)
|
||||
Composite(const sem::Type* t,
|
||||
utils::VectorRef<const sem::Constant*> els,
|
||||
bool all_0,
|
||||
bool any_0)
|
||||
: type(t), elements(std::move(els)), all_zero(all_0), any_zero(any_0), hash(CalcHash()) {}
|
||||
~Composite() override = default;
|
||||
const sem::Type* Type() const override { return type; }
|
||||
std::variant<std::monostate, AInt, AFloat> Value() const override { return {}; }
|
||||
const sem::Constant* Index(size_t i) const override {
|
||||
return i < elements.size() ? elements[i] : nullptr;
|
||||
return i < elements.Length() ? elements[i] : nullptr;
|
||||
}
|
||||
bool AllZero() const override { return all_zero; }
|
||||
bool AnyZero() const override { return any_zero; }
|
||||
|
@ -269,8 +272,8 @@ struct Composite : Constant {
|
|||
const Source& source) const override {
|
||||
// Convert each of the composite element types.
|
||||
auto* el_ty = sem::Type::ElementOf(target_ty);
|
||||
std::vector<const sem::Constant*> conv_els;
|
||||
conv_els.reserve(elements.size());
|
||||
utils::Vector<const sem::Constant*, 4> conv_els;
|
||||
conv_els.Reserve(elements.Length());
|
||||
for (auto* el : elements) {
|
||||
// Note: This file is the only place where `sem::Constant`s are created, so this
|
||||
// static_cast is safe.
|
||||
|
@ -281,7 +284,7 @@ struct Composite : Constant {
|
|||
if (!conv_el.Get()) {
|
||||
return nullptr;
|
||||
}
|
||||
conv_els.emplace_back(conv_el.Get());
|
||||
conv_els.Push(conv_el.Get());
|
||||
}
|
||||
return CreateComposite(builder, target_ty, std::move(conv_els));
|
||||
}
|
||||
|
@ -295,7 +298,7 @@ struct Composite : Constant {
|
|||
}
|
||||
|
||||
sem::Type const* const type;
|
||||
const std::vector<const sem::Constant*> elements;
|
||||
const utils::Vector<const sem::Constant*, 8> elements;
|
||||
const bool all_zero;
|
||||
const bool any_zero;
|
||||
const size_t hash;
|
||||
|
@ -327,15 +330,15 @@ const Constant* ZeroValue(ProgramBuilder& builder, const sem::Type* type) {
|
|||
},
|
||||
[&](const sem::Struct* s) -> const Constant* {
|
||||
std::unordered_map<sem::Type*, const Constant*> zero_by_type;
|
||||
std::vector<const sem::Constant*> zeros;
|
||||
zeros.reserve(s->Members().size());
|
||||
utils::Vector<const sem::Constant*, 4> zeros;
|
||||
zeros.Reserve(s->Members().size());
|
||||
for (auto* member : s->Members()) {
|
||||
auto* zero = utils::GetOrCreate(zero_by_type, member->Type(),
|
||||
[&] { return ZeroValue(builder, member->Type()); });
|
||||
if (!zero) {
|
||||
return nullptr;
|
||||
}
|
||||
zeros.emplace_back(zero);
|
||||
zeros.Push(zero);
|
||||
}
|
||||
if (zero_by_type.size() == 1) {
|
||||
// All members were of the same type, so the zero value is the same for all members.
|
||||
|
@ -392,14 +395,14 @@ bool Equal(const sem::Constant* a, const sem::Constant* b) {
|
|||
/// depending on the element types and values.
|
||||
const Constant* CreateComposite(ProgramBuilder& builder,
|
||||
const sem::Type* type,
|
||||
std::vector<const sem::Constant*> elements) {
|
||||
if (elements.size() == 0) {
|
||||
utils::VectorRef<const sem::Constant*> elements) {
|
||||
if (elements.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
bool any_zero = false;
|
||||
bool all_zero = true;
|
||||
bool all_equal = true;
|
||||
auto* first = elements.front();
|
||||
auto* first = elements.Front();
|
||||
for (auto* el : elements) {
|
||||
if (!el) {
|
||||
return nullptr;
|
||||
|
@ -417,7 +420,7 @@ const Constant* CreateComposite(ProgramBuilder& builder,
|
|||
}
|
||||
}
|
||||
if (all_equal) {
|
||||
return builder.create<Splat>(type, elements[0], elements.size());
|
||||
return builder.create<Splat>(type, elements[0], elements.Length());
|
||||
} else {
|
||||
return builder.create<Composite>(type, std::move(elements), all_zero, any_zero);
|
||||
}
|
||||
|
@ -433,9 +436,10 @@ const Constant* TransformElements(ProgramBuilder& builder, const sem::Constant*
|
|||
if (el_ty == ty) {
|
||||
return f(c);
|
||||
}
|
||||
std::vector<const sem::Constant*> els(n);
|
||||
utils::Vector<const sem::Constant*, 8> els;
|
||||
els.Reserve(n);
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
els[i] = TransformElements(builder, c->Index(i), f);
|
||||
els.Push(TransformElements(builder, c->Index(i), f));
|
||||
}
|
||||
return CreateComposite(builder, c->Type(), std::move(els));
|
||||
}
|
||||
|
@ -475,27 +479,29 @@ const sem::Constant* ConstEval::Literal(const sem::Type* ty,
|
|||
});
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::ArrayOrStructCtor(const sem::Type* ty,
|
||||
const std::vector<const sem::Expression*>& args) {
|
||||
if (args.empty()) {
|
||||
const sem::Constant* ConstEval::ArrayOrStructCtor(
|
||||
const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args) {
|
||||
if (args.IsEmpty()) {
|
||||
return ZeroValue(builder, ty);
|
||||
}
|
||||
|
||||
if (args.size() == 1 && args[0]->Type() == ty) {
|
||||
if (args.Length() == 1 && args[0]->Type() == ty) {
|
||||
// Identity constructor.
|
||||
return args[0]->ConstantValue();
|
||||
}
|
||||
|
||||
// Multiple arguments. Must be a type constructor.
|
||||
std::vector<const sem::Constant*> els;
|
||||
els.reserve(args.size());
|
||||
utils::Vector<const sem::Constant*, 4> els;
|
||||
els.Reserve(args.Length());
|
||||
for (auto* arg : args) {
|
||||
els.emplace_back(arg->ConstantValue());
|
||||
els.Push(arg->ConstantValue());
|
||||
}
|
||||
return CreateComposite(builder, ty, std::move(els));
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::Conv(const sem::Type* ty, ArgumentList args, size_t) {
|
||||
const sem::Constant* ConstEval::Conv(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args) {
|
||||
uint32_t el_count = 0;
|
||||
auto* el_ty = sem::Type::ElementOf(ty, &el_count);
|
||||
if (!el_ty) {
|
||||
|
@ -515,79 +521,79 @@ const sem::Constant* ConstEval::Conv(const sem::Type* ty, ArgumentList args, siz
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::Zero(const sem::Type* ty, ArgumentList, size_t) {
|
||||
const sem::Constant* ConstEval::Zero(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*>) {
|
||||
return ZeroValue(builder, ty);
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::Identity(const sem::Type*, ArgumentList args, size_t) {
|
||||
const sem::Constant* ConstEval::Identity(const sem::Type*,
|
||||
utils::ConstVectorRef<const sem::Expression*> args) {
|
||||
return args[0]->ConstantValue();
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::VecSplat(const sem::Type* ty,
|
||||
sem::Expression const* const* args,
|
||||
size_t) {
|
||||
utils::ConstVectorRef<const sem::Expression*> args) {
|
||||
if (auto* arg = args[0]->ConstantValue()) {
|
||||
return builder.create<Splat>(ty, arg, static_cast<const sem::Vector*>(ty)->Width());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::VecCtorS(const sem::Type* ty, ArgumentList args, size_t num_args) {
|
||||
std::vector<const sem::Constant*> els;
|
||||
els.reserve(num_args);
|
||||
for (size_t i = 0; i < num_args; i++) {
|
||||
els.emplace_back(args[i]->ConstantValue());
|
||||
const sem::Constant* ConstEval::VecCtorS(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args) {
|
||||
utils::Vector<const sem::Constant*, 4> els;
|
||||
for (auto* arg : args) {
|
||||
els.Push(arg->ConstantValue());
|
||||
}
|
||||
return CreateComposite(builder, ty, std::move(els));
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::VecCtorM(const sem::Type* ty, ArgumentList args, size_t num_args) {
|
||||
std::vector<const sem::Constant*> els;
|
||||
els.reserve(num_args);
|
||||
for (size_t i = 0; i < num_args; i++) {
|
||||
auto* arg = args[i]->ConstantValue();
|
||||
if (!arg) {
|
||||
const sem::Constant* ConstEval::VecCtorM(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args) {
|
||||
utils::Vector<const sem::Constant*, 4> els;
|
||||
for (auto* arg : args) {
|
||||
auto* val = arg->ConstantValue();
|
||||
if (!val) {
|
||||
return nullptr;
|
||||
}
|
||||
auto* arg_ty = arg->Type();
|
||||
if (auto* arg_vec = arg_ty->As<sem::Vector>()) {
|
||||
// Extract out vector elements.
|
||||
for (uint32_t j = 0; j < arg_vec->Width(); j++) {
|
||||
auto* el = arg->Index(j);
|
||||
auto* el = val->Index(j);
|
||||
if (!el) {
|
||||
return nullptr;
|
||||
}
|
||||
els.emplace_back(el);
|
||||
els.Push(el);
|
||||
}
|
||||
} else {
|
||||
els.emplace_back(arg);
|
||||
els.Push(val);
|
||||
}
|
||||
}
|
||||
return CreateComposite(builder, ty, std::move(els));
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::MatCtorS(const sem::Type* ty, ArgumentList args, size_t num_args) {
|
||||
const sem::Constant* ConstEval::MatCtorS(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args) {
|
||||
auto* m = static_cast<const sem::Matrix*>(ty);
|
||||
|
||||
std::vector<const sem::Constant*> els;
|
||||
els.reserve(num_args);
|
||||
utils::Vector<const sem::Constant*, 4> els;
|
||||
for (uint32_t c = 0; c < m->columns(); c++) {
|
||||
std::vector<const sem::Constant*> column;
|
||||
column.reserve(m->rows());
|
||||
utils::Vector<const sem::Constant*, 4> column;
|
||||
for (uint32_t r = 0; r < m->rows(); r++) {
|
||||
auto i = r + c * m->rows();
|
||||
column.emplace_back(args[i]->ConstantValue());
|
||||
column.Push(args[i]->ConstantValue());
|
||||
}
|
||||
els.push_back(CreateComposite(builder, m->ColumnType(), std::move(column)));
|
||||
els.Push(CreateComposite(builder, m->ColumnType(), std::move(column)));
|
||||
}
|
||||
return CreateComposite(builder, ty, std::move(els));
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::MatCtorV(const sem::Type* ty, ArgumentList args, size_t num_args) {
|
||||
std::vector<const sem::Constant*> els;
|
||||
els.reserve(num_args);
|
||||
for (size_t i = 0; i < num_args; i++) {
|
||||
els.emplace_back(args[i]->ConstantValue());
|
||||
const sem::Constant* ConstEval::MatCtorV(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args) {
|
||||
utils::Vector<const sem::Constant*, 4> els;
|
||||
for (auto* arg : args) {
|
||||
els.Push(arg->ConstantValue());
|
||||
}
|
||||
return CreateComposite(builder, ty, std::move(els));
|
||||
}
|
||||
|
@ -631,15 +637,15 @@ const sem::Constant* ConstEval::MemberAccess(const sem::Expression* obj_expr,
|
|||
|
||||
const sem::Constant* ConstEval::Swizzle(const sem::Type* ty,
|
||||
const sem::Expression* vec_expr,
|
||||
const std::vector<uint32_t>& indices) {
|
||||
utils::ConstVectorRef<uint32_t> indices) {
|
||||
auto* vec_val = vec_expr->ConstantValue();
|
||||
if (!vec_val) {
|
||||
return nullptr;
|
||||
}
|
||||
if (indices.size() == 1) {
|
||||
if (indices.Length() == 1) {
|
||||
return vec_val->Index(static_cast<size_t>(indices[0]));
|
||||
} else {
|
||||
auto values = utils::Transform(
|
||||
auto values = utils::Transform<4>(
|
||||
indices, [&](uint32_t i) { return vec_val->Index(static_cast<size_t>(i)); });
|
||||
return CreateComposite(builder, ty, std::move(values));
|
||||
}
|
||||
|
@ -651,8 +657,7 @@ const sem::Constant* ConstEval::Bitcast(const sem::Type*, const sem::Expression*
|
|||
}
|
||||
|
||||
const sem::Constant* ConstEval::OpComplement(const sem::Type*,
|
||||
sem::Expression const* const* args,
|
||||
size_t) {
|
||||
utils::ConstVectorRef<const sem::Expression*> args) {
|
||||
return TransformElements(builder, args[0]->ConstantValue(), [&](const sem::Constant* c) {
|
||||
return Dispatch_ia_iu32(c, [&](auto i) { //
|
||||
return CreateElement(builder, c->Type(), decltype(i)(~i.value));
|
||||
|
@ -661,8 +666,7 @@ const sem::Constant* ConstEval::OpComplement(const sem::Type*,
|
|||
}
|
||||
|
||||
const sem::Constant* ConstEval::OpMinus(const sem::Type*,
|
||||
sem::Expression const* const* args,
|
||||
size_t) {
|
||||
utils::ConstVectorRef<const sem::Expression*> args) {
|
||||
return TransformElements(builder, args[0]->ConstantValue(), [&](const sem::Constant* c) {
|
||||
return Dispatch_fia_fi32_f16(c, [&](auto i) { //
|
||||
// For signed integrals, avoid C++ UB by not negating the smallest negative number. In
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "src/tint/utils/result.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
|
||||
// Forward declarations
|
||||
namespace tint {
|
||||
|
@ -44,14 +44,9 @@ namespace tint::resolver {
|
|||
/// before calling a method to evaluate an expression's value.
|
||||
class ConstEval {
|
||||
public:
|
||||
/// Typedef for a pointer to an array of `const sem::Expression*`, where each expression is an
|
||||
/// argument to the function.
|
||||
using ArgumentList = sem::Expression const* const*;
|
||||
|
||||
/// Typedef for a constant evaluation function
|
||||
using Function = const sem::Constant* (ConstEval::*)(const sem::Type* result_ty,
|
||||
ArgumentList args,
|
||||
size_t num_args);
|
||||
using Function = const sem::Constant* (
|
||||
ConstEval::*)(const sem::Type* result_ty, utils::ConstVectorRef<const sem::Expression*>);
|
||||
|
||||
/// The result type of a method that may raise a diagnostic error and the caller should abort
|
||||
/// resolving. Can be one of three distinct values:
|
||||
|
@ -76,7 +71,7 @@ class ConstEval {
|
|||
/// @param args the input arguments
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* ArrayOrStructCtor(const sem::Type* ty,
|
||||
const std::vector<const sem::Expression*>& args);
|
||||
utils::ConstVectorRef<const sem::Expression*> args);
|
||||
|
||||
/// @param ty the target type
|
||||
/// @param expr the input expression
|
||||
|
@ -105,7 +100,7 @@ class ConstEval {
|
|||
/// @return the result of the swizzle, or null if the value cannot be calculated
|
||||
const sem::Constant* Swizzle(const sem::Type* ty,
|
||||
const sem::Expression* vector,
|
||||
const std::vector<uint32_t>& indices);
|
||||
utils::ConstVectorRef<uint32_t> indices);
|
||||
|
||||
/// Convert the `value` to `target_type`
|
||||
/// @param ty the result type
|
||||
|
@ -121,58 +116,58 @@ class ConstEval {
|
|||
/// Type conversion
|
||||
/// @param ty the result type
|
||||
/// @param args the input arguments
|
||||
/// @param num_args the number of input arguments
|
||||
/// @return the converted value, or null if the value cannot be calculated
|
||||
const sem::Constant* Conv(const sem::Type* ty, ArgumentList args, size_t num_args);
|
||||
const sem::Constant* Conv(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Zero value type constructor
|
||||
/// @param ty the result type
|
||||
/// @param args the input arguments (no arguments provided)
|
||||
/// @param num_args the number of input arguments (no arguments provided)
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* Zero(const sem::Type* ty, ArgumentList args, size_t num_args);
|
||||
const sem::Constant* Zero(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Identity value type constructor
|
||||
/// @param ty the result type
|
||||
/// @param args the input arguments
|
||||
/// @param num_args the number of input arguments (must be 1)
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* Identity(const sem::Type* ty, ArgumentList args, size_t num_args);
|
||||
const sem::Constant* Identity(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Vector splat constructor
|
||||
/// @param ty the vector type
|
||||
/// @param args the input arguments
|
||||
/// @param num_args the number of input arguments (must be 1)
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* VecSplat(const sem::Type* ty, ArgumentList args, size_t num_args);
|
||||
const sem::Constant* VecSplat(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Vector constructor using scalars
|
||||
/// @param ty the vector type
|
||||
/// @param args the input arguments
|
||||
/// @param num_args the number of input arguments (must be equal to vector width)
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* VecCtorS(const sem::Type* ty, ArgumentList args, size_t num_args);
|
||||
const sem::Constant* VecCtorS(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Vector constructor using a mix of scalars and smaller vectors
|
||||
/// @param ty the vector type
|
||||
/// @param args the input arguments
|
||||
/// @param num_args the number of input arguments
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* VecCtorM(const sem::Type* ty, ArgumentList args, size_t num_args);
|
||||
const sem::Constant* VecCtorM(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Matrix constructor using scalar values
|
||||
/// @param ty the matrix type
|
||||
/// @param args the input arguments
|
||||
/// @param num_args the number of input arguments (must equal num-columns * num-rows)
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* MatCtorS(const sem::Type* ty, ArgumentList args, size_t num_args);
|
||||
const sem::Constant* MatCtorS(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Matrix constructor using column vectors
|
||||
/// @param ty the matrix type
|
||||
/// @param args the input arguments
|
||||
/// @param num_args the number of input arguments (must equal num-columns)
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* MatCtorV(const sem::Type* ty, ArgumentList args, size_t num_args);
|
||||
const sem::Constant* MatCtorV(const sem::Type* ty,
|
||||
utils::ConstVectorRef<const sem::Expression*> args);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Operators
|
||||
|
@ -181,20 +176,16 @@ class ConstEval {
|
|||
/// Complement operator '~'
|
||||
/// @param ty the integer type
|
||||
/// @param args the input arguments
|
||||
/// @param num_args the number of input arguments (must be 1)
|
||||
/// @return the result value, or null if the value cannot be calculated
|
||||
const sem::Constant* OpComplement(const sem::Type* ty,
|
||||
sem::Expression const* const* args,
|
||||
size_t num_args);
|
||||
utils::ConstVectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Minus operator '-'
|
||||
/// @param ty the expression type
|
||||
/// @param args the input arguments
|
||||
/// @param num_args the number of input arguments (must be 1)
|
||||
/// @return the result value, or null if the value cannot be calculated
|
||||
const sem::Constant* OpMinus(const sem::Type* ty,
|
||||
sem::Expression const* const* args,
|
||||
size_t num_args);
|
||||
utils::ConstVectorRef<const sem::Expression*> args);
|
||||
|
||||
private:
|
||||
/// Adds the given error message to the diagnostics
|
||||
|
|
|
@ -48,6 +48,12 @@ class Matchers;
|
|||
class NumberMatcher;
|
||||
class TypeMatcher;
|
||||
|
||||
/// The utils::Vector `N` template argument value for arrays of parameters.
|
||||
constexpr static const size_t kNumFixedParams = 8;
|
||||
|
||||
/// The utils::Vector `N` template argument value for arrays of overload candidates.
|
||||
constexpr static const size_t kNumFixedCandidates = 8;
|
||||
|
||||
/// A special type that matches all TypeMatchers
|
||||
class Any final : public Castable<Any, sem::Type> {
|
||||
public:
|
||||
|
@ -882,7 +888,7 @@ struct IntrinsicPrototype {
|
|||
/// @param i the IntrinsicPrototype to create a hash for
|
||||
/// @return the hash value
|
||||
inline std::size_t operator()(const IntrinsicPrototype& i) const {
|
||||
size_t hash = utils::Hash(i.parameters.size());
|
||||
size_t hash = utils::Hash(i.parameters.Length());
|
||||
for (auto& p : i.parameters) {
|
||||
utils::HashCombine(&hash, p.type, p.usage);
|
||||
}
|
||||
|
@ -892,16 +898,16 @@ struct IntrinsicPrototype {
|
|||
|
||||
const OverloadInfo* overload = nullptr;
|
||||
sem::Type const* return_type = nullptr;
|
||||
std::vector<Parameter> parameters;
|
||||
utils::Vector<Parameter, kNumFixedParams> parameters;
|
||||
};
|
||||
|
||||
/// Equality operator for IntrinsicPrototype
|
||||
bool operator==(const IntrinsicPrototype& a, const IntrinsicPrototype& b) {
|
||||
if (a.overload != b.overload || a.return_type != b.return_type ||
|
||||
a.parameters.size() != b.parameters.size()) {
|
||||
a.parameters.Length() != b.parameters.Length()) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < a.parameters.size(); i++) {
|
||||
for (size_t i = 0; i < a.parameters.Length(); i++) {
|
||||
auto& pa = a.parameters[i];
|
||||
auto& pb = b.parameters[i];
|
||||
if (pa.type != pb.type || pa.usage != pb.usage) {
|
||||
|
@ -917,7 +923,7 @@ class Impl : public IntrinsicTable {
|
|||
explicit Impl(ProgramBuilder& builder);
|
||||
|
||||
Builtin Lookup(sem::BuiltinType builtin_type,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
const Source& source) override;
|
||||
|
||||
UnaryOperator Lookup(ast::UnaryOp op, const sem::Type* arg, const Source& source) override;
|
||||
|
@ -930,7 +936,7 @@ class Impl : public IntrinsicTable {
|
|||
|
||||
CtorOrConv Lookup(CtorConvIntrinsic type,
|
||||
const sem::Type* template_arg,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
const Source& source) override;
|
||||
|
||||
private:
|
||||
|
@ -941,7 +947,7 @@ class Impl : public IntrinsicTable {
|
|||
/// The template types and numbers
|
||||
TemplateState templates;
|
||||
/// The parameter types for the candidate overload
|
||||
std::vector<IntrinsicPrototype::Parameter> parameters;
|
||||
utils::Vector<IntrinsicPrototype::Parameter, kNumFixedParams> parameters;
|
||||
/// The match-score of the candidate overload.
|
||||
/// A score of zero indicates an exact match.
|
||||
/// Non-zero scores are used for diagnostics when no overload matches.
|
||||
|
@ -950,10 +956,10 @@ class Impl : public IntrinsicTable {
|
|||
};
|
||||
|
||||
/// A list of candidates
|
||||
using Candidates = std::vector<Candidate>;
|
||||
using Candidates = utils::Vector<Candidate, kNumFixedCandidates>;
|
||||
|
||||
/// Callback function when no overloads match.
|
||||
using OnNoMatch = std::function<void(Candidates)>;
|
||||
using OnNoMatch = std::function<void(utils::VectorRef<Candidate>)>;
|
||||
|
||||
/// Sorts the candidates based on their score, with the lowest (best-ranking) scores first.
|
||||
static inline void SortCandidates(Candidates& candidates) {
|
||||
|
@ -975,7 +981,7 @@ class Impl : public IntrinsicTable {
|
|||
/// IntrinsicPrototype::return_type.
|
||||
IntrinsicPrototype MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
||||
const char* intrinsic_name,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
TemplateState templates,
|
||||
OnNoMatch on_no_match) const;
|
||||
|
||||
|
@ -987,7 +993,7 @@ class Impl : public IntrinsicTable {
|
|||
/// template as `f32`.
|
||||
/// @returns the evaluated Candidate information.
|
||||
Candidate ScoreOverload(const OverloadInfo* overload,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
TemplateState templates) const;
|
||||
|
||||
/// Performs overload resolution given the list of candidates, by ranking the conversions of
|
||||
|
@ -1002,7 +1008,7 @@ class Impl : public IntrinsicTable {
|
|||
/// @returns the resolved Candidate.
|
||||
Candidate ResolveCandidate(Candidates&& candidates,
|
||||
const char* intrinsic_name,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
TemplateState templates) const;
|
||||
|
||||
/// Match constructs a new MatchState
|
||||
|
@ -1020,14 +1026,14 @@ class Impl : public IntrinsicTable {
|
|||
|
||||
// Prints the list of candidates for emitting diagnostics
|
||||
void PrintCandidates(std::ostream& ss,
|
||||
const Candidates& candidates,
|
||||
utils::ConstVectorRef<Candidate> candidates,
|
||||
const char* intrinsic_name) const;
|
||||
|
||||
/// Raises an error when no overload is a clear winner of overload resolution
|
||||
void ErrAmbiguousOverload(const char* intrinsic_name,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::ConstVectorRef<const sem::Type*> args,
|
||||
TemplateState templates,
|
||||
Candidates candidates) const;
|
||||
utils::ConstVectorRef<Candidate> candidates) const;
|
||||
|
||||
ProgramBuilder& builder;
|
||||
Matchers matchers;
|
||||
|
@ -1042,7 +1048,7 @@ class Impl : public IntrinsicTable {
|
|||
/// types.
|
||||
std::string CallSignature(ProgramBuilder& builder,
|
||||
const char* intrinsic_name,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
const sem::Type* template_arg = nullptr) {
|
||||
std::stringstream ss;
|
||||
ss << intrinsic_name;
|
||||
|
@ -1076,18 +1082,18 @@ std::string TemplateNumberMatcher::String(MatchState* state) const {
|
|||
Impl::Impl(ProgramBuilder& b) : builder(b) {}
|
||||
|
||||
Impl::Builtin Impl::Lookup(sem::BuiltinType builtin_type,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
const Source& source) {
|
||||
const char* intrinsic_name = sem::str(builtin_type);
|
||||
|
||||
// Generates an error when no overloads match the provided arguments
|
||||
auto on_no_match = [&](Candidates candidates) {
|
||||
auto on_no_match = [&](utils::VectorRef<Candidate> candidates) {
|
||||
std::stringstream ss;
|
||||
ss << "no matching call to " << CallSignature(builder, intrinsic_name, args) << std::endl;
|
||||
if (!candidates.empty()) {
|
||||
if (!candidates.IsEmpty()) {
|
||||
ss << std::endl
|
||||
<< candidates.size() << " candidate function" << (candidates.size() > 1 ? "s:" : ":")
|
||||
<< std::endl;
|
||||
<< candidates.Length() << " candidate function"
|
||||
<< (candidates.Length() > 1 ? "s:" : ":") << std::endl;
|
||||
PrintCandidates(ss, candidates, intrinsic_name);
|
||||
}
|
||||
builder.Diagnostics().add_error(diag::System::Resolver, ss.str(), source);
|
||||
|
@ -1102,11 +1108,11 @@ Impl::Builtin Impl::Lookup(sem::BuiltinType builtin_type,
|
|||
|
||||
// De-duplicate builtins that are identical.
|
||||
auto* sem = utils::GetOrCreate(builtins, match, [&] {
|
||||
std::vector<sem::Parameter*> params;
|
||||
params.reserve(match.parameters.size());
|
||||
utils::Vector<sem::Parameter*, kNumFixedParams> params;
|
||||
params.Reserve(match.parameters.Length());
|
||||
for (auto& p : match.parameters) {
|
||||
params.emplace_back(builder.create<sem::Parameter>(
|
||||
nullptr, static_cast<uint32_t>(params.size()), p.type, ast::StorageClass::kNone,
|
||||
params.Push(builder.create<sem::Parameter>(
|
||||
nullptr, static_cast<uint32_t>(params.Length()), p.type, ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, p.usage));
|
||||
}
|
||||
sem::PipelineStageSet supported_stages;
|
||||
|
@ -1144,21 +1150,23 @@ IntrinsicTable::UnaryOperator Impl::Lookup(ast::UnaryOp op,
|
|||
}
|
||||
}();
|
||||
|
||||
utils::Vector args{arg};
|
||||
|
||||
// Generates an error when no overloads match the provided arguments
|
||||
auto on_no_match = [&, name = intrinsic_name](Candidates candidates) {
|
||||
auto on_no_match = [&, name = intrinsic_name](utils::VectorRef<Candidate> candidates) {
|
||||
std::stringstream ss;
|
||||
ss << "no matching overload for " << CallSignature(builder, name, {arg}) << std::endl;
|
||||
if (!candidates.empty()) {
|
||||
ss << "no matching overload for " << CallSignature(builder, name, args) << std::endl;
|
||||
if (!candidates.IsEmpty()) {
|
||||
ss << std::endl
|
||||
<< candidates.size() << " candidate operator" << (candidates.size() > 1 ? "s:" : ":")
|
||||
<< std::endl;
|
||||
<< candidates.Length() << " candidate operator"
|
||||
<< (candidates.Length() > 1 ? "s:" : ":") << std::endl;
|
||||
PrintCandidates(ss, candidates, name);
|
||||
}
|
||||
builder.Diagnostics().add_error(diag::System::Resolver, ss.str(), source);
|
||||
};
|
||||
|
||||
// Resolve the intrinsic overload
|
||||
auto match = MatchIntrinsic(kUnaryOperators[intrinsic_index], intrinsic_name, {arg},
|
||||
auto match = MatchIntrinsic(kUnaryOperators[intrinsic_index], intrinsic_name, args,
|
||||
TemplateState{}, on_no_match);
|
||||
if (!match.overload) {
|
||||
return {};
|
||||
|
@ -1219,21 +1227,23 @@ IntrinsicTable::BinaryOperator Impl::Lookup(ast::BinaryOp op,
|
|||
}
|
||||
}();
|
||||
|
||||
utils::Vector args{lhs, rhs};
|
||||
|
||||
// Generates an error when no overloads match the provided arguments
|
||||
auto on_no_match = [&, name = intrinsic_name](Candidates candidates) {
|
||||
auto on_no_match = [&, name = intrinsic_name](utils::VectorRef<Candidate> candidates) {
|
||||
std::stringstream ss;
|
||||
ss << "no matching overload for " << CallSignature(builder, name, {lhs, rhs}) << std::endl;
|
||||
if (!candidates.empty()) {
|
||||
ss << "no matching overload for " << CallSignature(builder, name, args) << std::endl;
|
||||
if (!candidates.IsEmpty()) {
|
||||
ss << std::endl
|
||||
<< candidates.size() << " candidate operator" << (candidates.size() > 1 ? "s:" : ":")
|
||||
<< std::endl;
|
||||
<< candidates.Length() << " candidate operator"
|
||||
<< (candidates.Length() > 1 ? "s:" : ":") << std::endl;
|
||||
PrintCandidates(ss, candidates, name);
|
||||
}
|
||||
builder.Diagnostics().add_error(diag::System::Resolver, ss.str(), source);
|
||||
};
|
||||
|
||||
// Resolve the intrinsic overload
|
||||
auto match = MatchIntrinsic(kBinaryOperators[intrinsic_index], intrinsic_name, {lhs, rhs},
|
||||
auto match = MatchIntrinsic(kBinaryOperators[intrinsic_index], intrinsic_name, args,
|
||||
TemplateState{}, on_no_match);
|
||||
if (!match.overload) {
|
||||
return {};
|
||||
|
@ -1249,32 +1259,32 @@ IntrinsicTable::BinaryOperator Impl::Lookup(ast::BinaryOp op,
|
|||
|
||||
IntrinsicTable::CtorOrConv Impl::Lookup(CtorConvIntrinsic type,
|
||||
const sem::Type* template_arg,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
const Source& source) {
|
||||
auto name = str(type);
|
||||
|
||||
// Generates an error when no overloads match the provided arguments
|
||||
auto on_no_match = [&](Candidates candidates) {
|
||||
auto on_no_match = [&](utils::VectorRef<Candidate> candidates) {
|
||||
std::stringstream ss;
|
||||
ss << "no matching constructor for " << CallSignature(builder, name, args, template_arg)
|
||||
<< std::endl;
|
||||
Candidates ctor, conv;
|
||||
for (auto candidate : candidates) {
|
||||
if (candidate.overload->flags.Contains(OverloadFlag::kIsConstructor)) {
|
||||
ctor.emplace_back(candidate);
|
||||
ctor.Push(candidate);
|
||||
} else {
|
||||
conv.emplace_back(candidate);
|
||||
conv.Push(candidate);
|
||||
}
|
||||
}
|
||||
if (!ctor.empty()) {
|
||||
if (!ctor.IsEmpty()) {
|
||||
ss << std::endl
|
||||
<< ctor.size() << " candidate constructor" << (ctor.size() > 1 ? "s:" : ":")
|
||||
<< ctor.Length() << " candidate constructor" << (ctor.Length() > 1 ? "s:" : ":")
|
||||
<< std::endl;
|
||||
PrintCandidates(ss, ctor, name);
|
||||
}
|
||||
if (!conv.empty()) {
|
||||
if (!conv.IsEmpty()) {
|
||||
ss << std::endl
|
||||
<< conv.size() << " candidate conversion" << (conv.size() > 1 ? "s:" : ":")
|
||||
<< conv.Length() << " candidate conversion" << (conv.Length() > 1 ? "s:" : ":")
|
||||
<< std::endl;
|
||||
PrintCandidates(ss, conv, name);
|
||||
}
|
||||
|
@ -1296,11 +1306,11 @@ IntrinsicTable::CtorOrConv Impl::Lookup(CtorConvIntrinsic type,
|
|||
|
||||
// Was this overload a constructor or conversion?
|
||||
if (match.overload->flags.Contains(OverloadFlag::kIsConstructor)) {
|
||||
sem::ParameterList params;
|
||||
params.reserve(match.parameters.size());
|
||||
utils::Vector<const sem::Parameter*, 8> params;
|
||||
params.Reserve(match.parameters.Length());
|
||||
for (auto& p : match.parameters) {
|
||||
params.emplace_back(builder.create<sem::Parameter>(
|
||||
nullptr, static_cast<uint32_t>(params.size()), p.type, ast::StorageClass::kNone,
|
||||
params.Push(builder.create<sem::Parameter>(
|
||||
nullptr, static_cast<uint32_t>(params.Length()), p.type, ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, p.usage));
|
||||
}
|
||||
auto eval_stage = match.overload->const_eval_fn ? sem::EvaluationStage::kConstant
|
||||
|
@ -1326,13 +1336,13 @@ IntrinsicTable::CtorOrConv Impl::Lookup(CtorConvIntrinsic type,
|
|||
|
||||
IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
||||
const char* intrinsic_name,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
TemplateState templates,
|
||||
OnNoMatch on_no_match) const {
|
||||
size_t num_matched = 0;
|
||||
size_t match_idx = 0;
|
||||
Candidates candidates;
|
||||
candidates.reserve(intrinsic.num_overloads);
|
||||
utils::Vector<Candidate, kNumFixedCandidates> candidates;
|
||||
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);
|
||||
|
@ -1340,7 +1350,7 @@ IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
|||
match_idx = overload_idx;
|
||||
num_matched++;
|
||||
}
|
||||
candidates.emplace_back(std::move(candidate));
|
||||
candidates.Push(std::move(candidate));
|
||||
}
|
||||
|
||||
// How many candidates matched?
|
||||
|
@ -1380,7 +1390,7 @@ IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
|||
}
|
||||
|
||||
Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
TemplateState templates) const {
|
||||
// Penalty weights for overload mismatching.
|
||||
// This scoring is used to order the suggested overloads in diagnostic on overload mismatch, and
|
||||
|
@ -1392,7 +1402,7 @@ Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
|||
constexpr int kMismatchedTemplateNumberPenalty = 1;
|
||||
|
||||
size_t num_parameters = static_cast<size_t>(overload->num_parameters);
|
||||
size_t num_arguments = static_cast<size_t>(args.size());
|
||||
size_t num_arguments = static_cast<size_t>(args.Length());
|
||||
|
||||
size_t score = 0;
|
||||
|
||||
|
@ -1459,14 +1469,14 @@ 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;
|
||||
utils::Vector<IntrinsicPrototype::Parameter, kNumFixedParams> parameters;
|
||||
if (score == 0) {
|
||||
parameters.reserve(num_params);
|
||||
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});
|
||||
parameters.Emplace(ty, parameter.usage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1475,9 +1485,10 @@ Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
|||
|
||||
Impl::Candidate Impl::ResolveCandidate(Impl::Candidates&& candidates,
|
||||
const char* intrinsic_name,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
TemplateState templates) const {
|
||||
std::vector<uint32_t> best_ranks(args.size(), 0xffffffff);
|
||||
utils::Vector<uint32_t, kNumFixedParams> best_ranks;
|
||||
best_ranks.Resize(args.Length(), 0xffffffff);
|
||||
size_t num_matched = 0;
|
||||
Candidate* best = nullptr;
|
||||
for (auto& candidate : candidates) {
|
||||
|
@ -1486,7 +1497,7 @@ Impl::Candidate Impl::ResolveCandidate(Impl::Candidates&& candidates,
|
|||
}
|
||||
bool some_won = false; // An argument ranked less than the 'best' overload's argument
|
||||
bool some_lost = false; // An argument ranked more than the 'best' overload's argument
|
||||
for (size_t i = 0; i < args.size(); i++) {
|
||||
for (size_t i = 0; i < args.Length(); i++) {
|
||||
auto rank = sem::Type::ConversionRank(args[i], candidate.parameters[i].type);
|
||||
if (best_ranks[i] > rank) {
|
||||
best_ranks[i] = rank;
|
||||
|
@ -1593,7 +1604,7 @@ void Impl::PrintOverload(std::ostream& ss,
|
|||
}
|
||||
|
||||
void Impl::PrintCandidates(std::ostream& ss,
|
||||
const Candidates& candidates,
|
||||
utils::ConstVectorRef<Candidate> candidates,
|
||||
const char* intrinsic_name) const {
|
||||
for (auto& candidate : candidates) {
|
||||
ss << " ";
|
||||
|
@ -1627,9 +1638,9 @@ std::string MatchState::NumName() {
|
|||
}
|
||||
|
||||
void Impl::ErrAmbiguousOverload(const char* intrinsic_name,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::ConstVectorRef<const sem::Type*> args,
|
||||
TemplateState templates,
|
||||
Candidates candidates) const {
|
||||
utils::ConstVectorRef<Candidate> candidates) const {
|
||||
std::stringstream ss;
|
||||
ss << "ambiguous overload while attempting to match " << intrinsic_name;
|
||||
for (size_t i = 0; i < std::numeric_limits<size_t>::max(); i++) {
|
||||
|
|
|
@ -17,13 +17,13 @@
|
|||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "src/tint/ast/binary_expression.h"
|
||||
#include "src/tint/ast/unary_op.h"
|
||||
#include "src/tint/resolver/const_eval.h"
|
||||
#include "src/tint/resolver/ctor_conv_intrinsic.h"
|
||||
#include "src/tint/sem/builtin.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
|
||||
// Forward declarations
|
||||
namespace tint {
|
||||
|
@ -87,7 +87,7 @@ class IntrinsicTable {
|
|||
/// @param source the source of the builtin call
|
||||
/// @return the semantic builtin if found, otherwise nullptr
|
||||
virtual Builtin Lookup(sem::BuiltinType type,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
const Source& source) = 0;
|
||||
|
||||
/// Lookup looks for the unary op overload with the given signature, raising an error
|
||||
|
@ -123,7 +123,7 @@ class IntrinsicTable {
|
|||
/// @return a sem::TypeConstructor, sem::TypeConversion or nullptr if nothing matched
|
||||
virtual CtorOrConv Lookup(CtorConvIntrinsic type,
|
||||
const sem::Type* template_arg,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
utils::VectorRef<const sem::Type*> args,
|
||||
const Source& source) = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -53,18 +53,18 @@ class IntrinsicTableTest : public testing::Test, public ProgramBuilder {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MatchF32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kCos, {f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kCos, utils::Vector{f32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kCos);
|
||||
EXPECT_EQ(result.sem->ReturnType(), f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 1u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchF32) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto result = table->Lookup(BuiltinType::kCos, {i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kCos, utils::Vector{i32}, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -73,18 +73,18 @@ 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, {u32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kUnpack2x16float, utils::Vector{u32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kUnpack2x16float);
|
||||
EXPECT_EQ(result.sem->ReturnType(), vec2_f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 1u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), u32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchU32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kUnpack2x16float, {f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kUnpack2x16float, utils::Vector{f32}, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -94,12 +94,12 @@ 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, {tex, i32, i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, i32, i32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
|
||||
EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), i32);
|
||||
|
@ -111,48 +111,48 @@ 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, {tex, f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, f32}, 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, {i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kCountOneBits, utils::Vector{i32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kCountOneBits);
|
||||
EXPECT_EQ(result.sem->ReturnType(), i32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 1u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), i32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchIU32AsU32) {
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto result = table->Lookup(BuiltinType::kCountOneBits, {u32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kCountOneBits, utils::Vector{u32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kCountOneBits);
|
||||
EXPECT_EQ(result.sem->ReturnType(), u32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 1u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), u32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchIU32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kCountOneBits, {f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kCountOneBits, utils::Vector{f32}, 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, {i32, i32, i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{i32, i32, i32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
|
||||
EXPECT_EQ(result.sem->ReturnType(), i32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), i32);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), i32);
|
||||
EXPECT_EQ(result.sem->Parameters()[2]->Type(), i32);
|
||||
|
@ -160,12 +160,12 @@ TEST_F(IntrinsicTableTest, MatchFIU32AsI32) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MatchFIU32AsU32) {
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto result = table->Lookup(BuiltinType::kClamp, {u32, u32, u32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{u32, u32, u32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
|
||||
EXPECT_EQ(result.sem->ReturnType(), u32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), u32);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), u32);
|
||||
EXPECT_EQ(result.sem->Parameters()[2]->Type(), u32);
|
||||
|
@ -173,12 +173,12 @@ TEST_F(IntrinsicTableTest, MatchFIU32AsU32) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MatchFIU32AsF32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kClamp, {f32, f32, f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{f32, f32, f32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
|
||||
EXPECT_EQ(result.sem->ReturnType(), f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), f32);
|
||||
EXPECT_EQ(result.sem->Parameters()[2]->Type(), f32);
|
||||
|
@ -186,7 +186,7 @@ TEST_F(IntrinsicTableTest, MatchFIU32AsF32) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MismatchFIU32) {
|
||||
auto* bool_ = create<sem::Bool>();
|
||||
auto result = table->Lookup(BuiltinType::kClamp, {bool_, bool_, bool_}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{bool_, bool_, bool_}, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -194,12 +194,12 @@ TEST_F(IntrinsicTableTest, MismatchFIU32) {
|
|||
TEST_F(IntrinsicTableTest, MatchBool) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* bool_ = create<sem::Bool>();
|
||||
auto result = table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, bool_}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kSelect);
|
||||
EXPECT_EQ(result.sem->ReturnType(), f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), f32);
|
||||
EXPECT_EQ(result.sem->Parameters()[2]->Type(), bool_);
|
||||
|
@ -207,7 +207,7 @@ TEST_F(IntrinsicTableTest, MatchBool) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MismatchBool) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kSelect, {f32, f32, f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, f32}, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -217,19 +217,19 @@ TEST_F(IntrinsicTableTest, MatchPointer) {
|
|||
auto* atomicI32 = create<sem::Atomic>(i32);
|
||||
auto* ptr =
|
||||
create<sem::Pointer>(atomicI32, ast::StorageClass::kWorkgroup, ast::Access::kReadWrite);
|
||||
auto result = table->Lookup(BuiltinType::kAtomicLoad, {ptr}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kAtomicLoad, utils::Vector{ptr}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kAtomicLoad);
|
||||
EXPECT_EQ(result.sem->ReturnType(), i32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 1u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), ptr);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchPointer) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* atomicI32 = create<sem::Atomic>(i32);
|
||||
auto result = table->Lookup(BuiltinType::kAtomicLoad, {atomicI32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kAtomicLoad, utils::Vector{atomicI32}, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -237,12 +237,12 @@ TEST_F(IntrinsicTableTest, MismatchPointer) {
|
|||
TEST_F(IntrinsicTableTest, MatchArray) {
|
||||
auto* arr = create<sem::Array>(create<sem::U32>(), 0u, 4u, 4u, 4u, 4u);
|
||||
auto* arr_ptr = create<sem::Pointer>(arr, ast::StorageClass::kStorage, ast::Access::kReadWrite);
|
||||
auto result = table->Lookup(BuiltinType::kArrayLength, {arr_ptr}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kArrayLength, utils::Vector{arr_ptr}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kArrayLength);
|
||||
EXPECT_TRUE(result.sem->ReturnType()->Is<sem::U32>());
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 1u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
|
||||
auto* param_type = result.sem->Parameters()[0]->Type();
|
||||
ASSERT_TRUE(param_type->Is<sem::Pointer>());
|
||||
EXPECT_TRUE(param_type->As<sem::Pointer>()->StoreType()->Is<sem::Array>());
|
||||
|
@ -250,7 +250,7 @@ TEST_F(IntrinsicTableTest, MatchArray) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, MismatchArray) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kArrayLength, {f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kArrayLength, utils::Vector{f32}, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -261,12 +261,13 @@ 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, {tex, sampler, vec2_f32}, Source{});
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureSample, utils::Vector{tex, sampler, vec2_f32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureSample);
|
||||
EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), sampler);
|
||||
|
@ -279,7 +280,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, {tex, f32, vec2_f32}, Source{});
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureSample, utils::Vector{tex, f32, vec2_f32}, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -290,12 +292,13 @@ 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, {tex, vec2_i32, i32}, Source{});
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
|
||||
EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_i32);
|
||||
|
@ -310,12 +313,13 @@ 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, {tex, vec2_i32, i32}, Source{});
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
|
||||
EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_i32);
|
||||
|
@ -329,12 +333,13 @@ 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, {tex, vec2_i32, i32}, Source{});
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
|
||||
EXPECT_EQ(result.sem->ReturnType(), f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_i32);
|
||||
|
@ -348,12 +353,13 @@ 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, {tex, vec2_i32, i32}, Source{});
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32, i32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
|
||||
EXPECT_EQ(result.sem->ReturnType(), f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_i32);
|
||||
|
@ -368,12 +374,12 @@ 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, {tex, vec2_i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{tex, vec2_i32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureLoad);
|
||||
EXPECT_EQ(result.sem->ReturnType(), vec4_f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 2u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 2u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_i32);
|
||||
|
@ -389,12 +395,13 @@ 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, {tex, vec2_i32, vec4_f32}, Source{});
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kTextureStore, utils::Vector{tex, vec2_i32, vec4_f32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kTextureStore);
|
||||
EXPECT_TRUE(result.sem->ReturnType()->Is<sem::Void>());
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), tex);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Usage(), ParameterUsage::kTexture);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_i32);
|
||||
|
@ -407,7 +414,7 @@ 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, {f32, vec2_i32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kTextureLoad, utils::Vector{f32, vec2_i32}, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -416,19 +423,21 @@ TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) {
|
|||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(
|
||||
BuiltinType::kCos,
|
||||
{create<sem::Reference>(f32, ast::StorageClass::kFunction, ast::Access::kReadWrite)},
|
||||
utils::Vector{
|
||||
create<sem::Reference>(f32, ast::StorageClass::kFunction, ast::Access::kReadWrite),
|
||||
},
|
||||
Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kCos);
|
||||
EXPECT_EQ(result.sem->ReturnType(), f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 1u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), f32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchTemplateType) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(BuiltinType::kClamp, {f32, f32, f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{f32, f32, f32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
|
||||
|
@ -441,7 +450,7 @@ TEST_F(IntrinsicTableTest, MatchTemplateType) {
|
|||
TEST_F(IntrinsicTableTest, MismatchTemplateType) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto result = table->Lookup(BuiltinType::kClamp, {f32, u32, f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kClamp, utils::Vector{f32, u32, f32}, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -449,12 +458,13 @@ 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, {vec2_f32, vec2_f32, vec2_f32}, Source{});
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kClamp, utils::Vector{vec2_f32, vec2_f32, vec2_f32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kClamp);
|
||||
EXPECT_EQ(result.sem->ReturnType(), vec2_f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), vec2_f32);
|
||||
EXPECT_EQ(result.sem->Parameters()[1]->Type(), vec2_f32);
|
||||
EXPECT_EQ(result.sem->Parameters()[2]->Type(), vec2_f32);
|
||||
|
@ -464,7 +474,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, {vec2_f32, u32, vec2_f32}, Source{});
|
||||
auto result =
|
||||
table->Lookup(BuiltinType::kClamp, utils::Vector{vec2_f32, u32, vec2_f32}, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -473,12 +484,12 @@ 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, {mat3_f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kDeterminant, utils::Vector{mat3_f32}, Source{});
|
||||
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result.sem->Type(), BuiltinType::kDeterminant);
|
||||
EXPECT_EQ(result.sem->ReturnType(), f32);
|
||||
ASSERT_EQ(result.sem->Parameters().size(), 1u);
|
||||
ASSERT_EQ(result.sem->Parameters().Length(), 1u);
|
||||
EXPECT_EQ(result.sem->Parameters()[0]->Type(), mat3_f32);
|
||||
}
|
||||
|
||||
|
@ -486,7 +497,7 @@ 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, {mat3x2_f32}, Source{});
|
||||
auto result = table->Lookup(BuiltinType::kDeterminant, utils::Vector{mat3x2_f32}, Source{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
@ -495,7 +506,7 @@ 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, {bool_, bool_}, Source{});
|
||||
table->Lookup(BuiltinType::kTextureDimensions, utils::Vector{bool_, bool_}, Source{});
|
||||
ASSERT_EQ(Diagnostics().str(),
|
||||
R"(error: no matching call to textureDimensions(bool, bool)
|
||||
|
||||
|
@ -533,7 +544,7 @@ 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, {tex, bool_}, Source{});
|
||||
table->Lookup(BuiltinType::kTextureDimensions, utils::Vector{tex, bool_}, Source{});
|
||||
ASSERT_EQ(Diagnostics().str(),
|
||||
R"(error: no matching call to textureDimensions(texture_depth_2d, bool)
|
||||
|
||||
|
@ -572,14 +583,15 @@ 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, {f32, f32, bool_}, Source{});
|
||||
auto a = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, bool_}, Source{});
|
||||
ASSERT_NE(a.sem, nullptr) << Diagnostics().str();
|
||||
|
||||
auto b = table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
|
||||
auto b = table->Lookup(BuiltinType::kSelect, utils::Vector{f32, f32, bool_}, Source{});
|
||||
ASSERT_NE(b.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
|
||||
auto c = table->Lookup(BuiltinType::kSelect, {vec2_f32, vec2_f32, bool_}, Source{});
|
||||
auto c =
|
||||
table->Lookup(BuiltinType::kSelect, utils::Vector{vec2_f32, vec2_f32, bool_}, Source{});
|
||||
ASSERT_NE(c.sem, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
|
||||
|
@ -676,12 +688,12 @@ TEST_F(IntrinsicTableTest, MismatchCompoundOp) {
|
|||
TEST_F(IntrinsicTableTest, MatchTypeConstructorImplicit) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* vec3_i32 = create<sem::Vector>(i32, 3u);
|
||||
auto result =
|
||||
table->Lookup(CtorConvIntrinsic::kVec3, nullptr, {i32, i32, i32}, Source{{12, 34}});
|
||||
auto result = table->Lookup(CtorConvIntrinsic::kVec3, nullptr, utils::Vector{i32, i32, i32},
|
||||
Source{{12, 34}});
|
||||
ASSERT_NE(result.target, nullptr);
|
||||
EXPECT_EQ(result.target->ReturnType(), vec3_i32);
|
||||
EXPECT_TRUE(result.target->Is<sem::TypeConstructor>());
|
||||
ASSERT_EQ(result.target->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.target->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.target->Parameters()[0]->Type(), i32);
|
||||
EXPECT_EQ(result.target->Parameters()[1]->Type(), i32);
|
||||
EXPECT_EQ(result.target->Parameters()[2]->Type(), i32);
|
||||
|
@ -691,11 +703,12 @@ TEST_F(IntrinsicTableTest, MatchTypeConstructorImplicit) {
|
|||
TEST_F(IntrinsicTableTest, MatchTypeConstructorExplicit) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* vec3_i32 = create<sem::Vector>(i32, 3u);
|
||||
auto result = table->Lookup(CtorConvIntrinsic::kVec3, i32, {i32, i32, i32}, Source{{12, 34}});
|
||||
auto result = table->Lookup(CtorConvIntrinsic::kVec3, i32, utils::Vector{i32, i32, i32},
|
||||
Source{{12, 34}});
|
||||
ASSERT_NE(result.target, nullptr);
|
||||
EXPECT_EQ(result.target->ReturnType(), vec3_i32);
|
||||
EXPECT_TRUE(result.target->Is<sem::TypeConstructor>());
|
||||
ASSERT_EQ(result.target->Parameters().size(), 3u);
|
||||
ASSERT_EQ(result.target->Parameters().Length(), 3u);
|
||||
EXPECT_EQ(result.target->Parameters()[0]->Type(), i32);
|
||||
EXPECT_EQ(result.target->Parameters()[1]->Type(), i32);
|
||||
EXPECT_EQ(result.target->Parameters()[2]->Type(), i32);
|
||||
|
@ -705,10 +718,11 @@ TEST_F(IntrinsicTableTest, MatchTypeConstructorExplicit) {
|
|||
TEST_F(IntrinsicTableTest, MismatchTypeConstructorImplicit) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result =
|
||||
table->Lookup(CtorConvIntrinsic::kVec3, nullptr, {i32, f32, i32}, Source{{12, 34}});
|
||||
auto result = table->Lookup(CtorConvIntrinsic::kVec3, nullptr, utils::Vector{i32, f32, i32},
|
||||
Source{{12, 34}});
|
||||
ASSERT_EQ(result.target, nullptr);
|
||||
EXPECT_EQ(Diagnostics().str(), R"(12:34 error: no matching constructor for vec3(i32, f32, i32)
|
||||
EXPECT_EQ(Diagnostics().str(),
|
||||
R"(12:34 error: no matching constructor for vec3(i32, f32, i32)
|
||||
|
||||
6 candidate constructors:
|
||||
vec3(x: T, y: T, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
|
||||
|
@ -730,7 +744,8 @@ TEST_F(IntrinsicTableTest, MismatchTypeConstructorImplicit) {
|
|||
TEST_F(IntrinsicTableTest, MismatchTypeConstructorExplicit) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(CtorConvIntrinsic::kVec3, i32, {i32, f32, i32}, Source{{12, 34}});
|
||||
auto result = table->Lookup(CtorConvIntrinsic::kVec3, i32, utils::Vector{i32, f32, i32},
|
||||
Source{{12, 34}});
|
||||
ASSERT_EQ(result.target, nullptr);
|
||||
EXPECT_EQ(Diagnostics().str(),
|
||||
R"(12:34 error: no matching constructor for vec3<i32>(i32, f32, i32)
|
||||
|
@ -757,18 +772,20 @@ TEST_F(IntrinsicTableTest, MatchTypeConversion) {
|
|||
auto* vec3_i32 = create<sem::Vector>(i32, 3u);
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* vec3_f32 = create<sem::Vector>(f32, 3u);
|
||||
auto result = table->Lookup(CtorConvIntrinsic::kVec3, i32, {vec3_f32}, Source{{12, 34}});
|
||||
auto result =
|
||||
table->Lookup(CtorConvIntrinsic::kVec3, i32, utils::Vector{vec3_f32}, Source{{12, 34}});
|
||||
ASSERT_NE(result.target, nullptr);
|
||||
EXPECT_EQ(result.target->ReturnType(), vec3_i32);
|
||||
EXPECT_TRUE(result.target->Is<sem::TypeConversion>());
|
||||
ASSERT_EQ(result.target->Parameters().size(), 1u);
|
||||
ASSERT_EQ(result.target->Parameters().Length(), 1u);
|
||||
EXPECT_EQ(result.target->Parameters()[0]->Type(), vec3_f32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchTypeConversion) {
|
||||
auto* arr = create<sem::Array>(create<sem::U32>(), 0u, 4u, 4u, 4u, 4u);
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto result = table->Lookup(CtorConvIntrinsic::kVec3, f32, {arr}, Source{{12, 34}});
|
||||
auto result =
|
||||
table->Lookup(CtorConvIntrinsic::kVec3, f32, utils::Vector{arr}, Source{{12, 34}});
|
||||
ASSERT_EQ(result.target, nullptr);
|
||||
EXPECT_EQ(Diagnostics().str(),
|
||||
R"(12:34 error: no matching constructor for vec3<f32>(array<u32>)
|
||||
|
@ -792,7 +809,8 @@ TEST_F(IntrinsicTableTest, MismatchTypeConversion) {
|
|||
|
||||
TEST_F(IntrinsicTableTest, Err257Arguments) { // crbug.com/1323605
|
||||
auto* f32 = create<sem::F32>();
|
||||
std::vector<const sem::Type*> arg_tys(257, 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{});
|
||||
ASSERT_EQ(result.sem, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
|
@ -805,10 +823,10 @@ TEST_F(IntrinsicTableTest, OverloadResolution) {
|
|||
// The first should win overload resolution.
|
||||
auto* ai = create<sem::AbstractInt>();
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto result = table->Lookup(CtorConvIntrinsic::kI32, nullptr, {ai}, Source{});
|
||||
auto result = table->Lookup(CtorConvIntrinsic::kI32, nullptr, utils::Vector{ai}, Source{});
|
||||
ASSERT_NE(result.target, nullptr);
|
||||
EXPECT_EQ(result.target->ReturnType(), i32);
|
||||
EXPECT_EQ(result.target->Parameters().size(), 1u);
|
||||
EXPECT_EQ(result.target->Parameters().Length(), 1u);
|
||||
EXPECT_EQ(result.target->Parameters()[0]->Type(), i32);
|
||||
}
|
||||
|
||||
|
@ -816,7 +834,6 @@ TEST_F(IntrinsicTableTest, OverloadResolution) {
|
|||
// AbstractBinaryTests
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AbstractBinaryTests {
|
||||
|
||||
struct Case {
|
||||
template <typename RESULT,
|
||||
typename PARAM_LHS,
|
||||
|
@ -991,7 +1008,6 @@ Case::Create<u32V, u32V, u32V, u32V, AIntV>()
|
|||
// AbstractTernaryTests
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AbstractTernaryTests {
|
||||
|
||||
struct Case {
|
||||
template <typename RESULT,
|
||||
typename PARAM_A,
|
||||
|
@ -1030,7 +1046,8 @@ 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}});
|
||||
auto builtin = table->Lookup(sem::BuiltinType::kClamp, utils::Vector{arg_a, arg_b, arg_c},
|
||||
Source{{12, 34}});
|
||||
|
||||
bool matched = builtin.sem != nullptr;
|
||||
bool expected_match = GetParam().expected_match;
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
#include "src/tint/utils/reverse.h"
|
||||
#include "src/tint/utils/scoped_assignment.h"
|
||||
#include "src/tint/utils/transform.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
|
||||
namespace tint::resolver {
|
||||
|
||||
|
@ -720,7 +721,7 @@ sem::GlobalVariable* Resolver::GlobalVariable(const ast::Variable* v) {
|
|||
sem::Function* Resolver::Function(const ast::Function* decl) {
|
||||
uint32_t parameter_index = 0;
|
||||
std::unordered_map<Symbol, Source> parameter_names;
|
||||
std::vector<sem::Parameter*> parameters;
|
||||
utils::Vector<sem::Parameter*, 8> parameters;
|
||||
|
||||
// Resolve all the parameters
|
||||
for (auto* param : decl->params) {
|
||||
|
@ -745,7 +746,7 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
parameters.emplace_back(p);
|
||||
parameters.Push(p);
|
||||
|
||||
auto* p_ty = const_cast<sem::Type*>(p->Type());
|
||||
if (auto* str = p_ty->As<sem::Struct>()) {
|
||||
|
@ -799,7 +800,7 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
|
|||
}
|
||||
}
|
||||
|
||||
auto* func = builder_->create<sem::Function>(decl, return_type, parameters);
|
||||
auto* func = builder_->create<sem::Function>(decl, return_type, std::move(parameters));
|
||||
builder_->Sem().Add(decl, func);
|
||||
|
||||
TINT_SCOPED_ASSIGNMENT(current_function_, func);
|
||||
|
@ -1229,7 +1230,7 @@ sem::WhileStatement* Resolver::WhileStatement(const ast::WhileStatement* stmt) {
|
|||
}
|
||||
|
||||
sem::Expression* Resolver::Expression(const ast::Expression* root) {
|
||||
std::vector<const ast::Expression*> sorted;
|
||||
utils::Vector<const ast::Expression*, 128> sorted;
|
||||
constexpr size_t kMaxExpressionDepth = 512U;
|
||||
bool failed = false;
|
||||
if (!ast::TraverseExpressions<ast::TraverseOrder::RightToLeft>(
|
||||
|
@ -1245,7 +1246,7 @@ sem::Expression* Resolver::Expression(const ast::Expression* root) {
|
|||
failed = true;
|
||||
return ast::TraverseAction::Stop;
|
||||
}
|
||||
sorted.emplace_back(expr);
|
||||
sorted.Push(expr);
|
||||
return ast::TraverseAction::Descend;
|
||||
})) {
|
||||
return nullptr;
|
||||
|
@ -1377,9 +1378,9 @@ const sem::Expression* Resolver::Materialize(const sem::Expression* expr,
|
|||
[&](Default) { return expr; });
|
||||
}
|
||||
|
||||
bool Resolver::MaterializeArguments(std::vector<const sem::Expression*>& args,
|
||||
bool Resolver::MaterializeArguments(utils::VectorRef<const sem::Expression*> args,
|
||||
const sem::CallTarget* target) {
|
||||
for (size_t i = 0, n = std::min(args.size(), target->Parameters().size()); i < n; i++) {
|
||||
for (size_t i = 0, n = std::min(args.Length(), target->Parameters().Length()); i < n; i++) {
|
||||
const auto* param_ty = target->Parameters()[i]->Type();
|
||||
if (ShouldMaterializeArgument(param_ty)) {
|
||||
auto* materialized = Materialize(args[i], param_ty);
|
||||
|
@ -1480,7 +1481,8 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
|||
// * A type conversion.
|
||||
|
||||
// Resolve all of the arguments, their types and the set of behaviors.
|
||||
std::vector<const sem::Expression*> args(expr->args.size());
|
||||
utils::Vector<const sem::Expression*, 8> args;
|
||||
args.Reserve(expr->args.size());
|
||||
auto args_stage = sem::EvaluationStage::kConstant;
|
||||
sem::Behaviors arg_behaviors;
|
||||
for (size_t i = 0; i < expr->args.size(); i++) {
|
||||
|
@ -1488,7 +1490,7 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
|||
if (!arg) {
|
||||
return nullptr;
|
||||
}
|
||||
args[i] = arg;
|
||||
args.Push(arg);
|
||||
args_stage = sem::EarliestStage(args_stage, arg->Stage());
|
||||
arg_behaviors.Add(arg->Behaviors());
|
||||
}
|
||||
|
@ -1512,8 +1514,8 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
|||
const sem::Constant* value = nullptr;
|
||||
auto stage = sem::EarliestStage(ctor_or_conv.target->Stage(), args_stage);
|
||||
if (stage == sem::EvaluationStage::kConstant) {
|
||||
value = (const_eval_.*ctor_or_conv.const_eval_fn)(ctor_or_conv.target->ReturnType(),
|
||||
args.data(), args.size());
|
||||
value =
|
||||
(const_eval_.*ctor_or_conv.const_eval_fn)(ctor_or_conv.target->ReturnType(), args);
|
||||
}
|
||||
return builder_->create<sem::Call>(expr, ctor_or_conv.target, stage, std::move(args),
|
||||
current_statement_, value, has_side_effects);
|
||||
|
@ -1563,16 +1565,17 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
|||
[&](const sem::Bool*) { return ct_ctor_or_conv(CtorConvIntrinsic::kBool, nullptr); },
|
||||
[&](const sem::Array* arr) -> sem::Call* {
|
||||
auto* call_target = utils::GetOrCreate(
|
||||
array_ctors_, ArrayConstructorSig{{arr, args.size(), args_stage}},
|
||||
array_ctors_, ArrayConstructorSig{{arr, args.Length(), args_stage}},
|
||||
[&]() -> sem::TypeConstructor* {
|
||||
sem::ParameterList params(args.size());
|
||||
for (size_t i = 0; i < args.size(); i++) {
|
||||
params[i] = builder_->create<sem::Parameter>(
|
||||
nullptr, // declaration
|
||||
static_cast<uint32_t>(i), // index
|
||||
arr->ElemType(), // type
|
||||
ast::StorageClass::kNone, // storage_class
|
||||
ast::Access::kUndefined); // access
|
||||
utils::Vector<const sem::Parameter*, 8> params;
|
||||
params.Reserve(args.Length());
|
||||
for (size_t i = 0; i < args.Length(); i++) {
|
||||
params.Push(builder_->create<sem::Parameter>(
|
||||
nullptr, // declaration
|
||||
static_cast<uint32_t>(i), // index
|
||||
arr->ElemType(), // type
|
||||
ast::StorageClass::kNone, // storage_class
|
||||
ast::Access::kUndefined)); // access
|
||||
}
|
||||
return builder_->create<sem::TypeConstructor>(arr, std::move(params),
|
||||
args_stage);
|
||||
|
@ -1581,10 +1584,11 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
|||
},
|
||||
[&](const sem::Struct* str) -> sem::Call* {
|
||||
auto* call_target = utils::GetOrCreate(
|
||||
struct_ctors_, StructConstructorSig{{str, args.size(), args_stage}},
|
||||
struct_ctors_, StructConstructorSig{{str, args.Length(), args_stage}},
|
||||
[&]() -> sem::TypeConstructor* {
|
||||
sem::ParameterList params(std::min(args.size(), str->Members().size()));
|
||||
for (size_t i = 0, n = params.size(); i < n; i++) {
|
||||
utils::Vector<const sem::Parameter*, 8> params;
|
||||
params.Resize(std::min(args.Length(), str->Members().size()));
|
||||
for (size_t i = 0, n = params.Length(); i < n; i++) {
|
||||
params[i] = builder_->create<sem::Parameter>(
|
||||
nullptr, // declaration
|
||||
static_cast<uint32_t>(i), // index
|
||||
|
@ -1705,10 +1709,10 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
|||
|
||||
sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
||||
sem::BuiltinType builtin_type,
|
||||
std::vector<const sem::Expression*> args) {
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
IntrinsicTable::Builtin builtin;
|
||||
{
|
||||
auto arg_tys = utils::Transform(args, [](auto* arg) { return arg->Type(); });
|
||||
auto arg_tys = utils::Transform<8>(args, [](auto* arg) { return arg->Type(); });
|
||||
builtin = intrinsic_table_->Lookup(builtin_type, arg_tys, expr->source);
|
||||
if (!builtin.sem) {
|
||||
return nullptr;
|
||||
|
@ -1738,8 +1742,7 @@ sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
|||
// If the builtin is @const, and all arguments have constant values, evaluate the builtin now.
|
||||
const sem::Constant* value = nullptr;
|
||||
if (stage == sem::EvaluationStage::kConstant) {
|
||||
value = (const_eval_.*builtin.const_eval_fn)(builtin.sem->ReturnType(), args.data(),
|
||||
args.size());
|
||||
value = (const_eval_.*builtin.const_eval_fn)(builtin.sem->ReturnType(), args);
|
||||
}
|
||||
|
||||
bool has_side_effects =
|
||||
|
@ -1771,8 +1774,9 @@ sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
|||
return call;
|
||||
}
|
||||
|
||||
void Resolver::CollectTextureSamplerPairs(const sem::Builtin* builtin,
|
||||
const std::vector<const sem::Expression*>& args) const {
|
||||
void Resolver::CollectTextureSamplerPairs(
|
||||
const sem::Builtin* builtin,
|
||||
utils::ConstVectorRef<const sem::Expression*> args) const {
|
||||
// Collect a texture/sampler pair for this builtin.
|
||||
const auto& signature = builtin->Signature();
|
||||
int texture_index = signature.IndexOf(sem::ParameterUsage::kTexture);
|
||||
|
@ -1792,7 +1796,7 @@ void Resolver::CollectTextureSamplerPairs(const sem::Builtin* builtin,
|
|||
|
||||
sem::Call* Resolver::FunctionCall(const ast::CallExpression* expr,
|
||||
sem::Function* target,
|
||||
std::vector<const sem::Expression*> args,
|
||||
utils::VectorRef<const sem::Expression*> args,
|
||||
sem::Behaviors arg_behaviors) {
|
||||
auto sym = expr->target.name->symbol;
|
||||
auto name = builder_->Symbols().NameFor(sym);
|
||||
|
@ -1838,8 +1842,9 @@ sem::Call* Resolver::FunctionCall(const ast::CallExpression* expr,
|
|||
return call;
|
||||
}
|
||||
|
||||
void Resolver::CollectTextureSamplerPairs(sem::Function* func,
|
||||
const std::vector<const sem::Expression*>& args) const {
|
||||
void Resolver::CollectTextureSamplerPairs(
|
||||
sem::Function* func,
|
||||
utils::ConstVectorRef<const sem::Expression*> args) const {
|
||||
// Map all texture/sampler pairs from the target function to the
|
||||
// current function. These can only be global or parameter
|
||||
// variables. Resolve any parameter variables to the corresponding
|
||||
|
@ -1992,7 +1997,7 @@ sem::Expression* Resolver::MemberAccessor(const ast::MemberAccessorExpression* e
|
|||
auto* source_var = object->SourceVariable();
|
||||
|
||||
const sem::Type* ret = nullptr;
|
||||
std::vector<uint32_t> swizzle;
|
||||
utils::Vector<uint32_t, 4> swizzle;
|
||||
|
||||
// Object may be a side-effecting expression (e.g. function call).
|
||||
bool has_side_effects = object && object->HasSideEffects();
|
||||
|
@ -2030,33 +2035,33 @@ sem::Expression* Resolver::MemberAccessor(const ast::MemberAccessorExpression* e
|
|||
Mark(expr->member);
|
||||
std::string s = builder_->Symbols().NameFor(expr->member->symbol);
|
||||
auto size = s.size();
|
||||
swizzle.reserve(s.size());
|
||||
swizzle.Reserve(s.size());
|
||||
|
||||
for (auto c : s) {
|
||||
switch (c) {
|
||||
case 'x':
|
||||
case 'r':
|
||||
swizzle.emplace_back(0);
|
||||
swizzle.Push(0u);
|
||||
break;
|
||||
case 'y':
|
||||
case 'g':
|
||||
swizzle.emplace_back(1);
|
||||
swizzle.Push(1u);
|
||||
break;
|
||||
case 'z':
|
||||
case 'b':
|
||||
swizzle.emplace_back(2);
|
||||
swizzle.Push(2u);
|
||||
break;
|
||||
case 'w':
|
||||
case 'a':
|
||||
swizzle.emplace_back(3);
|
||||
swizzle.Push(3u);
|
||||
break;
|
||||
default:
|
||||
AddError("invalid vector swizzle character",
|
||||
expr->member->source.Begin() + swizzle.size());
|
||||
expr->member->source.Begin() + swizzle.Length());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (swizzle.back() >= vec->Width()) {
|
||||
if (swizzle.Back() >= vec->Width()) {
|
||||
AddError("invalid vector swizzle member", expr->member->source);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2126,8 +2131,7 @@ sem::Expression* Resolver::Binary(const ast::BinaryExpression* expr) {
|
|||
|
||||
const sem::Constant* value = nullptr;
|
||||
if (op.const_eval_fn) {
|
||||
const sem::Expression* args[] = {lhs, rhs};
|
||||
value = (const_eval_.*op.const_eval_fn)(op.result, args, 2u);
|
||||
value = (const_eval_.*op.const_eval_fn)(op.result, utils::Vector{lhs, rhs});
|
||||
}
|
||||
|
||||
bool has_side_effects = lhs->HasSideEffects() || rhs->HasSideEffects();
|
||||
|
@ -2203,7 +2207,7 @@ sem::Expression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
|
|||
stage = expr->Stage();
|
||||
if (stage == sem::EvaluationStage::kConstant) {
|
||||
if (op.const_eval_fn) {
|
||||
value = (const_eval_.*op.const_eval_fn)(ty, &expr, 1u);
|
||||
value = (const_eval_.*op.const_eval_fn)(ty, utils::Vector{expr});
|
||||
} else {
|
||||
stage = sem::EvaluationStage::kRuntime;
|
||||
}
|
||||
|
|
|
@ -195,12 +195,12 @@ class Resolver {
|
|||
sem::Function* Function(const ast::Function*);
|
||||
sem::Call* FunctionCall(const ast::CallExpression*,
|
||||
sem::Function* target,
|
||||
std::vector<const sem::Expression*> args,
|
||||
utils::VectorRef<const sem::Expression*> args,
|
||||
sem::Behaviors arg_behaviors);
|
||||
sem::Expression* Identifier(const ast::IdentifierExpression*);
|
||||
sem::Call* BuiltinCall(const ast::CallExpression*,
|
||||
sem::BuiltinType,
|
||||
std::vector<const sem::Expression*> args);
|
||||
utils::VectorRef<const sem::Expression*> args);
|
||||
sem::Expression* Literal(const ast::LiteralExpression*);
|
||||
sem::Expression* MemberAccessor(const ast::MemberAccessorExpression*);
|
||||
sem::Expression* UnaryOp(const ast::UnaryOpExpression*);
|
||||
|
@ -223,7 +223,7 @@ class Resolver {
|
|||
|
||||
/// Materializes all the arguments in `args` to the parameter types of `target`.
|
||||
/// @returns true on success, false on failure.
|
||||
bool MaterializeArguments(std::vector<const sem::Expression*>& args,
|
||||
bool MaterializeArguments(utils::VectorRef<const sem::Expression*> args,
|
||||
const sem::CallTarget* target);
|
||||
|
||||
/// @returns true if an argument of an abstract numeric type, passed to a parameter of type
|
||||
|
@ -257,9 +257,9 @@ class Resolver {
|
|||
// CollectTextureSamplerPairs() collects all the texture/sampler pairs from the target function
|
||||
// / builtin, and records these on the current function by calling AddTextureSamplerPair().
|
||||
void CollectTextureSamplerPairs(sem::Function* func,
|
||||
const std::vector<const sem::Expression*>& args) const;
|
||||
utils::ConstVectorRef<const sem::Expression*> args) const;
|
||||
void CollectTextureSamplerPairs(const sem::Builtin* builtin,
|
||||
const std::vector<const sem::Expression*>& args) const;
|
||||
utils::ConstVectorRef<const sem::Expression*> args) const;
|
||||
|
||||
/// Resolves the WorkgroupSize for the given function, assigning it to
|
||||
/// current_function_
|
||||
|
|
|
@ -763,7 +763,7 @@ TEST_F(ResolverTest, Function_Parameters) {
|
|||
|
||||
auto* func_sem = Sem().Get(func);
|
||||
ASSERT_NE(func_sem, nullptr);
|
||||
EXPECT_EQ(func_sem->Parameters().size(), 3u);
|
||||
EXPECT_EQ(func_sem->Parameters().Length(), 3u);
|
||||
EXPECT_TRUE(func_sem->Parameters()[0]->Type()->Is<sem::F32>());
|
||||
EXPECT_TRUE(func_sem->Parameters()[1]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(func_sem->Parameters()[2]->Type()->Is<sem::U32>());
|
||||
|
@ -796,7 +796,7 @@ TEST_F(ResolverTest, Function_RegisterInputOutputVariables) {
|
|||
|
||||
auto* func_sem = Sem().Get(func);
|
||||
ASSERT_NE(func_sem, nullptr);
|
||||
EXPECT_EQ(func_sem->Parameters().size(), 0u);
|
||||
EXPECT_EQ(func_sem->Parameters().Length(), 0u);
|
||||
EXPECT_TRUE(func_sem->ReturnType()->Is<sem::Void>());
|
||||
|
||||
const auto& vars = func_sem->TransitivelyReferencedGlobals();
|
||||
|
@ -832,7 +832,7 @@ TEST_F(ResolverTest, Function_RegisterInputOutputVariables_SubFunction) {
|
|||
|
||||
auto* func2_sem = Sem().Get(func2);
|
||||
ASSERT_NE(func2_sem, nullptr);
|
||||
EXPECT_EQ(func2_sem->Parameters().size(), 0u);
|
||||
EXPECT_EQ(func2_sem->Parameters().Length(), 0u);
|
||||
|
||||
const auto& vars = func2_sem->TransitivelyReferencedGlobals();
|
||||
ASSERT_EQ(vars.size(), 3u);
|
||||
|
@ -1867,9 +1867,9 @@ TEST_F(ResolverTest, Function_EntryPoints_StageAttribute) {
|
|||
ASSERT_NE(ep_1_sem, nullptr);
|
||||
ASSERT_NE(ep_2_sem, nullptr);
|
||||
|
||||
EXPECT_EQ(func_b_sem->Parameters().size(), 0u);
|
||||
EXPECT_EQ(func_a_sem->Parameters().size(), 0u);
|
||||
EXPECT_EQ(func_c_sem->Parameters().size(), 0u);
|
||||
EXPECT_EQ(func_b_sem->Parameters().Length(), 0u);
|
||||
EXPECT_EQ(func_a_sem->Parameters().Length(), 0u);
|
||||
EXPECT_EQ(func_c_sem->Parameters().Length(), 0u);
|
||||
|
||||
const auto& b_eps = func_b_sem->AncestorEntryPoints();
|
||||
ASSERT_EQ(2u, b_eps.size());
|
||||
|
|
|
@ -371,7 +371,7 @@ TEST_P(ConversionConstructorValidTest, All) {
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 1u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 1u);
|
||||
EXPECT_EQ(ctor->Parameters()[0]->Type(), TypeOf(arg));
|
||||
break;
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ TEST_P(ConversionConstructorValidTest, All) {
|
|||
auto* conv = call->Target()->As<sem::TypeConversion>();
|
||||
ASSERT_NE(conv, nullptr);
|
||||
EXPECT_EQ(call->Type(), conv->ReturnType());
|
||||
ASSERT_EQ(conv->Parameters().size(), 1u);
|
||||
ASSERT_EQ(conv->Parameters().Length(), 1u);
|
||||
EXPECT_EQ(conv->Parameters()[0]->Type(), TypeOf(arg));
|
||||
break;
|
||||
}
|
||||
|
@ -499,7 +499,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Array_ZeroValue_P
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 0u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Array_type_match) {
|
||||
|
@ -515,7 +515,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Array_type_match)
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 3u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 3u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::U32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::U32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::U32>());
|
||||
|
@ -686,7 +686,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Construct_i32_Success) {
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 1u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 1u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::I32>());
|
||||
}
|
||||
|
||||
|
@ -704,7 +704,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Construct_u32_Success) {
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 1u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 1u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::U32>());
|
||||
}
|
||||
|
||||
|
@ -722,7 +722,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Construct_f32_Success) {
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 1u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 1u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::F32>());
|
||||
}
|
||||
|
||||
|
@ -742,7 +742,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Construct_f16_Success) {
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 1u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 1u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::F16>());
|
||||
}
|
||||
|
||||
|
@ -760,7 +760,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Convert_f32_to_i32_Success) {
|
|||
auto* ctor = call->Target()->As<sem::TypeConversion>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 1u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 1u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::F32>());
|
||||
}
|
||||
|
||||
|
@ -778,7 +778,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Convert_i32_to_u32_Success) {
|
|||
auto* ctor = call->Target()->As<sem::TypeConversion>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 1u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 1u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::I32>());
|
||||
}
|
||||
|
||||
|
@ -798,7 +798,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Convert_u32_to_f16_Success) {
|
|||
auto* ctor = call->Target()->As<sem::TypeConversion>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 1u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 1u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::U32>());
|
||||
}
|
||||
|
||||
|
@ -818,7 +818,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Convert_f16_to_f32_Success) {
|
|||
auto* ctor = call->Target()->As<sem::TypeConversion>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 1u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 1u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::F16>());
|
||||
}
|
||||
|
||||
|
@ -941,7 +941,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2_Success_Zero
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 0u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2F32_Success_Scalar) {
|
||||
|
@ -960,7 +960,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2F32_Success_S
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 2u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 2u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::F32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::F32>());
|
||||
}
|
||||
|
@ -983,7 +983,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2F16_Success_S
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 2u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 2u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::F16>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::F16>());
|
||||
}
|
||||
|
@ -1004,7 +1004,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2U32_Success_S
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 2u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 2u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::U32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::U32>());
|
||||
}
|
||||
|
@ -1025,7 +1025,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2I32_Success_S
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 2u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 2u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::I32>());
|
||||
}
|
||||
|
@ -1046,7 +1046,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2Bool_Success_
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 2u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 2u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Bool>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::Bool>());
|
||||
}
|
||||
|
@ -1067,7 +1067,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2_Success_Iden
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 1u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 1u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
|
||||
}
|
||||
|
||||
|
@ -1087,7 +1087,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2_Success_Vec2
|
|||
auto* ctor = call->Target()->As<sem::TypeConversion>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 1u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 1u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
|
||||
}
|
||||
|
||||
|
@ -1223,7 +1223,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Success_Zero
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 0u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3F32_Success_Scalar) {
|
||||
|
@ -1242,7 +1242,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3F32_Success_S
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 3u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 3u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::F32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::F32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::F32>());
|
||||
|
@ -1266,7 +1266,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3F16_Success_S
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 3u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 3u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::F16>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::F16>());
|
||||
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::F16>());
|
||||
|
@ -1288,7 +1288,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3U32_Success_S
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 3u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 3u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::U32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::U32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::U32>());
|
||||
|
@ -1310,7 +1310,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3I32_Success_S
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 3u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 3u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::I32>());
|
||||
|
@ -1332,7 +1332,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3Bool_Success_
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 3u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 3u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Bool>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::Bool>());
|
||||
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::Bool>());
|
||||
|
@ -1354,7 +1354,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Success_Vec2
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 2u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 2u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::F32>());
|
||||
}
|
||||
|
@ -1375,7 +1375,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Success_Scal
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 2u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 2u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::F32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::Vector>());
|
||||
}
|
||||
|
@ -1396,7 +1396,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Success_Iden
|
|||
auto* ctor = call->Target()->As<sem::TypeConstructor>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 1u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 1u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
|
||||
}
|
||||
|
||||
|
@ -1416,7 +1416,7 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Success_Vec3
|
|||
auto* ctor = call->Target()->As<sem::TypeConversion>();
|
||||
ASSERT_NE(ctor, nullptr);
|
||||
EXPECT_EQ(call->Type(), ctor->ReturnType());
|
||||
ASSERT_EQ(ctor->Parameters().size(), 1u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 1u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
|
||||
}
|
||||
|
||||
|
|
|
@ -1739,17 +1739,17 @@ bool Validator::FunctionCall(const sem::Call* call, sem::Statement* current_stat
|
|||
return false;
|
||||
}
|
||||
|
||||
if (decl->args.size() != target->Parameters().size()) {
|
||||
bool more = decl->args.size() > target->Parameters().size();
|
||||
if (decl->args.size() != target->Parameters().Length()) {
|
||||
bool more = decl->args.size() > target->Parameters().Length();
|
||||
AddError("too " + (more ? std::string("many") : std::string("few")) +
|
||||
" arguments in call to '" + name + "', expected " +
|
||||
std::to_string(target->Parameters().size()) + ", got " +
|
||||
std::to_string(call->Arguments().size()),
|
||||
std::to_string(target->Parameters().Length()) + ", got " +
|
||||
std::to_string(call->Arguments().Length()),
|
||||
decl->source);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < call->Arguments().size(); ++i) {
|
||||
for (size_t i = 0; i < call->Arguments().Length(); ++i) {
|
||||
const sem::Variable* param = target->Parameters()[i];
|
||||
const ast::Expression* arg_expr = decl->args[i];
|
||||
auto* param_type = param->Type();
|
||||
|
|
|
@ -17,13 +17,25 @@
|
|||
|
||||
#include "src/tint/sem/builtin.h"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "src/tint/utils/to_const_ptr_vec.h"
|
||||
#include "src/tint/utils/transform.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::sem::Builtin);
|
||||
|
||||
namespace tint::sem {
|
||||
namespace {
|
||||
|
||||
utils::VectorRef<const Parameter*> SetOwner(utils::VectorRef<Parameter*> parameters,
|
||||
const tint::sem::CallTarget* owner) {
|
||||
for (auto* parameter : parameters) {
|
||||
parameter->SetOwner(owner);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const char* Builtin::str() const {
|
||||
return sem::str(type_);
|
||||
|
@ -89,18 +101,14 @@ bool IsDP4aBuiltin(BuiltinType i) {
|
|||
|
||||
Builtin::Builtin(BuiltinType type,
|
||||
const sem::Type* return_type,
|
||||
std::vector<Parameter*> parameters,
|
||||
utils::VectorRef<Parameter*> parameters,
|
||||
EvaluationStage eval_stage,
|
||||
PipelineStageSet supported_stages,
|
||||
bool is_deprecated)
|
||||
: Base(return_type, utils::ToConstPtrVec(parameters), eval_stage),
|
||||
: Base(return_type, SetOwner(std::move(parameters), this), eval_stage),
|
||||
type_(type),
|
||||
supported_stages_(supported_stages),
|
||||
is_deprecated_(is_deprecated) {
|
||||
for (auto* parameter : parameters) {
|
||||
parameter->SetOwner(this);
|
||||
}
|
||||
}
|
||||
is_deprecated_(is_deprecated) {}
|
||||
|
||||
Builtin::~Builtin() = default;
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ class Builtin final : public Castable<Builtin, CallTarget> {
|
|||
/// deprecated
|
||||
Builtin(BuiltinType type,
|
||||
const sem::Type* return_type,
|
||||
std::vector<Parameter*> parameters,
|
||||
utils::VectorRef<Parameter*> parameters,
|
||||
EvaluationStage eval_stage,
|
||||
PipelineStageSet supported_stages,
|
||||
bool is_deprecated);
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace tint::sem {
|
|||
Call::Call(const ast::CallExpression* declaration,
|
||||
const CallTarget* target,
|
||||
EvaluationStage stage,
|
||||
std::vector<const sem::Expression*> arguments,
|
||||
utils::VectorRef<const sem::Expression*> arguments,
|
||||
const Statement* statement,
|
||||
const Constant* constant,
|
||||
bool has_side_effects)
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "src/tint/ast/call_expression.h"
|
||||
#include "src/tint/sem/builtin.h"
|
||||
#include "src/tint/sem/expression.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
|
||||
namespace tint::sem {
|
||||
|
||||
|
@ -38,7 +39,7 @@ class Call final : public Castable<Call, Expression> {
|
|||
Call(const ast::CallExpression* declaration,
|
||||
const CallTarget* target,
|
||||
EvaluationStage stage,
|
||||
std::vector<const sem::Expression*> arguments,
|
||||
utils::VectorRef<const sem::Expression*> arguments,
|
||||
const Statement* statement,
|
||||
const Constant* constant,
|
||||
bool has_side_effects);
|
||||
|
@ -50,7 +51,7 @@ class Call final : public Castable<Call, Expression> {
|
|||
const CallTarget* Target() const { return target_; }
|
||||
|
||||
/// @return the call arguments
|
||||
const std::vector<const sem::Expression*>& Arguments() const { return arguments_; }
|
||||
const auto& Arguments() const { return arguments_; }
|
||||
|
||||
/// @returns the AST node
|
||||
const ast::CallExpression* Declaration() const {
|
||||
|
@ -59,7 +60,7 @@ class Call final : public Castable<Call, Expression> {
|
|||
|
||||
private:
|
||||
CallTarget const* const target_;
|
||||
std::vector<const sem::Expression*> arguments_;
|
||||
utils::Vector<const sem::Expression*, 8> arguments_;
|
||||
};
|
||||
|
||||
} // namespace tint::sem
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "src/tint/sem/call_target.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "src/tint/symbol_table.h"
|
||||
#include "src/tint/utils/hash.h"
|
||||
|
||||
|
@ -22,22 +24,23 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::CallTarget);
|
|||
namespace tint::sem {
|
||||
|
||||
CallTarget::CallTarget(const sem::Type* return_type,
|
||||
const ParameterList& parameters,
|
||||
utils::VectorRef<const Parameter*> parameters,
|
||||
EvaluationStage stage)
|
||||
: signature_{return_type, parameters}, stage_(stage) {
|
||||
: signature_{return_type, std::move(parameters)}, stage_(stage) {
|
||||
TINT_ASSERT(Semantic, return_type);
|
||||
}
|
||||
|
||||
CallTarget::CallTarget(const CallTarget&) = default;
|
||||
CallTarget::~CallTarget() = default;
|
||||
|
||||
CallTargetSignature::CallTargetSignature(const sem::Type* ret_ty, const ParameterList& params)
|
||||
: return_type(ret_ty), parameters(params) {}
|
||||
CallTargetSignature::CallTargetSignature(const sem::Type* ret_ty,
|
||||
utils::VectorRef<const Parameter*> params)
|
||||
: return_type(ret_ty), parameters(std::move(params)) {}
|
||||
CallTargetSignature::CallTargetSignature(const CallTargetSignature&) = default;
|
||||
CallTargetSignature::~CallTargetSignature() = default;
|
||||
|
||||
int CallTargetSignature::IndexOf(ParameterUsage usage) const {
|
||||
for (size_t i = 0; i < parameters.size(); i++) {
|
||||
for (size_t i = 0; i < parameters.Length(); i++) {
|
||||
if (parameters[i]->Usage() == usage) {
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
|
@ -46,10 +49,10 @@ int CallTargetSignature::IndexOf(ParameterUsage usage) const {
|
|||
}
|
||||
|
||||
bool CallTargetSignature::operator==(const CallTargetSignature& other) const {
|
||||
if (return_type != other.return_type || parameters.size() != other.parameters.size()) {
|
||||
if (return_type != other.return_type || parameters.Length() != other.parameters.Length()) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < parameters.size(); i++) {
|
||||
for (size_t i = 0; i < parameters.Length(); i++) {
|
||||
auto* a = parameters[i];
|
||||
auto* b = other.parameters[i];
|
||||
if (a->Type() != b->Type() || a->Usage() != b->Usage()) {
|
||||
|
@ -65,7 +68,7 @@ namespace std {
|
|||
|
||||
std::size_t hash<tint::sem::CallTargetSignature>::operator()(
|
||||
const tint::sem::CallTargetSignature& sig) const {
|
||||
size_t hash = tint::utils::Hash(sig.parameters.size());
|
||||
size_t hash = tint::utils::Hash(sig.parameters.Length());
|
||||
for (auto* p : sig.parameters) {
|
||||
tint::utils::HashCombine(&hash, p->Type(), p->Usage());
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "src/tint/sem/sampler.h"
|
||||
#include "src/tint/sem/variable.h"
|
||||
#include "src/tint/utils/hash.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
|
||||
// Forward declarations
|
||||
namespace tint::sem {
|
||||
|
@ -34,7 +35,7 @@ struct CallTargetSignature {
|
|||
/// Constructor
|
||||
/// @param ret_ty the call target return type
|
||||
/// @param params the call target parameters
|
||||
CallTargetSignature(const sem::Type* ret_ty, const ParameterList& params);
|
||||
CallTargetSignature(const sem::Type* ret_ty, utils::VectorRef<const Parameter*> params);
|
||||
|
||||
/// Copy constructor
|
||||
CallTargetSignature(const CallTargetSignature&);
|
||||
|
@ -45,7 +46,7 @@ struct CallTargetSignature {
|
|||
/// The type of the call target return value
|
||||
const sem::Type* const return_type = nullptr;
|
||||
/// The parameters of the call target
|
||||
const ParameterList parameters;
|
||||
const utils::Vector<const sem::Parameter*, 8> parameters;
|
||||
|
||||
/// Equality operator
|
||||
/// @param other the signature to compare this to
|
||||
|
@ -67,7 +68,7 @@ class CallTarget : public Castable<CallTarget, Node> {
|
|||
/// @param return_type the return type of the call target
|
||||
/// @param parameters the parameters for the call target
|
||||
CallTarget(const sem::Type* return_type,
|
||||
const ParameterList& parameters,
|
||||
utils::VectorRef<const Parameter*> parameters,
|
||||
EvaluationStage stage);
|
||||
|
||||
/// Copy constructor
|
||||
|
@ -80,7 +81,7 @@ class CallTarget : public Castable<CallTarget, Node> {
|
|||
const sem::Type* ReturnType() const { return signature_.return_type; }
|
||||
|
||||
/// @return the parameters of the call target
|
||||
const ParameterList& Parameters() const { return signature_.parameters; }
|
||||
auto& Parameters() const { return signature_.parameters; }
|
||||
|
||||
/// @return the signature of the call target
|
||||
const CallTargetSignature& Signature() const { return signature_; }
|
||||
|
|
|
@ -21,22 +21,29 @@
|
|||
#include "src/tint/sem/sampled_texture.h"
|
||||
#include "src/tint/sem/storage_texture.h"
|
||||
#include "src/tint/sem/variable.h"
|
||||
#include "src/tint/utils/to_const_ptr_vec.h"
|
||||
#include "src/tint/utils/transform.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::sem::Function);
|
||||
|
||||
namespace tint::sem {
|
||||
namespace {
|
||||
|
||||
utils::VectorRef<const Parameter*> SetOwner(utils::VectorRef<Parameter*> parameters,
|
||||
const tint::sem::CallTarget* owner) {
|
||||
for (auto* parameter : parameters) {
|
||||
parameter->SetOwner(owner);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Function::Function(const ast::Function* declaration,
|
||||
Type* return_type,
|
||||
std::vector<Parameter*> parameters)
|
||||
: Base(return_type, utils::ToConstPtrVec(parameters), EvaluationStage::kRuntime),
|
||||
utils::VectorRef<Parameter*> parameters)
|
||||
: Base(return_type, SetOwner(std::move(parameters), this), EvaluationStage::kRuntime),
|
||||
declaration_(declaration),
|
||||
workgroup_size_{WorkgroupDimension{1}, WorkgroupDimension{1}, WorkgroupDimension{1}} {
|
||||
for (auto* parameter : parameters) {
|
||||
parameter->SetOwner(this);
|
||||
}
|
||||
}
|
||||
workgroup_size_{WorkgroupDimension{1}, WorkgroupDimension{1}, WorkgroupDimension{1}} {}
|
||||
|
||||
Function::~Function() = default;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "src/tint/ast/variable.h"
|
||||
#include "src/tint/sem/call.h"
|
||||
#include "src/tint/utils/unique_vector.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
|
||||
// Forward declarations
|
||||
namespace tint::ast {
|
||||
|
@ -62,7 +63,7 @@ class Function final : public Castable<Function, CallTarget> {
|
|||
/// @param parameters the parameters to the function
|
||||
Function(const ast::Function* declaration,
|
||||
Type* return_type,
|
||||
std::vector<Parameter*> parameters);
|
||||
utils::VectorRef<Parameter*> parameters);
|
||||
|
||||
/// Destructor
|
||||
~Function() override;
|
||||
|
|
|
@ -61,7 +61,7 @@ Swizzle::Swizzle(const ast::MemberAccessorExpression* declaration,
|
|||
const Statement* statement,
|
||||
const Constant* constant,
|
||||
const Expression* object,
|
||||
std::vector<uint32_t> indices,
|
||||
utils::VectorRef<uint32_t> indices,
|
||||
bool has_side_effects,
|
||||
const Variable* source_var /* = nullptr */)
|
||||
: Base(declaration,
|
||||
|
|
|
@ -15,9 +15,8 @@
|
|||
#ifndef SRC_TINT_SEM_MEMBER_ACCESSOR_EXPRESSION_H_
|
||||
#define SRC_TINT_SEM_MEMBER_ACCESSOR_EXPRESSION_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/tint/sem/expression.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
|
||||
// Forward declarations
|
||||
namespace tint::ast {
|
||||
|
@ -113,7 +112,7 @@ class Swizzle final : public Castable<Swizzle, MemberAccessorExpression> {
|
|||
const Statement* statement,
|
||||
const Constant* constant,
|
||||
const Expression* object,
|
||||
std::vector<uint32_t> indices,
|
||||
utils::VectorRef<uint32_t> indices,
|
||||
bool has_side_effects,
|
||||
const Variable* source_var = nullptr);
|
||||
|
||||
|
@ -121,10 +120,10 @@ class Swizzle final : public Castable<Swizzle, MemberAccessorExpression> {
|
|||
~Swizzle() override;
|
||||
|
||||
/// @return the swizzle indices, if this is a vector swizzle
|
||||
const std::vector<uint32_t>& Indices() const { return indices_; }
|
||||
const auto& Indices() const { return indices_; }
|
||||
|
||||
private:
|
||||
std::vector<uint32_t> const indices_;
|
||||
utils::Vector<uint32_t, 4> const indices_;
|
||||
};
|
||||
|
||||
} // namespace tint::sem
|
||||
|
|
|
@ -14,14 +14,16 @@
|
|||
|
||||
#include "src/tint/sem/type_constructor.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::sem::TypeConstructor);
|
||||
|
||||
namespace tint::sem {
|
||||
|
||||
TypeConstructor::TypeConstructor(const sem::Type* type,
|
||||
const ParameterList& parameters,
|
||||
utils::VectorRef<const Parameter*> parameters,
|
||||
EvaluationStage stage)
|
||||
: Base(type, parameters, stage) {}
|
||||
: Base(type, std::move(parameters), stage) {}
|
||||
|
||||
TypeConstructor::~TypeConstructor() = default;
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define SRC_TINT_SEM_TYPE_CONSTRUCTOR_H_
|
||||
|
||||
#include "src/tint/sem/call_target.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
|
||||
namespace tint::sem {
|
||||
|
||||
|
@ -26,7 +27,9 @@ class TypeConstructor final : public Castable<TypeConstructor, CallTarget> {
|
|||
/// @param type the type that's being constructed
|
||||
/// @param parameters the type constructor parameters
|
||||
/// @param stage the earliest evaluation stage for the expression
|
||||
TypeConstructor(const sem::Type* type, const ParameterList& parameters, EvaluationStage stage);
|
||||
TypeConstructor(const sem::Type* type,
|
||||
utils::VectorRef<const Parameter*> parameters,
|
||||
EvaluationStage stage);
|
||||
|
||||
/// Destructor
|
||||
~TypeConstructor() override;
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace tint::sem {
|
|||
TypeConversion::TypeConversion(const sem::Type* type,
|
||||
const sem::Parameter* parameter,
|
||||
EvaluationStage stage)
|
||||
: Base(type, ParameterList{parameter}, stage) {}
|
||||
: Base(type, utils::Vector<const sem::Parameter*, 1>{parameter}, stage) {}
|
||||
|
||||
TypeConversion::~TypeConversion() = default;
|
||||
|
||||
|
|
|
@ -222,9 +222,6 @@ class Parameter final : public Castable<Parameter, Variable> {
|
|||
const sem::Node* shadows_ = nullptr;
|
||||
};
|
||||
|
||||
/// ParameterList is a list of Parameter
|
||||
using ParameterList = std::vector<const Parameter*>;
|
||||
|
||||
/// VariableUser holds the semantic information for an identifier expression
|
||||
/// node that resolves to a variable.
|
||||
class VariableUser final : public Castable<VariableUser, Expression> {
|
||||
|
|
|
@ -509,7 +509,7 @@ struct CanonicalizeEntryPointIO::State {
|
|||
}
|
||||
|
||||
// Exit early if there is no shader IO to handle.
|
||||
if (func_sem->Parameters().size() == 0 && func_sem->ReturnType()->Is<sem::Void>() &&
|
||||
if (func_sem->Parameters().Length() == 0 && func_sem->ReturnType()->Is<sem::Void>() &&
|
||||
!needs_fixed_sample_mask && !needs_vertex_point_size &&
|
||||
cfg.shader_style != ShaderStyle::kGlsl) {
|
||||
return;
|
||||
|
@ -517,7 +517,7 @@ struct CanonicalizeEntryPointIO::State {
|
|||
|
||||
// Process the entry point parameters, collecting those that need to be
|
||||
// aggregated into a single structure.
|
||||
if (!func_sem->Parameters().empty()) {
|
||||
if (!func_sem->Parameters().IsEmpty()) {
|
||||
for (auto* param : func_sem->Parameters()) {
|
||||
if (param->Type()->Is<sem::Struct>()) {
|
||||
ProcessStructParameter(param);
|
||||
|
|
|
@ -635,7 +635,7 @@ struct DecomposeMemoryAccess::State {
|
|||
};
|
||||
|
||||
// Other parameters are copied as-is:
|
||||
for (size_t i = 1; i < intrinsic->Parameters().size(); i++) {
|
||||
for (size_t i = 1; i < intrinsic->Parameters().Length(); i++) {
|
||||
auto* param = intrinsic->Parameters()[i];
|
||||
auto* ty = CreateASTTypeFor(ctx, param->Type());
|
||||
params.emplace_back(b.Param("param_" + std::to_string(i), ty));
|
||||
|
@ -834,7 +834,7 @@ void DecomposeMemoryAccess::Run(CloneContext& ctx, const DataMap&, DataMap&) con
|
|||
// X.Y
|
||||
auto* accessor_sem = sem.Get(accessor);
|
||||
if (auto* swizzle = accessor_sem->As<sem::Swizzle>()) {
|
||||
if (swizzle->Indices().size() == 1) {
|
||||
if (swizzle->Indices().Length() == 1) {
|
||||
if (auto access = state.TakeAccess(accessor->structure)) {
|
||||
auto* vec_ty = access.type->As<sem::Vector>();
|
||||
auto* offset = state.Mul(vec_ty->type()->Size(), swizzle->Indices()[0u]);
|
||||
|
|
|
@ -187,7 +187,7 @@ struct MultiplanarExternalTexture::State {
|
|||
auto* call = sem.Get(expr)->UnwrapMaterialize()->As<sem::Call>();
|
||||
auto* builtin = call->Target()->As<sem::Builtin>();
|
||||
|
||||
if (builtin && !builtin->Parameters().empty() &&
|
||||
if (builtin && !builtin->Parameters().IsEmpty() &&
|
||||
builtin->Parameters()[0]->Type()->Is<sem::ExternalTexture>() &&
|
||||
builtin->Type() != sem::BuiltinType::kTextureDimensions) {
|
||||
if (auto* var_user = sem.Get<sem::VariableUser>(expr->args[0])) {
|
||||
|
|
|
@ -36,7 +36,7 @@ bool VectorizeScalarMatrixConstructors::ShouldRun(const Program* program, const
|
|||
if (auto* call = program->Sem().Get<sem::Call>(node)) {
|
||||
if (call->Target()->Is<sem::TypeConstructor>() && call->Type()->Is<sem::Matrix>()) {
|
||||
auto& args = call->Arguments();
|
||||
if (args.size() > 0 && args[0]->Type()->UnwrapRef()->is_scalar()) {
|
||||
if (!args.IsEmpty() && args[0]->Type()->UnwrapRef()->is_scalar()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ void VectorizeScalarMatrixConstructors::Run(CloneContext& ctx, const DataMap&, D
|
|||
}
|
||||
|
||||
auto& args = call->Arguments();
|
||||
if (args.size() == 0) {
|
||||
if (args.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!args[0]->Type()->UnwrapRef()->is_scalar()) {
|
||||
|
@ -85,7 +85,7 @@ void VectorizeScalarMatrixConstructors::Run(CloneContext& ctx, const DataMap&, D
|
|||
return ctx.dst->Construct(CreateASTTypeFor(ctx, mat_type), columns);
|
||||
};
|
||||
|
||||
if (args.size() == 1) {
|
||||
if (args.Length() == 1) {
|
||||
// Generate a helper function for constructing the matrix.
|
||||
// This is done to ensure that the single argument value is only evaluated once, and
|
||||
// with the correct expression evaluation order.
|
||||
|
@ -109,7 +109,7 @@ void VectorizeScalarMatrixConstructors::Run(CloneContext& ctx, const DataMap&, D
|
|||
return ctx.dst->Call(fn, ctx.Clone(args[0]->Declaration()));
|
||||
}
|
||||
|
||||
if (args.size() == mat_type->columns() * mat_type->rows()) {
|
||||
if (args.Length() == mat_type->columns() * mat_type->rows()) {
|
||||
return build_mat([&](uint32_t c, uint32_t r) {
|
||||
return ctx.Clone(args[c * mat_type->rows() + r]->Declaration());
|
||||
});
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
|
||||
// Copyright 2021 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SRC_TINT_UTILS_TO_CONST_PTR_VEC_H_
|
||||
#define SRC_TINT_UTILS_TO_CONST_PTR_VEC_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace tint::utils {
|
||||
|
||||
/// @param in a vector of `T*`
|
||||
/// @returns a vector of `const T*` with the content of `in`.
|
||||
template <typename T>
|
||||
std::vector<const T*> ToConstPtrVec(const std::vector<T*>& in) {
|
||||
std::vector<const T*> out;
|
||||
out.reserve(in.size());
|
||||
for (auto* ptr : in) {
|
||||
out.emplace_back(ptr);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace tint::utils
|
||||
|
||||
#endif // SRC_TINT_UTILS_TO_CONST_PTR_VEC_H_
|
|
@ -112,23 +112,23 @@ const sem::Call* AppendVector(ProgramBuilder* b,
|
|||
// to convert a vector of a different type, e.g. vec2<i32>(vec2<u32>()).
|
||||
// In that case, preserve the original argument, or you'll get a type error.
|
||||
|
||||
std::vector<const sem::Expression*> packed;
|
||||
utils::Vector<const sem::Expression*, 4> packed;
|
||||
if (auto vc = AsVectorConstructor(vector_sem)) {
|
||||
const auto num_supplied = vc.call->Arguments().size();
|
||||
const auto num_supplied = vc.call->Arguments().Length();
|
||||
if (num_supplied == 0) {
|
||||
// Zero-value vector constructor. Populate with zeros
|
||||
for (uint32_t i = 0; i < packed_size - 1; i++) {
|
||||
auto* zero = Zero(*b, packed_el_sem_ty, statement);
|
||||
packed.emplace_back(zero);
|
||||
packed.Push(zero);
|
||||
}
|
||||
} else if (num_supplied + 1 == packed_size) {
|
||||
// All vector components were supplied as scalars. Pass them through.
|
||||
packed = vc.call->Arguments();
|
||||
}
|
||||
}
|
||||
if (packed.empty()) {
|
||||
if (packed.IsEmpty()) {
|
||||
// The special cases didn't occur. Use the vector argument as-is.
|
||||
packed.emplace_back(vector_sem);
|
||||
packed.Push(vector_sem);
|
||||
}
|
||||
|
||||
if (packed_el_sem_ty != scalar_sem->Type()->UnwrapRef()) {
|
||||
|
@ -141,17 +141,18 @@ const sem::Call* AppendVector(ProgramBuilder* b,
|
|||
sem::EvaluationStage::kRuntime);
|
||||
auto* scalar_cast_sem = b->create<sem::Call>(
|
||||
scalar_cast_ast, scalar_cast_target, sem::EvaluationStage::kRuntime,
|
||||
std::vector<const sem::Expression*>{scalar_sem}, statement,
|
||||
utils::Vector<const sem::Expression*, 1>{scalar_sem}, statement,
|
||||
/* constant_value */ nullptr, /* has_side_effects */ false);
|
||||
b->Sem().Add(scalar_cast_ast, scalar_cast_sem);
|
||||
packed.emplace_back(scalar_cast_sem);
|
||||
packed.Push(scalar_cast_sem);
|
||||
} else {
|
||||
packed.emplace_back(scalar_sem);
|
||||
packed.Push(scalar_sem);
|
||||
}
|
||||
|
||||
auto* constructor_ast = b->Construct(
|
||||
packed_ast_ty,
|
||||
utils::Transform(packed, [&](const sem::Expression* expr) { return expr->Declaration(); }));
|
||||
packed_ast_ty, utils::ToStdVector(utils::Transform(packed, [&](const sem::Expression* expr) {
|
||||
return expr->Declaration();
|
||||
})));
|
||||
auto* constructor_target = b->create<sem::TypeConstructor>(
|
||||
packed_sem_ty,
|
||||
utils::Transform(packed,
|
||||
|
@ -163,7 +164,8 @@ const sem::Call* AppendVector(ProgramBuilder* b,
|
|||
sem::EvaluationStage::kRuntime);
|
||||
auto* constructor_sem =
|
||||
b->create<sem::Call>(constructor_ast, constructor_target, sem::EvaluationStage::kRuntime,
|
||||
packed, statement, /* constant_value */ nullptr,
|
||||
std::move(packed), statement,
|
||||
/* constant_value */ nullptr,
|
||||
/* has_side_effects */ false);
|
||||
b->Sem().Add(constructor_ast, constructor_sem);
|
||||
return constructor_sem;
|
||||
|
|
|
@ -48,7 +48,7 @@ TEST_F(AppendVectorTest, Vec2i32_i32) {
|
|||
|
||||
auto* call = Sem().Get<sem::Call>(vec_123);
|
||||
ASSERT_NE(call, nullptr);
|
||||
ASSERT_EQ(call->Arguments().size(), 3u);
|
||||
ASSERT_EQ(call->Arguments().Length(), 3u);
|
||||
EXPECT_EQ(call->Arguments()[0], Sem().Get(scalar_1));
|
||||
EXPECT_EQ(call->Arguments()[1], Sem().Get(scalar_2));
|
||||
EXPECT_EQ(call->Arguments()[2], Sem().Get(scalar_3));
|
||||
|
@ -60,7 +60,7 @@ TEST_F(AppendVectorTest, Vec2i32_i32) {
|
|||
EXPECT_TRUE(ctor->ReturnType()->As<sem::Vector>()->type()->Is<sem::I32>());
|
||||
EXPECT_EQ(ctor->ReturnType(), call->Type());
|
||||
|
||||
ASSERT_EQ(ctor->Parameters().size(), 3u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 3u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::I32>());
|
||||
|
@ -92,7 +92,7 @@ TEST_F(AppendVectorTest, Vec2i32_u32) {
|
|||
|
||||
auto* call = Sem().Get<sem::Call>(vec_123);
|
||||
ASSERT_NE(call, nullptr);
|
||||
ASSERT_EQ(call->Arguments().size(), 3u);
|
||||
ASSERT_EQ(call->Arguments().Length(), 3u);
|
||||
EXPECT_EQ(call->Arguments()[0], Sem().Get(scalar_1));
|
||||
EXPECT_EQ(call->Arguments()[1], Sem().Get(scalar_2));
|
||||
EXPECT_EQ(call->Arguments()[2], Sem().Get(u32_to_i32));
|
||||
|
@ -104,7 +104,7 @@ TEST_F(AppendVectorTest, Vec2i32_u32) {
|
|||
EXPECT_TRUE(ctor->ReturnType()->As<sem::Vector>()->type()->Is<sem::I32>());
|
||||
EXPECT_EQ(ctor->ReturnType(), call->Type());
|
||||
|
||||
ASSERT_EQ(ctor->Parameters().size(), 3u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 3u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::I32>());
|
||||
|
@ -144,7 +144,7 @@ TEST_F(AppendVectorTest, Vec2i32FromVec2u32_u32) {
|
|||
|
||||
auto* call = Sem().Get<sem::Call>(vec_123);
|
||||
ASSERT_NE(call, nullptr);
|
||||
ASSERT_EQ(call->Arguments().size(), 2u);
|
||||
ASSERT_EQ(call->Arguments().Length(), 2u);
|
||||
EXPECT_EQ(call->Arguments()[0], Sem().Get(vec_12));
|
||||
EXPECT_EQ(call->Arguments()[1], Sem().Get(u32_to_i32));
|
||||
|
||||
|
@ -155,7 +155,7 @@ TEST_F(AppendVectorTest, Vec2i32FromVec2u32_u32) {
|
|||
EXPECT_TRUE(ctor->ReturnType()->As<sem::Vector>()->type()->Is<sem::I32>());
|
||||
EXPECT_EQ(ctor->ReturnType(), call->Type());
|
||||
|
||||
ASSERT_EQ(ctor->Parameters().size(), 2u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 2u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::I32>());
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ TEST_F(AppendVectorTest, Vec2i32_f32) {
|
|||
|
||||
auto* call = Sem().Get<sem::Call>(vec_123);
|
||||
ASSERT_NE(call, nullptr);
|
||||
ASSERT_EQ(call->Arguments().size(), 3u);
|
||||
ASSERT_EQ(call->Arguments().Length(), 3u);
|
||||
EXPECT_EQ(call->Arguments()[0], Sem().Get(scalar_1));
|
||||
EXPECT_EQ(call->Arguments()[1], Sem().Get(scalar_2));
|
||||
EXPECT_EQ(call->Arguments()[2], Sem().Get(f32_to_i32));
|
||||
|
@ -198,7 +198,7 @@ TEST_F(AppendVectorTest, Vec2i32_f32) {
|
|||
EXPECT_TRUE(ctor->ReturnType()->As<sem::Vector>()->type()->Is<sem::I32>());
|
||||
EXPECT_EQ(ctor->ReturnType(), call->Type());
|
||||
|
||||
ASSERT_EQ(ctor->Parameters().size(), 3u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 3u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::I32>());
|
||||
|
@ -228,7 +228,7 @@ TEST_F(AppendVectorTest, Vec3i32_i32) {
|
|||
|
||||
auto* call = Sem().Get<sem::Call>(vec_1234);
|
||||
ASSERT_NE(call, nullptr);
|
||||
ASSERT_EQ(call->Arguments().size(), 4u);
|
||||
ASSERT_EQ(call->Arguments().Length(), 4u);
|
||||
EXPECT_EQ(call->Arguments()[0], Sem().Get(scalar_1));
|
||||
EXPECT_EQ(call->Arguments()[1], Sem().Get(scalar_2));
|
||||
EXPECT_EQ(call->Arguments()[2], Sem().Get(scalar_3));
|
||||
|
@ -241,7 +241,7 @@ TEST_F(AppendVectorTest, Vec3i32_i32) {
|
|||
EXPECT_TRUE(ctor->ReturnType()->As<sem::Vector>()->type()->Is<sem::I32>());
|
||||
EXPECT_EQ(ctor->ReturnType(), call->Type());
|
||||
|
||||
ASSERT_EQ(ctor->Parameters().size(), 4u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 4u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::I32>());
|
||||
|
@ -268,7 +268,7 @@ TEST_F(AppendVectorTest, Vec2i32Var_i32) {
|
|||
|
||||
auto* call = Sem().Get<sem::Call>(vec_123);
|
||||
ASSERT_NE(call, nullptr);
|
||||
ASSERT_EQ(call->Arguments().size(), 2u);
|
||||
ASSERT_EQ(call->Arguments().Length(), 2u);
|
||||
EXPECT_EQ(call->Arguments()[0], Sem().Get(vec_12));
|
||||
EXPECT_EQ(call->Arguments()[1], Sem().Get(scalar_3));
|
||||
|
||||
|
@ -279,7 +279,7 @@ TEST_F(AppendVectorTest, Vec2i32Var_i32) {
|
|||
EXPECT_TRUE(ctor->ReturnType()->As<sem::Vector>()->type()->Is<sem::I32>());
|
||||
EXPECT_EQ(ctor->ReturnType(), call->Type());
|
||||
|
||||
ASSERT_EQ(ctor->Parameters().size(), 2u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 2u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::I32>());
|
||||
}
|
||||
|
@ -307,7 +307,7 @@ TEST_F(AppendVectorTest, Vec2i32_i32Var) {
|
|||
|
||||
auto* call = Sem().Get<sem::Call>(vec_123);
|
||||
ASSERT_NE(call, nullptr);
|
||||
ASSERT_EQ(call->Arguments().size(), 3u);
|
||||
ASSERT_EQ(call->Arguments().Length(), 3u);
|
||||
EXPECT_EQ(call->Arguments()[0], Sem().Get(scalar_1));
|
||||
EXPECT_EQ(call->Arguments()[1], Sem().Get(scalar_2));
|
||||
EXPECT_EQ(call->Arguments()[2], Sem().Get(scalar_3));
|
||||
|
@ -319,7 +319,7 @@ TEST_F(AppendVectorTest, Vec2i32_i32Var) {
|
|||
EXPECT_TRUE(ctor->ReturnType()->As<sem::Vector>()->type()->Is<sem::I32>());
|
||||
EXPECT_EQ(ctor->ReturnType(), call->Type());
|
||||
|
||||
ASSERT_EQ(ctor->Parameters().size(), 3u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 3u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::I32>());
|
||||
|
@ -346,7 +346,7 @@ TEST_F(AppendVectorTest, Vec2i32Var_i32Var) {
|
|||
|
||||
auto* call = Sem().Get<sem::Call>(vec_123);
|
||||
ASSERT_NE(call, nullptr);
|
||||
ASSERT_EQ(call->Arguments().size(), 2u);
|
||||
ASSERT_EQ(call->Arguments().Length(), 2u);
|
||||
EXPECT_EQ(call->Arguments()[0], Sem().Get(vec_12));
|
||||
EXPECT_EQ(call->Arguments()[1], Sem().Get(scalar_3));
|
||||
|
||||
|
@ -357,7 +357,7 @@ TEST_F(AppendVectorTest, Vec2i32Var_i32Var) {
|
|||
EXPECT_TRUE(ctor->ReturnType()->As<sem::Vector>()->type()->Is<sem::I32>());
|
||||
EXPECT_EQ(ctor->ReturnType(), call->Type());
|
||||
|
||||
ASSERT_EQ(ctor->Parameters().size(), 2u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 2u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::I32>());
|
||||
}
|
||||
|
@ -387,7 +387,7 @@ TEST_F(AppendVectorTest, Vec2i32Var_f32Var) {
|
|||
|
||||
auto* call = Sem().Get<sem::Call>(vec_123);
|
||||
ASSERT_NE(call, nullptr);
|
||||
ASSERT_EQ(call->Arguments().size(), 2u);
|
||||
ASSERT_EQ(call->Arguments().Length(), 2u);
|
||||
EXPECT_EQ(call->Arguments()[0], Sem().Get(vec_12));
|
||||
EXPECT_EQ(call->Arguments()[1], Sem().Get(f32_to_i32));
|
||||
|
||||
|
@ -398,7 +398,7 @@ TEST_F(AppendVectorTest, Vec2i32Var_f32Var) {
|
|||
EXPECT_TRUE(ctor->ReturnType()->As<sem::Vector>()->type()->Is<sem::I32>());
|
||||
EXPECT_EQ(ctor->ReturnType(), call->Type());
|
||||
|
||||
ASSERT_EQ(ctor->Parameters().size(), 2u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 2u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::I32>());
|
||||
}
|
||||
|
@ -424,7 +424,7 @@ TEST_F(AppendVectorTest, Vec2boolVar_boolVar) {
|
|||
|
||||
auto* call = Sem().Get<sem::Call>(vec_123);
|
||||
ASSERT_NE(call, nullptr);
|
||||
ASSERT_EQ(call->Arguments().size(), 2u);
|
||||
ASSERT_EQ(call->Arguments().Length(), 2u);
|
||||
EXPECT_EQ(call->Arguments()[0], Sem().Get(vec_12));
|
||||
EXPECT_EQ(call->Arguments()[1], Sem().Get(scalar_3));
|
||||
|
||||
|
@ -435,7 +435,7 @@ TEST_F(AppendVectorTest, Vec2boolVar_boolVar) {
|
|||
EXPECT_TRUE(ctor->ReturnType()->As<sem::Vector>()->type()->Is<sem::Bool>());
|
||||
EXPECT_EQ(ctor->ReturnType(), call->Type());
|
||||
|
||||
ASSERT_EQ(ctor->Parameters().size(), 2u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 2u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::Bool>());
|
||||
}
|
||||
|
@ -463,7 +463,7 @@ TEST_F(AppendVectorTest, ZeroVec3i32_i32) {
|
|||
|
||||
auto* call = Sem().Get<sem::Call>(vec_0004);
|
||||
ASSERT_NE(call, nullptr);
|
||||
ASSERT_EQ(call->Arguments().size(), 4u);
|
||||
ASSERT_EQ(call->Arguments().Length(), 4u);
|
||||
EXPECT_EQ(call->Arguments()[0], Sem().Get(vec_0004->args[0]));
|
||||
EXPECT_EQ(call->Arguments()[1], Sem().Get(vec_0004->args[1]));
|
||||
EXPECT_EQ(call->Arguments()[2], Sem().Get(vec_0004->args[2]));
|
||||
|
@ -476,7 +476,7 @@ TEST_F(AppendVectorTest, ZeroVec3i32_i32) {
|
|||
EXPECT_TRUE(ctor->ReturnType()->As<sem::Vector>()->type()->Is<sem::I32>());
|
||||
EXPECT_EQ(ctor->ReturnType(), call->Type());
|
||||
|
||||
ASSERT_EQ(ctor->Parameters().size(), 4u);
|
||||
ASSERT_EQ(ctor->Parameters().Length(), 4u);
|
||||
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::I32>());
|
||||
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::I32>());
|
||||
|
|
|
@ -861,7 +861,7 @@ bool GeneratorImpl::EmitTypeConstructor(std::ostream& out,
|
|||
|
||||
// If the type constructor is empty then we need to construct with the zero
|
||||
// value for all components.
|
||||
if (call->Arguments().empty()) {
|
||||
if (call->Arguments().IsEmpty()) {
|
||||
return EmitZeroValue(out, type);
|
||||
}
|
||||
|
||||
|
|
|
@ -1120,13 +1120,13 @@ bool GeneratorImpl::EmitTypeConstructor(std::ostream& out,
|
|||
|
||||
// If the type constructor is empty then we need to construct with the zero
|
||||
// value for all components.
|
||||
if (call->Arguments().empty()) {
|
||||
if (call->Arguments().IsEmpty()) {
|
||||
return EmitZeroValue(out, type);
|
||||
}
|
||||
|
||||
// Single parameter matrix initializers must be identity constructor.
|
||||
// It could also be conversions between f16 and f32 matrix when f16 is properly supported.
|
||||
if (type->Is<sem::Matrix>() && call->Arguments().size() == 1) {
|
||||
if (type->Is<sem::Matrix>() && call->Arguments().Length() == 1) {
|
||||
if (!ctor->Parameters()[0]->Type()->UnwrapRef()->is_float_matrix()) {
|
||||
TINT_UNREACHABLE(Writer, diagnostics_)
|
||||
<< "found a single-parameter matrix constructor that is not identity constructor";
|
||||
|
@ -1139,7 +1139,7 @@ bool GeneratorImpl::EmitTypeConstructor(std::ostream& out,
|
|||
// For single-value vector initializers, swizzle the scalar to the right
|
||||
// vector dimension using .x
|
||||
const bool is_single_value_vector_init = type->is_scalar_vector() &&
|
||||
call->Arguments().size() == 1 &&
|
||||
call->Arguments().Length() == 1 &&
|
||||
ctor->Parameters()[0]->Type()->is_scalar();
|
||||
|
||||
if (brackets) {
|
||||
|
|
|
@ -2304,7 +2304,7 @@ bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
|
|||
// For multi-element swizzles, we need to cast to a regular vector type
|
||||
// first. Note that we do not currently allow assignments to swizzles, so
|
||||
// the casting which will convert the l-value to r-value is fine.
|
||||
if (swizzle->Indices().size() == 1) {
|
||||
if (swizzle->Indices().Length() == 1) {
|
||||
if (!write_lhs()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1023,7 +1023,7 @@ bool Builder::GenerateMemberAccessor(const ast::MemberAccessorExpression* expr,
|
|||
if (auto* swizzle = expr_sem->As<sem::Swizzle>()) {
|
||||
// Single element swizzle is either an access chain or a composite extract
|
||||
auto& indices = swizzle->Indices();
|
||||
if (indices.size() == 1) {
|
||||
if (indices.Length() == 1) {
|
||||
if (info->source_type->Is<sem::Reference>()) {
|
||||
auto idx_id = GenerateConstantIfNeeded(ScalarConstant::U32(indices[0]));
|
||||
if (idx_id == 0) {
|
||||
|
@ -1338,7 +1338,7 @@ uint32_t Builder::GenerateTypeConstructorOrConversion(const sem::Call* call,
|
|||
auto* result_type = call->Type();
|
||||
|
||||
// Generate the zero initializer if there are no values provided.
|
||||
if (args.empty()) {
|
||||
if (args.IsEmpty()) {
|
||||
if (global_var && global_var->Declaration()->Is<ast::Override>()) {
|
||||
auto constant_id = global_var->ConstantId();
|
||||
if (result_type->Is<sem::I32>()) {
|
||||
|
@ -1491,7 +1491,7 @@ uint32_t Builder::GenerateTypeConstructorOrConversion(const sem::Call* call,
|
|||
|
||||
// For a single-value vector initializer, splat the initializer value.
|
||||
auto* const init_result_type = call->Type()->UnwrapRef();
|
||||
if (args.size() == 1 && init_result_type->is_scalar_vector() &&
|
||||
if (args.Length() == 1 && init_result_type->is_scalar_vector() &&
|
||||
args[0]->Type()->UnwrapRef()->is_scalar()) {
|
||||
size_t vec_size = init_result_type->As<sem::Vector>()->Width();
|
||||
for (size_t i = 0; i < (vec_size - 1); ++i) {
|
||||
|
@ -2667,7 +2667,7 @@ uint32_t Builder::GenerateBuiltinCall(const sem::Call* call, const sem::Builtin*
|
|||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < call->Arguments().size(); i++) {
|
||||
for (size_t i = 0; i < call->Arguments().Length(); i++) {
|
||||
if (auto val_id = get_arg_as_value_id(i)) {
|
||||
params.emplace_back(Operand(val_id));
|
||||
} else {
|
||||
|
@ -3172,8 +3172,8 @@ bool Builder::GenerateAtomicBuiltin(const sem::Call* call,
|
|||
}
|
||||
|
||||
uint32_t value_id = 0;
|
||||
if (call->Arguments().size() > 1) {
|
||||
value_id = GenerateExpressionWithLoadIfNeeded(call->Arguments().back());
|
||||
if (call->Arguments().Length() > 1) {
|
||||
value_id = GenerateExpressionWithLoadIfNeeded(call->Arguments().Back());
|
||||
if (value_id == 0) {
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue