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:
Ben Clayton 2022-07-26 07:55:24 +00:00 committed by Dawn LUCI CQ
parent 4b3d53d141
commit 958a4642f1
38 changed files with 493 additions and 478 deletions

View File

@ -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>()) {

View File

@ -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>

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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++) {

View File

@ -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;
};

View File

@ -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;

View File

@ -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;
}

View File

@ -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_

View File

@ -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());

View File

@ -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>());
}

View File

@ -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();

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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());
}

View File

@ -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_; }

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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> {

View File

@ -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);

View File

@ -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]);

View File

@ -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])) {

View File

@ -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());
});

View File

@ -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_

View File

@ -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;

View File

@ -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>());

View File

@ -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);
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}