ast::Builder: Make the interface more fluent

Add C++ aliases for the wgsl types `i32`, `u32` and `f32`.

Separate types out from the builder and into a `Builder::Types` class. An instance of this is now held by the `Builder::ty` field. Makes it clear when you are referencing a `ast::type` instead of a constructor method.

Rework a number of builder methods so they take the type as a template argument instead of a parameter. This more closely resembles wgsl (example: `vec2<i32>(1,2)`)

Use PascalCase for the constructor methods, but keep the wgsl-like constructors lowercase to imitate the language style.

Add `BuilderWithContext` so that `Builder` can be truely immutable, and so we can remove `set_context()`.

Change-Id: Idf2d7d5abe7d11e27671b8e80d3d56d6bc4b3ca2
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32980
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
Ben Clayton 2020-11-17 15:23:48 +00:00 committed by Commit Bot service account
parent 90f3253645
commit 165ff1c978
4 changed files with 427 additions and 314 deletions

View File

@ -17,16 +17,28 @@
namespace tint { namespace tint {
namespace ast { namespace ast {
Builder::Builder() = default; TypesBuilder::TypesBuilder(TypeManager* tm)
: bool_(tm->Get<ast::type::BoolType>()),
Builder::Builder(tint::Context* ctx) : ctx_(ctx) {} f32(tm->Get<ast::type::F32Type>()),
i32(tm->Get<ast::type::I32Type>()),
u32(tm->Get<ast::type::U32Type>()),
void_(tm->Get<ast::type::VoidType>()),
tm_(tm) {}
Builder::Builder(tint::Context* c) : ctx(c), ty(&c->type_mgr()) {}
Builder::~Builder() = default; Builder::~Builder() = default;
ast::Variable* Builder::make_var(const std::string& name, ast::Variable* Builder::Var(const std::string& name,
ast::StorageClass storage, ast::StorageClass storage,
ast::type::Type* type) { ast::type::Type* type) {
return create<ast::Variable>(name, storage, type); auto* var = create<ast::Variable>(name, storage, type);
OnVariableBuilt(var);
return var;
}
BuilderWithContext::BuilderWithContext() : Builder(new Context()) {}
BuilderWithContext::~BuilderWithContext() {
delete ctx;
} }
} // namespace ast } // namespace ast

View File

@ -15,8 +15,6 @@
#ifndef SRC_AST_BUILDER_H_ #ifndef SRC_AST_BUILDER_H_
#define SRC_AST_BUILDER_H_ #define SRC_AST_BUILDER_H_
#include <assert.h>
#include <memory> #include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
@ -42,175 +40,234 @@
namespace tint { namespace tint {
namespace ast { namespace ast {
/// Helper for building common AST constructs /// TypesBuilder holds basic `ast::tint` types and methods for constructing
class Builder { /// complex types.
class TypesBuilder {
public: public:
/// Constructor /// Constructor
/// Note, the context _must_ be set with |set_context| before the builder /// @param tm the type manager
/// is used. explicit TypesBuilder(TypeManager* tm);
Builder();
/// A boolean type
ast::type::BoolType* const bool_;
/// A f32 type
ast::type::F32Type* const f32;
/// A i32 type
ast::type::I32Type* const i32;
/// A u32 type
ast::type::U32Type* const u32;
/// A void type
ast::type::VoidType* const void_;
/// @return the tint AST type for the C type `T`.
template <typename T>
ast::type::Type* Of() const;
/// @return the tint AST type for a 2-element vector of the C type `T`.
template <typename T>
ast::type::Type* vec2() const;
/// @return the tint AST type for a 3-element vector of the C type `T`.
template <typename T>
ast::type::Type* vec3() const;
/// @return the tint AST type for a 4-element vector of the C type `T`.
template <typename T>
ast::type::Type* vec4() const;
/// @return the tint AST type for a 3x3 matrix of the C type `T`.
template <typename T>
ast::type::Type* mat3x3() const;
/// @return the tint AST type for an array of type `T`.
template <typename T>
ast::type::Type* arr() const;
private:
/// CToAST<T> is specialized for various `T` types and each specialization
/// contains a single static `get()` method for obtaining the corresponding
/// AST type for the C type `T`.
/// `get()` has the signature:
/// `static ast::type::Type* get(Types* t)`
template <typename T>
struct CToAST {};
TypeManager* const tm_;
};
/// Helper for building common AST constructs.
class Builder {
public:
/// `i32` is a type alias to `int`.
/// Useful for passing to template methods such as `vec2<i32>()` to imitate
/// WGSL syntax.
/// Note: this is intentionally not aliased to uint32_t as we want integer
/// literals passed to the builder to match WGSL's integer literal types.
using i32 = decltype(1);
/// `u32` is a type alias to `unsigned int`.
/// Useful for passing to template methods such as `vec2<u32>()` to imitate
/// WGSL syntax.
/// Note: this is intentionally not aliased to uint32_t as we want integer
/// literals passed to the builder to match WGSL's integer literal types.
using u32 = decltype(1u);
/// `f32` is a type alias to `float`
/// Useful for passing to template methods such as `vec2<f32>()` to imitate
/// WGSL syntax.
using f32 = float;
/// Constructor /// Constructor
/// @param ctx the context to use in the builder /// @param ctx the context to use in the builder
explicit Builder(tint::Context* ctx); explicit Builder(tint::Context* ctx);
virtual ~Builder(); virtual ~Builder();
/// Sets the given context into the builder
/// @param ctx the context to set
void set_context(tint::Context* ctx) { ctx_ = ctx; }
/// Creates a new type
/// @param args the arguments to pass to the type constructor
/// @returns a registered pointer to the requested type
template <typename T, typename... ARGS>
ast::type::Type* type(ARGS&&... args) {
assert(ctx_);
return ctx_->type_mgr().Get(
std::make_unique<T>(std::forward<ARGS>(args)...));
}
/// @returns a pointer to the bool type
ast::type::BoolType* bool_type() {
return type<ast::type::BoolType>()->AsBool();
}
/// @returns a pointer to the f32 type
ast::type::F32Type* f32() { return type<ast::type::F32Type>()->AsF32(); }
/// @returns a pointer to the i32 type
ast::type::I32Type* i32() { return type<ast::type::I32Type>()->AsI32(); }
/// @param ty the type of the matrix components
/// @param rows the number of rows
/// @param cols the number of columns
/// @returns a pointer to the u32 type
ast::type::MatrixType* mat(ast::type::Type* ty,
uint32_t rows,
uint32_t cols) {
return type<ast::type::MatrixType>(ty, rows, cols)->AsMatrix();
}
/// @returns a pointer to the u32 type
ast::type::U32Type* u32() { return type<ast::type::U32Type>()->AsU32(); }
/// @param ty the type of the vector components
/// @param size the size of the vector
/// @returns a pointer to the vector type
ast::type::VectorType* vec(ast::type::Type* ty, uint32_t size) {
return type<ast::type::VectorType>(ty, size)->AsVector();
}
/// @returns a pointer to the void type
ast::type::VoidType* void_type() {
return type<ast::type::VoidType>()->AsVoid();
}
/// @param expr the expression /// @param expr the expression
/// @return expr /// @return expr
ast::Expression* make_expr(ast::Expression* expr) { return expr; } ast::Expression* Expr(ast::Expression* expr) { return expr; }
/// @param name the identifier name /// @param name the identifier name
/// @return an IdentifierExpression with the given name /// @return an IdentifierExpression with the given name
ast::IdentifierExpression* make_expr(const std::string& name) { ast::IdentifierExpression* Expr(const std::string& name) {
return create<ast::IdentifierExpression>(name); return create<ast::IdentifierExpression>(name);
} }
/// @param name the identifier name /// @param name the identifier name
/// @return an IdentifierExpression with the given name /// @return an IdentifierExpression with the given name
ast::IdentifierExpression* make_expr(const char* name) { ast::IdentifierExpression* Expr(const char* name) {
return create<ast::IdentifierExpression>(name); return create<ast::IdentifierExpression>(name);
} }
/// @param value the float value /// @param value the float value
/// @return a Scalar constructor for the given value /// @return a Scalar constructor for the given value
ast::ScalarConstructorExpression* make_expr(float value) { ast::ScalarConstructorExpression* Expr(f32 value) {
return create<ast::ScalarConstructorExpression>(make_literal(value)); return create<ast::ScalarConstructorExpression>(Literal(value));
} }
/// @param value the int value /// @param value the integer value
/// @return a Scalar constructor for the given value /// @return a Scalar constructor for the given value
ast::ScalarConstructorExpression* make_expr(int32_t value) { ast::ScalarConstructorExpression* Expr(i32 value) {
return create<ast::ScalarConstructorExpression>(make_literal(value)); return create<ast::ScalarConstructorExpression>(Literal(value));
} }
/// @param value the unsigned int value /// @param value the unsigned int value
/// @return a Scalar constructor for the given value /// @return a Scalar constructor for the given value
ast::ScalarConstructorExpression* make_expr(uint32_t value) { ast::ScalarConstructorExpression* Expr(u32 value) {
return create<ast::ScalarConstructorExpression>(make_literal(value)); return create<ast::ScalarConstructorExpression>(Literal(value));
} }
/// @param val the boolan value /// Converts `arg` to an `ast::Expression` using `Expr()`, then appends it to
/// @return a boolean literal with the given value /// `list`.
ast::BoolLiteral* make_literal(bool val) {
return create<ast::BoolLiteral>(bool_type(), val);
}
/// @param val the float value
/// @return a float literal with the given value
ast::FloatLiteral* make_literal(float val) {
return create<ast::FloatLiteral>(f32(), val);
}
/// @param val the unsigned int value
/// @return a UintLiteral with the given value
ast::UintLiteral* make_literal(uint32_t val) {
return create<ast::UintLiteral>(u32(), val);
}
/// @param val the integer value
/// @return the SintLiteral with the given value
ast::SintLiteral* make_literal(int32_t val) {
return create<ast::SintLiteral>(i32(), val);
}
/// Converts `arg` to an `ast::Expression` using `make_expr()`, then appends
/// it to `list`.
/// @param list the list to append too /// @param list the list to append too
/// @param arg the arg to create /// @param arg the arg to create
template <typename ARG> template <typename ARG>
void append_expr(ast::ExpressionList& list, ARG&& arg) { void Append(ast::ExpressionList& list, ARG&& arg) {
list.emplace_back(make_expr(std::forward<ARG>(arg))); list.emplace_back(Expr(std::forward<ARG>(arg)));
} }
/// Converts `arg0` and `args` to `ast::Expression`s using `make_expr()`, /// Converts `arg0` and `args` to `ast::Expression`s using `Expr()`,
/// then appends them to `list`. /// then appends them to `list`.
/// @param list the list to append too /// @param list the list to append too
/// @param arg0 the first argument /// @param arg0 the first argument
/// @param args the rest of the arguments /// @param args the rest of the arguments
template <typename ARG0, typename... ARGS> template <typename ARG0, typename... ARGS>
void append_expr(ast::ExpressionList& list, ARG0&& arg0, ARGS&&... args) { void Append(ast::ExpressionList& list, ARG0&& arg0, ARGS&&... args) {
append_expr(list, std::forward<ARG0>(arg0)); Append(list, std::forward<ARG0>(arg0));
append_expr(list, std::forward<ARGS>(args)...); Append(list, std::forward<ARGS>(args)...);
}
/// @param args the list of expressions
/// @return the list of expressions converted to `ast::Expression`s using
/// `Expr()`,
template <typename... ARGS>
ast::ExpressionList ExprList(ARGS&&... args) {
ast::ExpressionList list;
list.reserve(sizeof...(args));
Append(list, std::forward<ARGS>(args)...);
return list;
}
/// @param val the boolan value
/// @return a boolean literal with the given value
ast::BoolLiteral* Literal(bool val) {
return create<ast::BoolLiteral>(ty.bool_, val);
}
/// @param val the float value
/// @return a float literal with the given value
ast::FloatLiteral* Literal(f32 val) {
return create<ast::FloatLiteral>(ty.f32, val);
}
/// @param val the unsigned int value
/// @return a UintLiteral with the given value
ast::UintLiteral* Literal(u32 val) {
return create<ast::UintLiteral>(ty.u32, val);
}
/// @param val the integer value
/// @return the SintLiteral with the given value
ast::SintLiteral* Literal(i32 val) {
return create<ast::SintLiteral>(ty.i32, val);
} }
/// @param ty the type
/// @param args the arguments for the type constructor /// @param args the arguments for the type constructor
/// @return an `ast::TypeConstructorExpression` of type `ty`, with the values /// @return an `ast::TypeConstructorExpression` of type `ty`, with the values
/// of `args` converted to `ast::Expression`s using `make_expr()` /// of `args` converted to `ast::Expression`s using `Expr()`
template <typename... ARGS> template <typename T, typename... ARGS>
ast::TypeConstructorExpression* construct(ast::type::Type* ty, ast::TypeConstructorExpression* Construct(ARGS&&... args) {
ARGS&&... args) { return create<ast::TypeConstructorExpression>(
ast::ExpressionList vals; ty.Of<T>(), ExprList(std::forward<ARGS>(args)...));
append_expr(vals, std::forward<ARGS>(args)...); }
return create<ast::TypeConstructorExpression>(ty, std::move(vals));
/// @param x the first component of the vector
/// @param y the second component of the vector
/// @return an `ast::TypeConstructorExpression` of a 2-element vector of type
/// `T`, constructed with the values `x` and `y`.
template <typename T>
ast::TypeConstructorExpression* vec2(T&& x, T&& y) {
return create<ast::TypeConstructorExpression>(
ty.vec2<T>(), ExprList(std::move(x), std::move(y)));
}
/// @param x the first component of the vector
/// @param y the second component of the vector
/// @param z the third component of the vector
/// @return an `ast::TypeConstructorExpression` of a 3-element vector of type
/// `T`, constructed with the values `x`, `y` and `z`.
template <typename T>
ast::TypeConstructorExpression* vec3(T&& x, T&& y, T&& z) {
return create<ast::TypeConstructorExpression>(
ty.vec3<T>(), ExprList(std::move(x), std::move(y), std::move(z)));
}
/// @param x the first component of the vector
/// @param y the second component of the vector
/// @param z the third component of the vector
/// @param w the fourth component of the vector
/// @return an `ast::TypeConstructorExpression` of a 4-element vector of type
/// `T`, constructed with the values `x`, `y`, `z` and `w`.
template <typename T>
ast::TypeConstructorExpression* vec4(T&& x, T&& y, T&& z, T&& w) {
return create<ast::TypeConstructorExpression>(
ty.vec4<T>(),
ExprList(std::move(x), std::move(y), std::move(z), std::move(w)));
} }
/// @param name the variable name /// @param name the variable name
/// @param storage the variable storage class /// @param storage the variable storage class
/// @param type the variable type /// @param type the variable type
/// @returns a `ast::Variable` with the given name, storage and type /// @returns a `ast::Variable` with the given name, storage and type
virtual ast::Variable* make_var(const std::string& name, ast::Variable* Var(const std::string& name,
ast::StorageClass storage, ast::StorageClass storage,
ast::type::Type* type); ast::type::Type* type);
/// @param func the function name /// @param func the function name
/// @param args the function call arguments /// @param args the function call arguments
/// @returns a `ast::CallExpression` to the function `func`, with the /// @returns a `ast::CallExpression` to the function `func`, with the
/// arguments of `args` converted to `ast::Expression`s using `make_expr()`. /// arguments of `args` converted to `ast::Expression`s using `Expr()`.
template <typename... ARGS> template <typename... ARGS>
ast::CallExpression call_expr(const std::string& func, ARGS&&... args) { ast::CallExpression Call(const std::string& func, ARGS&&... args) {
ast::ExpressionList params; return ast::CallExpression{Expr(func),
append_expr(params, std::forward<ARGS>(args)...); ExprList(std::forward<ARGS>(args)...)};
return ast::CallExpression{make_expr(func), std::move(params)};
} }
/// Creates a new `ast::Node` owned by the Context. When the Context is /// Creates a new `ast::Node` owned by the Context. When the Context is
@ -219,13 +276,76 @@ class Builder {
/// @returns the node pointer /// @returns the node pointer
template <typename T, typename... ARGS> template <typename T, typename... ARGS>
T* create(ARGS&&... args) { T* create(ARGS&&... args) {
return ctx_->create<T>(std::forward<ARGS>(args)...); return ctx->create<T>(std::forward<ARGS>(args)...);
} }
private: /// The builder context
tint::Context* ctx_ = nullptr; tint::Context* const ctx;
/// The builder types
const TypesBuilder ty;
protected:
/// Called whenever a new variable is built with `Var()`.
virtual void OnVariableBuilt(ast::Variable*) {}
}; };
template <typename T>
ast::type::Type* TypesBuilder::Of() const {
return CToAST<T>::get(this);
}
template <typename T>
ast::type::Type* TypesBuilder::vec2() const {
return tm_->Get<ast::type::VectorType>(Of<T>(), 2);
}
template <typename T>
ast::type::Type* TypesBuilder::vec3() const {
return tm_->Get<ast::type::VectorType>(Of<T>(), 3);
}
template <typename T>
ast::type::Type* TypesBuilder::vec4() const {
return tm_->Get<ast::type::VectorType>(Of<T>(), 4);
}
template <typename T>
ast::type::Type* TypesBuilder::mat3x3() const {
return tm_->Get<ast::type::MatrixType>(Of<T>(), 3, 3);
}
template <typename T>
ast::type::Type* TypesBuilder::arr() const {
return tm_->Get<ast::type::ArrayType>(Of<T>());
}
/// BuilderWithContext is a `Builder` that constructs and owns its `Context`.
class BuilderWithContext : public Builder {
public:
BuilderWithContext();
~BuilderWithContext() override;
};
//! @cond Doxygen_Suppress
// Various template specializations for TypesBuilder::CToAST.
template <>
struct TypesBuilder::CToAST<Builder::i32> {
static ast::type::Type* get(const TypesBuilder* t) { return t->i32; }
};
template <>
struct TypesBuilder::CToAST<Builder::u32> {
static ast::type::Type* get(const TypesBuilder* t) { return t->u32; }
};
template <>
struct TypesBuilder::CToAST<Builder::f32> {
static ast::type::Type* get(const TypesBuilder* t) { return t->f32; }
};
template <>
struct TypesBuilder::CToAST<bool> {
static ast::type::Type* get(const TypesBuilder* t) { return t->bool_; }
};
template <>
struct TypesBuilder::CToAST<void> {
static ast::type::Type* get(const TypesBuilder* t) { return t->void_; }
};
//! @endcond
} // namespace ast } // namespace ast
} // namespace tint } // namespace tint

View File

@ -18,6 +18,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <utility>
#include "src/ast/type/type.h" #include "src/ast/type/type.h"
@ -37,6 +38,15 @@ class TypeManager {
/// @return the pointer to the registered type /// @return the pointer to the registered type
ast::type::Type* Get(std::unique_ptr<ast::type::Type> type); ast::type::Type* Get(std::unique_ptr<ast::type::Type> type);
/// Get the given type `T` from the type manager
/// @param args the arguments to pass to the type constructor
/// @return the pointer to the registered type
template <typename T, typename... ARGS>
T* Get(ARGS&&... args) {
auto ty = Get(std::make_unique<T>(std::forward<ARGS>(args)...));
return static_cast<T*>(ty);
}
/// Returns the type map /// Returns the type map
/// @returns the mapping from name string to type. /// @returns the mapping from name string to type.
const std::unordered_map<std::string, std::unique_ptr<ast::type::Type>>& const std::unordered_map<std::string, std::unique_ptr<ast::type::Type>>&

View File

@ -45,29 +45,22 @@
#include "src/type_determiner.h" #include "src/type_determiner.h"
#include "src/writer/spirv/builder.h" #include "src/writer/spirv/builder.h"
#include "src/writer/spirv/spv_dump.h" #include "src/writer/spirv/spv_dump.h"
#include "src/writer/spirv/test_helper.h"
namespace tint { namespace tint {
namespace writer { namespace writer {
namespace spirv { namespace spirv {
namespace { namespace {
class IntrinsicBuilderTest : public ast::Builder, public testing::Test { class IntrinsicBuilderTest : public ast::BuilderWithContext,
public: public testing::Test {
IntrinsicBuilderTest() { set_context(&ctx); } protected:
void OnVariableBuilt(ast::Variable* var) override {
ast::Variable* make_var(const std::string& name,
ast::StorageClass storage,
ast::type::Type* type) override {
auto* var = ast::Builder::make_var(name, storage, type);
td.RegisterVariableForTesting(var); td.RegisterVariableForTesting(var);
return var;
} }
Context ctx;
ast::Module mod; ast::Module mod;
TypeDeterminer td{&ctx, &mod}; TypeDeterminer td{ctx, &mod};
spirv::Builder b{&ctx, &mod}; spirv::Builder b{ctx, &mod};
}; };
template <typename T> template <typename T>
@ -87,8 +80,8 @@ using IntrinsicBoolTest = IntrinsicBuilderTestWithParam<IntrinsicData>;
TEST_P(IntrinsicBoolTest, Call_Bool) { TEST_P(IntrinsicBoolTest, Call_Bool) {
auto param = GetParam(); auto param = GetParam();
auto* var = make_var("v", ast::StorageClass::kPrivate, vec(bool_type(), 3)); auto* var = Var("v", ast::StorageClass::kPrivate, ty.vec3<bool>());
auto expr = call_expr(param.name, "v"); auto expr = Call(param.name, "v");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
@ -116,8 +109,8 @@ using IntrinsicFloatTest = IntrinsicBuilderTestWithParam<IntrinsicData>;
TEST_P(IntrinsicFloatTest, Call_Float_Scalar) { TEST_P(IntrinsicFloatTest, Call_Float_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* var = make_var("v", ast::StorageClass::kPrivate, f32()); auto* var = Var("v", ast::StorageClass::kPrivate, ty.f32);
auto expr = call_expr(param.name, "v"); auto expr = Call(param.name, "v");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
@ -140,8 +133,8 @@ TEST_P(IntrinsicFloatTest, Call_Float_Scalar) {
TEST_P(IntrinsicFloatTest, Call_Float_Vector) { TEST_P(IntrinsicFloatTest, Call_Float_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* var = make_var("v", ast::StorageClass::kPrivate, vec(f32(), 3)); auto* var = Var("v", ast::StorageClass::kPrivate, ty.vec3<f32>());
auto expr = call_expr(param.name, "v"); auto expr = Call(param.name, "v");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
@ -171,8 +164,8 @@ using IntrinsicIntTest = IntrinsicBuilderTestWithParam<IntrinsicData>;
TEST_P(IntrinsicIntTest, Call_SInt_Scalar) { TEST_P(IntrinsicIntTest, Call_SInt_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* var = make_var("v", ast::StorageClass::kPrivate, i32()); auto* var = Var("v", ast::StorageClass::kPrivate, ty.i32);
auto expr = call_expr(param.name, "v"); auto expr = Call(param.name, "v");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
@ -194,8 +187,8 @@ TEST_P(IntrinsicIntTest, Call_SInt_Scalar) {
TEST_P(IntrinsicIntTest, Call_SInt_Vector) { TEST_P(IntrinsicIntTest, Call_SInt_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* var = make_var("v", ast::StorageClass::kPrivate, vec(i32(), 3)); auto* var = Var("v", ast::StorageClass::kPrivate, ty.vec3<i32>());
auto expr = call_expr(param.name, "v"); auto expr = Call(param.name, "v");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
@ -218,8 +211,8 @@ TEST_P(IntrinsicIntTest, Call_SInt_Vector) {
TEST_P(IntrinsicIntTest, Call_UInt_Scalar) { TEST_P(IntrinsicIntTest, Call_UInt_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* var = make_var("v", ast::StorageClass::kPrivate, u32()); auto* var = Var("v", ast::StorageClass::kPrivate, ty.u32);
auto expr = call_expr(param.name, "v"); auto expr = Call(param.name, "v");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
@ -241,8 +234,8 @@ TEST_P(IntrinsicIntTest, Call_UInt_Scalar) {
TEST_P(IntrinsicIntTest, Call_UInt_Vector) { TEST_P(IntrinsicIntTest, Call_UInt_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* var = make_var("v", ast::StorageClass::kPrivate, vec(u32(), 3)); auto* var = Var("v", ast::StorageClass::kPrivate, ty.vec3<u32>());
auto expr = call_expr(param.name, "v"); auto expr = Call(param.name, "v");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
@ -268,8 +261,8 @@ INSTANTIATE_TEST_SUITE_P(
IntrinsicData{"reverseBits", "OpBitReverse"})); IntrinsicData{"reverseBits", "OpBitReverse"}));
TEST_F(IntrinsicBuilderTest, Call_Dot) { TEST_F(IntrinsicBuilderTest, Call_Dot) {
auto* var = make_var("v", ast::StorageClass::kPrivate, vec(f32(), 3)); auto* var = Var("v", ast::StorageClass::kPrivate, ty.vec3<f32>());
auto expr = call_expr("dot", "v", "v"); auto expr = Call("dot", "v", "v");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
@ -294,8 +287,8 @@ using IntrinsicDeriveTest = IntrinsicBuilderTestWithParam<IntrinsicData>;
TEST_P(IntrinsicDeriveTest, Call_Derivative_Scalar) { TEST_P(IntrinsicDeriveTest, Call_Derivative_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto* var = make_var("v", ast::StorageClass::kPrivate, f32()); auto* var = Var("v", ast::StorageClass::kPrivate, ty.f32);
auto expr = call_expr(param.name, "v"); auto expr = Call(param.name, "v");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
@ -317,8 +310,8 @@ TEST_P(IntrinsicDeriveTest, Call_Derivative_Scalar) {
TEST_P(IntrinsicDeriveTest, Call_Derivative_Vector) { TEST_P(IntrinsicDeriveTest, Call_Derivative_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* var = make_var("v", ast::StorageClass::kPrivate, vec(f32(), 3)); auto* var = Var("v", ast::StorageClass::kPrivate, ty.vec3<f32>());
auto expr = call_expr(param.name, "v"); auto expr = Call(param.name, "v");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
@ -358,10 +351,10 @@ INSTANTIATE_TEST_SUITE_P(
IntrinsicData{"fwidthCoarse", "OpFwidthCoarse"})); IntrinsicData{"fwidthCoarse", "OpFwidthCoarse"}));
TEST_F(IntrinsicBuilderTest, Call_OuterProduct) { TEST_F(IntrinsicBuilderTest, Call_OuterProduct) {
auto* v2 = make_var("v2", ast::StorageClass::kPrivate, vec(f32(), 2)); auto* v2 = Var("v2", ast::StorageClass::kPrivate, ty.vec2<f32>());
auto* v3 = make_var("v3", ast::StorageClass::kPrivate, vec(f32(), 3)); auto* v3 = Var("v3", ast::StorageClass::kPrivate, ty.vec3<f32>());
auto expr = call_expr("outerProduct", "v2", "v3"); auto expr = Call("outerProduct", "v2", "v3");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
@ -390,10 +383,9 @@ TEST_F(IntrinsicBuilderTest, Call_OuterProduct) {
} }
TEST_F(IntrinsicBuilderTest, Call_Select) { TEST_F(IntrinsicBuilderTest, Call_Select) {
auto* v3 = make_var("v3", ast::StorageClass::kPrivate, vec(f32(), 3)); auto* v3 = Var("v3", ast::StorageClass::kPrivate, ty.vec3<f32>());
auto* bool_v3 = auto* bool_v3 = Var("bool_v3", ast::StorageClass::kPrivate, ty.vec3<bool>());
make_var("bool_v3", ast::StorageClass::kPrivate, vec(bool_type(), 3)); auto expr = Call("select", "v3", "v3", "bool_v3");
auto expr = call_expr("select", "v3", "v3", "bool_v3");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
@ -431,10 +423,10 @@ TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Storage_RO_1d) {
b.push_function(Function{}); b.push_function(Function{});
auto* tex = make_var("texture", ast::StorageClass::kNone, &s); auto* tex = Var("texture", ast::StorageClass::kNone, &s);
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
auto expr = call_expr("textureLoad", "texture", 1.0f, 2); auto expr = Call("textureLoad", "texture", 1.0f, 2);
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error(); EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error();
@ -465,11 +457,10 @@ TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Storage_RO_2d) {
b.push_function(Function{}); b.push_function(Function{});
auto* tex = make_var("texture", ast::StorageClass::kNone, &s); auto* tex = Var("texture", ast::StorageClass::kNone, &s);
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
auto expr = call_expr("textureLoad", "texture", auto expr = Call("textureLoad", "texture", vec2<f32>(1.0f, 2.0f), 2);
construct(vec(f32(), 2), 1.0f, 2.0f), 2);
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error(); EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error();
@ -495,14 +486,14 @@ TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Storage_RO_2d) {
} }
TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Sampled_1d) { TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Sampled_1d) {
ast::type::SampledTextureType s(ast::type::TextureDimension::k1d, f32()); ast::type::SampledTextureType s(ast::type::TextureDimension::k1d, ty.f32);
b.push_function(Function{}); b.push_function(Function{});
auto* tex = make_var("texture", ast::StorageClass::kNone, &s); auto* tex = Var("texture", ast::StorageClass::kNone, &s);
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
auto expr = call_expr("textureLoad", "texture", 1.0f, 2); auto expr = Call("textureLoad", "texture", 1.0f, 2);
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error(); EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error();
@ -525,15 +516,14 @@ TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Sampled_1d) {
} }
TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Sampled_2d) { TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Sampled_2d) {
ast::type::SampledTextureType s(ast::type::TextureDimension::k2d, f32()); ast::type::SampledTextureType s(ast::type::TextureDimension::k2d, ty.f32);
b.push_function(Function{}); b.push_function(Function{});
auto* tex = make_var("texture", ast::StorageClass::kNone, &s); auto* tex = Var("texture", ast::StorageClass::kNone, &s);
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
auto expr = call_expr("textureLoad", "texture", auto expr = Call("textureLoad", "texture", vec2<f32>(1.0f, 2.0f), 2);
construct(vec(f32(), 2), 1.0f, 2.0f), 2);
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error(); EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error();
@ -559,15 +549,15 @@ TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Sampled_2d) {
} }
TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Multisampled_2d) { TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Multisampled_2d) {
ast::type::MultisampledTextureType s(ast::type::TextureDimension::k2d, f32()); ast::type::MultisampledTextureType s(ast::type::TextureDimension::k2d,
ty.f32);
b.push_function(Function{}); b.push_function(Function{});
auto* tex = make_var("texture", ast::StorageClass::kNone, &s); auto* tex = Var("texture", ast::StorageClass::kNone, &s);
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
auto expr = call_expr("textureLoad", "texture", auto expr = Call("textureLoad", "texture", vec2<f32>(1.0f, 2.0f), 2);
construct(vec(f32(), 2), 1.0f, 2.0f), 2);
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error(); EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error();
@ -598,13 +588,13 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSample_1d) {
b.push_function(Function{}); b.push_function(Function{});
auto* tex = make_var("texture", ast::StorageClass::kNone, &t); auto* tex = Var("texture", ast::StorageClass::kNone, &t);
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
auto* sampler = make_var("sampler", ast::StorageClass::kNone, &s); auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
auto expr = call_expr("textureSample", "texture", "sampler", 1.0f); auto expr = Call("textureSample", "texture", "sampler", 1.0f);
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
EXPECT_EQ(b.GenerateExpression(&expr), 7u) << b.error(); EXPECT_EQ(b.GenerateExpression(&expr), 7u) << b.error();
@ -635,14 +625,14 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSample_2d) {
b.push_function(Function{}); b.push_function(Function{});
auto* tex = make_var("texture", ast::StorageClass::kNone, &t); auto* tex = Var("texture", ast::StorageClass::kNone, &t);
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
auto* sampler = make_var("sampler", ast::StorageClass::kNone, &s); auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
auto expr = call_expr("textureSample", "texture", "sampler", auto expr =
construct(vec(f32(), 2), 1.0f, 2.0f)); Call("textureSample", "texture", "sampler", vec2<f32>(1.0f, 2.0f));
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
EXPECT_EQ(b.GenerateExpression(&expr), 7u) << b.error(); EXPECT_EQ(b.GenerateExpression(&expr), 7u) << b.error();
@ -672,17 +662,17 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSample_2d) {
TEST_F(IntrinsicBuilderTest, Call_TextureSampleLevel_1d) { TEST_F(IntrinsicBuilderTest, Call_TextureSampleLevel_1d) {
ast::type::SamplerType s(ast::type::SamplerKind::kSampler); ast::type::SamplerType s(ast::type::SamplerKind::kSampler);
ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, f32()); ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, ty.f32);
b.push_function(Function{}); b.push_function(Function{});
auto* tex = make_var("texture", ast::StorageClass::kNone, &t); auto* tex = Var("texture", ast::StorageClass::kNone, &t);
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
auto* sampler = make_var("sampler", ast::StorageClass::kNone, &s); auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
auto expr = call_expr("textureSampleLevel", "texture", "sampler", 1.0f, 2.0f); auto expr = Call("textureSampleLevel", "texture", "sampler", 1.0f, 2.0f);
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error(); EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error();
@ -711,18 +701,18 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleLevel_1d) {
TEST_F(IntrinsicBuilderTest, Call_TextureSampleLevel_2d) { TEST_F(IntrinsicBuilderTest, Call_TextureSampleLevel_2d) {
ast::type::SamplerType s(ast::type::SamplerKind::kSampler); ast::type::SamplerType s(ast::type::SamplerKind::kSampler);
ast::type::SampledTextureType t(ast::type::TextureDimension::k2d, f32()); ast::type::SampledTextureType t(ast::type::TextureDimension::k2d, ty.f32);
b.push_function(Function{}); b.push_function(Function{});
auto* tex = make_var("texture", ast::StorageClass::kNone, &t); auto* tex = Var("texture", ast::StorageClass::kNone, &t);
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
auto* sampler = make_var("sampler", ast::StorageClass::kNone, &s); auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
auto expr = call_expr("textureSampleLevel", "texture", "sampler", auto expr = Call("textureSampleLevel", "texture", "sampler",
construct(vec(f32(), 2), 1.0f, 2.0f), 2.0f); vec2<f32>(1.0f, 2.0f), 2.0f);
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error(); EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error();
@ -753,17 +743,17 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleLevel_2d) {
TEST_F(IntrinsicBuilderTest, Call_TextureSampleBias_1d) { TEST_F(IntrinsicBuilderTest, Call_TextureSampleBias_1d) {
ast::type::SamplerType s(ast::type::SamplerKind::kSampler); ast::type::SamplerType s(ast::type::SamplerKind::kSampler);
ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, f32()); ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, ty.f32);
b.push_function(Function{}); b.push_function(Function{});
auto* tex = make_var("texture", ast::StorageClass::kNone, &t); auto* tex = Var("texture", ast::StorageClass::kNone, &t);
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
auto* sampler = make_var("sampler", ast::StorageClass::kNone, &s); auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
auto expr = call_expr("textureSampleBias", "texture", "sampler", 1.0f, 2.0f); auto expr = Call("textureSampleBias", "texture", "sampler", 1.0f, 2.0f);
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error(); EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error();
@ -792,18 +782,18 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleBias_1d) {
TEST_F(IntrinsicBuilderTest, Call_TextureSampleBias_2d) { TEST_F(IntrinsicBuilderTest, Call_TextureSampleBias_2d) {
ast::type::SamplerType s(ast::type::SamplerKind::kSampler); ast::type::SamplerType s(ast::type::SamplerKind::kSampler);
ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, f32()); ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, ty.f32);
b.push_function(Function{}); b.push_function(Function{});
auto* tex = make_var("texture", ast::StorageClass::kNone, &t); auto* tex = Var("texture", ast::StorageClass::kNone, &t);
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
auto* sampler = make_var("sampler", ast::StorageClass::kNone, &s); auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
auto expr = call_expr("textureSampleBias", "texture", "sampler", auto expr = Call("textureSampleBias", "texture", "sampler",
construct(vec(f32(), 2), 1.0f, 2.0f), 2.0f); vec2<f32>(1.0f, 2.0f), 2.0f);
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error(); EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error();
@ -838,14 +828,14 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare) {
b.push_function(Function{}); b.push_function(Function{});
auto* tex = make_var("texture", ast::StorageClass::kNone, &t); auto* tex = Var("texture", ast::StorageClass::kNone, &t);
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
auto* sampler = make_var("sampler", ast::StorageClass::kNone, &s); auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
auto expr = call_expr("textureSampleCompare", "texture", "sampler", auto expr = Call("textureSampleCompare", "texture", "sampler",
construct(vec(f32(), 2), 1.0f, 2.0f), 2.0f); vec2<f32>(1.0f, 2.0f), 2.0f);
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error(); EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error();
@ -875,24 +865,22 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare) {
// This tests that we do not push OpTypeSampledImage and float_0 type twice. // This tests that we do not push OpTypeSampledImage and float_0 type twice.
TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) { TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) {
auto* vec2 = vec(f32(), 2);
ast::type::SamplerType s(ast::type::SamplerKind::kComparisonSampler); ast::type::SamplerType s(ast::type::SamplerKind::kComparisonSampler);
ast::type::DepthTextureType t(ast::type::TextureDimension::k2d); ast::type::DepthTextureType t(ast::type::TextureDimension::k2d);
b.push_function(Function{}); b.push_function(Function{});
auto* tex = make_var("texture", ast::StorageClass::kNone, &t); auto* tex = Var("texture", ast::StorageClass::kNone, &t);
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
auto* sampler = make_var("sampler", ast::StorageClass::kNone, &s); auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
auto expr1 = call_expr("textureSampleCompare", "texture", "sampler", auto expr1 = Call("textureSampleCompare", "texture", "sampler",
construct(vec2, 1.0f, 2.0f), 2.0f); vec2<f32>(1.0f, 2.0f), 2.0f);
auto expr2 = call_expr("textureSampleCompare", "texture", "sampler", auto expr2 = Call("textureSampleCompare", "texture", "sampler",
construct(vec2, 1.0f, 2.0f), 2.0f); vec2<f32>(1.0f, 2.0f), 2.0f);
EXPECT_TRUE(td.DetermineResultType(&expr1)) << td.error(); EXPECT_TRUE(td.DetermineResultType(&expr1)) << td.error();
EXPECT_TRUE(td.DetermineResultType(&expr2)) << td.error(); EXPECT_TRUE(td.DetermineResultType(&expr2)) << td.error();
@ -928,12 +916,12 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) {
} }
TEST_F(IntrinsicBuilderTest, Call_GLSLMethod_WithLoad) { TEST_F(IntrinsicBuilderTest, Call_GLSLMethod_WithLoad) {
auto* var = make_var("ident", ast::StorageClass::kPrivate, f32()); auto* var = Var("ident", ast::StorageClass::kPrivate, ty.f32);
auto expr = call_expr("round", "ident"); auto expr = Call("round", "ident");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -961,10 +949,10 @@ using Intrinsic_Builtin_SingleParam_Float_Test =
TEST_P(Intrinsic_Builtin_SingleParam_Float_Test, Call_Scalar) { TEST_P(Intrinsic_Builtin_SingleParam_Float_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto expr = call_expr(param.name, 1.0f); auto expr = Call(param.name, 1.0f);
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -986,10 +974,10 @@ OpFunctionEnd
TEST_P(Intrinsic_Builtin_SingleParam_Float_Test, Call_Vector) { TEST_P(Intrinsic_Builtin_SingleParam_Float_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto expr = call_expr(param.name, construct(vec(f32(), 2), 1.0f, 1.0f)); auto expr = Call(param.name, vec2<f32>(1.0f, 1.0f));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1036,11 +1024,11 @@ INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest,
IntrinsicData{"trunc", "Trunc"})); IntrinsicData{"trunc", "Trunc"}));
TEST_F(IntrinsicBuilderTest, Call_Length_Scalar) { TEST_F(IntrinsicBuilderTest, Call_Length_Scalar) {
auto expr = call_expr("length", 1.0f); auto expr = Call("length", 1.0f);
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1059,10 +1047,10 @@ OpFunctionEnd
} }
TEST_F(IntrinsicBuilderTest, Call_Length_Vector) { TEST_F(IntrinsicBuilderTest, Call_Length_Vector) {
auto expr = call_expr("length", construct(vec(f32(), 2), 1.0f, 1.0f)); auto expr = Call("length", vec2<f32>(1.0f, 1.0f));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1083,10 +1071,10 @@ OpFunctionEnd
} }
TEST_F(IntrinsicBuilderTest, Call_Normalize) { TEST_F(IntrinsicBuilderTest, Call_Normalize) {
auto expr = call_expr("normalize", construct(vec(f32(), 2), 1.0f, 1.0f)); auto expr = Call("normalize", vec2<f32>(1.0f, 1.0f));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1111,10 +1099,11 @@ using Intrinsic_Builtin_DualParam_Float_Test =
TEST_P(Intrinsic_Builtin_DualParam_Float_Test, Call_Scalar) { TEST_P(Intrinsic_Builtin_DualParam_Float_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto expr = call_expr(param.name, 1.0f, 1.0f); auto expr = Call(param.name, 1.0f, 1.0f);
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1136,13 +1125,11 @@ OpFunctionEnd
TEST_P(Intrinsic_Builtin_DualParam_Float_Test, Call_Vector) { TEST_P(Intrinsic_Builtin_DualParam_Float_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* vec2 = vec(f32(), 2); auto expr = Call(param.name, vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f));
auto expr = call_expr(param.name, construct(vec2, 1.0f, 1.0f),
construct(vec2, 1.0f, 1.0f));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1172,10 +1159,11 @@ INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest,
IntrinsicData{"step", "Step"})); IntrinsicData{"step", "Step"}));
TEST_F(IntrinsicBuilderTest, Call_Distance_Scalar) { TEST_F(IntrinsicBuilderTest, Call_Distance_Scalar) {
auto expr = call_expr("distance", 1.0f, 1.0f); auto expr = Call("distance", 1.0f, 1.0f);
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1194,13 +1182,11 @@ OpFunctionEnd
} }
TEST_F(IntrinsicBuilderTest, Call_Distance_Vector) { TEST_F(IntrinsicBuilderTest, Call_Distance_Vector) {
auto* vec3 = vec(f32(), 2); auto expr = Call("distance", vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f));
auto expr = call_expr("distance", construct(vec3, 1.0f, 1.0f),
construct(vec3, 1.0f, 1.0f));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1221,13 +1207,12 @@ OpFunctionEnd
} }
TEST_F(IntrinsicBuilderTest, Call_Cross) { TEST_F(IntrinsicBuilderTest, Call_Cross) {
auto* vec3 = vec(f32(), 3); auto expr =
auto expr = call_expr("cross", construct(vec3, 1.0f, 1.0f, 1.0f), Call("cross", vec3<f32>(1.0f, 1.0f, 1.0f), vec3<f32>(1.0f, 1.0f, 1.0f));
construct(vec3, 1.0f, 1.0f, 1.0f));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1252,10 +1237,10 @@ using Intrinsic_Builtin_ThreeParam_Float_Test =
TEST_P(Intrinsic_Builtin_ThreeParam_Float_Test, Call_Scalar) { TEST_P(Intrinsic_Builtin_ThreeParam_Float_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto expr = call_expr(param.name, 1.0f, 1.0f, 1.0f); auto expr = Call(param.name, 1.0f, 1.0f, 1.0f);
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1277,14 +1262,12 @@ OpFunctionEnd
TEST_P(Intrinsic_Builtin_ThreeParam_Float_Test, Call_Vector) { TEST_P(Intrinsic_Builtin_ThreeParam_Float_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* vec3 = vec(f32(), 2); auto expr = Call(param.name, vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f),
auto expr = vec2<f32>(1.0f, 1.0f));
call_expr(param.name, construct(vec3, 1.0f, 1.0f),
construct(vec3, 1.0f, 1.0f), construct(vec3, 1.0f, 1.0f));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1319,10 +1302,10 @@ using Intrinsic_Builtin_SingleParam_Sint_Test =
TEST_P(Intrinsic_Builtin_SingleParam_Sint_Test, Call_Scalar) { TEST_P(Intrinsic_Builtin_SingleParam_Sint_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto expr = call_expr(param.name, 1); auto expr = Call(param.name, 1);
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1344,10 +1327,10 @@ OpFunctionEnd
TEST_P(Intrinsic_Builtin_SingleParam_Sint_Test, Call_Vector) { TEST_P(Intrinsic_Builtin_SingleParam_Sint_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto expr = call_expr(param.name, construct(vec(i32(), 2), 1, 1)); auto expr = Call(param.name, vec2<i32>(1, 1));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1376,10 +1359,10 @@ using Intrinsic_Builtin_SingleParam_Uint_Test =
TEST_P(Intrinsic_Builtin_SingleParam_Uint_Test, Call_Scalar) { TEST_P(Intrinsic_Builtin_SingleParam_Uint_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto expr = call_expr(param.name, 1u); auto expr = Call(param.name, 1u);
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1401,10 +1384,10 @@ OpFunctionEnd
TEST_P(Intrinsic_Builtin_SingleParam_Uint_Test, Call_Vector) { TEST_P(Intrinsic_Builtin_SingleParam_Uint_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto expr = call_expr(param.name, construct(vec(u32(), 2), 1u, 1u)); auto expr = Call(param.name, vec2<u32>(1u, 1u));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1433,10 +1416,10 @@ using Intrinsic_Builtin_DualParam_SInt_Test =
TEST_P(Intrinsic_Builtin_DualParam_SInt_Test, Call_Scalar) { TEST_P(Intrinsic_Builtin_DualParam_SInt_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto expr = call_expr(param.name, 1, 1); auto expr = Call(param.name, 1, 1);
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1458,12 +1441,10 @@ OpFunctionEnd
TEST_P(Intrinsic_Builtin_DualParam_SInt_Test, Call_Vector) { TEST_P(Intrinsic_Builtin_DualParam_SInt_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* vec2 = vec(i32(), 2); auto expr = Call(param.name, vec2<i32>(1, 1), vec2<i32>(1, 1));
auto expr =
call_expr(param.name, construct(vec2, 1, 1), construct(vec2, 1, 1));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1493,10 +1474,10 @@ using Intrinsic_Builtin_DualParam_UInt_Test =
TEST_P(Intrinsic_Builtin_DualParam_UInt_Test, Call_Scalar) { TEST_P(Intrinsic_Builtin_DualParam_UInt_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto expr = call_expr(param.name, 1u, 1u); auto expr = Call(param.name, 1u, 1u);
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1518,13 +1499,10 @@ OpFunctionEnd
TEST_P(Intrinsic_Builtin_DualParam_UInt_Test, Call_Vector) { TEST_P(Intrinsic_Builtin_DualParam_UInt_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* vec2 = vec(u32(), 2); auto expr = Call(param.name, vec2<u32>(1u, 1u), vec2<u32>(1u, 1u));
auto expr =
call_expr(param.name, construct(vec2, 1u, 1u), construct(vec2, 1u, 1u));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1554,10 +1532,10 @@ using Intrinsic_Builtin_ThreeParam_Sint_Test =
TEST_P(Intrinsic_Builtin_ThreeParam_Sint_Test, Call_Scalar) { TEST_P(Intrinsic_Builtin_ThreeParam_Sint_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto expr = call_expr(param.name, 1, 1, 1); auto expr = Call(param.name, 1, 1, 1);
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1579,13 +1557,12 @@ OpFunctionEnd
TEST_P(Intrinsic_Builtin_ThreeParam_Sint_Test, Call_Vector) { TEST_P(Intrinsic_Builtin_ThreeParam_Sint_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* vec2 = vec(i32(), 2); auto expr =
auto expr = call_expr(param.name, construct(vec2, 1, 1), Call(param.name, vec2<i32>(1, 1), vec2<i32>(1, 1), vec2<i32>(1, 1));
construct(vec2, 1, 1), construct(vec2, 1, 1));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1614,10 +1591,10 @@ using Intrinsic_Builtin_ThreeParam_Uint_Test =
TEST_P(Intrinsic_Builtin_ThreeParam_Uint_Test, Call_Scalar) { TEST_P(Intrinsic_Builtin_ThreeParam_Uint_Test, Call_Scalar) {
auto param = GetParam(); auto param = GetParam();
auto expr = call_expr(param.name, 1u, 1u, 1u); auto expr = Call(param.name, 1u, 1u, 1u);
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1639,13 +1616,12 @@ OpFunctionEnd
TEST_P(Intrinsic_Builtin_ThreeParam_Uint_Test, Call_Vector) { TEST_P(Intrinsic_Builtin_ThreeParam_Uint_Test, Call_Vector) {
auto param = GetParam(); auto param = GetParam();
auto* vec2 = vec(u32(), 2); auto expr =
auto expr = call_expr(param.name, construct(vec2, 1u, 1u), Call(param.name, vec2<u32>(1u, 1u), vec2<u32>(1u, 1u), vec2<u32>(1u, 1u));
construct(vec2, 1u, 1u), construct(vec2, 1u, 1u));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1670,12 +1646,12 @@ INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest,
testing::Values(IntrinsicData{"clamp", "UClamp"})); testing::Values(IntrinsicData{"clamp", "UClamp"}));
TEST_F(IntrinsicBuilderTest, Call_Determinant) { TEST_F(IntrinsicBuilderTest, Call_Determinant) {
auto* var = make_var("var", ast::StorageClass::kPrivate, mat(f32(), 3, 3)); auto* var = Var("var", ast::StorageClass::kPrivate, ty.mat3x3<f32>());
auto expr = call_expr("determinant", "var"); auto expr = Call("determinant", "var");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@ -1702,23 +1678,21 @@ OpFunctionEnd
} }
TEST_F(IntrinsicBuilderTest, Call_ArrayLength) { TEST_F(IntrinsicBuilderTest, Call_ArrayLength) {
ast::type::ArrayType ary(f32());
ast::StructMemberDecorationList decos; ast::StructMemberDecorationList decos;
ast::StructMemberList members; ast::StructMemberList members;
members.push_back(create<ast::StructMember>("a", &ary, decos)); members.push_back(create<ast::StructMember>("a", ty.arr<f32>(), decos));
auto* s = create<ast::Struct>(members); auto* s = create<ast::Struct>(members);
ast::type::StructType s_type("my_struct", s); ast::type::StructType s_type("my_struct", s);
auto* var = make_var("b", ast::StorageClass::kPrivate, &s_type); auto* var = Var("b", ast::StorageClass::kPrivate, &s_type);
auto expr = call_expr("arrayLength", create<ast::MemberAccessorExpression>( auto expr = Call("arrayLength",
make_expr("b"), make_expr("a"))); create<ast::MemberAccessorExpression>(Expr("b"), Expr("a")));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
@ -1742,23 +1716,21 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength) {
} }
TEST_F(IntrinsicBuilderTest, Call_ArrayLength_OtherMembersInStruct) { TEST_F(IntrinsicBuilderTest, Call_ArrayLength_OtherMembersInStruct) {
ast::type::ArrayType ary(f32());
ast::StructMemberDecorationList decos; ast::StructMemberDecorationList decos;
ast::StructMemberList members; ast::StructMemberList members;
members.push_back(create<ast::StructMember>("z", f32(), decos)); members.push_back(create<ast::StructMember>("z", ty.f32, decos));
members.push_back(create<ast::StructMember>("a", &ary, decos)); members.push_back(create<ast::StructMember>("a", ty.arr<f32>(), decos));
auto* s = create<ast::Struct>(members); auto* s = create<ast::Struct>(members);
ast::type::StructType s_type("my_struct", s); ast::type::StructType s_type("my_struct", s);
auto* var = make_var("b", ast::StorageClass::kPrivate, &s_type); auto* var = Var("b", ast::StorageClass::kPrivate, &s_type);
auto expr = call_expr("arrayLength", create<ast::MemberAccessorExpression>( auto expr = Call("arrayLength",
make_expr("b"), make_expr("a"))); create<ast::MemberAccessorExpression>(Expr("b"), Expr("a")));
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
@ -1783,27 +1755,26 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength_OtherMembersInStruct) {
// TODO(dsinclair): https://bugs.chromium.org/p/tint/issues/detail?id=266 // TODO(dsinclair): https://bugs.chromium.org/p/tint/issues/detail?id=266
TEST_F(IntrinsicBuilderTest, DISABLED_Call_ArrayLength_Ptr) { TEST_F(IntrinsicBuilderTest, DISABLED_Call_ArrayLength_Ptr) {
ast::type::ArrayType ary(f32()); ast::type::PointerType ptr(ty.arr<f32>(), ast::StorageClass::kStorageBuffer);
ast::type::PointerType ptr(&ary, ast::StorageClass::kStorageBuffer);
ast::StructMemberDecorationList decos; ast::StructMemberDecorationList decos;
ast::StructMemberList members; ast::StructMemberList members;
members.push_back(create<ast::StructMember>("z", f32(), decos)); members.push_back(create<ast::StructMember>("z", ty.f32, decos));
members.push_back(create<ast::StructMember>("a", &ary, decos)); members.push_back(create<ast::StructMember>("a", ty.arr<f32>(), decos));
auto* s = create<ast::Struct>(members); auto* s = create<ast::Struct>(members);
ast::type::StructType s_type("my_struct", s); ast::type::StructType s_type("my_struct", s);
auto* var = make_var("b", ast::StorageClass::kPrivate, &s_type); auto* var = Var("b", ast::StorageClass::kPrivate, &s_type);
auto* ptr_var = make_var("ptr_var", ast::StorageClass::kPrivate, &ptr); auto* ptr_var = Var("ptr_var", ast::StorageClass::kPrivate, &ptr);
ptr_var->set_constructor( ptr_var->set_constructor(
create<ast::MemberAccessorExpression>(make_expr("b"), make_expr("a"))); create<ast::MemberAccessorExpression>(Expr("b"), Expr("a")));
auto expr = call_expr("arrayLength", "ptr_var"); auto expr = Call("arrayLength", "ptr_var");
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
ast::Function func("a_func", {}, void_type(), create<ast::BlockStatement>()); ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();