tint/ast: Migrate to utils::Vector
Change-Id: I10dd2feeaeb86a1ee7769d2bfd172e49c2805cb3 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/97843 Reviewed-by: Dan Sinclair <dsinclair@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
34d46731bb
commit
783b169bf4
|
@ -1110,6 +1110,7 @@ if (tint_build_unittests) {
|
||||||
"resolver/function_validation_test.cc",
|
"resolver/function_validation_test.cc",
|
||||||
"resolver/host_shareable_validation_test.cc",
|
"resolver/host_shareable_validation_test.cc",
|
||||||
"resolver/increment_decrement_validation_test.cc",
|
"resolver/increment_decrement_validation_test.cc",
|
||||||
|
"resolver/inferred_type_test.cc",
|
||||||
"resolver/intrinsic_table_test.cc",
|
"resolver/intrinsic_table_test.cc",
|
||||||
"resolver/is_host_shareable_test.cc",
|
"resolver/is_host_shareable_test.cc",
|
||||||
"resolver/is_storeable_test.cc",
|
"resolver/is_storeable_test.cc",
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "src/tint/ast/array.h"
|
#include "src/tint/ast/array.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "src/tint/program_builder.h"
|
#include "src/tint/program_builder.h"
|
||||||
|
|
||||||
|
@ -42,8 +43,8 @@ Array::Array(ProgramID pid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
const Type* subtype,
|
const Type* subtype,
|
||||||
const Expression* cnt,
|
const Expression* cnt,
|
||||||
AttributeList attrs)
|
utils::VectorRef<const Attribute*> attrs)
|
||||||
: Base(pid, nid, src), type(subtype), count(cnt), attributes(attrs) {}
|
: Base(pid, nid, src), type(subtype), count(cnt), attributes(std::move(attrs)) {}
|
||||||
|
|
||||||
Array::Array(Array&&) = default;
|
Array::Array(Array&&) = default;
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ const Array* Array::Clone(CloneContext* ctx) const {
|
||||||
auto* ty = ctx->Clone(type);
|
auto* ty = ctx->Clone(type);
|
||||||
auto* cnt = ctx->Clone(count);
|
auto* cnt = ctx->Clone(count);
|
||||||
auto attrs = ctx->Clone(attributes);
|
auto attrs = ctx->Clone(attributes);
|
||||||
return ctx->dst->create<Array>(src, ty, cnt, attrs);
|
return ctx->dst->create<Array>(src, ty, cnt, std::move(attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -43,7 +43,7 @@ class Array final : public Castable<Array, Type> {
|
||||||
const Source& src,
|
const Source& src,
|
||||||
const Type* subtype,
|
const Type* subtype,
|
||||||
const Expression* count,
|
const Expression* count,
|
||||||
AttributeList attributes);
|
utils::VectorRef<const Attribute*> attributes);
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
Array(Array&&);
|
Array(Array&&);
|
||||||
~Array() override;
|
~Array() override;
|
||||||
|
@ -69,7 +69,7 @@ class Array final : public Castable<Array, Type> {
|
||||||
const Expression* const count;
|
const Expression* const count;
|
||||||
|
|
||||||
/// the array attributes
|
/// the array attributes
|
||||||
const AttributeList attributes;
|
const utils::Vector<const Attribute*, 1> attributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -26,7 +26,7 @@ using AstArrayTest = TestHelper;
|
||||||
TEST_F(AstArrayTest, CreateSizedArray) {
|
TEST_F(AstArrayTest, CreateSizedArray) {
|
||||||
auto* u32 = create<U32>();
|
auto* u32 = create<U32>();
|
||||||
auto* count = Expr(3_u);
|
auto* count = Expr(3_u);
|
||||||
auto* arr = create<Array>(u32, count, AttributeList{});
|
auto* arr = create<Array>(u32, count, utils::Empty);
|
||||||
EXPECT_EQ(arr->type, u32);
|
EXPECT_EQ(arr->type, u32);
|
||||||
EXPECT_EQ(arr->count, count);
|
EXPECT_EQ(arr->count, count);
|
||||||
EXPECT_TRUE(arr->Is<Array>());
|
EXPECT_TRUE(arr->Is<Array>());
|
||||||
|
@ -35,7 +35,7 @@ TEST_F(AstArrayTest, CreateSizedArray) {
|
||||||
|
|
||||||
TEST_F(AstArrayTest, CreateRuntimeArray) {
|
TEST_F(AstArrayTest, CreateRuntimeArray) {
|
||||||
auto* u32 = create<U32>();
|
auto* u32 = create<U32>();
|
||||||
auto* arr = create<Array>(u32, nullptr, AttributeList{});
|
auto* arr = create<Array>(u32, nullptr, utils::Empty);
|
||||||
EXPECT_EQ(arr->type, u32);
|
EXPECT_EQ(arr->type, u32);
|
||||||
EXPECT_EQ(arr->count, nullptr);
|
EXPECT_EQ(arr->count, nullptr);
|
||||||
EXPECT_TRUE(arr->Is<Array>());
|
EXPECT_TRUE(arr->Is<Array>());
|
||||||
|
@ -43,7 +43,7 @@ TEST_F(AstArrayTest, CreateRuntimeArray) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AstArrayTest, CreateInferredTypeArray) {
|
TEST_F(AstArrayTest, CreateInferredTypeArray) {
|
||||||
auto* arr = create<Array>(nullptr, nullptr, AttributeList{});
|
auto* arr = create<Array>(nullptr, nullptr, utils::Empty);
|
||||||
EXPECT_EQ(arr->type, nullptr);
|
EXPECT_EQ(arr->type, nullptr);
|
||||||
EXPECT_EQ(arr->count, nullptr);
|
EXPECT_EQ(arr->count, nullptr);
|
||||||
EXPECT_TRUE(arr->Is<Array>());
|
EXPECT_TRUE(arr->Is<Array>());
|
||||||
|
@ -52,35 +52,35 @@ TEST_F(AstArrayTest, CreateInferredTypeArray) {
|
||||||
|
|
||||||
TEST_F(AstArrayTest, FriendlyName_RuntimeSized) {
|
TEST_F(AstArrayTest, FriendlyName_RuntimeSized) {
|
||||||
auto* i32 = create<I32>();
|
auto* i32 = create<I32>();
|
||||||
auto* arr = create<Array>(i32, nullptr, AttributeList{});
|
auto* arr = create<Array>(i32, nullptr, utils::Empty);
|
||||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32>");
|
EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32>");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AstArrayTest, FriendlyName_LiteralSized) {
|
TEST_F(AstArrayTest, FriendlyName_LiteralSized) {
|
||||||
auto* i32 = create<I32>();
|
auto* i32 = create<I32>();
|
||||||
auto* arr = create<Array>(i32, Expr(5_u), AttributeList{});
|
auto* arr = create<Array>(i32, Expr(5_u), utils::Empty);
|
||||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32, 5>");
|
EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32, 5>");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AstArrayTest, FriendlyName_ConstantSized) {
|
TEST_F(AstArrayTest, FriendlyName_ConstantSized) {
|
||||||
auto* i32 = create<I32>();
|
auto* i32 = create<I32>();
|
||||||
auto* arr = create<Array>(i32, Expr("size"), AttributeList{});
|
auto* arr = create<Array>(i32, Expr("size"), utils::Empty);
|
||||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32, size>");
|
EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32, size>");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AstArrayTest, FriendlyName_WithStride) {
|
TEST_F(AstArrayTest, FriendlyName_WithStride) {
|
||||||
auto* i32 = create<I32>();
|
auto* i32 = create<I32>();
|
||||||
auto* arr = create<Array>(i32, Expr(5_u), AttributeList{create<StrideAttribute>(32u)});
|
auto* arr = create<Array>(i32, Expr(5_u), utils::Vector{create<StrideAttribute>(32u)});
|
||||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "@stride(32) array<i32, 5>");
|
EXPECT_EQ(arr->FriendlyName(Symbols()), "@stride(32) array<i32, 5>");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AstArrayTest, FriendlyName_InferredTypeAndCount) {
|
TEST_F(AstArrayTest, FriendlyName_InferredTypeAndCount) {
|
||||||
auto* arr = create<Array>(nullptr, nullptr, AttributeList{});
|
auto* arr = create<Array>(nullptr, nullptr, utils::Empty);
|
||||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "array");
|
EXPECT_EQ(arr->FriendlyName(Symbols()), "array");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AstArrayTest, FriendlyName_InferredTypeAndCount_WithStrize) {
|
TEST_F(AstArrayTest, FriendlyName_InferredTypeAndCount_WithStrize) {
|
||||||
auto* arr = create<Array>(nullptr, nullptr, AttributeList{create<StrideAttribute>(32u)});
|
auto* arr = create<Array>(nullptr, nullptr, utils::Vector{create<StrideAttribute>(32u)});
|
||||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "@stride(32) array");
|
EXPECT_EQ(arr->FriendlyName(Symbols()), "@stride(32) array");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,13 +38,10 @@ class Attribute : public Castable<Attribute, Node> {
|
||||||
Attribute(ProgramID pid, NodeID nid, const Source& src) : Base(pid, nid, src) {}
|
Attribute(ProgramID pid, NodeID nid, const Source& src) : Base(pid, nid, src) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A list of attributes
|
|
||||||
using AttributeList = std::vector<const Attribute*>;
|
|
||||||
|
|
||||||
/// @param attributes the list of attributes to search
|
/// @param attributes the list of attributes to search
|
||||||
/// @returns true if `attributes` includes a attribute of type `T`
|
/// @returns true if `attributes` includes a attribute of type `T`
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
bool HasAttribute(const AttributeList& attributes) {
|
bool HasAttribute(utils::VectorRef<const Attribute*> attributes) {
|
||||||
for (auto* attr : attributes) {
|
for (auto* attr : attributes) {
|
||||||
if (attr->IsAnyOf<Ts...>()) {
|
if (attr->IsAnyOf<Ts...>()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -56,7 +53,7 @@ bool HasAttribute(const AttributeList& attributes) {
|
||||||
/// @param attributes the list of attributes to search
|
/// @param attributes the list of attributes to search
|
||||||
/// @returns a pointer to `T` from `attributes` if found, otherwise nullptr.
|
/// @returns a pointer to `T` from `attributes` if found, otherwise nullptr.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const T* GetAttribute(const AttributeList& attributes) {
|
const T* GetAttribute(utils::VectorRef<const Attribute*> attributes) {
|
||||||
for (auto* attr : attributes) {
|
for (auto* attr : attributes) {
|
||||||
if (attr->Is<T>()) {
|
if (attr->Is<T>()) {
|
||||||
return attr->As<T>();
|
return attr->As<T>();
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace tint::ast {
|
||||||
BlockStatement::BlockStatement(ProgramID pid,
|
BlockStatement::BlockStatement(ProgramID pid,
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
const StatementList& stmts)
|
utils::VectorRef<const Statement*> stmts)
|
||||||
: Base(pid, nid, src), statements(std::move(stmts)) {
|
: Base(pid, nid, src), statements(std::move(stmts)) {
|
||||||
for (auto* stmt : statements) {
|
for (auto* stmt : statements) {
|
||||||
TINT_ASSERT(AST, stmt);
|
TINT_ASSERT(AST, stmt);
|
||||||
|
@ -39,7 +39,7 @@ const BlockStatement* BlockStatement::Clone(CloneContext* ctx) const {
|
||||||
// Clone arguments outside of create() call to have deterministic ordering
|
// Clone arguments outside of create() call to have deterministic ordering
|
||||||
auto src = ctx->Clone(source);
|
auto src = ctx->Clone(source);
|
||||||
auto stmts = ctx->Clone(statements);
|
auto stmts = ctx->Clone(statements);
|
||||||
return ctx->dst->create<BlockStatement>(src, stmts);
|
return ctx->dst->create<BlockStatement>(src, std::move(stmts));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -32,16 +32,16 @@ class BlockStatement final : public Castable<BlockStatement, Statement> {
|
||||||
BlockStatement(ProgramID pid,
|
BlockStatement(ProgramID pid,
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& source,
|
const Source& source,
|
||||||
const StatementList& statements);
|
utils::VectorRef<const Statement*> statements);
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
BlockStatement(BlockStatement&&);
|
BlockStatement(BlockStatement&&);
|
||||||
~BlockStatement() override;
|
~BlockStatement() override;
|
||||||
|
|
||||||
/// @returns true if the block has no statements
|
/// @returns true if the block has no statements
|
||||||
bool Empty() const { return statements.empty(); }
|
bool Empty() const { return statements.IsEmpty(); }
|
||||||
|
|
||||||
/// @returns the last statement in the block or nullptr if block empty
|
/// @returns the last statement in the block or nullptr if block empty
|
||||||
const Statement* Last() const { return statements.empty() ? nullptr : statements.back(); }
|
const Statement* Last() const { return statements.IsEmpty() ? nullptr : statements.Back(); }
|
||||||
|
|
||||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||||
/// `ctx`.
|
/// `ctx`.
|
||||||
|
@ -50,7 +50,7 @@ class BlockStatement final : public Castable<BlockStatement, Statement> {
|
||||||
const BlockStatement* Clone(CloneContext* ctx) const override;
|
const BlockStatement* Clone(CloneContext* ctx) const override;
|
||||||
|
|
||||||
/// the statement list
|
/// the statement list
|
||||||
const StatementList statements;
|
const utils::Vector<const Statement*, 8> statements;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -26,21 +26,21 @@ TEST_F(BlockStatementTest, Creation) {
|
||||||
auto* d = create<DiscardStatement>();
|
auto* d = create<DiscardStatement>();
|
||||||
auto* ptr = d;
|
auto* ptr = d;
|
||||||
|
|
||||||
auto* b = create<BlockStatement>(StatementList{d});
|
auto* b = create<BlockStatement>(utils::Vector{d});
|
||||||
|
|
||||||
ASSERT_EQ(b->statements.size(), 1u);
|
ASSERT_EQ(b->statements.Length(), 1u);
|
||||||
EXPECT_EQ(b->statements[0], ptr);
|
EXPECT_EQ(b->statements[0], ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlockStatementTest, Creation_WithSource) {
|
TEST_F(BlockStatementTest, Creation_WithSource) {
|
||||||
auto* b = create<BlockStatement>(Source{Source::Location{20, 2}}, ast::StatementList{});
|
auto* b = create<BlockStatement>(Source{Source::Location{20, 2}}, utils::Empty);
|
||||||
auto src = b->source;
|
auto src = b->source;
|
||||||
EXPECT_EQ(src.range.begin.line, 20u);
|
EXPECT_EQ(src.range.begin.line, 20u);
|
||||||
EXPECT_EQ(src.range.begin.column, 2u);
|
EXPECT_EQ(src.range.begin.column, 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlockStatementTest, IsBlock) {
|
TEST_F(BlockStatementTest, IsBlock) {
|
||||||
auto* b = create<BlockStatement>(ast::StatementList{});
|
auto* b = create<BlockStatement>(utils::Empty);
|
||||||
EXPECT_TRUE(b->Is<BlockStatement>());
|
EXPECT_TRUE(b->Is<BlockStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ TEST_F(BlockStatementTest, Assert_Null_Statement) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
b.create<BlockStatement>(ast::StatementList{nullptr});
|
b.create<BlockStatement>(utils::Vector<const ast::Statement*, 1>{nullptr});
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ TEST_F(BlockStatementTest, Assert_DifferentProgramID_Statement) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<BlockStatement>(ast::StatementList{b2.create<DiscardStatement>()});
|
b1.create<BlockStatement>(utils::Vector{b2.create<DiscardStatement>()});
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ TextureOverloadCase::TextureOverloadCase(ValidTextureOverload o,
|
||||||
ast::TextureDimension dims,
|
ast::TextureDimension dims,
|
||||||
TextureDataType datatype,
|
TextureDataType datatype,
|
||||||
const char* f,
|
const char* f,
|
||||||
std::function<ExpressionList(ProgramBuilder*)> a)
|
std::function<Args(ProgramBuilder*)> a)
|
||||||
: overload(o),
|
: overload(o),
|
||||||
description(desc),
|
description(desc),
|
||||||
texture_kind(tk),
|
texture_kind(tk),
|
||||||
|
@ -44,7 +44,7 @@ TextureOverloadCase::TextureOverloadCase(ValidTextureOverload o,
|
||||||
ast::TextureDimension dims,
|
ast::TextureDimension dims,
|
||||||
TextureDataType datatype,
|
TextureDataType datatype,
|
||||||
const char* f,
|
const char* f,
|
||||||
std::function<ExpressionList(ProgramBuilder*)> a)
|
std::function<Args(ProgramBuilder*)> a)
|
||||||
: overload(o),
|
: overload(o),
|
||||||
description(desc),
|
description(desc),
|
||||||
texture_kind(tk),
|
texture_kind(tk),
|
||||||
|
@ -59,7 +59,7 @@ TextureOverloadCase::TextureOverloadCase(ValidTextureOverload o,
|
||||||
ast::TextureDimension dims,
|
ast::TextureDimension dims,
|
||||||
TextureDataType datatype,
|
TextureDataType datatype,
|
||||||
const char* f,
|
const char* f,
|
||||||
std::function<ExpressionList(ProgramBuilder*)> a)
|
std::function<Args(ProgramBuilder*)> a)
|
||||||
: overload(o),
|
: overload(o),
|
||||||
description(d),
|
description(d),
|
||||||
texture_kind(TextureKind::kStorage),
|
texture_kind(TextureKind::kStorage),
|
||||||
|
@ -141,7 +141,7 @@ const ast::Type* TextureOverloadCase::BuildResultVectorComponentType(ProgramBuil
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Variable* TextureOverloadCase::BuildTextureVariable(ProgramBuilder* b) const {
|
const ast::Variable* TextureOverloadCase::BuildTextureVariable(ProgramBuilder* b) const {
|
||||||
AttributeList attrs = {
|
utils::Vector attrs{
|
||||||
b->create<ast::GroupAttribute>(0u),
|
b->create<ast::GroupAttribute>(0u),
|
||||||
b->create<ast::BindingAttribute>(0u),
|
b->create<ast::BindingAttribute>(0u),
|
||||||
};
|
};
|
||||||
|
@ -175,7 +175,7 @@ const ast::Variable* TextureOverloadCase::BuildTextureVariable(ProgramBuilder* b
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Variable* TextureOverloadCase::BuildSamplerVariable(ProgramBuilder* b) const {
|
const ast::Variable* TextureOverloadCase::BuildSamplerVariable(ProgramBuilder* b) const {
|
||||||
AttributeList attrs = {
|
utils::Vector attrs = {
|
||||||
b->create<ast::GroupAttribute>(0u),
|
b->create<ast::GroupAttribute>(0u),
|
||||||
b->create<ast::BindingAttribute>(1u),
|
b->create<ast::BindingAttribute>(1u),
|
||||||
};
|
};
|
||||||
|
|
|
@ -177,6 +177,9 @@ bool ReturnsVoid(ValidTextureOverload texture_overload);
|
||||||
|
|
||||||
/// Describes a texture builtin overload
|
/// Describes a texture builtin overload
|
||||||
struct TextureOverloadCase {
|
struct TextureOverloadCase {
|
||||||
|
/// Args is a list of ast::Expression used as arguments to the texture overload case.
|
||||||
|
using Args = utils::Vector<const ast::Expression*, 8>;
|
||||||
|
|
||||||
/// Constructor for textureSample...() functions
|
/// Constructor for textureSample...() functions
|
||||||
TextureOverloadCase(ValidTextureOverload,
|
TextureOverloadCase(ValidTextureOverload,
|
||||||
const char*,
|
const char*,
|
||||||
|
@ -185,7 +188,7 @@ struct TextureOverloadCase {
|
||||||
ast::TextureDimension,
|
ast::TextureDimension,
|
||||||
TextureDataType,
|
TextureDataType,
|
||||||
const char*,
|
const char*,
|
||||||
std::function<ExpressionList(ProgramBuilder*)>);
|
std::function<Args(ProgramBuilder*)>);
|
||||||
/// Constructor for textureLoad() functions with non-storage textures
|
/// Constructor for textureLoad() functions with non-storage textures
|
||||||
TextureOverloadCase(ValidTextureOverload,
|
TextureOverloadCase(ValidTextureOverload,
|
||||||
const char*,
|
const char*,
|
||||||
|
@ -193,7 +196,7 @@ struct TextureOverloadCase {
|
||||||
ast::TextureDimension,
|
ast::TextureDimension,
|
||||||
TextureDataType,
|
TextureDataType,
|
||||||
const char*,
|
const char*,
|
||||||
std::function<ExpressionList(ProgramBuilder*)>);
|
std::function<Args(ProgramBuilder*)>);
|
||||||
/// Constructor for textureLoad() with storage textures
|
/// Constructor for textureLoad() with storage textures
|
||||||
TextureOverloadCase(ValidTextureOverload,
|
TextureOverloadCase(ValidTextureOverload,
|
||||||
const char*,
|
const char*,
|
||||||
|
@ -202,7 +205,7 @@ struct TextureOverloadCase {
|
||||||
ast::TextureDimension,
|
ast::TextureDimension,
|
||||||
TextureDataType,
|
TextureDataType,
|
||||||
const char*,
|
const char*,
|
||||||
std::function<ExpressionList(ProgramBuilder*)>);
|
std::function<Args(ProgramBuilder*)>);
|
||||||
/// Copy constructor
|
/// Copy constructor
|
||||||
TextureOverloadCase(const TextureOverloadCase&);
|
TextureOverloadCase(const TextureOverloadCase&);
|
||||||
/// Destructor
|
/// Destructor
|
||||||
|
@ -246,7 +249,7 @@ struct TextureOverloadCase {
|
||||||
/// Name of the function. e.g. `textureSample`, `textureSampleGrad`, etc
|
/// Name of the function. e.g. `textureSample`, `textureSampleGrad`, etc
|
||||||
const char* const function;
|
const char* const function;
|
||||||
/// A function that builds the AST arguments for the overload
|
/// A function that builds the AST arguments for the overload
|
||||||
std::function<ExpressionList(ProgramBuilder*)> const args;
|
std::function<Args(ProgramBuilder*)> const args;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const TextureOverloadCase& data);
|
std::ostream& operator<<(std::ostream& out, const TextureOverloadCase& data);
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "src/tint/ast/call_expression.h"
|
#include "src/tint/ast/call_expression.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "src/tint/program_builder.h"
|
#include "src/tint/program_builder.h"
|
||||||
|
|
||||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::CallExpression);
|
TINT_INSTANTIATE_TYPEINFO(tint::ast::CallExpression);
|
||||||
|
@ -37,8 +39,8 @@ CallExpression::CallExpression(ProgramID pid,
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
const IdentifierExpression* name,
|
const IdentifierExpression* name,
|
||||||
ExpressionList a)
|
utils::VectorRef<const Expression*> a)
|
||||||
: Base(pid, nid, src), target(ToTarget(name)), args(a) {
|
: Base(pid, nid, src), target(ToTarget(name)), args(std::move(a)) {
|
||||||
TINT_ASSERT(AST, name);
|
TINT_ASSERT(AST, name);
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, name, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, name, program_id);
|
||||||
for (auto* arg : args) {
|
for (auto* arg : args) {
|
||||||
|
@ -51,8 +53,8 @@ CallExpression::CallExpression(ProgramID pid,
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
const Type* type,
|
const Type* type,
|
||||||
ExpressionList a)
|
utils::VectorRef<const Expression*> a)
|
||||||
: Base(pid, nid, src), target(ToTarget(type)), args(a) {
|
: Base(pid, nid, src), target(ToTarget(type)), args(std::move(a)) {
|
||||||
TINT_ASSERT(AST, type);
|
TINT_ASSERT(AST, type);
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
|
||||||
for (auto* arg : args) {
|
for (auto* arg : args) {
|
||||||
|
@ -69,8 +71,9 @@ const CallExpression* CallExpression::Clone(CloneContext* ctx) const {
|
||||||
// Clone arguments outside of create() call to have deterministic ordering
|
// Clone arguments outside of create() call to have deterministic ordering
|
||||||
auto src = ctx->Clone(source);
|
auto src = ctx->Clone(source);
|
||||||
auto p = ctx->Clone(args);
|
auto p = ctx->Clone(args);
|
||||||
return target.name ? ctx->dst->create<CallExpression>(src, ctx->Clone(target.name), p)
|
return target.name
|
||||||
: ctx->dst->create<CallExpression>(src, ctx->Clone(target.type), p);
|
? ctx->dst->create<CallExpression>(src, ctx->Clone(target.name), std::move(p))
|
||||||
|
: ctx->dst->create<CallExpression>(src, ctx->Clone(target.type), std::move(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -42,7 +42,7 @@ class CallExpression final : public Castable<CallExpression, Expression> {
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& source,
|
const Source& source,
|
||||||
const IdentifierExpression* name,
|
const IdentifierExpression* name,
|
||||||
ExpressionList args);
|
utils::VectorRef<const Expression*> args);
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// @param pid the identifier of the program that owns this node
|
/// @param pid the identifier of the program that owns this node
|
||||||
|
@ -54,7 +54,7 @@ class CallExpression final : public Castable<CallExpression, Expression> {
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& source,
|
const Source& source,
|
||||||
const Type* type,
|
const Type* type,
|
||||||
ExpressionList args);
|
utils::VectorRef<const Expression*> args);
|
||||||
|
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
CallExpression(CallExpression&&);
|
CallExpression(CallExpression&&);
|
||||||
|
@ -80,7 +80,7 @@ class CallExpression final : public Castable<CallExpression, Expression> {
|
||||||
const Target target;
|
const Target target;
|
||||||
|
|
||||||
/// The arguments
|
/// The arguments
|
||||||
const ExpressionList args;
|
const utils::Vector<const Expression*, 8> args;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -22,23 +22,24 @@ using CallExpressionTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(CallExpressionTest, CreationIdentifier) {
|
TEST_F(CallExpressionTest, CreationIdentifier) {
|
||||||
auto* func = Expr("func");
|
auto* func = Expr("func");
|
||||||
ExpressionList params;
|
utils::Vector params{
|
||||||
params.push_back(Expr("param1"));
|
Expr("param1"),
|
||||||
params.push_back(Expr("param2"));
|
Expr("param2"),
|
||||||
|
};
|
||||||
|
|
||||||
auto* stmt = create<CallExpression>(func, params);
|
auto* stmt = create<CallExpression>(func, params);
|
||||||
EXPECT_EQ(stmt->target.name, func);
|
EXPECT_EQ(stmt->target.name, func);
|
||||||
EXPECT_EQ(stmt->target.type, nullptr);
|
EXPECT_EQ(stmt->target.type, nullptr);
|
||||||
|
|
||||||
const auto& vec = stmt->args;
|
const auto& vec = stmt->args;
|
||||||
ASSERT_EQ(vec.size(), 2u);
|
ASSERT_EQ(vec.Length(), 2u);
|
||||||
EXPECT_EQ(vec[0], params[0]);
|
EXPECT_EQ(vec[0], params[0]);
|
||||||
EXPECT_EQ(vec[1], params[1]);
|
EXPECT_EQ(vec[1], params[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CallExpressionTest, CreationIdentifier_WithSource) {
|
TEST_F(CallExpressionTest, CreationIdentifier_WithSource) {
|
||||||
auto* func = Expr("func");
|
auto* func = Expr("func");
|
||||||
auto* stmt = create<CallExpression>(Source{{20, 2}}, func, ExpressionList{});
|
auto* stmt = create<CallExpression>(Source{{20, 2}}, func, utils::Empty);
|
||||||
EXPECT_EQ(stmt->target.name, func);
|
EXPECT_EQ(stmt->target.name, func);
|
||||||
EXPECT_EQ(stmt->target.type, nullptr);
|
EXPECT_EQ(stmt->target.type, nullptr);
|
||||||
|
|
||||||
|
@ -49,23 +50,24 @@ TEST_F(CallExpressionTest, CreationIdentifier_WithSource) {
|
||||||
|
|
||||||
TEST_F(CallExpressionTest, CreationType) {
|
TEST_F(CallExpressionTest, CreationType) {
|
||||||
auto* type = ty.f32();
|
auto* type = ty.f32();
|
||||||
ExpressionList params;
|
utils::Vector params{
|
||||||
params.push_back(Expr("param1"));
|
Expr("param1"),
|
||||||
params.push_back(Expr("param2"));
|
Expr("param2"),
|
||||||
|
};
|
||||||
|
|
||||||
auto* stmt = create<CallExpression>(type, params);
|
auto* stmt = create<CallExpression>(type, params);
|
||||||
EXPECT_EQ(stmt->target.name, nullptr);
|
EXPECT_EQ(stmt->target.name, nullptr);
|
||||||
EXPECT_EQ(stmt->target.type, type);
|
EXPECT_EQ(stmt->target.type, type);
|
||||||
|
|
||||||
const auto& vec = stmt->args;
|
const auto& vec = stmt->args;
|
||||||
ASSERT_EQ(vec.size(), 2u);
|
ASSERT_EQ(vec.Length(), 2u);
|
||||||
EXPECT_EQ(vec[0], params[0]);
|
EXPECT_EQ(vec[0], params[0]);
|
||||||
EXPECT_EQ(vec[1], params[1]);
|
EXPECT_EQ(vec[1], params[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CallExpressionTest, CreationType_WithSource) {
|
TEST_F(CallExpressionTest, CreationType_WithSource) {
|
||||||
auto* type = ty.f32();
|
auto* type = ty.f32();
|
||||||
auto* stmt = create<CallExpression>(Source{{20, 2}}, type, ExpressionList{});
|
auto* stmt = create<CallExpression>(Source{{20, 2}}, type, utils::Empty);
|
||||||
EXPECT_EQ(stmt->target.name, nullptr);
|
EXPECT_EQ(stmt->target.name, nullptr);
|
||||||
EXPECT_EQ(stmt->target.type, type);
|
EXPECT_EQ(stmt->target.type, type);
|
||||||
|
|
||||||
|
@ -76,7 +78,7 @@ TEST_F(CallExpressionTest, CreationType_WithSource) {
|
||||||
|
|
||||||
TEST_F(CallExpressionTest, IsCall) {
|
TEST_F(CallExpressionTest, IsCall) {
|
||||||
auto* func = Expr("func");
|
auto* func = Expr("func");
|
||||||
auto* stmt = create<CallExpression>(func, ExpressionList{});
|
auto* stmt = create<CallExpression>(func, utils::Empty);
|
||||||
EXPECT_TRUE(stmt->Is<CallExpression>());
|
EXPECT_TRUE(stmt->Is<CallExpression>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +86,7 @@ TEST_F(CallExpressionTest, Assert_Null_Identifier) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
b.create<CallExpression>(static_cast<IdentifierExpression*>(nullptr), ExpressionList{});
|
b.create<CallExpression>(static_cast<IdentifierExpression*>(nullptr), utils::Empty);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -93,7 +95,7 @@ TEST_F(CallExpressionTest, Assert_Null_Type) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
b.create<CallExpression>(static_cast<Type*>(nullptr), ExpressionList{});
|
b.create<CallExpression>(static_cast<Type*>(nullptr), utils::Empty);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -102,11 +104,11 @@ TEST_F(CallExpressionTest, Assert_Null_Param) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
ExpressionList params;
|
b.create<CallExpression>(b.Expr("func"), utils::Vector{
|
||||||
params.push_back(b.Expr("param1"));
|
b.Expr("param1"),
|
||||||
params.push_back(nullptr);
|
nullptr,
|
||||||
params.push_back(b.Expr("param2"));
|
b.Expr("param2"),
|
||||||
b.create<CallExpression>(b.Expr("func"), params);
|
});
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -116,7 +118,7 @@ TEST_F(CallExpressionTest, Assert_DifferentProgramID_Identifier) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<CallExpression>(b2.Expr("func"), ExpressionList{});
|
b1.create<CallExpression>(b2.Expr("func"), utils::Empty);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -126,7 +128,7 @@ TEST_F(CallExpressionTest, Assert_DifferentProgramID_Type) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<CallExpression>(b2.ty.f32(), ExpressionList{});
|
b1.create<CallExpression>(b2.ty.f32(), utils::Empty);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -136,7 +138,7 @@ TEST_F(CallExpressionTest, Assert_DifferentProgramID_Param) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<CallExpression>(b1.Expr("func"), ExpressionList{b2.Expr("param1")});
|
b1.create<CallExpression>(b1.Expr("func"), utils::Vector{b2.Expr("param1")});
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace {
|
||||||
using CallStatementTest = TestHelper;
|
using CallStatementTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(CallStatementTest, Creation) {
|
TEST_F(CallStatementTest, Creation) {
|
||||||
auto* expr = create<CallExpression>(Expr("func"), ExpressionList{});
|
auto* expr = create<CallExpression>(Expr("func"), utils::Empty);
|
||||||
|
|
||||||
auto* c = create<CallStatement>(expr);
|
auto* c = create<CallStatement>(expr);
|
||||||
EXPECT_EQ(c->expr, expr);
|
EXPECT_EQ(c->expr, expr);
|
||||||
|
@ -48,7 +48,7 @@ TEST_F(CallStatementTest, Assert_DifferentProgramID_Call) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<CallStatement>(b2.create<CallExpression>(b2.Expr("func"), ExpressionList{}));
|
b1.create<CallStatement>(b2.create<CallExpression>(b2.Expr("func"), utils::Empty));
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "src/tint/ast/case_statement.h"
|
#include "src/tint/ast/case_statement.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "src/tint/program_builder.h"
|
#include "src/tint/program_builder.h"
|
||||||
|
|
||||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::CaseStatement);
|
TINT_INSTANTIATE_TYPEINFO(tint::ast::CaseStatement);
|
||||||
|
@ -23,9 +25,9 @@ namespace tint::ast {
|
||||||
CaseStatement::CaseStatement(ProgramID pid,
|
CaseStatement::CaseStatement(ProgramID pid,
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
CaseSelectorList s,
|
utils::VectorRef<const IntLiteralExpression*> s,
|
||||||
const BlockStatement* b)
|
const BlockStatement* b)
|
||||||
: Base(pid, nid, src), selectors(s), body(b) {
|
: Base(pid, nid, src), selectors(std::move(s)), body(b) {
|
||||||
TINT_ASSERT(AST, body);
|
TINT_ASSERT(AST, body);
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
|
||||||
for (auto* selector : selectors) {
|
for (auto* selector : selectors) {
|
||||||
|
@ -43,7 +45,7 @@ const CaseStatement* CaseStatement::Clone(CloneContext* ctx) const {
|
||||||
auto src = ctx->Clone(source);
|
auto src = ctx->Clone(source);
|
||||||
auto sel = ctx->Clone(selectors);
|
auto sel = ctx->Clone(selectors);
|
||||||
auto* b = ctx->Clone(body);
|
auto* b = ctx->Clone(body);
|
||||||
return ctx->dst->create<CaseStatement>(src, sel, b);
|
return ctx->dst->create<CaseStatement>(src, std::move(sel), b);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -22,9 +22,6 @@
|
||||||
|
|
||||||
namespace tint::ast {
|
namespace tint::ast {
|
||||||
|
|
||||||
/// A list of case literals
|
|
||||||
using CaseSelectorList = std::vector<const IntLiteralExpression*>;
|
|
||||||
|
|
||||||
/// A case statement
|
/// A case statement
|
||||||
class CaseStatement final : public Castable<CaseStatement, Statement> {
|
class CaseStatement final : public Castable<CaseStatement, Statement> {
|
||||||
public:
|
public:
|
||||||
|
@ -37,14 +34,14 @@ class CaseStatement final : public Castable<CaseStatement, Statement> {
|
||||||
CaseStatement(ProgramID pid,
|
CaseStatement(ProgramID pid,
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
CaseSelectorList selectors,
|
utils::VectorRef<const IntLiteralExpression*> selectors,
|
||||||
const BlockStatement* body);
|
const BlockStatement* body);
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
CaseStatement(CaseStatement&&);
|
CaseStatement(CaseStatement&&);
|
||||||
~CaseStatement() override;
|
~CaseStatement() override;
|
||||||
|
|
||||||
/// @returns true if this is a default statement
|
/// @returns true if this is a default statement
|
||||||
bool IsDefault() const { return selectors.empty(); }
|
bool IsDefault() const { return selectors.IsEmpty(); }
|
||||||
|
|
||||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||||
/// `ctx`.
|
/// `ctx`.
|
||||||
|
@ -53,15 +50,12 @@ class CaseStatement final : public Castable<CaseStatement, Statement> {
|
||||||
const CaseStatement* Clone(CloneContext* ctx) const override;
|
const CaseStatement* Clone(CloneContext* ctx) const override;
|
||||||
|
|
||||||
/// The case selectors, empty if none set
|
/// The case selectors, empty if none set
|
||||||
const CaseSelectorList selectors;
|
const utils::Vector<const IntLiteralExpression*, 4> selectors;
|
||||||
|
|
||||||
/// The case body
|
/// The case body
|
||||||
const BlockStatement* const body;
|
const BlockStatement* const body;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A list of case statements
|
|
||||||
using CaseStatementList = std::vector<const CaseStatement*>;
|
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
||||||
#endif // SRC_TINT_AST_CASE_STATEMENT_H_
|
#endif // SRC_TINT_AST_CASE_STATEMENT_H_
|
||||||
|
|
|
@ -27,40 +27,37 @@ namespace {
|
||||||
using CaseStatementTest = TestHelper;
|
using CaseStatementTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(CaseStatementTest, Creation_i32) {
|
TEST_F(CaseStatementTest, Creation_i32) {
|
||||||
CaseSelectorList b;
|
|
||||||
auto* selector = Expr(2_i);
|
auto* selector = Expr(2_i);
|
||||||
b.push_back(selector);
|
utils::Vector b{selector};
|
||||||
|
|
||||||
auto* discard = create<DiscardStatement>();
|
auto* discard = create<DiscardStatement>();
|
||||||
auto* body = create<BlockStatement>(StatementList{discard});
|
auto* body = create<BlockStatement>(utils::Vector{discard});
|
||||||
|
|
||||||
auto* c = create<CaseStatement>(b, body);
|
auto* c = create<CaseStatement>(b, body);
|
||||||
ASSERT_EQ(c->selectors.size(), 1u);
|
ASSERT_EQ(c->selectors.Length(), 1u);
|
||||||
EXPECT_EQ(c->selectors[0], selector);
|
EXPECT_EQ(c->selectors[0], selector);
|
||||||
ASSERT_EQ(c->body->statements.size(), 1u);
|
ASSERT_EQ(c->body->statements.Length(), 1u);
|
||||||
EXPECT_EQ(c->body->statements[0], discard);
|
EXPECT_EQ(c->body->statements[0], discard);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CaseStatementTest, Creation_u32) {
|
TEST_F(CaseStatementTest, Creation_u32) {
|
||||||
CaseSelectorList b;
|
|
||||||
auto* selector = Expr(2_u);
|
auto* selector = Expr(2_u);
|
||||||
b.push_back(selector);
|
utils::Vector b{selector};
|
||||||
|
|
||||||
auto* discard = create<DiscardStatement>();
|
auto* discard = create<DiscardStatement>();
|
||||||
auto* body = create<BlockStatement>(StatementList{discard});
|
auto* body = create<BlockStatement>(utils::Vector{discard});
|
||||||
|
|
||||||
auto* c = create<CaseStatement>(b, body);
|
auto* c = create<CaseStatement>(b, body);
|
||||||
ASSERT_EQ(c->selectors.size(), 1u);
|
ASSERT_EQ(c->selectors.Length(), 1u);
|
||||||
EXPECT_EQ(c->selectors[0], selector);
|
EXPECT_EQ(c->selectors[0], selector);
|
||||||
ASSERT_EQ(c->body->statements.size(), 1u);
|
ASSERT_EQ(c->body->statements.Length(), 1u);
|
||||||
EXPECT_EQ(c->body->statements[0], discard);
|
EXPECT_EQ(c->body->statements[0], discard);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CaseStatementTest, Creation_WithSource) {
|
TEST_F(CaseStatementTest, Creation_WithSource) {
|
||||||
CaseSelectorList b;
|
utils::Vector b{Expr(2_i)};
|
||||||
b.push_back(Expr(2_i));
|
|
||||||
|
|
||||||
auto* body = create<BlockStatement>(StatementList{
|
auto* body = create<BlockStatement>(utils::Vector{
|
||||||
create<DiscardStatement>(),
|
create<DiscardStatement>(),
|
||||||
});
|
});
|
||||||
auto* c = create<CaseStatement>(Source{Source::Location{20, 2}}, b, body);
|
auto* c = create<CaseStatement>(Source{Source::Location{20, 2}}, b, body);
|
||||||
|
@ -70,23 +67,21 @@ TEST_F(CaseStatementTest, Creation_WithSource) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CaseStatementTest, IsDefault_WithoutSelectors) {
|
TEST_F(CaseStatementTest, IsDefault_WithoutSelectors) {
|
||||||
auto* body = create<BlockStatement>(StatementList{
|
auto* body = create<BlockStatement>(utils::Vector{
|
||||||
create<DiscardStatement>(),
|
create<DiscardStatement>(),
|
||||||
});
|
});
|
||||||
auto* c = create<CaseStatement>(CaseSelectorList{}, body);
|
auto* c = create<CaseStatement>(utils::Empty, body);
|
||||||
EXPECT_TRUE(c->IsDefault());
|
EXPECT_TRUE(c->IsDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CaseStatementTest, IsDefault_WithSelectors) {
|
TEST_F(CaseStatementTest, IsDefault_WithSelectors) {
|
||||||
CaseSelectorList b;
|
utils::Vector b{Expr(2_i)};
|
||||||
b.push_back(Expr(2_i));
|
auto* c = create<CaseStatement>(b, create<BlockStatement>(utils::Empty));
|
||||||
|
|
||||||
auto* c = create<CaseStatement>(b, create<BlockStatement>(StatementList{}));
|
|
||||||
EXPECT_FALSE(c->IsDefault());
|
EXPECT_FALSE(c->IsDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CaseStatementTest, IsCase) {
|
TEST_F(CaseStatementTest, IsCase) {
|
||||||
auto* c = create<CaseStatement>(CaseSelectorList{}, create<BlockStatement>(StatementList{}));
|
auto* c = create<CaseStatement>(utils::Empty, create<BlockStatement>(utils::Empty));
|
||||||
EXPECT_TRUE(c->Is<CaseStatement>());
|
EXPECT_TRUE(c->Is<CaseStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +89,7 @@ TEST_F(CaseStatementTest, Assert_Null_Body) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
b.create<CaseStatement>(CaseSelectorList{}, nullptr);
|
b.create<CaseStatement>(utils::Empty, nullptr);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -103,8 +98,8 @@ TEST_F(CaseStatementTest, Assert_Null_Selector) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
b.create<CaseStatement>(CaseSelectorList{nullptr},
|
b.create<CaseStatement>(utils::Vector<const ast::IntLiteralExpression*, 1>{nullptr},
|
||||||
b.create<BlockStatement>(StatementList{}));
|
b.create<BlockStatement>(utils::Empty));
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -114,8 +109,7 @@ TEST_F(CaseStatementTest, Assert_DifferentProgramID_Call) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<CaseStatement>(CaseSelectorList{},
|
b1.create<CaseStatement>(utils::Empty, b2.create<BlockStatement>(utils::Empty));
|
||||||
b2.create<BlockStatement>(StatementList{}));
|
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -125,8 +119,8 @@ TEST_F(CaseStatementTest, Assert_DifferentProgramID_Selector) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<CaseStatement>(CaseSelectorList{b2.Expr(2_i)},
|
b1.create<CaseStatement>(utils::Vector{b2.Expr(2_i)},
|
||||||
b1.create<BlockStatement>(StatementList{}));
|
b1.create<BlockStatement>(utils::Empty));
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "src/tint/ast/const.h"
|
#include "src/tint/ast/const.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "src/tint/program_builder.h"
|
#include "src/tint/program_builder.h"
|
||||||
|
|
||||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::Const);
|
TINT_INSTANTIATE_TYPEINFO(tint::ast::Const);
|
||||||
|
@ -26,8 +28,8 @@ Const::Const(ProgramID pid,
|
||||||
const Symbol& sym,
|
const Symbol& sym,
|
||||||
const ast::Type* ty,
|
const ast::Type* ty,
|
||||||
const Expression* ctor,
|
const Expression* ctor,
|
||||||
AttributeList attrs)
|
utils::VectorRef<const Attribute*> attrs)
|
||||||
: Base(pid, nid, src, sym, ty, ctor, attrs) {
|
: Base(pid, nid, src, sym, ty, ctor, std::move(attrs)) {
|
||||||
TINT_ASSERT(AST, ctor != nullptr);
|
TINT_ASSERT(AST, ctor != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +47,7 @@ const Const* Const::Clone(CloneContext* ctx) const {
|
||||||
auto* ty = ctx->Clone(type);
|
auto* ty = ctx->Clone(type);
|
||||||
auto* ctor = ctx->Clone(constructor);
|
auto* ctor = ctx->Clone(constructor);
|
||||||
auto attrs = ctx->Clone(attributes);
|
auto attrs = ctx->Clone(attributes);
|
||||||
return ctx->dst->create<Const>(src, sym, ty, ctor, attrs);
|
return ctx->dst->create<Const>(src, sym, ty, ctor, std::move(attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -46,7 +46,7 @@ class Const final : public Castable<Const, Variable> {
|
||||||
const Symbol& sym,
|
const Symbol& sym,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
const Expression* constructor,
|
const Expression* constructor,
|
||||||
AttributeList attributes);
|
utils::VectorRef<const Attribute*> attributes);
|
||||||
|
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
Const(Const&&);
|
Const(Const&&);
|
||||||
|
|
|
@ -52,9 +52,6 @@ class Enable final : public Castable<Enable, Node> {
|
||||||
const Extension extension;
|
const Extension extension;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A list of enables
|
|
||||||
using EnableList = std::vector<const Enable*>;
|
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
||||||
#endif // SRC_TINT_AST_ENABLE_H_
|
#endif // SRC_TINT_AST_ENABLE_H_
|
||||||
|
|
|
@ -38,9 +38,6 @@ class Expression : public Castable<Expression, Node> {
|
||||||
Expression(Expression&&);
|
Expression(Expression&&);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A list of expressions
|
|
||||||
using ExpressionList = std::vector<const Expression*>;
|
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
||||||
#endif // SRC_TINT_AST_EXPRESSION_H_
|
#endif // SRC_TINT_AST_EXPRESSION_H_
|
||||||
|
|
|
@ -26,11 +26,11 @@ Function::Function(ProgramID pid,
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
Symbol sym,
|
Symbol sym,
|
||||||
ParameterList parameters,
|
utils::VectorRef<const Parameter*> parameters,
|
||||||
const Type* return_ty,
|
const Type* return_ty,
|
||||||
const BlockStatement* b,
|
const BlockStatement* b,
|
||||||
AttributeList attrs,
|
utils::VectorRef<const Attribute*> attrs,
|
||||||
AttributeList return_type_attrs)
|
utils::VectorRef<const Attribute*> return_type_attrs)
|
||||||
: Base(pid, nid, src),
|
: Base(pid, nid, src),
|
||||||
symbol(sym),
|
symbol(sym),
|
||||||
params(std::move(parameters)),
|
params(std::move(parameters)),
|
||||||
|
|
|
@ -48,11 +48,11 @@ class Function final : public Castable<Function, Node> {
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& source,
|
const Source& source,
|
||||||
Symbol symbol,
|
Symbol symbol,
|
||||||
ParameterList params,
|
utils::VectorRef<const Parameter*> params,
|
||||||
const Type* return_type,
|
const Type* return_type,
|
||||||
const BlockStatement* body,
|
const BlockStatement* body,
|
||||||
AttributeList attributes,
|
utils::VectorRef<const Attribute*> attributes,
|
||||||
AttributeList return_type_attributes);
|
utils::VectorRef<const Attribute*> return_type_attributes);
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
Function(Function&&);
|
Function(Function&&);
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ class Function final : public Castable<Function, Node> {
|
||||||
const Symbol symbol;
|
const Symbol symbol;
|
||||||
|
|
||||||
/// The function params
|
/// The function params
|
||||||
const ParameterList params;
|
const utils::Vector<const Parameter*, 8> params;
|
||||||
|
|
||||||
/// The function return type
|
/// The function return type
|
||||||
const Type* const return_type;
|
const Type* const return_type;
|
||||||
|
@ -83,18 +83,18 @@ class Function final : public Castable<Function, Node> {
|
||||||
const BlockStatement* const body;
|
const BlockStatement* const body;
|
||||||
|
|
||||||
/// The attributes attached to this function
|
/// The attributes attached to this function
|
||||||
const AttributeList attributes;
|
const utils::Vector<const Attribute*, 2> attributes;
|
||||||
|
|
||||||
/// The attributes attached to the function return type.
|
/// The attributes attached to the function return type.
|
||||||
const AttributeList return_type_attributes;
|
const utils::Vector<const Attribute*, 2> return_type_attributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A list of functions
|
/// A list of functions
|
||||||
class FunctionList : public std::vector<const Function*> {
|
class FunctionList : public utils::Vector<const Function*, 8> {
|
||||||
public:
|
public:
|
||||||
/// Appends f to the end of the list
|
/// Appends f to the end of the list
|
||||||
/// @param f the function to append to this list
|
/// @param f the function to append to this list
|
||||||
void Add(const Function* f) { this->emplace_back(f); }
|
void Add(const Function* f) { this->Push(f); }
|
||||||
|
|
||||||
/// Returns the function with the given name
|
/// Returns the function with the given name
|
||||||
/// @param sym the function symbol to search for
|
/// @param sym the function symbol to search for
|
||||||
|
|
|
@ -26,20 +26,20 @@ namespace {
|
||||||
using FunctionTest = TestHelper;
|
using FunctionTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(FunctionTest, Creation) {
|
TEST_F(FunctionTest, Creation) {
|
||||||
ParameterList params{Param("var", ty.i32())};
|
utils::Vector params{Param("var", ty.i32())};
|
||||||
auto* var = params[0];
|
auto* var = params[0];
|
||||||
|
|
||||||
auto* f = Func("func", params, ty.void_(), {});
|
auto* f = Func("func", params, ty.void_(), utils::Empty);
|
||||||
EXPECT_EQ(f->symbol, Symbols().Get("func"));
|
EXPECT_EQ(f->symbol, Symbols().Get("func"));
|
||||||
ASSERT_EQ(f->params.size(), 1u);
|
ASSERT_EQ(f->params.Length(), 1u);
|
||||||
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
||||||
EXPECT_EQ(f->params[0], var);
|
EXPECT_EQ(f->params[0], var);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FunctionTest, Creation_WithSource) {
|
TEST_F(FunctionTest, Creation_WithSource) {
|
||||||
ParameterList params{Param("var", ty.i32())};
|
utils::Vector params{Param("var", ty.i32())};
|
||||||
|
|
||||||
auto* f = Func(Source{Source::Location{20, 2}}, "func", params, ty.void_(), {});
|
auto* f = Func(Source{Source::Location{20, 2}}, "func", params, ty.void_(), utils::Empty);
|
||||||
auto src = f->source;
|
auto src = f->source;
|
||||||
EXPECT_EQ(src.range.begin.line, 20u);
|
EXPECT_EQ(src.range.begin.line, 20u);
|
||||||
EXPECT_EQ(src.range.begin.column, 2u);
|
EXPECT_EQ(src.range.begin.column, 2u);
|
||||||
|
@ -49,7 +49,7 @@ TEST_F(FunctionTest, Assert_InvalidName) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
b.Func("", {}, b.ty.void_(), {});
|
b.Func("", utils::Empty, b.ty.void_(), utils::Empty);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -58,20 +58,20 @@ TEST_F(FunctionTest, Assert_Null_ReturnType) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
b.Func("f", {}, nullptr, {});
|
b.Func("f", utils::Empty, nullptr, utils::Empty);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FunctionTest, Assert_Null_Param) {
|
TEST_F(FunctionTest, Assert_Null_Param) {
|
||||||
|
using ParamList = utils::Vector<const ast::Parameter*, 2>;
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
ParameterList params;
|
ParamList params;
|
||||||
params.push_back(b.Param("var", b.ty.i32()));
|
params.Push(b.Param("var", b.ty.i32()));
|
||||||
params.push_back(nullptr);
|
params.Push(nullptr);
|
||||||
|
b.Func("f", params, b.ty.void_(), utils::Empty);
|
||||||
b.Func("f", params, b.ty.void_(), {});
|
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ TEST_F(FunctionTest, Assert_DifferentProgramID_Symbol) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.Func(b2.Sym("func"), {}, b1.ty.void_(), {});
|
b1.Func(b2.Sym("func"), utils::Empty, b1.ty.void_(), utils::Empty);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,11 @@ TEST_F(FunctionTest, Assert_DifferentProgramID_Param) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.Func("func", {b2.Param("var", b2.ty.i32())}, b1.ty.void_(), {});
|
b1.Func("func",
|
||||||
|
utils::Vector{
|
||||||
|
b2.Param("var", b2.ty.i32()),
|
||||||
|
},
|
||||||
|
b1.ty.void_(), utils::Empty);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -101,8 +105,8 @@ TEST_F(FunctionTest, Assert_DifferentProgramID_Attr) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.Func("func", {}, b1.ty.void_(), {},
|
b1.Func("func", utils::Empty, b1.ty.void_(), utils::Empty,
|
||||||
{
|
utils::Vector{
|
||||||
b2.WorkgroupSize(2_i, 4_i, 6_i),
|
b2.WorkgroupSize(2_i, 4_i, 6_i),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -114,8 +118,8 @@ TEST_F(FunctionTest, Assert_DifferentProgramID_ReturnAttr) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.Func("func", {}, b1.ty.void_(), {}, {},
|
b1.Func("func", utils::Empty, b1.ty.void_(), utils::Empty, utils::Empty,
|
||||||
{
|
utils::Vector{
|
||||||
b2.WorkgroupSize(2_i, 4_i, 6_i),
|
b2.WorkgroupSize(2_i, 4_i, 6_i),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -125,7 +129,7 @@ TEST_F(FunctionTest, Assert_DifferentProgramID_ReturnAttr) {
|
||||||
using FunctionListTest = TestHelper;
|
using FunctionListTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(FunctionListTest, FindSymbol) {
|
TEST_F(FunctionListTest, FindSymbol) {
|
||||||
auto* func = Func("main", {}, ty.f32(), {});
|
auto* func = Func("main", utils::Empty, ty.f32(), utils::Empty);
|
||||||
FunctionList list;
|
FunctionList list;
|
||||||
list.Add(func);
|
list.Add(func);
|
||||||
EXPECT_EQ(func, list.Find(Symbols().Register("main")));
|
EXPECT_EQ(func, list.Find(Symbols().Register("main")));
|
||||||
|
@ -137,12 +141,12 @@ TEST_F(FunctionListTest, FindSymbolMissing) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FunctionListTest, FindSymbolStage) {
|
TEST_F(FunctionListTest, FindSymbolStage) {
|
||||||
auto* fs = Func("main", {}, ty.f32(), {},
|
auto* fs = Func("main", utils::Empty, ty.f32(), utils::Empty,
|
||||||
{
|
utils::Vector{
|
||||||
Stage(PipelineStage::kFragment),
|
Stage(PipelineStage::kFragment),
|
||||||
});
|
});
|
||||||
auto* vs = Func("main", {}, ty.f32(), {},
|
auto* vs = Func("main", utils::Empty, ty.f32(), utils::Empty,
|
||||||
{
|
utils::Vector{
|
||||||
Stage(PipelineStage::kVertex),
|
Stage(PipelineStage::kVertex),
|
||||||
});
|
});
|
||||||
FunctionList list;
|
FunctionList list;
|
||||||
|
@ -154,8 +158,8 @@ TEST_F(FunctionListTest, FindSymbolStage) {
|
||||||
|
|
||||||
TEST_F(FunctionListTest, FindSymbolStageMissing) {
|
TEST_F(FunctionListTest, FindSymbolStageMissing) {
|
||||||
FunctionList list;
|
FunctionList list;
|
||||||
list.Add(Func("main", {}, ty.f32(), {},
|
list.Add(Func("main", utils::Empty, ty.f32(), utils::Empty,
|
||||||
{
|
utils::Vector{
|
||||||
Stage(PipelineStage::kFragment),
|
Stage(PipelineStage::kFragment),
|
||||||
}));
|
}));
|
||||||
EXPECT_EQ(nullptr, list.Find(Symbols().Register("main"), PipelineStage::kVertex));
|
EXPECT_EQ(nullptr, list.Find(Symbols().Register("main"), PipelineStage::kVertex));
|
||||||
|
@ -163,8 +167,8 @@ TEST_F(FunctionListTest, FindSymbolStageMissing) {
|
||||||
|
|
||||||
TEST_F(FunctionListTest, HasStage) {
|
TEST_F(FunctionListTest, HasStage) {
|
||||||
FunctionList list;
|
FunctionList list;
|
||||||
list.Add(Func("main", {}, ty.f32(), {},
|
list.Add(Func("main", utils::Empty, ty.f32(), utils::Empty,
|
||||||
{
|
utils::Vector{
|
||||||
Stage(PipelineStage::kFragment),
|
Stage(PipelineStage::kFragment),
|
||||||
}));
|
}));
|
||||||
EXPECT_TRUE(list.HasStage(PipelineStage::kFragment));
|
EXPECT_TRUE(list.HasStage(PipelineStage::kFragment));
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "src/tint/ast/let.h"
|
#include "src/tint/ast/let.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "src/tint/program_builder.h"
|
#include "src/tint/program_builder.h"
|
||||||
|
|
||||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::Let);
|
TINT_INSTANTIATE_TYPEINFO(tint::ast::Let);
|
||||||
|
@ -26,8 +28,8 @@ Let::Let(ProgramID pid,
|
||||||
const Symbol& sym,
|
const Symbol& sym,
|
||||||
const ast::Type* ty,
|
const ast::Type* ty,
|
||||||
const Expression* ctor,
|
const Expression* ctor,
|
||||||
AttributeList attrs)
|
utils::VectorRef<const Attribute*> attrs)
|
||||||
: Base(pid, nid, src, sym, ty, ctor, attrs) {
|
: Base(pid, nid, src, sym, ty, ctor, std::move(attrs)) {
|
||||||
TINT_ASSERT(AST, ctor != nullptr);
|
TINT_ASSERT(AST, ctor != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +47,7 @@ const Let* Let::Clone(CloneContext* ctx) const {
|
||||||
auto* ty = ctx->Clone(type);
|
auto* ty = ctx->Clone(type);
|
||||||
auto* ctor = ctx->Clone(constructor);
|
auto* ctor = ctx->Clone(constructor);
|
||||||
auto attrs = ctx->Clone(attributes);
|
auto attrs = ctx->Clone(attributes);
|
||||||
return ctx->dst->create<Let>(src, sym, ty, ctor, attrs);
|
return ctx->dst->create<Let>(src, sym, ty, ctor, std::move(attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -43,7 +43,7 @@ class Let final : public Castable<Let, Variable> {
|
||||||
const Symbol& sym,
|
const Symbol& sym,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
const Expression* constructor,
|
const Expression* constructor,
|
||||||
AttributeList attributes);
|
utils::VectorRef<const Attribute*> attributes);
|
||||||
|
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
Let(Let&&);
|
Let(Let&&);
|
||||||
|
|
|
@ -31,9 +31,9 @@ TEST_F(LoopStatementTest, Creation) {
|
||||||
auto* continuing = Block(create<DiscardStatement>());
|
auto* continuing = Block(create<DiscardStatement>());
|
||||||
|
|
||||||
auto* l = create<LoopStatement>(body, continuing);
|
auto* l = create<LoopStatement>(body, continuing);
|
||||||
ASSERT_EQ(l->body->statements.size(), 1u);
|
ASSERT_EQ(l->body->statements.Length(), 1u);
|
||||||
EXPECT_EQ(l->body->statements[0], b);
|
EXPECT_EQ(l->body->statements[0], b);
|
||||||
ASSERT_EQ(l->continuing->statements.size(), 1u);
|
ASSERT_EQ(l->continuing->statements.Length(), 1u);
|
||||||
EXPECT_EQ(l->continuing->statements[0], continuing->Last());
|
EXPECT_EQ(l->continuing->statements[0], continuing->Last());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ Module::Module(ProgramID pid, NodeID nid, const Source& src) : Base(pid, nid, sr
|
||||||
Module::Module(ProgramID pid,
|
Module::Module(ProgramID pid,
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
std::vector<const ast::Node*> global_decls)
|
utils::VectorRef<const ast::Node*> global_decls)
|
||||||
: Base(pid, nid, src), global_declarations_(std::move(global_decls)) {
|
: Base(pid, nid, src), global_declarations_(std::move(global_decls)) {
|
||||||
for (auto* decl : global_declarations_) {
|
for (auto* decl : global_declarations_) {
|
||||||
if (decl == nullptr) {
|
if (decl == nullptr) {
|
||||||
|
@ -53,7 +53,7 @@ const ast::TypeDecl* Module::LookupType(Symbol name) const {
|
||||||
void Module::AddGlobalDeclaration(const tint::ast::Node* decl) {
|
void Module::AddGlobalDeclaration(const tint::ast::Node* decl) {
|
||||||
diag::List diags;
|
diag::List diags;
|
||||||
BinGlobalDeclaration(decl, diags);
|
BinGlobalDeclaration(decl, diags);
|
||||||
global_declarations_.emplace_back(decl);
|
global_declarations_.Push(decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::BinGlobalDeclaration(const tint::ast::Node* decl, diag::List& diags) {
|
void Module::BinGlobalDeclaration(const tint::ast::Node* decl, diag::List& diags) {
|
||||||
|
@ -61,19 +61,19 @@ void Module::BinGlobalDeclaration(const tint::ast::Node* decl, diag::List& diags
|
||||||
decl, //
|
decl, //
|
||||||
[&](const ast::TypeDecl* type) {
|
[&](const ast::TypeDecl* type) {
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
|
||||||
type_decls_.push_back(type);
|
type_decls_.Push(type);
|
||||||
},
|
},
|
||||||
[&](const Function* func) {
|
[&](const Function* func) {
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id);
|
||||||
functions_.push_back(func);
|
functions_.Push(func);
|
||||||
},
|
},
|
||||||
[&](const Variable* var) {
|
[&](const Variable* var) {
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id);
|
||||||
global_variables_.push_back(var);
|
global_variables_.Push(var);
|
||||||
},
|
},
|
||||||
[&](const Enable* enable) {
|
[&](const Enable* enable) {
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, enable, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, enable, program_id);
|
||||||
enables_.push_back(enable);
|
enables_.Push(enable);
|
||||||
},
|
},
|
||||||
[&](Default) { TINT_ICE(AST, diags) << "Unknown global declaration type"; });
|
[&](Default) { TINT_ICE(AST, diags) << "Unknown global declaration type"; });
|
||||||
}
|
}
|
||||||
|
@ -81,29 +81,29 @@ void Module::BinGlobalDeclaration(const tint::ast::Node* decl, diag::List& diags
|
||||||
void Module::AddEnable(const ast::Enable* enable) {
|
void Module::AddEnable(const ast::Enable* enable) {
|
||||||
TINT_ASSERT(AST, enable);
|
TINT_ASSERT(AST, enable);
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, enable, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, enable, program_id);
|
||||||
global_declarations_.push_back(enable);
|
global_declarations_.Push(enable);
|
||||||
enables_.push_back(enable);
|
enables_.Push(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::AddGlobalVariable(const ast::Variable* var) {
|
void Module::AddGlobalVariable(const ast::Variable* var) {
|
||||||
TINT_ASSERT(AST, var);
|
TINT_ASSERT(AST, var);
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id);
|
||||||
global_variables_.push_back(var);
|
global_variables_.Push(var);
|
||||||
global_declarations_.push_back(var);
|
global_declarations_.Push(var);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::AddTypeDecl(const ast::TypeDecl* type) {
|
void Module::AddTypeDecl(const ast::TypeDecl* type) {
|
||||||
TINT_ASSERT(AST, type);
|
TINT_ASSERT(AST, type);
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
|
||||||
type_decls_.push_back(type);
|
type_decls_.Push(type);
|
||||||
global_declarations_.push_back(type);
|
global_declarations_.Push(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::AddFunction(const ast::Function* func) {
|
void Module::AddFunction(const ast::Function* func) {
|
||||||
TINT_ASSERT(AST, func);
|
TINT_ASSERT(AST, func);
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id);
|
||||||
functions_.push_back(func);
|
functions_.Push(func);
|
||||||
global_declarations_.push_back(func);
|
global_declarations_.Push(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Module* Module::Clone(CloneContext* ctx) const {
|
const Module* Module::Clone(CloneContext* ctx) const {
|
||||||
|
@ -117,10 +117,10 @@ void Module::Copy(CloneContext* ctx, const Module* src) {
|
||||||
|
|
||||||
// During the clone, declarations may have been placed into the module.
|
// During the clone, declarations may have been placed into the module.
|
||||||
// Clear everything out, as we're about to re-bin the declarations.
|
// Clear everything out, as we're about to re-bin the declarations.
|
||||||
type_decls_.clear();
|
type_decls_.Clear();
|
||||||
functions_.clear();
|
functions_.Clear();
|
||||||
global_variables_.clear();
|
global_variables_.Clear();
|
||||||
enables_.clear();
|
enables_.Clear();
|
||||||
|
|
||||||
for (auto* decl : global_declarations_) {
|
for (auto* decl : global_declarations_) {
|
||||||
if (!decl) {
|
if (!decl) {
|
||||||
|
|
|
@ -16,11 +16,11 @@
|
||||||
#define SRC_TINT_AST_MODULE_H_
|
#define SRC_TINT_AST_MODULE_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "src/tint/ast/enable.h"
|
#include "src/tint/ast/enable.h"
|
||||||
#include "src/tint/ast/function.h"
|
#include "src/tint/ast/function.h"
|
||||||
#include "src/tint/ast/type.h"
|
#include "src/tint/ast/type.h"
|
||||||
|
#include "src/tint/utils/vector.h"
|
||||||
|
|
||||||
namespace tint::ast {
|
namespace tint::ast {
|
||||||
|
|
||||||
|
@ -42,13 +42,16 @@ class Module final : public Castable<Module, Node> {
|
||||||
/// @param src the source of this node
|
/// @param src the source of this node
|
||||||
/// @param global_decls the list of global types, functions, and variables, in
|
/// @param global_decls the list of global types, functions, and variables, in
|
||||||
/// the order they were declared in the source program
|
/// the order they were declared in the source program
|
||||||
Module(ProgramID pid, NodeID nid, const Source& src, std::vector<const Node*> global_decls);
|
Module(ProgramID pid,
|
||||||
|
NodeID nid,
|
||||||
|
const Source& src,
|
||||||
|
utils::VectorRef<const ast::Node*> global_decls);
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~Module() override;
|
~Module() override;
|
||||||
|
|
||||||
/// @returns the declaration-ordered global declarations for the module
|
/// @returns the declaration-ordered global declarations for the module
|
||||||
const std::vector<const Node*>& GlobalDeclarations() const { return global_declarations_; }
|
const auto& GlobalDeclarations() const { return global_declarations_; }
|
||||||
|
|
||||||
/// Add a enable directive to the Builder
|
/// Add a enable directive to the Builder
|
||||||
/// @param ext the enable directive to add
|
/// @param ext the enable directive to add
|
||||||
|
@ -74,26 +77,26 @@ class Module final : public Castable<Module, Node> {
|
||||||
void AddGlobalDeclaration(const tint::ast::Node* decl);
|
void AddGlobalDeclaration(const tint::ast::Node* decl);
|
||||||
|
|
||||||
/// @returns the global variables for the module
|
/// @returns the global variables for the module
|
||||||
const VariableList& GlobalVariables() const { return global_variables_; }
|
const auto& GlobalVariables() const { return global_variables_; }
|
||||||
|
|
||||||
/// @returns the global variables for the module
|
/// @returns the global variables for the module
|
||||||
VariableList& GlobalVariables() { return global_variables_; }
|
auto& GlobalVariables() { return global_variables_; }
|
||||||
|
|
||||||
/// @returns the global variable declarations of kind 'T' for the module
|
/// @returns the global variable declarations of kind 'T' for the module
|
||||||
template <typename T, typename = traits::EnableIfIsType<T, ast::Variable>>
|
template <typename T, typename = traits::EnableIfIsType<T, ast::Variable>>
|
||||||
std::vector<const T*> Globals() const {
|
auto Globals() const {
|
||||||
std::vector<const T*> out;
|
utils::Vector<const T*, 32> out;
|
||||||
out.reserve(global_variables_.size());
|
out.Reserve(global_variables_.Length());
|
||||||
for (auto* global : global_variables_) {
|
for (auto* global : global_variables_) {
|
||||||
if (auto* var = global->As<T>()) {
|
if (auto* var = global->As<T>()) {
|
||||||
out.emplace_back(var);
|
out.Push(var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns the extension set for the module
|
/// @returns the extension set for the module
|
||||||
const EnableList& Enables() const { return enables_; }
|
const auto& Enables() const { return enables_; }
|
||||||
|
|
||||||
/// Adds a type declaration to the Builder.
|
/// Adds a type declaration to the Builder.
|
||||||
/// @param decl the type declaration to add
|
/// @param decl the type declaration to add
|
||||||
|
@ -104,7 +107,7 @@ class Module final : public Castable<Module, Node> {
|
||||||
const TypeDecl* LookupType(Symbol name) const;
|
const TypeDecl* LookupType(Symbol name) const;
|
||||||
|
|
||||||
/// @returns the declared types in the module
|
/// @returns the declared types in the module
|
||||||
const std::vector<const TypeDecl*>& TypeDecls() const { return type_decls_; }
|
const auto& TypeDecls() const { return type_decls_; }
|
||||||
|
|
||||||
/// Add a function to the Builder
|
/// Add a function to the Builder
|
||||||
/// @param func the function to add
|
/// @param func the function to add
|
||||||
|
@ -131,11 +134,11 @@ class Module final : public Castable<Module, Node> {
|
||||||
/// * #functions_
|
/// * #functions_
|
||||||
void BinGlobalDeclaration(const tint::ast::Node* decl, diag::List& diags);
|
void BinGlobalDeclaration(const tint::ast::Node* decl, diag::List& diags);
|
||||||
|
|
||||||
std::vector<const Node*> global_declarations_;
|
utils::Vector<const Node*, 64> global_declarations_;
|
||||||
std::vector<const TypeDecl*> type_decls_;
|
utils::Vector<const TypeDecl*, 16> type_decls_;
|
||||||
FunctionList functions_;
|
FunctionList functions_;
|
||||||
VariableList global_variables_;
|
utils::Vector<const Variable*, 32> global_variables_;
|
||||||
EnableList enables_;
|
utils::Vector<const Enable*, 8> enables_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace {
|
||||||
using ModuleTest = TestHelper;
|
using ModuleTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(ModuleTest, Creation) {
|
TEST_F(ModuleTest, Creation) {
|
||||||
EXPECT_EQ(Program(std::move(*this)).AST().Functions().size(), 0u);
|
EXPECT_EQ(Program(std::move(*this)).AST().Functions().Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ModuleTest, LookupFunction) {
|
TEST_F(ModuleTest, LookupFunction) {
|
||||||
|
@ -61,8 +61,8 @@ TEST_F(ModuleTest, Assert_DifferentProgramID_Function) {
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.AST().AddFunction(b2.create<ast::Function>(b2.Symbols().Register("func"),
|
b1.AST().AddFunction(b2.create<ast::Function>(b2.Symbols().Register("func"),
|
||||||
ParameterList{}, b2.ty.f32(), b2.Block(),
|
utils::Empty, b2.ty.f32(), b2.Block(),
|
||||||
AttributeList{}, AttributeList{}));
|
utils::Empty, utils::Empty));
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ TEST_F(ModuleTest, CloneOrder) {
|
||||||
ctx.Clone();
|
ctx.Clone();
|
||||||
|
|
||||||
auto& decls = cloned.AST().GlobalDeclarations();
|
auto& decls = cloned.AST().GlobalDeclarations();
|
||||||
ASSERT_EQ(decls.size(), 6u);
|
ASSERT_EQ(decls.Length(), 6u);
|
||||||
EXPECT_TRUE(decls[1]->Is<ast::Function>());
|
EXPECT_TRUE(decls[1]->Is<ast::Function>());
|
||||||
EXPECT_TRUE(decls[3]->Is<ast::Alias>());
|
EXPECT_TRUE(decls[3]->Is<ast::Alias>());
|
||||||
EXPECT_TRUE(decls[5]->Is<ast::Variable>());
|
EXPECT_TRUE(decls[5]->Is<ast::Variable>());
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "src/tint/ast/override.h"
|
#include "src/tint/ast/override.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "src/tint/program_builder.h"
|
#include "src/tint/program_builder.h"
|
||||||
|
|
||||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::Override);
|
TINT_INSTANTIATE_TYPEINFO(tint::ast::Override);
|
||||||
|
@ -26,8 +28,8 @@ Override::Override(ProgramID pid,
|
||||||
const Symbol& sym,
|
const Symbol& sym,
|
||||||
const ast::Type* ty,
|
const ast::Type* ty,
|
||||||
const Expression* ctor,
|
const Expression* ctor,
|
||||||
AttributeList attrs)
|
utils::VectorRef<const Attribute*> attrs)
|
||||||
: Base(pid, nid, src, sym, ty, ctor, attrs) {}
|
: Base(pid, nid, src, sym, ty, ctor, std::move(attrs)) {}
|
||||||
|
|
||||||
Override::Override(Override&&) = default;
|
Override::Override(Override&&) = default;
|
||||||
|
|
||||||
|
@ -43,7 +45,7 @@ const Override* Override::Clone(CloneContext* ctx) const {
|
||||||
auto* ty = ctx->Clone(type);
|
auto* ty = ctx->Clone(type);
|
||||||
auto* ctor = ctx->Clone(constructor);
|
auto* ctor = ctx->Clone(constructor);
|
||||||
auto attrs = ctx->Clone(attributes);
|
auto attrs = ctx->Clone(attributes);
|
||||||
return ctx->dst->create<Override>(src, sym, ty, ctor, attrs);
|
return ctx->dst->create<Override>(src, sym, ty, ctor, std::move(attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Override::Identifier(const SymbolTable& symbols) const {
|
std::string Override::Identifier(const SymbolTable& symbols) const {
|
||||||
|
|
|
@ -46,7 +46,7 @@ class Override final : public Castable<Override, Variable> {
|
||||||
const Symbol& sym,
|
const Symbol& sym,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
const Expression* constructor,
|
const Expression* constructor,
|
||||||
AttributeList attributes);
|
utils::VectorRef<const Attribute*> attributes);
|
||||||
|
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
Override(Override&&);
|
Override(Override&&);
|
||||||
|
|
|
@ -27,7 +27,7 @@ TEST_F(OverrideTest, Identifier_NoId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(OverrideTest, Identifier_WithId) {
|
TEST_F(OverrideTest, Identifier_WithId) {
|
||||||
auto* o = Override("o", nullptr, Expr(f32(1.0)), {Id(4u)});
|
auto* o = Override("o", nullptr, Expr(f32(1.0)), utils::Vector{Id(4u)});
|
||||||
EXPECT_EQ(std::string("4"), o->Identifier(Symbols()));
|
EXPECT_EQ(std::string("4"), o->Identifier(Symbols()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "src/tint/ast/parameter.h"
|
#include "src/tint/ast/parameter.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "src/tint/program_builder.h"
|
#include "src/tint/program_builder.h"
|
||||||
|
|
||||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::Parameter);
|
TINT_INSTANTIATE_TYPEINFO(tint::ast::Parameter);
|
||||||
|
@ -25,8 +27,8 @@ Parameter::Parameter(ProgramID pid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
const Symbol& sym,
|
const Symbol& sym,
|
||||||
const ast::Type* ty,
|
const ast::Type* ty,
|
||||||
AttributeList attrs)
|
utils::VectorRef<const Attribute*> attrs)
|
||||||
: Base(pid, nid, src, sym, ty, nullptr, attrs) {}
|
: Base(pid, nid, src, sym, ty, nullptr, std::move(attrs)) {}
|
||||||
|
|
||||||
Parameter::Parameter(Parameter&&) = default;
|
Parameter::Parameter(Parameter&&) = default;
|
||||||
|
|
||||||
|
@ -41,7 +43,7 @@ const Parameter* Parameter::Clone(CloneContext* ctx) const {
|
||||||
auto sym = ctx->Clone(symbol);
|
auto sym = ctx->Clone(symbol);
|
||||||
auto* ty = ctx->Clone(type);
|
auto* ty = ctx->Clone(type);
|
||||||
auto attrs = ctx->Clone(attributes);
|
auto attrs = ctx->Clone(attributes);
|
||||||
return ctx->dst->create<Parameter>(src, sym, ty, attrs);
|
return ctx->dst->create<Parameter>(src, sym, ty, std::move(attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -45,7 +45,7 @@ class Parameter final : public Castable<Parameter, Variable> {
|
||||||
const Source& source,
|
const Source& source,
|
||||||
const Symbol& sym,
|
const Symbol& sym,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
AttributeList attributes);
|
utils::VectorRef<const Attribute*> attributes);
|
||||||
|
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
Parameter(Parameter&&);
|
Parameter(Parameter&&);
|
||||||
|
@ -63,9 +63,6 @@ class Parameter final : public Castable<Parameter, Variable> {
|
||||||
const Parameter* Clone(CloneContext* ctx) const override;
|
const Parameter* Clone(CloneContext* ctx) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A list of parameters
|
|
||||||
using ParameterList = std::vector<const Parameter*>;
|
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
||||||
#endif // SRC_TINT_AST_PARAMETER_H_
|
#endif // SRC_TINT_AST_PARAMETER_H_
|
||||||
|
|
|
@ -39,9 +39,6 @@ class Statement : public Castable<Statement, Node> {
|
||||||
Statement(Statement&&);
|
Statement(Statement&&);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A list of statements
|
|
||||||
using StatementList = std::vector<const Statement*>;
|
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
||||||
#endif // SRC_TINT_AST_STATEMENT_H_
|
#endif // SRC_TINT_AST_STATEMENT_H_
|
||||||
|
|
|
@ -26,8 +26,8 @@ Struct::Struct(ProgramID pid,
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
Symbol n,
|
Symbol n,
|
||||||
StructMemberList m,
|
utils::VectorRef<const ast::StructMember*> m,
|
||||||
AttributeList attrs)
|
utils::VectorRef<const ast::Attribute*> attrs)
|
||||||
: Base(pid, nid, src, n), members(std::move(m)), attributes(std::move(attrs)) {
|
: Base(pid, nid, src, n), members(std::move(m)), attributes(std::move(attrs)) {
|
||||||
for (auto* mem : members) {
|
for (auto* mem : members) {
|
||||||
TINT_ASSERT(AST, mem);
|
TINT_ASSERT(AST, mem);
|
||||||
|
@ -49,7 +49,7 @@ const Struct* Struct::Clone(CloneContext* ctx) const {
|
||||||
auto n = ctx->Clone(name);
|
auto n = ctx->Clone(name);
|
||||||
auto mem = ctx->Clone(members);
|
auto mem = ctx->Clone(members);
|
||||||
auto attrs = ctx->Clone(attributes);
|
auto attrs = ctx->Clone(attributes);
|
||||||
return ctx->dst->create<Struct>(src, n, mem, attrs);
|
return ctx->dst->create<Struct>(src, n, std::move(mem), std::move(attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "src/tint/ast/attribute.h"
|
#include "src/tint/ast/attribute.h"
|
||||||
#include "src/tint/ast/struct_member.h"
|
#include "src/tint/ast/struct_member.h"
|
||||||
#include "src/tint/ast/type_decl.h"
|
#include "src/tint/ast/type_decl.h"
|
||||||
|
#include "src/tint/utils/vector.h"
|
||||||
|
|
||||||
namespace tint::ast {
|
namespace tint::ast {
|
||||||
|
|
||||||
|
@ -38,8 +39,8 @@ class Struct final : public Castable<Struct, TypeDecl> {
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
Symbol name,
|
Symbol name,
|
||||||
StructMemberList members,
|
utils::VectorRef<const ast::StructMember*> members,
|
||||||
AttributeList attributes);
|
utils::VectorRef<const ast::Attribute*> attributes);
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
Struct(Struct&&);
|
Struct(Struct&&);
|
||||||
|
|
||||||
|
@ -52,10 +53,10 @@ class Struct final : public Castable<Struct, TypeDecl> {
|
||||||
const Struct* Clone(CloneContext* ctx) const override;
|
const Struct* Clone(CloneContext* ctx) const override;
|
||||||
|
|
||||||
/// The members
|
/// The members
|
||||||
const StructMemberList members;
|
const utils::Vector<const ast::StructMember*, 8> members;
|
||||||
|
|
||||||
/// The struct attributes
|
/// The struct attributes
|
||||||
const AttributeList attributes;
|
const utils::Vector<const ast::Attribute*, 4> attributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -25,7 +25,7 @@ StructMember::StructMember(ProgramID pid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
const Symbol& sym,
|
const Symbol& sym,
|
||||||
const ast::Type* ty,
|
const ast::Type* ty,
|
||||||
AttributeList attrs)
|
utils::VectorRef<const Attribute*> attrs)
|
||||||
: Base(pid, nid, src), symbol(sym), type(ty), attributes(std::move(attrs)) {
|
: Base(pid, nid, src), symbol(sym), type(ty), attributes(std::move(attrs)) {
|
||||||
TINT_ASSERT(AST, type);
|
TINT_ASSERT(AST, type);
|
||||||
TINT_ASSERT(AST, symbol.IsValid());
|
TINT_ASSERT(AST, symbol.IsValid());
|
||||||
|
@ -46,7 +46,7 @@ const StructMember* StructMember::Clone(CloneContext* ctx) const {
|
||||||
auto sym = ctx->Clone(symbol);
|
auto sym = ctx->Clone(symbol);
|
||||||
auto* ty = ctx->Clone(type);
|
auto* ty = ctx->Clone(type);
|
||||||
auto attrs = ctx->Clone(attributes);
|
auto attrs = ctx->Clone(attributes);
|
||||||
return ctx->dst->create<StructMember>(src, sym, ty, attrs);
|
return ctx->dst->create<StructMember>(src, sym, ty, std::move(attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#define SRC_TINT_AST_STRUCT_MEMBER_H_
|
#define SRC_TINT_AST_STRUCT_MEMBER_H_
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "src/tint/ast/attribute.h"
|
#include "src/tint/ast/attribute.h"
|
||||||
|
|
||||||
|
@ -42,7 +41,7 @@ class StructMember final : public Castable<StructMember, Node> {
|
||||||
const Source& src,
|
const Source& src,
|
||||||
const Symbol& sym,
|
const Symbol& sym,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
AttributeList attributes);
|
utils::VectorRef<const Attribute*> attributes);
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
StructMember(StructMember&&);
|
StructMember(StructMember&&);
|
||||||
|
|
||||||
|
@ -61,12 +60,9 @@ class StructMember final : public Castable<StructMember, Node> {
|
||||||
const ast::Type* const type;
|
const ast::Type* const type;
|
||||||
|
|
||||||
/// The attributes
|
/// The attributes
|
||||||
const AttributeList attributes;
|
const utils::Vector<const Attribute*, 4> attributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A list of struct members
|
|
||||||
using StructMemberList = std::vector<const StructMember*>;
|
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
||||||
#endif // SRC_TINT_AST_STRUCT_MEMBER_H_
|
#endif // SRC_TINT_AST_STRUCT_MEMBER_H_
|
||||||
|
|
|
@ -21,10 +21,10 @@ namespace {
|
||||||
using StructMemberTest = TestHelper;
|
using StructMemberTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(StructMemberTest, Creation) {
|
TEST_F(StructMemberTest, Creation) {
|
||||||
auto* st = Member("a", ty.i32(), {MemberSize(4)});
|
auto* st = Member("a", ty.i32(), utils::Vector{MemberSize(4)});
|
||||||
EXPECT_EQ(st->symbol, Symbol(1, ID()));
|
EXPECT_EQ(st->symbol, Symbol(1, ID()));
|
||||||
EXPECT_TRUE(st->type->Is<ast::I32>());
|
EXPECT_TRUE(st->type->Is<ast::I32>());
|
||||||
EXPECT_EQ(st->attributes.size(), 1u);
|
EXPECT_EQ(st->attributes.Length(), 1u);
|
||||||
EXPECT_TRUE(st->attributes[0]->Is<StructMemberSizeAttribute>());
|
EXPECT_TRUE(st->attributes[0]->Is<StructMemberSizeAttribute>());
|
||||||
EXPECT_EQ(st->source.range.begin.line, 0u);
|
EXPECT_EQ(st->source.range.begin.line, 0u);
|
||||||
EXPECT_EQ(st->source.range.begin.column, 0u);
|
EXPECT_EQ(st->source.range.begin.column, 0u);
|
||||||
|
@ -37,7 +37,7 @@ TEST_F(StructMemberTest, CreationWithSource) {
|
||||||
ty.i32());
|
ty.i32());
|
||||||
EXPECT_EQ(st->symbol, Symbol(1, ID()));
|
EXPECT_EQ(st->symbol, Symbol(1, ID()));
|
||||||
EXPECT_TRUE(st->type->Is<ast::I32>());
|
EXPECT_TRUE(st->type->Is<ast::I32>());
|
||||||
EXPECT_EQ(st->attributes.size(), 0u);
|
EXPECT_EQ(st->attributes.Length(), 0u);
|
||||||
EXPECT_EQ(st->source.range.begin.line, 27u);
|
EXPECT_EQ(st->source.range.begin.line, 27u);
|
||||||
EXPECT_EQ(st->source.range.begin.column, 4u);
|
EXPECT_EQ(st->source.range.begin.column, 4u);
|
||||||
EXPECT_EQ(st->source.range.end.line, 27u);
|
EXPECT_EQ(st->source.range.end.line, 27u);
|
||||||
|
@ -66,7 +66,7 @@ TEST_F(StructMemberTest, Assert_Null_Attribute) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
b.Member("a", b.ty.i32(), {b.MemberSize(4), nullptr});
|
b.Member("a", b.ty.i32(), utils::Vector{b.MemberSize(4), nullptr});
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ TEST_F(StructMemberTest, Assert_DifferentProgramID_Symbol) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.Member(b2.Sym("a"), b1.ty.i32(), {b1.MemberSize(4)});
|
b1.Member(b2.Sym("a"), b1.ty.i32(), utils::Vector{b1.MemberSize(4)});
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ TEST_F(StructMemberTest, Assert_DifferentProgramID_Attribute) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.Member("a", b1.ty.i32(), {b2.MemberSize(4)});
|
b1.Member("a", b1.ty.i32(), utils::Vector{b2.MemberSize(4)});
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,10 +36,10 @@ using SpirvBlockAttribute = transform::AddSpirvBlockAttribute::SpirvBlockAttribu
|
||||||
|
|
||||||
TEST_F(AstStructTest, Creation) {
|
TEST_F(AstStructTest, Creation) {
|
||||||
auto name = Sym("s");
|
auto name = Sym("s");
|
||||||
auto* s = create<Struct>(name, StructMemberList{Member("a", ty.i32())}, AttributeList{});
|
auto* s = create<Struct>(name, utils::Vector{Member("a", ty.i32())}, utils::Empty);
|
||||||
EXPECT_EQ(s->name, name);
|
EXPECT_EQ(s->name, name);
|
||||||
EXPECT_EQ(s->members.size(), 1u);
|
EXPECT_EQ(s->members.Length(), 1u);
|
||||||
EXPECT_TRUE(s->attributes.empty());
|
EXPECT_TRUE(s->attributes.IsEmpty());
|
||||||
EXPECT_EQ(s->source.range.begin.line, 0u);
|
EXPECT_EQ(s->source.range.begin.line, 0u);
|
||||||
EXPECT_EQ(s->source.range.begin.column, 0u);
|
EXPECT_EQ(s->source.range.begin.column, 0u);
|
||||||
EXPECT_EQ(s->source.range.end.line, 0u);
|
EXPECT_EQ(s->source.range.end.line, 0u);
|
||||||
|
@ -48,13 +48,14 @@ TEST_F(AstStructTest, Creation) {
|
||||||
|
|
||||||
TEST_F(AstStructTest, Creation_WithAttributes) {
|
TEST_F(AstStructTest, Creation_WithAttributes) {
|
||||||
auto name = Sym("s");
|
auto name = Sym("s");
|
||||||
AttributeList attrs;
|
|
||||||
attrs.push_back(ASTNodes().Create<SpirvBlockAttribute>(ID(), AllocateNodeID()));
|
|
||||||
|
|
||||||
auto* s = create<Struct>(name, StructMemberList{Member("a", ty.i32())}, attrs);
|
auto* s = create<Struct>(name, utils::Vector{Member("a", ty.i32())},
|
||||||
|
utils::Vector{
|
||||||
|
ASTNodes().Create<SpirvBlockAttribute>(ID(), AllocateNodeID()),
|
||||||
|
});
|
||||||
EXPECT_EQ(s->name, name);
|
EXPECT_EQ(s->name, name);
|
||||||
EXPECT_EQ(s->members.size(), 1u);
|
EXPECT_EQ(s->members.Length(), 1u);
|
||||||
ASSERT_EQ(s->attributes.size(), 1u);
|
ASSERT_EQ(s->attributes.Length(), 1u);
|
||||||
EXPECT_TRUE(s->attributes[0]->Is<SpirvBlockAttribute>());
|
EXPECT_TRUE(s->attributes[0]->Is<SpirvBlockAttribute>());
|
||||||
EXPECT_EQ(s->source.range.begin.line, 0u);
|
EXPECT_EQ(s->source.range.begin.line, 0u);
|
||||||
EXPECT_EQ(s->source.range.begin.column, 0u);
|
EXPECT_EQ(s->source.range.begin.column, 0u);
|
||||||
|
@ -66,11 +67,11 @@ TEST_F(AstStructTest, CreationWithSourceAndAttributes) {
|
||||||
auto name = Sym("s");
|
auto name = Sym("s");
|
||||||
auto* s = create<Struct>(
|
auto* s = create<Struct>(
|
||||||
Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 8}}}, name,
|
Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 8}}}, name,
|
||||||
StructMemberList{Member("a", ty.i32())},
|
utils::Vector{Member("a", ty.i32())},
|
||||||
AttributeList{ASTNodes().Create<SpirvBlockAttribute>(ID(), AllocateNodeID())});
|
utils::Vector{ASTNodes().Create<SpirvBlockAttribute>(ID(), AllocateNodeID())});
|
||||||
EXPECT_EQ(s->name, name);
|
EXPECT_EQ(s->name, name);
|
||||||
EXPECT_EQ(s->members.size(), 1u);
|
EXPECT_EQ(s->members.Length(), 1u);
|
||||||
ASSERT_EQ(s->attributes.size(), 1u);
|
ASSERT_EQ(s->attributes.Length(), 1u);
|
||||||
EXPECT_TRUE(s->attributes[0]->Is<SpirvBlockAttribute>());
|
EXPECT_TRUE(s->attributes[0]->Is<SpirvBlockAttribute>());
|
||||||
EXPECT_EQ(s->source.range.begin.line, 27u);
|
EXPECT_EQ(s->source.range.begin.line, 27u);
|
||||||
EXPECT_EQ(s->source.range.begin.column, 4u);
|
EXPECT_EQ(s->source.range.begin.column, 4u);
|
||||||
|
@ -82,8 +83,8 @@ TEST_F(AstStructTest, Assert_Null_StructMember) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
b.create<Struct>(b.Sym("S"), StructMemberList{b.Member("a", b.ty.i32()), nullptr},
|
b.create<Struct>(b.Sym("S"), utils::Vector{b.Member("a", b.ty.i32()), nullptr},
|
||||||
AttributeList{});
|
utils::Empty);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -92,8 +93,8 @@ TEST_F(AstStructTest, Assert_Null_Attribute) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
b.create<Struct>(b.Sym("S"), StructMemberList{b.Member("a", b.ty.i32())},
|
b.create<Struct>(b.Sym("S"), utils::Vector{b.Member("a", b.ty.i32())},
|
||||||
AttributeList{nullptr});
|
utils::Vector<const ast::Attribute*, 1>{nullptr});
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -103,8 +104,8 @@ TEST_F(AstStructTest, Assert_DifferentProgramID_StructMember) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<Struct>(b1.Sym("S"), StructMemberList{b2.Member("a", b2.ty.i32())},
|
b1.create<Struct>(b1.Sym("S"), utils::Vector{b2.Member("a", b2.ty.i32())},
|
||||||
AttributeList{});
|
utils::Empty);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -114,8 +115,8 @@ TEST_F(AstStructTest, Assert_DifferentProgramID_Attribute) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<Struct>(b1.Sym("S"), StructMemberList{b1.Member("a", b1.ty.i32())},
|
b1.create<Struct>(b1.Sym("S"), utils::Vector{b1.Member("a", b1.ty.i32())},
|
||||||
AttributeList{b2.ASTNodes().Create<SpirvBlockAttribute>(
|
utils::Vector{b2.ASTNodes().Create<SpirvBlockAttribute>(
|
||||||
b2.ID(), b2.AllocateNodeID())});
|
b2.ID(), b2.AllocateNodeID())});
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "src/tint/ast/switch_statement.h"
|
#include "src/tint/ast/switch_statement.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "src/tint/program_builder.h"
|
#include "src/tint/program_builder.h"
|
||||||
|
|
||||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::SwitchStatement);
|
TINT_INSTANTIATE_TYPEINFO(tint::ast::SwitchStatement);
|
||||||
|
@ -24,8 +26,8 @@ SwitchStatement::SwitchStatement(ProgramID pid,
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
const Expression* cond,
|
const Expression* cond,
|
||||||
CaseStatementList b)
|
utils::VectorRef<const CaseStatement*> b)
|
||||||
: Base(pid, nid, src), condition(cond), body(b) {
|
: Base(pid, nid, src), condition(cond), body(std::move(b)) {
|
||||||
TINT_ASSERT(AST, condition);
|
TINT_ASSERT(AST, condition);
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition, program_id);
|
||||||
for (auto* stmt : body) {
|
for (auto* stmt : body) {
|
||||||
|
@ -43,7 +45,7 @@ const SwitchStatement* SwitchStatement::Clone(CloneContext* ctx) const {
|
||||||
auto src = ctx->Clone(source);
|
auto src = ctx->Clone(source);
|
||||||
auto* cond = ctx->Clone(condition);
|
auto* cond = ctx->Clone(condition);
|
||||||
auto b = ctx->Clone(body);
|
auto b = ctx->Clone(body);
|
||||||
return ctx->dst->create<SwitchStatement>(src, cond, b);
|
return ctx->dst->create<SwitchStatement>(src, cond, std::move(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -33,7 +33,7 @@ class SwitchStatement final : public Castable<SwitchStatement, Statement> {
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
const Expression* condition,
|
const Expression* condition,
|
||||||
CaseStatementList body);
|
utils::VectorRef<const CaseStatement*> body);
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
SwitchStatement(SwitchStatement&&);
|
SwitchStatement(SwitchStatement&&);
|
||||||
~SwitchStatement() override;
|
~SwitchStatement() override;
|
||||||
|
@ -51,7 +51,7 @@ class SwitchStatement final : public Castable<SwitchStatement, Statement> {
|
||||||
const Expression* const condition;
|
const Expression* const condition;
|
||||||
|
|
||||||
/// The Switch body
|
/// The Switch body
|
||||||
const CaseStatementList body;
|
const utils::Vector<const CaseStatement*, 4> body;
|
||||||
SwitchStatement(const SwitchStatement&) = delete;
|
SwitchStatement(const SwitchStatement&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,54 +25,47 @@ namespace {
|
||||||
using SwitchStatementTest = TestHelper;
|
using SwitchStatementTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(SwitchStatementTest, Creation) {
|
TEST_F(SwitchStatementTest, Creation) {
|
||||||
CaseSelectorList lit;
|
auto* case_stmt = create<CaseStatement>(utils::Vector{Expr(1_u)}, Block());
|
||||||
lit.push_back(Expr(1_u));
|
|
||||||
|
|
||||||
auto* ident = Expr("ident");
|
auto* ident = Expr("ident");
|
||||||
CaseStatementList body;
|
utils::Vector body{case_stmt};
|
||||||
auto* case_stmt = create<CaseStatement>(lit, Block());
|
|
||||||
body.push_back(case_stmt);
|
|
||||||
|
|
||||||
auto* stmt = create<SwitchStatement>(ident, body);
|
auto* stmt = create<SwitchStatement>(ident, body);
|
||||||
EXPECT_EQ(stmt->condition, ident);
|
EXPECT_EQ(stmt->condition, ident);
|
||||||
ASSERT_EQ(stmt->body.size(), 1u);
|
ASSERT_EQ(stmt->body.Length(), 1u);
|
||||||
EXPECT_EQ(stmt->body[0], case_stmt);
|
EXPECT_EQ(stmt->body[0], case_stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SwitchStatementTest, Creation_WithSource) {
|
TEST_F(SwitchStatementTest, Creation_WithSource) {
|
||||||
auto* ident = Expr("ident");
|
auto* ident = Expr("ident");
|
||||||
|
auto* stmt = create<SwitchStatement>(Source{Source::Location{20, 2}}, ident, utils::Empty);
|
||||||
auto* stmt =
|
|
||||||
create<SwitchStatement>(Source{Source::Location{20, 2}}, ident, CaseStatementList());
|
|
||||||
auto src = stmt->source;
|
auto src = stmt->source;
|
||||||
EXPECT_EQ(src.range.begin.line, 20u);
|
EXPECT_EQ(src.range.begin.line, 20u);
|
||||||
EXPECT_EQ(src.range.begin.column, 2u);
|
EXPECT_EQ(src.range.begin.column, 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SwitchStatementTest, IsSwitch) {
|
TEST_F(SwitchStatementTest, IsSwitch) {
|
||||||
CaseSelectorList lit;
|
utils::Vector lit{Expr(2_i)};
|
||||||
lit.push_back(Expr(2_i));
|
|
||||||
|
|
||||||
auto* ident = Expr("ident");
|
auto* ident = Expr("ident");
|
||||||
CaseStatementList body;
|
utils::Vector body{create<CaseStatement>(lit, Block())};
|
||||||
body.push_back(create<CaseStatement>(lit, Block()));
|
|
||||||
|
|
||||||
auto* stmt = create<SwitchStatement>(ident, body);
|
auto* stmt = create<SwitchStatement>(ident, body);
|
||||||
EXPECT_TRUE(stmt->Is<SwitchStatement>());
|
EXPECT_TRUE(stmt->Is<SwitchStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SwitchStatementTest, Assert_Null_Condition) {
|
TEST_F(SwitchStatementTest, Assert_Null_Condition) {
|
||||||
|
using CaseStatementList = utils::Vector<const ast::CaseStatement*, 2>;
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
CaseStatementList cases;
|
CaseStatementList cases;
|
||||||
cases.push_back(b.create<CaseStatement>(CaseSelectorList{b.Expr(1_i)}, b.Block()));
|
cases.Push(b.create<CaseStatement>(utils::Vector{b.Expr(1_i)}, b.Block()));
|
||||||
b.create<SwitchStatement>(nullptr, cases);
|
b.create<SwitchStatement>(nullptr, cases);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SwitchStatementTest, Assert_Null_CaseStatement) {
|
TEST_F(SwitchStatementTest, Assert_Null_CaseStatement) {
|
||||||
|
using CaseStatementList = utils::Vector<const ast::CaseStatement*, 2>;
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
|
@ -86,9 +79,9 @@ TEST_F(SwitchStatementTest, Assert_DifferentProgramID_Condition) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<SwitchStatement>(b2.Expr(true), CaseStatementList{
|
b1.create<SwitchStatement>(b2.Expr(true), utils::Vector{
|
||||||
b1.create<CaseStatement>(
|
b1.create<CaseStatement>(
|
||||||
CaseSelectorList{
|
utils::Vector{
|
||||||
b1.Expr(1_i),
|
b1.Expr(1_i),
|
||||||
},
|
},
|
||||||
b1.Block()),
|
b1.Block()),
|
||||||
|
@ -102,9 +95,9 @@ TEST_F(SwitchStatementTest, Assert_DifferentProgramID_CaseStatement) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<SwitchStatement>(b1.Expr(true), CaseStatementList{
|
b1.create<SwitchStatement>(b1.Expr(true), utils::Vector{
|
||||||
b2.create<CaseStatement>(
|
b2.create<CaseStatement>(
|
||||||
CaseSelectorList{
|
utils::Vector{
|
||||||
b2.Expr(1_i),
|
b2.Expr(1_i),
|
||||||
},
|
},
|
||||||
b2.Block()),
|
b2.Block()),
|
||||||
|
|
|
@ -82,7 +82,7 @@ bool TraverseExpressions(const ast::Expression* root, diag::List& diags, CALLBAC
|
||||||
to_visit.Push({right, depth});
|
to_visit.Push({right, depth});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
auto push_list = [&](const std::vector<const ast::Expression*>& exprs, size_t depth) {
|
auto push_list = [&](utils::VectorRef<const ast::Expression*> exprs, size_t depth) {
|
||||||
if (ORDER == TraverseOrder::LeftToRight) {
|
if (ORDER == TraverseOrder::LeftToRight) {
|
||||||
for (auto* expr : utils::Reverse(exprs)) {
|
for (auto* expr : utils::Reverse(exprs)) {
|
||||||
to_visit.Push({expr, depth});
|
to_visit.Push({expr, depth});
|
||||||
|
|
|
@ -97,19 +97,19 @@ TEST_F(TraverseExpressionsTest, DescendBitcastExpression) {
|
||||||
auto* b2 = Bitcast<i32>(b1);
|
auto* b2 = Bitcast<i32>(b1);
|
||||||
auto* root = Bitcast<i32>(b2);
|
auto* root = Bitcast<i32>(b2);
|
||||||
{
|
{
|
||||||
std::vector<const ast::Expression*> l2r;
|
utils::Vector<const ast::Expression*, 8> l2r;
|
||||||
TraverseExpressions<TraverseOrder::LeftToRight>(root, Diagnostics(),
|
TraverseExpressions<TraverseOrder::LeftToRight>(root, Diagnostics(),
|
||||||
[&](const ast::Expression* expr) {
|
[&](const ast::Expression* expr) {
|
||||||
l2r.push_back(expr);
|
l2r.Push(expr);
|
||||||
return ast::TraverseAction::Descend;
|
return ast::TraverseAction::Descend;
|
||||||
});
|
});
|
||||||
EXPECT_THAT(l2r, ElementsAre(root, b2, b1, b0, e));
|
EXPECT_THAT(l2r, ElementsAre(root, b2, b1, b0, e));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<const ast::Expression*> r2l;
|
utils::Vector<const ast::Expression*, 8> r2l;
|
||||||
TraverseExpressions<TraverseOrder::RightToLeft>(root, Diagnostics(),
|
TraverseExpressions<TraverseOrder::RightToLeft>(root, Diagnostics(),
|
||||||
[&](const ast::Expression* expr) {
|
[&](const ast::Expression* expr) {
|
||||||
r2l.push_back(expr);
|
r2l.Push(expr);
|
||||||
return ast::TraverseAction::Descend;
|
return ast::TraverseAction::Descend;
|
||||||
});
|
});
|
||||||
EXPECT_THAT(r2l, ElementsAre(root, b2, b1, b0, e));
|
EXPECT_THAT(r2l, ElementsAre(root, b2, b1, b0, e));
|
||||||
|
@ -117,23 +117,23 @@ TEST_F(TraverseExpressionsTest, DescendBitcastExpression) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TraverseExpressionsTest, DescendCallExpression) {
|
TEST_F(TraverseExpressionsTest, DescendCallExpression) {
|
||||||
std::vector<const ast::Expression*> e = {Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
|
utils::Vector e{Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
|
||||||
std::vector<const ast::Expression*> c = {Call("a", e[0], e[1]), Call("b", e[2], e[3])};
|
utils::Vector c{Call("a", e[0], e[1]), Call("b", e[2], e[3])};
|
||||||
auto* root = Call("c", c[0], c[1]);
|
auto* root = Call("c", c[0], c[1]);
|
||||||
{
|
{
|
||||||
std::vector<const ast::Expression*> l2r;
|
utils::Vector<const ast::Expression*, 8> l2r;
|
||||||
TraverseExpressions<TraverseOrder::LeftToRight>(root, Diagnostics(),
|
TraverseExpressions<TraverseOrder::LeftToRight>(root, Diagnostics(),
|
||||||
[&](const ast::Expression* expr) {
|
[&](const ast::Expression* expr) {
|
||||||
l2r.push_back(expr);
|
l2r.Push(expr);
|
||||||
return ast::TraverseAction::Descend;
|
return ast::TraverseAction::Descend;
|
||||||
});
|
});
|
||||||
EXPECT_THAT(l2r, ElementsAre(root, c[0], e[0], e[1], c[1], e[2], e[3]));
|
EXPECT_THAT(l2r, ElementsAre(root, c[0], e[0], e[1], c[1], e[2], e[3]));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<const ast::Expression*> r2l;
|
utils::Vector<const ast::Expression*, 8> r2l;
|
||||||
TraverseExpressions<TraverseOrder::RightToLeft>(root, Diagnostics(),
|
TraverseExpressions<TraverseOrder::RightToLeft>(root, Diagnostics(),
|
||||||
[&](const ast::Expression* expr) {
|
[&](const ast::Expression* expr) {
|
||||||
r2l.push_back(expr);
|
r2l.Push(expr);
|
||||||
return ast::TraverseAction::Descend;
|
return ast::TraverseAction::Descend;
|
||||||
});
|
});
|
||||||
EXPECT_THAT(r2l, ElementsAre(root, c[1], e[3], e[2], c[0], e[1], e[0]));
|
EXPECT_THAT(r2l, ElementsAre(root, c[1], e[3], e[2], c[0], e[1], e[0]));
|
||||||
|
|
|
@ -28,8 +28,8 @@ Var::Var(ProgramID pid,
|
||||||
StorageClass storage_class,
|
StorageClass storage_class,
|
||||||
Access access,
|
Access access,
|
||||||
const Expression* ctor,
|
const Expression* ctor,
|
||||||
AttributeList attrs)
|
utils::VectorRef<const Attribute*> attrs)
|
||||||
: Base(pid, nid, src, sym, ty, ctor, attrs),
|
: Base(pid, nid, src, sym, ty, ctor, std::move(attrs)),
|
||||||
declared_storage_class(storage_class),
|
declared_storage_class(storage_class),
|
||||||
declared_access(access) {}
|
declared_access(access) {}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ const Var* Var::Clone(CloneContext* ctx) const {
|
||||||
auto* ctor = ctx->Clone(constructor);
|
auto* ctor = ctx->Clone(constructor);
|
||||||
auto attrs = ctx->Clone(attributes);
|
auto attrs = ctx->Clone(attributes);
|
||||||
return ctx->dst->create<Var>(src, sym, ty, declared_storage_class, declared_access, ctor,
|
return ctx->dst->create<Var>(src, sym, ty, declared_storage_class, declared_access, ctor,
|
||||||
attrs);
|
std::move(attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -59,7 +59,7 @@ class Var final : public Castable<Var, Variable> {
|
||||||
StorageClass declared_storage_class,
|
StorageClass declared_storage_class,
|
||||||
Access declared_access,
|
Access declared_access,
|
||||||
const Expression* constructor,
|
const Expression* constructor,
|
||||||
AttributeList attributes);
|
utils::VectorRef<const Attribute*> attributes);
|
||||||
|
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
Var(Var&&);
|
Var(Var&&);
|
||||||
|
|
|
@ -26,7 +26,7 @@ Variable::Variable(ProgramID pid,
|
||||||
const Symbol& sym,
|
const Symbol& sym,
|
||||||
const ast::Type* ty,
|
const ast::Type* ty,
|
||||||
const Expression* ctor,
|
const Expression* ctor,
|
||||||
AttributeList attrs)
|
utils::VectorRef<const Attribute*> attrs)
|
||||||
: Base(pid, nid, src), symbol(sym), type(ty), constructor(ctor), attributes(std::move(attrs)) {
|
: Base(pid, nid, src), symbol(sym), type(ty), constructor(ctor), attributes(std::move(attrs)) {
|
||||||
TINT_ASSERT(AST, symbol.IsValid());
|
TINT_ASSERT(AST, symbol.IsValid());
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol, program_id);
|
||||||
|
|
|
@ -67,7 +67,7 @@ class Variable : public Castable<Variable, Node> {
|
||||||
const Symbol& sym,
|
const Symbol& sym,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
const Expression* constructor,
|
const Expression* constructor,
|
||||||
AttributeList attributes);
|
utils::VectorRef<const Attribute*> attributes);
|
||||||
|
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
Variable(Variable&&);
|
Variable(Variable&&);
|
||||||
|
@ -95,12 +95,9 @@ class Variable : public Castable<Variable, Node> {
|
||||||
const Expression* const constructor;
|
const Expression* const constructor;
|
||||||
|
|
||||||
/// The attributes attached to this variable
|
/// The attributes attached to this variable
|
||||||
const AttributeList attributes;
|
const utils::Vector<const Attribute*, 2> attributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A list of variables
|
|
||||||
using VariableList = std::vector<const Variable*>;
|
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
||||||
#endif // SRC_TINT_AST_VARIABLE_H_
|
#endif // SRC_TINT_AST_VARIABLE_H_
|
||||||
|
|
|
@ -38,7 +38,7 @@ TEST_F(VariableTest, Creation) {
|
||||||
|
|
||||||
TEST_F(VariableTest, CreationWithSource) {
|
TEST_F(VariableTest, CreationWithSource) {
|
||||||
auto* v = Var(Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 5}}}, "i",
|
auto* v = Var(Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 5}}}, "i",
|
||||||
ty.f32(), StorageClass::kPrivate, nullptr, AttributeList{});
|
ty.f32(), StorageClass::kPrivate, nullptr, utils::Empty);
|
||||||
|
|
||||||
EXPECT_EQ(v->symbol, Symbol(1, ID()));
|
EXPECT_EQ(v->symbol, Symbol(1, ID()));
|
||||||
EXPECT_EQ(v->declared_storage_class, StorageClass::kPrivate);
|
EXPECT_EQ(v->declared_storage_class, StorageClass::kPrivate);
|
||||||
|
@ -51,7 +51,7 @@ TEST_F(VariableTest, CreationWithSource) {
|
||||||
|
|
||||||
TEST_F(VariableTest, CreationEmpty) {
|
TEST_F(VariableTest, CreationEmpty) {
|
||||||
auto* v = Var(Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 7}}}, "a_var",
|
auto* v = Var(Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 7}}}, "a_var",
|
||||||
ty.i32(), StorageClass::kWorkgroup, nullptr, AttributeList{});
|
ty.i32(), StorageClass::kWorkgroup, nullptr, utils::Empty);
|
||||||
|
|
||||||
EXPECT_EQ(v->symbol, Symbol(1, ID()));
|
EXPECT_EQ(v->symbol, Symbol(1, ID()));
|
||||||
EXPECT_EQ(v->declared_storage_class, StorageClass::kWorkgroup);
|
EXPECT_EQ(v->declared_storage_class, StorageClass::kWorkgroup);
|
||||||
|
@ -93,7 +93,7 @@ TEST_F(VariableTest, Assert_DifferentProgramID_Constructor) {
|
||||||
|
|
||||||
TEST_F(VariableTest, WithAttributes) {
|
TEST_F(VariableTest, WithAttributes) {
|
||||||
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
|
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
|
||||||
AttributeList{
|
utils::Vector{
|
||||||
create<LocationAttribute>(1u),
|
create<LocationAttribute>(1u),
|
||||||
create<BuiltinAttribute>(BuiltinValue::kPosition),
|
create<BuiltinAttribute>(BuiltinValue::kPosition),
|
||||||
create<IdAttribute>(1200u),
|
create<IdAttribute>(1200u),
|
||||||
|
@ -111,7 +111,7 @@ TEST_F(VariableTest, WithAttributes) {
|
||||||
|
|
||||||
TEST_F(VariableTest, BindingPoint) {
|
TEST_F(VariableTest, BindingPoint) {
|
||||||
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
|
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
|
||||||
AttributeList{
|
utils::Vector{
|
||||||
create<BindingAttribute>(2u),
|
create<BindingAttribute>(2u),
|
||||||
create<GroupAttribute>(1u),
|
create<GroupAttribute>(1u),
|
||||||
});
|
});
|
||||||
|
@ -123,7 +123,7 @@ TEST_F(VariableTest, BindingPoint) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(VariableTest, BindingPointAttributes) {
|
TEST_F(VariableTest, BindingPointAttributes) {
|
||||||
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr, AttributeList{});
|
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr, utils::Empty);
|
||||||
EXPECT_FALSE(var->BindingPoint());
|
EXPECT_FALSE(var->BindingPoint());
|
||||||
EXPECT_EQ(var->BindingPoint().group, nullptr);
|
EXPECT_EQ(var->BindingPoint().group, nullptr);
|
||||||
EXPECT_EQ(var->BindingPoint().binding, nullptr);
|
EXPECT_EQ(var->BindingPoint().binding, nullptr);
|
||||||
|
@ -131,7 +131,7 @@ TEST_F(VariableTest, BindingPointAttributes) {
|
||||||
|
|
||||||
TEST_F(VariableTest, BindingPointMissingGroupAttribute) {
|
TEST_F(VariableTest, BindingPointMissingGroupAttribute) {
|
||||||
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
|
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
|
||||||
AttributeList{
|
utils::Vector{
|
||||||
create<BindingAttribute>(2u),
|
create<BindingAttribute>(2u),
|
||||||
});
|
});
|
||||||
EXPECT_FALSE(var->BindingPoint());
|
EXPECT_FALSE(var->BindingPoint());
|
||||||
|
@ -142,7 +142,7 @@ TEST_F(VariableTest, BindingPointMissingGroupAttribute) {
|
||||||
|
|
||||||
TEST_F(VariableTest, BindingPointMissingBindingAttribute) {
|
TEST_F(VariableTest, BindingPointMissingBindingAttribute) {
|
||||||
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
|
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
|
||||||
AttributeList{create<GroupAttribute>(1u)});
|
utils::Vector{create<GroupAttribute>(1u)});
|
||||||
EXPECT_FALSE(var->BindingPoint());
|
EXPECT_FALSE(var->BindingPoint());
|
||||||
ASSERT_NE(var->BindingPoint().group, nullptr);
|
ASSERT_NE(var->BindingPoint().group, nullptr);
|
||||||
EXPECT_EQ(var->BindingPoint().group->value, 1u);
|
EXPECT_EQ(var->BindingPoint().group->value, 1u);
|
||||||
|
|
|
@ -62,7 +62,7 @@ void CloneContext::Clone() {
|
||||||
|
|
||||||
ast::FunctionList CloneContext::Clone(const ast::FunctionList& v) {
|
ast::FunctionList CloneContext::Clone(const ast::FunctionList& v) {
|
||||||
ast::FunctionList out;
|
ast::FunctionList out;
|
||||||
out.reserve(v.size());
|
out.Reserve(v.Length());
|
||||||
for (const ast::Function* el : v) {
|
for (const ast::Function* el : v) {
|
||||||
out.Add(Clone(el));
|
out.Add(Clone(el));
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "src/tint/program_id.h"
|
#include "src/tint/program_id.h"
|
||||||
#include "src/tint/symbol.h"
|
#include "src/tint/symbol.h"
|
||||||
#include "src/tint/traits.h"
|
#include "src/tint/traits.h"
|
||||||
|
#include "src/tint/utils/vector.h"
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
@ -163,12 +164,12 @@ class CloneContext {
|
||||||
///
|
///
|
||||||
/// @param v the vector to clone
|
/// @param v the vector to clone
|
||||||
/// @return the cloned vector
|
/// @return the cloned vector
|
||||||
template <typename T, typename A>
|
template <typename T, size_t N>
|
||||||
std::vector<T> Clone(const std::vector<T, A>& v) {
|
utils::Vector<T, N> Clone(const utils::Vector<T, N>& v) {
|
||||||
std::vector<T> out;
|
utils::Vector<T, N> out;
|
||||||
out.reserve(v.size());
|
out.reserve(v.size());
|
||||||
for (auto& el : v) {
|
for (auto& el : v) {
|
||||||
out.emplace_back(Clone(el));
|
out.Push(Clone(el));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -181,9 +182,9 @@ class CloneContext {
|
||||||
///
|
///
|
||||||
/// @param v the vector to clone
|
/// @param v the vector to clone
|
||||||
/// @return the cloned vector
|
/// @return the cloned vector
|
||||||
template <typename T, typename A>
|
template <typename T, size_t N>
|
||||||
std::vector<T*, A> Clone(const std::vector<T*, A>& v) {
|
utils::Vector<T*, N> Clone(const utils::Vector<T*, N>& v) {
|
||||||
std::vector<T*, A> out;
|
utils::Vector<T*, N> out;
|
||||||
Clone(out, v);
|
Clone(out, v);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -196,39 +197,39 @@ class CloneContext {
|
||||||
///
|
///
|
||||||
/// @param from the vector to clone
|
/// @param from the vector to clone
|
||||||
/// @param to the cloned result
|
/// @param to the cloned result
|
||||||
template <typename T, typename A>
|
template <typename T, size_t N>
|
||||||
void Clone(std::vector<T*, A>& to, const std::vector<T*, A>& from) {
|
void Clone(utils::Vector<T*, N>& to, const utils::Vector<T*, N>& from) {
|
||||||
to.reserve(from.size());
|
to.Reserve(from.Length());
|
||||||
|
|
||||||
auto list_transform_it = list_transforms_.find(&from);
|
auto list_transform_it = list_transforms_.find(&from);
|
||||||
if (list_transform_it != list_transforms_.end()) {
|
if (list_transform_it != list_transforms_.end()) {
|
||||||
const auto& transforms = list_transform_it->second;
|
const auto& transforms = list_transform_it->second;
|
||||||
for (auto* o : transforms.insert_front_) {
|
for (auto* o : transforms.insert_front_) {
|
||||||
to.emplace_back(CheckedCast<T>(o));
|
to.Push(CheckedCast<T>(o));
|
||||||
}
|
}
|
||||||
for (auto& el : from) {
|
for (auto& el : from) {
|
||||||
auto insert_before_it = transforms.insert_before_.find(el);
|
auto insert_before_it = transforms.insert_before_.find(el);
|
||||||
if (insert_before_it != transforms.insert_before_.end()) {
|
if (insert_before_it != transforms.insert_before_.end()) {
|
||||||
for (auto insert : insert_before_it->second) {
|
for (auto insert : insert_before_it->second) {
|
||||||
to.emplace_back(CheckedCast<T>(insert));
|
to.Push(CheckedCast<T>(insert));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (transforms.remove_.count(el) == 0) {
|
if (transforms.remove_.count(el) == 0) {
|
||||||
to.emplace_back(Clone(el));
|
to.Push(Clone(el));
|
||||||
}
|
}
|
||||||
auto insert_after_it = transforms.insert_after_.find(el);
|
auto insert_after_it = transforms.insert_after_.find(el);
|
||||||
if (insert_after_it != transforms.insert_after_.end()) {
|
if (insert_after_it != transforms.insert_after_.end()) {
|
||||||
for (auto insert : insert_after_it->second) {
|
for (auto insert : insert_after_it->second) {
|
||||||
to.emplace_back(CheckedCast<T>(insert));
|
to.Push(CheckedCast<T>(insert));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto* o : transforms.insert_back_) {
|
for (auto* o : transforms.insert_back_) {
|
||||||
to.emplace_back(CheckedCast<T>(o));
|
to.Push(CheckedCast<T>(o));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto& el : from) {
|
for (auto& el : from) {
|
||||||
to.emplace_back(Clone(el));
|
to.Push(Clone(el));
|
||||||
|
|
||||||
// Clone(el) may have inserted after
|
// Clone(el) may have inserted after
|
||||||
list_transform_it = list_transforms_.find(&from);
|
list_transform_it = list_transforms_.find(&from);
|
||||||
|
@ -238,7 +239,7 @@ class CloneContext {
|
||||||
auto insert_after_it = transforms.insert_after_.find(el);
|
auto insert_after_it = transforms.insert_after_.find(el);
|
||||||
if (insert_after_it != transforms.insert_after_.end()) {
|
if (insert_after_it != transforms.insert_after_.end()) {
|
||||||
for (auto insert : insert_after_it->second) {
|
for (auto insert : insert_after_it->second) {
|
||||||
to.emplace_back(CheckedCast<T>(insert));
|
to.Push(CheckedCast<T>(insert));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,7 +251,7 @@ class CloneContext {
|
||||||
const auto& transforms = list_transform_it->second;
|
const auto& transforms = list_transform_it->second;
|
||||||
|
|
||||||
for (auto* o : transforms.insert_back_) {
|
for (auto* o : transforms.insert_back_) {
|
||||||
to.emplace_back(CheckedCast<T>(o));
|
to.Push(CheckedCast<T>(o));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,7 +319,7 @@ class CloneContext {
|
||||||
CloneableTransform transform;
|
CloneableTransform transform;
|
||||||
transform.typeinfo = &TypeInfo::Of<T>();
|
transform.typeinfo = &TypeInfo::Of<T>();
|
||||||
transform.function = [=](const Cloneable* in) { return replacer(in->As<T>()); };
|
transform.function = [=](const Cloneable* in) { return replacer(in->As<T>()); };
|
||||||
transforms_.emplace_back(std::move(transform));
|
transforms_.Push(std::move(transform));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,8 +387,8 @@ class CloneContext {
|
||||||
/// @param object a pointer to the object in #src that will be omitted from
|
/// @param object a pointer to the object in #src that will be omitted from
|
||||||
/// the cloned vector.
|
/// the cloned vector.
|
||||||
/// @returns this CloneContext so calls can be chained
|
/// @returns this CloneContext so calls can be chained
|
||||||
template <typename T, typename A, typename OBJECT>
|
template <typename T, size_t N, typename OBJECT>
|
||||||
CloneContext& Remove(const std::vector<T, A>& vector, OBJECT* object) {
|
CloneContext& Remove(const utils::Vector<T, N>& vector, OBJECT* object) {
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, object);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, object);
|
||||||
if (std::find(vector.begin(), vector.end(), object) == vector.end()) {
|
if (std::find(vector.begin(), vector.end(), object) == vector.end()) {
|
||||||
TINT_ICE(Clone, Diagnostics())
|
TINT_ICE(Clone, Diagnostics())
|
||||||
|
@ -404,12 +405,12 @@ class CloneContext {
|
||||||
/// @param object a pointer to the object in #dst that will be inserted at the
|
/// @param object a pointer to the object in #dst that will be inserted at the
|
||||||
/// front of the vector
|
/// front of the vector
|
||||||
/// @returns this CloneContext so calls can be chained
|
/// @returns this CloneContext so calls can be chained
|
||||||
template <typename T, typename A, typename OBJECT>
|
template <typename T, size_t N, typename OBJECT>
|
||||||
CloneContext& InsertFront(const std::vector<T, A>& vector, OBJECT* object) {
|
CloneContext& InsertFront(const utils::Vector<T, N>& vector, OBJECT* object) {
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, object);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, object);
|
||||||
auto& transforms = list_transforms_[&vector];
|
auto& transforms = list_transforms_[&vector];
|
||||||
auto& list = transforms.insert_front_;
|
auto& list = transforms.insert_front_;
|
||||||
list.emplace_back(object);
|
list.Push(object);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,12 +419,12 @@ class CloneContext {
|
||||||
/// @param object a pointer to the object in #dst that will be inserted at the
|
/// @param object a pointer to the object in #dst that will be inserted at the
|
||||||
/// end of the vector
|
/// end of the vector
|
||||||
/// @returns this CloneContext so calls can be chained
|
/// @returns this CloneContext so calls can be chained
|
||||||
template <typename T, typename A, typename OBJECT>
|
template <typename T, size_t N, typename OBJECT>
|
||||||
CloneContext& InsertBack(const std::vector<T, A>& vector, OBJECT* object) {
|
CloneContext& InsertBack(const utils::Vector<T, N>& vector, OBJECT* object) {
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, object);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, object);
|
||||||
auto& transforms = list_transforms_[&vector];
|
auto& transforms = list_transforms_[&vector];
|
||||||
auto& list = transforms.insert_back_;
|
auto& list = transforms.insert_back_;
|
||||||
list.emplace_back(object);
|
list.Push(object);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,8 +434,8 @@ class CloneContext {
|
||||||
/// @param object a pointer to the object in #dst that will be inserted before
|
/// @param object a pointer to the object in #dst that will be inserted before
|
||||||
/// any occurrence of the clone of `before`
|
/// any occurrence of the clone of `before`
|
||||||
/// @returns this CloneContext so calls can be chained
|
/// @returns this CloneContext so calls can be chained
|
||||||
template <typename T, typename A, typename BEFORE, typename OBJECT>
|
template <typename T, size_t N, typename BEFORE, typename OBJECT>
|
||||||
CloneContext& InsertBefore(const std::vector<T, A>& vector,
|
CloneContext& InsertBefore(const utils::Vector<T, N>& vector,
|
||||||
const BEFORE* before,
|
const BEFORE* before,
|
||||||
const OBJECT* object) {
|
const OBJECT* object) {
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, before);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, before);
|
||||||
|
@ -447,7 +448,7 @@ class CloneContext {
|
||||||
|
|
||||||
auto& transforms = list_transforms_[&vector];
|
auto& transforms = list_transforms_[&vector];
|
||||||
auto& list = transforms.insert_before_[before];
|
auto& list = transforms.insert_before_[before];
|
||||||
list.emplace_back(object);
|
list.Push(object);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,8 +458,8 @@ class CloneContext {
|
||||||
/// @param object a pointer to the object in #dst that will be inserted after
|
/// @param object a pointer to the object in #dst that will be inserted after
|
||||||
/// any occurrence of the clone of `after`
|
/// any occurrence of the clone of `after`
|
||||||
/// @returns this CloneContext so calls can be chained
|
/// @returns this CloneContext so calls can be chained
|
||||||
template <typename T, typename A, typename AFTER, typename OBJECT>
|
template <typename T, size_t N, typename AFTER, typename OBJECT>
|
||||||
CloneContext& InsertAfter(const std::vector<T, A>& vector,
|
CloneContext& InsertAfter(const utils::Vector<T, N>& vector,
|
||||||
const AFTER* after,
|
const AFTER* after,
|
||||||
const OBJECT* object) {
|
const OBJECT* object) {
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, after);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, after);
|
||||||
|
@ -471,7 +472,7 @@ class CloneContext {
|
||||||
|
|
||||||
auto& transforms = list_transforms_[&vector];
|
auto& transforms = list_transforms_[&vector];
|
||||||
auto& list = transforms.insert_after_[after];
|
auto& list = transforms.insert_after_[after];
|
||||||
list.emplace_back(object);
|
list.Push(object);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,7 +531,7 @@ class CloneContext {
|
||||||
diag::List& Diagnostics() const;
|
diag::List& Diagnostics() const;
|
||||||
|
|
||||||
/// A vector of const Cloneable*
|
/// A vector of const Cloneable*
|
||||||
using CloneableList = std::vector<const Cloneable*>;
|
using CloneableList = utils::Vector<const Cloneable*, 4>;
|
||||||
|
|
||||||
/// Transformations to be applied to a list (vector)
|
/// Transformations to be applied to a list (vector)
|
||||||
struct ListTransforms {
|
struct ListTransforms {
|
||||||
|
@ -551,12 +552,12 @@ class CloneContext {
|
||||||
CloneableList insert_back_;
|
CloneableList insert_back_;
|
||||||
|
|
||||||
/// A map of object in #src to the list of cloned objects in #dst.
|
/// A map of object in #src to the list of cloned objects in #dst.
|
||||||
/// Clone(const std::vector<T*>& v) will use this to insert the map-value
|
/// Clone(const utils::Vector<T*>& v) will use this to insert the map-value
|
||||||
/// list into the target vector before cloning and inserting the map-key.
|
/// list into the target vector before cloning and inserting the map-key.
|
||||||
std::unordered_map<const Cloneable*, CloneableList> insert_before_;
|
std::unordered_map<const Cloneable*, CloneableList> insert_before_;
|
||||||
|
|
||||||
/// A map of object in #src to the list of cloned objects in #dst.
|
/// A map of object in #src to the list of cloned objects in #dst.
|
||||||
/// Clone(const std::vector<T*>& v) will use this to insert the map-value
|
/// Clone(const utils::Vector<T*>& v) will use this to insert the map-value
|
||||||
/// list into the target vector after cloning and inserting the map-key.
|
/// list into the target vector after cloning and inserting the map-key.
|
||||||
std::unordered_map<const Cloneable*, CloneableList> insert_after_;
|
std::unordered_map<const Cloneable*, CloneableList> insert_after_;
|
||||||
};
|
};
|
||||||
|
@ -569,9 +570,9 @@ class CloneContext {
|
||||||
std::unordered_map<Symbol, Symbol> cloned_symbols_;
|
std::unordered_map<Symbol, Symbol> cloned_symbols_;
|
||||||
|
|
||||||
/// Cloneable transform functions registered with ReplaceAll()
|
/// Cloneable transform functions registered with ReplaceAll()
|
||||||
std::vector<CloneableTransform> transforms_;
|
utils::Vector<CloneableTransform, 8> transforms_;
|
||||||
|
|
||||||
/// Map of std::vector pointer to transforms for that list
|
/// Map of utils::Vector pointer to transforms for that list
|
||||||
std::unordered_map<const void*, ListTransforms> list_transforms_;
|
std::unordered_map<const void*, ListTransforms> list_transforms_;
|
||||||
|
|
||||||
/// Symbol transform registered with ReplaceAll()
|
/// Symbol transform registered with ReplaceAll()
|
||||||
|
|
|
@ -37,12 +37,13 @@ struct Node : public Castable<Node, Cloneable> {
|
||||||
const Node* node_b = nullptr,
|
const Node* node_b = nullptr,
|
||||||
const Node* node_c = nullptr)
|
const Node* node_c = nullptr)
|
||||||
: allocator(alloc), name(n), a(node_a), b(node_b), c(node_c) {}
|
: allocator(alloc), name(n), a(node_a), b(node_b), c(node_c) {}
|
||||||
|
Node(Node&&) = delete;
|
||||||
Allocator* const allocator;
|
Allocator* const allocator;
|
||||||
Symbol name;
|
Symbol name;
|
||||||
const Node* a = nullptr;
|
const Node* a = nullptr;
|
||||||
const Node* b = nullptr;
|
const Node* b = nullptr;
|
||||||
const Node* c = nullptr;
|
const Node* c = nullptr;
|
||||||
std::vector<const Node*> vec;
|
utils::Vector<const Node*, 8> vec;
|
||||||
|
|
||||||
Node* Clone(CloneContext* ctx) const override {
|
Node* Clone(CloneContext* ctx) const override {
|
||||||
auto* out = allocator->Create<Node>(ctx->Clone(name));
|
auto* out = allocator->Create<Node>(ctx->Clone(name));
|
||||||
|
@ -387,7 +388,7 @@ TEST_F(CloneContextNodeTest, CloneWithRemove) {
|
||||||
.Remove(original_root->vec, original_root->vec[1])
|
.Remove(original_root->vec, original_root->vec[1])
|
||||||
.Clone(original_root);
|
.Clone(original_root);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->vec.size(), 2u);
|
EXPECT_EQ(cloned_root->vec.Length(), 2u);
|
||||||
|
|
||||||
EXPECT_NE(cloned_root->vec[0], cloned_root->a);
|
EXPECT_NE(cloned_root->vec[0], cloned_root->a);
|
||||||
EXPECT_NE(cloned_root->vec[1], cloned_root->c);
|
EXPECT_NE(cloned_root->vec[1], cloned_root->c);
|
||||||
|
@ -416,7 +417,7 @@ TEST_F(CloneContextNodeTest, CloneWithInsertFront) {
|
||||||
.InsertFront(original_root->vec, insertion)
|
.InsertFront(original_root->vec, insertion)
|
||||||
.Clone(original_root);
|
.Clone(original_root);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->vec.size(), 4u);
|
EXPECT_EQ(cloned_root->vec.Length(), 4u);
|
||||||
|
|
||||||
EXPECT_NE(cloned_root->vec[0], cloned_root->a);
|
EXPECT_NE(cloned_root->vec[0], cloned_root->a);
|
||||||
EXPECT_NE(cloned_root->vec[1], cloned_root->b);
|
EXPECT_NE(cloned_root->vec[1], cloned_root->b);
|
||||||
|
@ -434,7 +435,7 @@ TEST_F(CloneContextNodeTest, CloneWithInsertFront_Empty) {
|
||||||
|
|
||||||
ProgramBuilder builder;
|
ProgramBuilder builder;
|
||||||
auto* original_root = a.Create<Node>(builder.Symbols().Register("root"));
|
auto* original_root = a.Create<Node>(builder.Symbols().Register("root"));
|
||||||
original_root->vec = {};
|
original_root->vec.Clear();
|
||||||
Program original(std::move(builder));
|
Program original(std::move(builder));
|
||||||
|
|
||||||
ProgramBuilder cloned;
|
ProgramBuilder cloned;
|
||||||
|
@ -444,7 +445,7 @@ TEST_F(CloneContextNodeTest, CloneWithInsertFront_Empty) {
|
||||||
.InsertFront(original_root->vec, insertion)
|
.InsertFront(original_root->vec, insertion)
|
||||||
.Clone(original_root);
|
.Clone(original_root);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->vec.size(), 1u);
|
EXPECT_EQ(cloned_root->vec.Length(), 1u);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
||||||
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("insertion"));
|
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("insertion"));
|
||||||
|
@ -469,7 +470,7 @@ TEST_F(CloneContextNodeTest, CloneWithInsertBack) {
|
||||||
.InsertBack(original_root->vec, insertion)
|
.InsertBack(original_root->vec, insertion)
|
||||||
.Clone(original_root);
|
.Clone(original_root);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->vec.size(), 4u);
|
EXPECT_EQ(cloned_root->vec.Length(), 4u);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
||||||
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("a"));
|
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("a"));
|
||||||
|
@ -483,7 +484,7 @@ TEST_F(CloneContextNodeTest, CloneWithInsertBack_Empty) {
|
||||||
|
|
||||||
ProgramBuilder builder;
|
ProgramBuilder builder;
|
||||||
auto* original_root = a.Create<Node>(builder.Symbols().Register("root"));
|
auto* original_root = a.Create<Node>(builder.Symbols().Register("root"));
|
||||||
original_root->vec = {};
|
original_root->vec.Clear();
|
||||||
Program original(std::move(builder));
|
Program original(std::move(builder));
|
||||||
|
|
||||||
ProgramBuilder cloned;
|
ProgramBuilder cloned;
|
||||||
|
@ -493,7 +494,7 @@ TEST_F(CloneContextNodeTest, CloneWithInsertBack_Empty) {
|
||||||
.InsertBack(original_root->vec, insertion)
|
.InsertBack(original_root->vec, insertion)
|
||||||
.Clone(original_root);
|
.Clone(original_root);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->vec.size(), 1u);
|
EXPECT_EQ(cloned_root->vec.Length(), 1u);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
||||||
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("insertion"));
|
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("insertion"));
|
||||||
|
@ -504,7 +505,7 @@ TEST_F(CloneContextNodeTest, CloneWithInsertFrontAndBack_Empty) {
|
||||||
|
|
||||||
ProgramBuilder builder;
|
ProgramBuilder builder;
|
||||||
auto* original_root = a.Create<Node>(builder.Symbols().Register("root"));
|
auto* original_root = a.Create<Node>(builder.Symbols().Register("root"));
|
||||||
original_root->vec = {};
|
original_root->vec.Clear();
|
||||||
Program original(std::move(builder));
|
Program original(std::move(builder));
|
||||||
|
|
||||||
ProgramBuilder cloned;
|
ProgramBuilder cloned;
|
||||||
|
@ -516,7 +517,7 @@ TEST_F(CloneContextNodeTest, CloneWithInsertFrontAndBack_Empty) {
|
||||||
.InsertFront(original_root->vec, insertion_front)
|
.InsertFront(original_root->vec, insertion_front)
|
||||||
.Clone(original_root);
|
.Clone(original_root);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->vec.size(), 2u);
|
EXPECT_EQ(cloned_root->vec.Length(), 2u);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
||||||
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("insertion_front"));
|
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("insertion_front"));
|
||||||
|
@ -542,7 +543,7 @@ TEST_F(CloneContextNodeTest, CloneWithInsertBefore) {
|
||||||
.InsertBefore(original_root->vec, original_root->vec[1], insertion)
|
.InsertBefore(original_root->vec, original_root->vec[1], insertion)
|
||||||
.Clone(original_root);
|
.Clone(original_root);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->vec.size(), 4u);
|
EXPECT_EQ(cloned_root->vec.Length(), 4u);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
||||||
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("a"));
|
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("a"));
|
||||||
|
@ -570,7 +571,7 @@ TEST_F(CloneContextNodeTest, CloneWithInsertAfter) {
|
||||||
.InsertAfter(original_root->vec, original_root->vec[1], insertion)
|
.InsertAfter(original_root->vec, original_root->vec[1], insertion)
|
||||||
.Clone(original_root);
|
.Clone(original_root);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->vec.size(), 4u);
|
EXPECT_EQ(cloned_root->vec.Length(), 4u);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
||||||
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("a"));
|
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("a"));
|
||||||
|
@ -602,7 +603,7 @@ TEST_F(CloneContextNodeTest, CloneWithInsertAfterInVectorNodeClone) {
|
||||||
|
|
||||||
auto* cloned_root = ctx.Clone(original_root);
|
auto* cloned_root = ctx.Clone(original_root);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->vec.size(), 4u);
|
EXPECT_EQ(cloned_root->vec.Length(), 4u);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
||||||
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("a"));
|
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("a"));
|
||||||
|
@ -634,7 +635,7 @@ TEST_F(CloneContextNodeTest, CloneWithInsertBackInVectorNodeClone) {
|
||||||
|
|
||||||
auto* cloned_root = ctx.Clone(original_root);
|
auto* cloned_root = ctx.Clone(original_root);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->vec.size(), 4u);
|
EXPECT_EQ(cloned_root->vec.Length(), 4u);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
||||||
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("a"));
|
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("a"));
|
||||||
|
@ -666,7 +667,7 @@ TEST_F(CloneContextNodeTest, CloneWithInsertBeforeAndAfterRemoved) {
|
||||||
.Remove(original_root->vec, original_root->vec[1])
|
.Remove(original_root->vec, original_root->vec[1])
|
||||||
.Clone(original_root);
|
.Clone(original_root);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->vec.size(), 4u);
|
EXPECT_EQ(cloned_root->vec.Length(), 4u);
|
||||||
|
|
||||||
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
EXPECT_EQ(cloned_root->name, cloned.Symbols().Get("root"));
|
||||||
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("a"));
|
EXPECT_EQ(cloned_root->vec[0]->name, cloned.Symbols().Get("a"));
|
||||||
|
|
|
@ -107,7 +107,7 @@ std::tuple<ComponentType, CompositionType> CalculateComponentAndComposition(cons
|
||||||
|
|
||||||
std::tuple<InterpolationType, InterpolationSampling> CalculateInterpolationData(
|
std::tuple<InterpolationType, InterpolationSampling> CalculateInterpolationData(
|
||||||
const sem::Type* type,
|
const sem::Type* type,
|
||||||
const ast::AttributeList& attributes) {
|
utils::VectorRef<const ast::Attribute*> attributes) {
|
||||||
auto* interpolation_attribute = ast::GetAttribute<ast::InterpolateAttribute>(attributes);
|
auto* interpolation_attribute = ast::GetAttribute<ast::InterpolateAttribute>(attributes);
|
||||||
if (type->is_integer_scalar_or_vector()) {
|
if (type->is_integer_scalar_or_vector()) {
|
||||||
return {InterpolationType::kFlat, InterpolationSampling::kNone};
|
return {InterpolationType::kFlat, InterpolationSampling::kNone};
|
||||||
|
@ -608,7 +608,7 @@ const ast::Function* Inspector::FindEntryPointByName(const std::string& name) {
|
||||||
|
|
||||||
void Inspector::AddEntryPointInOutVariables(std::string name,
|
void Inspector::AddEntryPointInOutVariables(std::string name,
|
||||||
const sem::Type* type,
|
const sem::Type* type,
|
||||||
const ast::AttributeList& attributes,
|
utils::VectorRef<const ast::Attribute*> attributes,
|
||||||
std::vector<StageVariable>& variables) const {
|
std::vector<StageVariable>& variables) const {
|
||||||
// Skip builtins.
|
// Skip builtins.
|
||||||
if (ast::HasAttribute<ast::BuiltinAttribute>(attributes)) {
|
if (ast::HasAttribute<ast::BuiltinAttribute>(attributes)) {
|
||||||
|
@ -647,7 +647,7 @@ void Inspector::AddEntryPointInOutVariables(std::string name,
|
||||||
|
|
||||||
bool Inspector::ContainsBuiltin(ast::BuiltinValue builtin,
|
bool Inspector::ContainsBuiltin(ast::BuiltinValue builtin,
|
||||||
const sem::Type* type,
|
const sem::Type* type,
|
||||||
const ast::AttributeList& attributes) const {
|
utils::VectorRef<const ast::Attribute*> attributes) const {
|
||||||
auto* unwrapped_type = type->UnwrapRef();
|
auto* unwrapped_type = type->UnwrapRef();
|
||||||
|
|
||||||
if (auto* struct_ty = unwrapped_type->As<sem::Struct>()) {
|
if (auto* struct_ty = unwrapped_type->As<sem::Struct>()) {
|
||||||
|
|
|
@ -170,7 +170,7 @@ class Inspector {
|
||||||
/// @param variables the list to add the variables to
|
/// @param variables the list to add the variables to
|
||||||
void AddEntryPointInOutVariables(std::string name,
|
void AddEntryPointInOutVariables(std::string name,
|
||||||
const sem::Type* type,
|
const sem::Type* type,
|
||||||
const ast::AttributeList& attributes,
|
utils::VectorRef<const ast::Attribute*> attributes,
|
||||||
std::vector<StageVariable>& variables) const;
|
std::vector<StageVariable>& variables) const;
|
||||||
|
|
||||||
/// Recursively determine if the type contains builtin.
|
/// Recursively determine if the type contains builtin.
|
||||||
|
@ -178,7 +178,7 @@ class Inspector {
|
||||||
/// Otherwise, check `attributes` for the attribute.
|
/// Otherwise, check `attributes` for the attribute.
|
||||||
bool ContainsBuiltin(ast::BuiltinValue builtin,
|
bool ContainsBuiltin(ast::BuiltinValue builtin,
|
||||||
const sem::Type* type,
|
const sem::Type* type,
|
||||||
const ast::AttributeList& attributes) const;
|
utils::VectorRef<const ast::Attribute*> attributes) const;
|
||||||
|
|
||||||
/// Gathers all the texture resource bindings of the given type for the given
|
/// Gathers all the texture resource bindings of the given type for the given
|
||||||
/// entry point.
|
/// entry point.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -27,32 +27,36 @@ namespace tint::inspector {
|
||||||
InspectorBuilder::InspectorBuilder() = default;
|
InspectorBuilder::InspectorBuilder() = default;
|
||||||
InspectorBuilder::~InspectorBuilder() = default;
|
InspectorBuilder::~InspectorBuilder() = default;
|
||||||
|
|
||||||
void InspectorBuilder::MakeEmptyBodyFunction(std::string name, ast::AttributeList attributes) {
|
void InspectorBuilder::MakeEmptyBodyFunction(std::string name,
|
||||||
Func(name, {}, ty.void_(), {Return()}, attributes);
|
utils::VectorRef<const ast::Attribute*> attributes) {
|
||||||
|
Func(name, utils::Empty, ty.void_(), utils::Vector{Return()}, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InspectorBuilder::MakeCallerBodyFunction(std::string caller,
|
void InspectorBuilder::MakeCallerBodyFunction(std::string caller,
|
||||||
std::vector<std::string> callees,
|
utils::VectorRef<std::string> callees,
|
||||||
ast::AttributeList attributes) {
|
utils::VectorRef<const ast::Attribute*> attributes) {
|
||||||
ast::StatementList body;
|
utils::Vector<const ast::Statement*, 8> body;
|
||||||
body.reserve(callees.size() + 1);
|
body.Reserve(callees.Length() + 1);
|
||||||
for (auto callee : callees) {
|
for (auto callee : callees) {
|
||||||
body.push_back(CallStmt(Call(callee)));
|
body.Push(CallStmt(Call(callee)));
|
||||||
}
|
}
|
||||||
body.push_back(Return());
|
body.Push(Return());
|
||||||
|
|
||||||
Func(caller, {}, ty.void_(), body, attributes);
|
Func(caller, utils::Empty, ty.void_(), body, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Struct* InspectorBuilder::MakeInOutStruct(
|
const ast::Struct* InspectorBuilder::MakeInOutStruct(std::string name,
|
||||||
std::string name,
|
utils::VectorRef<InOutInfo> inout_vars) {
|
||||||
std::vector<std::tuple<std::string, uint32_t>> inout_vars) {
|
utils::Vector<const ast::StructMember*, 8> members;
|
||||||
ast::StructMemberList members;
|
|
||||||
for (auto var : inout_vars) {
|
for (auto var : inout_vars) {
|
||||||
std::string member_name;
|
std::string member_name;
|
||||||
uint32_t location;
|
uint32_t location;
|
||||||
std::tie(member_name, location) = var;
|
std::tie(member_name, location) = var;
|
||||||
members.push_back(Member(member_name, ty.u32(), {Location(location), Flat()}));
|
members.Push(Member(member_name, ty.u32(),
|
||||||
|
utils::Vector{
|
||||||
|
Location(location),
|
||||||
|
Flat(),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
return Structure(name, members);
|
return Structure(name, members);
|
||||||
}
|
}
|
||||||
|
@ -61,17 +65,15 @@ const ast::Function* InspectorBuilder::MakePlainGlobalReferenceBodyFunction(
|
||||||
std::string func,
|
std::string func,
|
||||||
std::string var,
|
std::string var,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
ast::AttributeList attributes) {
|
utils::VectorRef<const ast::Attribute*> attributes) {
|
||||||
ast::StatementList stmts;
|
utils::Vector<const ast::Statement*, 3> stmts;
|
||||||
stmts.emplace_back(Decl(Var("local_" + var, type)));
|
stmts.Push(Decl(Var("local_" + var, type)));
|
||||||
stmts.emplace_back(Assign("local_" + var, var));
|
stmts.Push(Assign("local_" + var, var));
|
||||||
stmts.emplace_back(Return());
|
stmts.Push(Return());
|
||||||
|
return Func(func, utils::Empty, ty.void_(), std::move(stmts), std::move(attributes));
|
||||||
return Func(func, {}, ty.void_(), stmts, attributes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InspectorBuilder::ContainsName(const std::vector<StageVariable>& vec,
|
bool InspectorBuilder::ContainsName(utils::VectorRef<StageVariable> vec, const std::string& name) {
|
||||||
const std::string& name) {
|
|
||||||
for (auto& s : vec) {
|
for (auto& s : vec) {
|
||||||
if (s.name == name) {
|
if (s.name == name) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -84,35 +86,38 @@ std::string InspectorBuilder::StructMemberName(size_t idx, const ast::Type* type
|
||||||
return std::to_string(idx) + type->FriendlyName(Symbols());
|
return std::to_string(idx) + type->FriendlyName(Symbols());
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Struct* InspectorBuilder::MakeStructType(const std::string& name,
|
const ast::Struct* InspectorBuilder::MakeStructType(
|
||||||
std::vector<const ast::Type*> member_types) {
|
const std::string& name,
|
||||||
ast::StructMemberList members;
|
utils::VectorRef<const ast::Type*> member_types) {
|
||||||
|
utils::Vector<const ast::StructMember*, 8> members;
|
||||||
for (auto* type : member_types) {
|
for (auto* type : member_types) {
|
||||||
members.push_back(MakeStructMember(members.size(), type, {}));
|
members.Push(MakeStructMember(members.Length(), type, {}));
|
||||||
}
|
}
|
||||||
return MakeStructTypeFromMembers(name, std::move(members));
|
return MakeStructTypeFromMembers(name, std::move(members));
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Struct* InspectorBuilder::MakeStructTypeFromMembers(const std::string& name,
|
const ast::Struct* InspectorBuilder::MakeStructTypeFromMembers(
|
||||||
ast::StructMemberList members) {
|
const std::string& name,
|
||||||
|
utils::VectorRef<const ast::StructMember*> members) {
|
||||||
return Structure(name, std::move(members));
|
return Structure(name, std::move(members));
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::StructMember* InspectorBuilder::MakeStructMember(size_t index,
|
const ast::StructMember* InspectorBuilder::MakeStructMember(
|
||||||
const ast::Type* type,
|
size_t index,
|
||||||
ast::AttributeList attributes) {
|
const ast::Type* type,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes) {
|
||||||
return Member(StructMemberName(index, type), type, std::move(attributes));
|
return Member(StructMemberName(index, type), type, std::move(attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Struct* InspectorBuilder::MakeUniformBufferType(
|
const ast::Struct* InspectorBuilder::MakeUniformBufferType(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
std::vector<const ast::Type*> member_types) {
|
utils::VectorRef<const ast::Type*> member_types) {
|
||||||
return MakeStructType(name, member_types);
|
return MakeStructType(name, member_types);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<const ast::TypeName*()> InspectorBuilder::MakeStorageBufferTypes(
|
std::function<const ast::TypeName*()> InspectorBuilder::MakeStorageBufferTypes(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
std::vector<const ast::Type*> member_types) {
|
utils::VectorRef<const ast::Type*> member_types) {
|
||||||
MakeStructType(name, member_types);
|
MakeStructType(name, member_types);
|
||||||
return [this, name] { return ty.type_name(name); };
|
return [this, name] { return ty.type_name(name); };
|
||||||
}
|
}
|
||||||
|
@ -122,7 +127,7 @@ void InspectorBuilder::AddUniformBuffer(const std::string& name,
|
||||||
uint32_t group,
|
uint32_t group,
|
||||||
uint32_t binding) {
|
uint32_t binding) {
|
||||||
GlobalVar(name, type, ast::StorageClass::kUniform,
|
GlobalVar(name, type, ast::StorageClass::kUniform,
|
||||||
ast::AttributeList{
|
utils::Vector{
|
||||||
create<ast::BindingAttribute>(binding),
|
create<ast::BindingAttribute>(binding),
|
||||||
create<ast::GroupAttribute>(group),
|
create<ast::GroupAttribute>(group),
|
||||||
});
|
});
|
||||||
|
@ -138,7 +143,7 @@ void InspectorBuilder::AddStorageBuffer(const std::string& name,
|
||||||
uint32_t group,
|
uint32_t group,
|
||||||
uint32_t binding) {
|
uint32_t binding) {
|
||||||
GlobalVar(name, type, ast::StorageClass::kStorage, access,
|
GlobalVar(name, type, ast::StorageClass::kStorage, access,
|
||||||
ast::AttributeList{
|
utils::Vector{
|
||||||
create<ast::BindingAttribute>(binding),
|
create<ast::BindingAttribute>(binding),
|
||||||
create<ast::GroupAttribute>(group),
|
create<ast::GroupAttribute>(group),
|
||||||
});
|
});
|
||||||
|
@ -147,15 +152,15 @@ void InspectorBuilder::AddStorageBuffer(const std::string& name,
|
||||||
void InspectorBuilder::MakeStructVariableReferenceBodyFunction(
|
void InspectorBuilder::MakeStructVariableReferenceBodyFunction(
|
||||||
std::string func_name,
|
std::string func_name,
|
||||||
std::string struct_name,
|
std::string struct_name,
|
||||||
std::vector<std::tuple<size_t, const ast::Type*>> members) {
|
utils::VectorRef<std::tuple<size_t, const ast::Type*>> members) {
|
||||||
ast::StatementList stmts;
|
utils::Vector<const ast::Statement*, 8> stmts;
|
||||||
for (auto member : members) {
|
for (auto member : members) {
|
||||||
size_t member_idx;
|
size_t member_idx;
|
||||||
const ast::Type* member_type;
|
const ast::Type* member_type;
|
||||||
std::tie(member_idx, member_type) = member;
|
std::tie(member_idx, member_type) = member;
|
||||||
std::string member_name = StructMemberName(member_idx, member_type);
|
std::string member_name = StructMemberName(member_idx, member_type);
|
||||||
|
|
||||||
stmts.emplace_back(Decl(Var("local" + member_name, member_type)));
|
stmts.Push(Decl(Var("local" + member_name, member_type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto member : members) {
|
for (auto member : members) {
|
||||||
|
@ -164,17 +169,17 @@ void InspectorBuilder::MakeStructVariableReferenceBodyFunction(
|
||||||
std::tie(member_idx, member_type) = member;
|
std::tie(member_idx, member_type) = member;
|
||||||
std::string member_name = StructMemberName(member_idx, member_type);
|
std::string member_name = StructMemberName(member_idx, member_type);
|
||||||
|
|
||||||
stmts.emplace_back(Assign("local" + member_name, MemberAccessor(struct_name, member_name)));
|
stmts.Push(Assign("local" + member_name, MemberAccessor(struct_name, member_name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
stmts.emplace_back(Return());
|
stmts.Push(Return());
|
||||||
|
|
||||||
Func(func_name, {}, ty.void_(), stmts);
|
Func(func_name, utils::Empty, ty.void_(), stmts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InspectorBuilder::AddSampler(const std::string& name, uint32_t group, uint32_t binding) {
|
void InspectorBuilder::AddSampler(const std::string& name, uint32_t group, uint32_t binding) {
|
||||||
GlobalVar(name, sampler_type(),
|
GlobalVar(name, sampler_type(),
|
||||||
ast::AttributeList{
|
utils::Vector{
|
||||||
create<ast::BindingAttribute>(binding),
|
create<ast::BindingAttribute>(binding),
|
||||||
create<ast::GroupAttribute>(group),
|
create<ast::GroupAttribute>(group),
|
||||||
});
|
});
|
||||||
|
@ -184,7 +189,7 @@ void InspectorBuilder::AddComparisonSampler(const std::string& name,
|
||||||
uint32_t group,
|
uint32_t group,
|
||||||
uint32_t binding) {
|
uint32_t binding) {
|
||||||
GlobalVar(name, comparison_sampler_type(),
|
GlobalVar(name, comparison_sampler_type(),
|
||||||
ast::AttributeList{
|
utils::Vector{
|
||||||
create<ast::BindingAttribute>(binding),
|
create<ast::BindingAttribute>(binding),
|
||||||
create<ast::GroupAttribute>(group),
|
create<ast::GroupAttribute>(group),
|
||||||
});
|
});
|
||||||
|
@ -195,7 +200,7 @@ void InspectorBuilder::AddResource(const std::string& name,
|
||||||
uint32_t group,
|
uint32_t group,
|
||||||
uint32_t binding) {
|
uint32_t binding) {
|
||||||
GlobalVar(name, type,
|
GlobalVar(name, type,
|
||||||
ast::AttributeList{
|
utils::Vector{
|
||||||
create<ast::BindingAttribute>(binding),
|
create<ast::BindingAttribute>(binding),
|
||||||
create<ast::GroupAttribute>(group),
|
create<ast::GroupAttribute>(group),
|
||||||
});
|
});
|
||||||
|
@ -211,17 +216,15 @@ const ast::Function* InspectorBuilder::MakeSamplerReferenceBodyFunction(
|
||||||
const std::string& sampler_name,
|
const std::string& sampler_name,
|
||||||
const std::string& coords_name,
|
const std::string& coords_name,
|
||||||
const ast::Type* base_type,
|
const ast::Type* base_type,
|
||||||
ast::AttributeList attributes) {
|
utils::VectorRef<const ast::Attribute*> attributes) {
|
||||||
std::string result_name = "sampler_result";
|
std::string result_name = "sampler_result";
|
||||||
|
|
||||||
ast::StatementList stmts;
|
utils::Vector stmts{
|
||||||
stmts.emplace_back(Decl(Var(result_name, ty.vec(base_type, 4))));
|
Decl(Var(result_name, ty.vec(base_type, 4))),
|
||||||
|
Assign(result_name, Call("textureSample", texture_name, sampler_name, coords_name)),
|
||||||
stmts.emplace_back(
|
Return(),
|
||||||
Assign(result_name, Call("textureSample", texture_name, sampler_name, coords_name)));
|
};
|
||||||
stmts.emplace_back(Return());
|
return Func(func_name, utils::Empty, ty.void_(), std::move(stmts), std::move(attributes));
|
||||||
|
|
||||||
return Func(func_name, {}, ty.void_(), stmts, attributes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Function* InspectorBuilder::MakeSamplerReferenceBodyFunction(
|
const ast::Function* InspectorBuilder::MakeSamplerReferenceBodyFunction(
|
||||||
|
@ -231,18 +234,16 @@ const ast::Function* InspectorBuilder::MakeSamplerReferenceBodyFunction(
|
||||||
const std::string& coords_name,
|
const std::string& coords_name,
|
||||||
const std::string& array_index,
|
const std::string& array_index,
|
||||||
const ast::Type* base_type,
|
const ast::Type* base_type,
|
||||||
ast::AttributeList attributes) {
|
utils::VectorRef<const ast::Attribute*> attributes) {
|
||||||
std::string result_name = "sampler_result";
|
std::string result_name = "sampler_result";
|
||||||
|
|
||||||
ast::StatementList stmts;
|
utils::Vector stmts{
|
||||||
|
Decl(Var("sampler_result", ty.vec(base_type, 4))),
|
||||||
stmts.emplace_back(Decl(Var("sampler_result", ty.vec(base_type, 4))));
|
Assign("sampler_result",
|
||||||
|
Call("textureSample", texture_name, sampler_name, coords_name, array_index)),
|
||||||
stmts.emplace_back(Assign("sampler_result", Call("textureSample", texture_name, sampler_name,
|
Return(),
|
||||||
coords_name, array_index)));
|
};
|
||||||
stmts.emplace_back(Return());
|
return Func(func_name, utils::Empty, ty.void_(), std::move(stmts), std::move(attributes));
|
||||||
|
|
||||||
return Func(func_name, {}, ty.void_(), stmts, attributes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Function* InspectorBuilder::MakeComparisonSamplerReferenceBodyFunction(
|
const ast::Function* InspectorBuilder::MakeComparisonSamplerReferenceBodyFunction(
|
||||||
|
@ -252,17 +253,16 @@ const ast::Function* InspectorBuilder::MakeComparisonSamplerReferenceBodyFunctio
|
||||||
const std::string& coords_name,
|
const std::string& coords_name,
|
||||||
const std::string& depth_name,
|
const std::string& depth_name,
|
||||||
const ast::Type* base_type,
|
const ast::Type* base_type,
|
||||||
ast::AttributeList attributes) {
|
utils::VectorRef<const ast::Attribute*> attributes) {
|
||||||
std::string result_name = "sampler_result";
|
std::string result_name = "sampler_result";
|
||||||
|
|
||||||
ast::StatementList stmts;
|
utils::Vector stmts{
|
||||||
|
Decl(Var("sampler_result", base_type)),
|
||||||
stmts.emplace_back(Decl(Var("sampler_result", base_type)));
|
Assign("sampler_result",
|
||||||
stmts.emplace_back(Assign("sampler_result", Call("textureSampleCompare", texture_name,
|
Call("textureSampleCompare", texture_name, sampler_name, coords_name, depth_name)),
|
||||||
sampler_name, coords_name, depth_name)));
|
Return(),
|
||||||
stmts.emplace_back(Return());
|
};
|
||||||
|
return Func(func_name, utils::Empty, ty.void_(), std::move(stmts), std::move(attributes));
|
||||||
return Func(func_name, {}, ty.void_(), stmts, attributes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Type* InspectorBuilder::GetBaseType(ResourceBinding::SampledKind sampled_kind) {
|
const ast::Type* InspectorBuilder::GetBaseType(ResourceBinding::SampledKind sampled_kind) {
|
||||||
|
@ -306,7 +306,7 @@ void InspectorBuilder::AddStorageTexture(const std::string& name,
|
||||||
uint32_t group,
|
uint32_t group,
|
||||||
uint32_t binding) {
|
uint32_t binding) {
|
||||||
GlobalVar(name, type,
|
GlobalVar(name, type,
|
||||||
ast::AttributeList{
|
utils::Vector{
|
||||||
create<ast::BindingAttribute>(binding),
|
create<ast::BindingAttribute>(binding),
|
||||||
create<ast::GroupAttribute>(group),
|
create<ast::GroupAttribute>(group),
|
||||||
});
|
});
|
||||||
|
@ -316,14 +316,14 @@ const ast::Function* InspectorBuilder::MakeStorageTextureBodyFunction(
|
||||||
const std::string& func_name,
|
const std::string& func_name,
|
||||||
const std::string& st_name,
|
const std::string& st_name,
|
||||||
const ast::Type* dim_type,
|
const ast::Type* dim_type,
|
||||||
ast::AttributeList attributes) {
|
utils::VectorRef<const ast::Attribute*> attributes) {
|
||||||
ast::StatementList stmts;
|
utils::Vector stmts{
|
||||||
|
Decl(Var("dim", dim_type)),
|
||||||
|
Assign("dim", Call("textureDimensions", st_name)),
|
||||||
|
Return(),
|
||||||
|
};
|
||||||
|
|
||||||
stmts.emplace_back(Decl(Var("dim", dim_type)));
|
return Func(func_name, utils::Empty, ty.void_(), std::move(stmts), std::move(attributes));
|
||||||
stmts.emplace_back(Assign("dim", Call("textureDimensions", st_name)));
|
|
||||||
stmts.emplace_back(Return());
|
|
||||||
|
|
||||||
return Func(func_name, {}, ty.void_(), stmts, attributes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<const ast::Type*()> InspectorBuilder::GetTypeFunction(ComponentType component,
|
std::function<const ast::Type*()> InspectorBuilder::GetTypeFunction(ComponentType component,
|
||||||
|
|
|
@ -44,28 +44,31 @@ class InspectorBuilder : public ProgramBuilder {
|
||||||
/// Generates an empty function
|
/// Generates an empty function
|
||||||
/// @param name name of the function created
|
/// @param name name of the function created
|
||||||
/// @param attributes the function attributes
|
/// @param attributes the function attributes
|
||||||
void MakeEmptyBodyFunction(std::string name, ast::AttributeList attributes);
|
void MakeEmptyBodyFunction(std::string name,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes);
|
||||||
|
|
||||||
/// Generates a function that calls other functions
|
/// Generates a function that calls other functions
|
||||||
/// @param caller name of the function created
|
/// @param caller name of the function created
|
||||||
/// @param callees names of the functions to be called
|
/// @param callees names of the functions to be called
|
||||||
/// @param attributes the function attributes
|
/// @param attributes the function attributes
|
||||||
void MakeCallerBodyFunction(std::string caller,
|
void MakeCallerBodyFunction(std::string caller,
|
||||||
std::vector<std::string> callees,
|
utils::VectorRef<std::string> callees,
|
||||||
ast::AttributeList attributes);
|
utils::VectorRef<const ast::Attribute*> attributes);
|
||||||
|
|
||||||
|
/// InOutInfo is a tuple of name and location for a structure member
|
||||||
|
using InOutInfo = std::tuple<std::string, uint32_t>;
|
||||||
|
|
||||||
/// Generates a struct that contains user-defined IO members
|
/// Generates a struct that contains user-defined IO members
|
||||||
/// @param name the name of the generated struct
|
/// @param name the name of the generated struct
|
||||||
/// @param inout_vars tuples of {name, loc} that will be the struct members
|
/// @param inout_vars tuples of {name, loc} that will be the struct members
|
||||||
/// @returns a structure object
|
/// @returns a structure object
|
||||||
const ast::Struct* MakeInOutStruct(std::string name,
|
const ast::Struct* MakeInOutStruct(std::string name, utils::VectorRef<InOutInfo> inout_vars);
|
||||||
std::vector<std::tuple<std::string, uint32_t>> inout_vars);
|
|
||||||
|
|
||||||
// TODO(crbug.com/tint/697): Remove this.
|
// TODO(crbug.com/tint/697): Remove this.
|
||||||
/// Add In/Out variables to the global variables
|
/// Add In/Out variables to the global variables
|
||||||
/// @param inout_vars tuples of {in, out} that will be added as entries to the
|
/// @param inout_vars tuples of {in, out} that will be added as entries to the
|
||||||
/// global variables
|
/// global variables
|
||||||
void AddInOutVariables(std::vector<std::tuple<std::string, std::string>> inout_vars);
|
void AddInOutVariables(utils::VectorRef<std::tuple<std::string, std::string>> inout_vars);
|
||||||
|
|
||||||
// TODO(crbug.com/tint/697): Remove this.
|
// TODO(crbug.com/tint/697): Remove this.
|
||||||
/// Generates a function that references in/out variables
|
/// Generates a function that references in/out variables
|
||||||
|
@ -73,9 +76,10 @@ class InspectorBuilder : public ProgramBuilder {
|
||||||
/// @param inout_vars tuples of {in, out} that will be converted into out = in
|
/// @param inout_vars tuples of {in, out} that will be converted into out = in
|
||||||
/// calls in the function body
|
/// calls in the function body
|
||||||
/// @param attributes the function attributes
|
/// @param attributes the function attributes
|
||||||
void MakeInOutVariableBodyFunction(std::string name,
|
void MakeInOutVariableBodyFunction(
|
||||||
std::vector<std::tuple<std::string, std::string>> inout_vars,
|
std::string name,
|
||||||
ast::AttributeList attributes);
|
utils::VectorRef<std::tuple<std::string, std::string>> inout_vars,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes);
|
||||||
|
|
||||||
// TODO(crbug.com/tint/697): Remove this.
|
// TODO(crbug.com/tint/697): Remove this.
|
||||||
/// Generates a function that references in/out variables and calls another
|
/// Generates a function that references in/out variables and calls another
|
||||||
|
@ -89,9 +93,8 @@ class InspectorBuilder : public ProgramBuilder {
|
||||||
const ast::Function* MakeInOutVariableCallerBodyFunction(
|
const ast::Function* MakeInOutVariableCallerBodyFunction(
|
||||||
std::string caller,
|
std::string caller,
|
||||||
std::string callee,
|
std::string callee,
|
||||||
std::vector<std::tuple<std::string, std::string>> inout_vars,
|
utils::VectorRef<std::tuple<std::string, std::string>> inout_vars,
|
||||||
ast::AttributeList attributes);
|
utils::VectorRef<const ast::Attribute*> attributes);
|
||||||
|
|
||||||
|
|
||||||
/// Generates a function that references module-scoped, plain-typed constant
|
/// Generates a function that references module-scoped, plain-typed constant
|
||||||
/// or variable.
|
/// or variable.
|
||||||
|
@ -100,15 +103,16 @@ class InspectorBuilder : public ProgramBuilder {
|
||||||
/// @param type type of the const being referenced
|
/// @param type type of the const being referenced
|
||||||
/// @param attributes the function attributes
|
/// @param attributes the function attributes
|
||||||
/// @returns a function object
|
/// @returns a function object
|
||||||
const ast::Function* MakePlainGlobalReferenceBodyFunction(std::string func,
|
const ast::Function* MakePlainGlobalReferenceBodyFunction(
|
||||||
std::string var,
|
std::string func,
|
||||||
const ast::Type* type,
|
std::string var,
|
||||||
ast::AttributeList attributes);
|
const ast::Type* type,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes);
|
||||||
|
|
||||||
/// @param vec Vector of StageVariable to be searched
|
/// @param vec Vector of StageVariable to be searched
|
||||||
/// @param name Name to be searching for
|
/// @param name Name to be searching for
|
||||||
/// @returns true if name is in vec, otherwise false
|
/// @returns true if name is in vec, otherwise false
|
||||||
bool ContainsName(const std::vector<StageVariable>& vec, const std::string& name);
|
bool ContainsName(utils::VectorRef<StageVariable> vec, const std::string& name);
|
||||||
|
|
||||||
/// Builds a string for accessing a member in a generated struct
|
/// Builds a string for accessing a member in a generated struct
|
||||||
/// @param idx index of member
|
/// @param idx index of member
|
||||||
|
@ -121,14 +125,15 @@ class InspectorBuilder : public ProgramBuilder {
|
||||||
/// @param member_types a vector of member types
|
/// @param member_types a vector of member types
|
||||||
/// @returns a struct type
|
/// @returns a struct type
|
||||||
const ast::Struct* MakeStructType(const std::string& name,
|
const ast::Struct* MakeStructType(const std::string& name,
|
||||||
std::vector<const ast::Type*> member_types);
|
utils::VectorRef<const ast::Type*> member_types);
|
||||||
|
|
||||||
/// Generates a struct type from a list of member nodes.
|
/// Generates a struct type from a list of member nodes.
|
||||||
/// @param name name for the struct type
|
/// @param name name for the struct type
|
||||||
/// @param members a vector of members
|
/// @param members a vector of members
|
||||||
/// @returns a struct type
|
/// @returns a struct type
|
||||||
const ast::Struct* MakeStructTypeFromMembers(const std::string& name,
|
const ast::Struct* MakeStructTypeFromMembers(
|
||||||
ast::StructMemberList members);
|
const std::string& name,
|
||||||
|
utils::VectorRef<const ast::StructMember*> members);
|
||||||
|
|
||||||
/// Generates a struct member with a specified index and type.
|
/// Generates a struct member with a specified index and type.
|
||||||
/// @param index index of the field within the struct
|
/// @param index index of the field within the struct
|
||||||
|
@ -137,14 +142,14 @@ class InspectorBuilder : public ProgramBuilder {
|
||||||
/// @returns a struct member
|
/// @returns a struct member
|
||||||
const ast::StructMember* MakeStructMember(size_t index,
|
const ast::StructMember* MakeStructMember(size_t index,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
ast::AttributeList attributes);
|
utils::VectorRef<const ast::Attribute*> attributes);
|
||||||
|
|
||||||
/// Generates types appropriate for using in an uniform buffer
|
/// Generates types appropriate for using in an uniform buffer
|
||||||
/// @param name name for the type
|
/// @param name name for the type
|
||||||
/// @param member_types a vector of member types
|
/// @param member_types a vector of member types
|
||||||
/// @returns a struct type that has the layout for an uniform buffer.
|
/// @returns a struct type that has the layout for an uniform buffer.
|
||||||
const ast::Struct* MakeUniformBufferType(const std::string& name,
|
const ast::Struct* MakeUniformBufferType(const std::string& name,
|
||||||
std::vector<const ast::Type*> member_types);
|
utils::VectorRef<const ast::Type*> member_types);
|
||||||
|
|
||||||
/// Generates types appropriate for using in a storage buffer
|
/// Generates types appropriate for using in a storage buffer
|
||||||
/// @param name name for the type
|
/// @param name name for the type
|
||||||
|
@ -152,7 +157,7 @@ class InspectorBuilder : public ProgramBuilder {
|
||||||
/// @returns a function that returns the created structure.
|
/// @returns a function that returns the created structure.
|
||||||
std::function<const ast::TypeName*()> MakeStorageBufferTypes(
|
std::function<const ast::TypeName*()> MakeStorageBufferTypes(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
std::vector<const ast::Type*> member_types);
|
utils::VectorRef<const ast::Type*> member_types);
|
||||||
|
|
||||||
/// Adds an uniform buffer variable to the program
|
/// Adds an uniform buffer variable to the program
|
||||||
/// @param name the name of the variable
|
/// @param name the name of the variable
|
||||||
|
@ -181,14 +186,16 @@ class InspectorBuilder : public ProgramBuilder {
|
||||||
uint32_t group,
|
uint32_t group,
|
||||||
uint32_t binding);
|
uint32_t binding);
|
||||||
|
|
||||||
|
/// MemberInfo is a tuple of member index and type.
|
||||||
|
using MemberInfo = std::tuple<size_t, const ast::Type*>;
|
||||||
|
|
||||||
/// Generates a function that references a specific struct variable
|
/// Generates a function that references a specific struct variable
|
||||||
/// @param func_name name of the function created
|
/// @param func_name name of the function created
|
||||||
/// @param struct_name name of the struct variabler to be accessed
|
/// @param struct_name name of the struct variabler to be accessed
|
||||||
/// @param members list of members to access, by index and type
|
/// @param members list of members to access, by index and type
|
||||||
void MakeStructVariableReferenceBodyFunction(
|
void MakeStructVariableReferenceBodyFunction(std::string func_name,
|
||||||
std::string func_name,
|
std::string struct_name,
|
||||||
std::string struct_name,
|
utils::VectorRef<MemberInfo> members);
|
||||||
std::vector<std::tuple<size_t, const ast::Type*>> members);
|
|
||||||
|
|
||||||
/// Adds a regular sampler variable to the program
|
/// Adds a regular sampler variable to the program
|
||||||
/// @param name the name of the variable
|
/// @param name the name of the variable
|
||||||
|
@ -225,12 +232,13 @@ class InspectorBuilder : public ProgramBuilder {
|
||||||
/// @param base_type sampler base type
|
/// @param base_type sampler base type
|
||||||
/// @param attributes the function attributes
|
/// @param attributes the function attributes
|
||||||
/// @returns a function that references all of the values specified
|
/// @returns a function that references all of the values specified
|
||||||
const ast::Function* MakeSamplerReferenceBodyFunction(const std::string& func_name,
|
const ast::Function* MakeSamplerReferenceBodyFunction(
|
||||||
const std::string& texture_name,
|
const std::string& func_name,
|
||||||
const std::string& sampler_name,
|
const std::string& texture_name,
|
||||||
const std::string& coords_name,
|
const std::string& sampler_name,
|
||||||
const ast::Type* base_type,
|
const std::string& coords_name,
|
||||||
ast::AttributeList attributes);
|
const ast::Type* base_type,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes);
|
||||||
|
|
||||||
/// Generates a function that references a specific sampler variable
|
/// Generates a function that references a specific sampler variable
|
||||||
/// @param func_name name of the function created
|
/// @param func_name name of the function created
|
||||||
|
@ -241,13 +249,14 @@ class InspectorBuilder : public ProgramBuilder {
|
||||||
/// @param base_type sampler base type
|
/// @param base_type sampler base type
|
||||||
/// @param attributes the function attributes
|
/// @param attributes the function attributes
|
||||||
/// @returns a function that references all of the values specified
|
/// @returns a function that references all of the values specified
|
||||||
const ast::Function* MakeSamplerReferenceBodyFunction(const std::string& func_name,
|
const ast::Function* MakeSamplerReferenceBodyFunction(
|
||||||
const std::string& texture_name,
|
const std::string& func_name,
|
||||||
const std::string& sampler_name,
|
const std::string& texture_name,
|
||||||
const std::string& coords_name,
|
const std::string& sampler_name,
|
||||||
const std::string& array_index,
|
const std::string& coords_name,
|
||||||
const ast::Type* base_type,
|
const std::string& array_index,
|
||||||
ast::AttributeList attributes);
|
const ast::Type* base_type,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes);
|
||||||
|
|
||||||
/// Generates a function that references a specific comparison sampler
|
/// Generates a function that references a specific comparison sampler
|
||||||
/// variable.
|
/// variable.
|
||||||
|
@ -259,13 +268,14 @@ class InspectorBuilder : public ProgramBuilder {
|
||||||
/// @param base_type sampler base type
|
/// @param base_type sampler base type
|
||||||
/// @param attributes the function attributes
|
/// @param attributes the function attributes
|
||||||
/// @returns a function that references all of the values specified
|
/// @returns a function that references all of the values specified
|
||||||
const ast::Function* MakeComparisonSamplerReferenceBodyFunction(const std::string& func_name,
|
const ast::Function* MakeComparisonSamplerReferenceBodyFunction(
|
||||||
const std::string& texture_name,
|
const std::string& func_name,
|
||||||
const std::string& sampler_name,
|
const std::string& texture_name,
|
||||||
const std::string& coords_name,
|
const std::string& sampler_name,
|
||||||
const std::string& depth_name,
|
const std::string& coords_name,
|
||||||
const ast::Type* base_type,
|
const std::string& depth_name,
|
||||||
ast::AttributeList attributes);
|
const ast::Type* base_type,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes);
|
||||||
|
|
||||||
/// Gets an appropriate type for the data in a given texture type.
|
/// Gets an appropriate type for the data in a given texture type.
|
||||||
/// @param sampled_kind type of in the texture
|
/// @param sampled_kind type of in the texture
|
||||||
|
@ -301,10 +311,11 @@ class InspectorBuilder : public ProgramBuilder {
|
||||||
/// @param dim_type type expected by textureDimensons to return
|
/// @param dim_type type expected by textureDimensons to return
|
||||||
/// @param attributes the function attributes
|
/// @param attributes the function attributes
|
||||||
/// @returns a function that references all of the values specified
|
/// @returns a function that references all of the values specified
|
||||||
const ast::Function* MakeStorageTextureBodyFunction(const std::string& func_name,
|
const ast::Function* MakeStorageTextureBodyFunction(
|
||||||
const std::string& st_name,
|
const std::string& func_name,
|
||||||
const ast::Type* dim_type,
|
const std::string& st_name,
|
||||||
ast::AttributeList attributes);
|
const ast::Type* dim_type,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes);
|
||||||
|
|
||||||
/// Get a generator function that returns a type appropriate for a stage
|
/// Get a generator function that returns a type appropriate for a stage
|
||||||
/// variable with the given combination of component and composition type.
|
/// variable with the given combination of component and composition type.
|
||||||
|
|
|
@ -129,9 +129,9 @@ const ast::Statement* ProgramBuilder::WrapInStatement(const ast::Statement* stmt
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Function* ProgramBuilder::WrapInFunction(const ast::StatementList stmts) {
|
const ast::Function* ProgramBuilder::WrapInFunction(utils::VectorRef<const ast::Statement*> stmts) {
|
||||||
return Func("test_function", {}, ty.void_(), std::move(stmts),
|
return Func("test_function", {}, ty.void_(), std::move(stmts),
|
||||||
{
|
utils::Vector{
|
||||||
create<ast::StageAttribute>(ast::PipelineStage::kCompute),
|
create<ast::StageAttribute>(ast::PipelineStage::kCompute),
|
||||||
WorkgroupSize(1_i, 1_i, 1_i),
|
WorkgroupSize(1_i, 1_i, 1_i),
|
||||||
});
|
});
|
||||||
|
|
|
@ -120,6 +120,30 @@ class VariableDeclStatement;
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/// IsVectorLike<T>::value is true if T is a utils::Vector or utils::VectorRef.
|
||||||
|
template <typename T>
|
||||||
|
struct IsVectorLike {
|
||||||
|
/// Non-specialized form of IsVectorLike defaults to false
|
||||||
|
static constexpr bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// IsVectorLike specialization for utils::Vector
|
||||||
|
template <typename T, size_t N>
|
||||||
|
struct IsVectorLike<utils::Vector<T, N>> {
|
||||||
|
/// True for the IsVectorLike specialization of utils::Vector
|
||||||
|
static constexpr bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// IsVectorLike specialization for utils::VectorRef
|
||||||
|
template <typename T>
|
||||||
|
struct IsVectorLike<utils::VectorRef<T>> {
|
||||||
|
/// True for the IsVectorLike specialization of utils::VectorRef
|
||||||
|
static constexpr bool value = true;
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
/// ProgramBuilder is a mutable builder for a Program.
|
/// ProgramBuilder is a mutable builder for a Program.
|
||||||
/// To construct a Program, populate the builder and then `std::move` it to a
|
/// To construct a Program, populate the builder and then `std::move` it to a
|
||||||
/// Program.
|
/// Program.
|
||||||
|
@ -131,6 +155,12 @@ class ProgramBuilder {
|
||||||
using DisableIfSource =
|
using DisableIfSource =
|
||||||
traits::EnableIfIsNotType<traits::Decay<traits::NthTypeOf<0, TYPES..., void>>, Source>;
|
traits::EnableIfIsNotType<traits::Decay<traits::NthTypeOf<0, TYPES..., void>>, Source>;
|
||||||
|
|
||||||
|
/// A helper used to disable overloads if the first type in `TYPES` is a utils::Vector,
|
||||||
|
/// utils::VectorRef or utils::VectorRef.
|
||||||
|
template <typename... TYPES>
|
||||||
|
using DisableIfVectorLike = traits::EnableIf<
|
||||||
|
!detail::IsVectorLike<traits::Decay<traits::NthTypeOf<0, TYPES..., void>>>::value>;
|
||||||
|
|
||||||
/// VarOptionals is a helper for accepting a number of optional, extra
|
/// VarOptionals is a helper for accepting a number of optional, extra
|
||||||
/// arguments for Var() and GlobalVar().
|
/// arguments for Var() and GlobalVar().
|
||||||
struct VarOptionals {
|
struct VarOptionals {
|
||||||
|
@ -143,13 +173,13 @@ class ProgramBuilder {
|
||||||
ast::StorageClass storage = ast::StorageClass::kNone;
|
ast::StorageClass storage = ast::StorageClass::kNone;
|
||||||
ast::Access access = ast::Access::kUndefined;
|
ast::Access access = ast::Access::kUndefined;
|
||||||
const ast::Expression* constructor = nullptr;
|
const ast::Expression* constructor = nullptr;
|
||||||
ast::AttributeList attributes = {};
|
utils::Vector<const ast::Attribute*, 4> attributes;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Set(ast::StorageClass sc) { storage = sc; }
|
void Set(ast::StorageClass sc) { storage = sc; }
|
||||||
void Set(ast::Access ac) { access = ac; }
|
void Set(ast::Access ac) { access = ac; }
|
||||||
void Set(const ast::Expression* c) { constructor = c; }
|
void Set(const ast::Expression* c) { constructor = c; }
|
||||||
void Set(const ast::AttributeList& l) { attributes = l; }
|
void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
|
||||||
|
|
||||||
template <typename FIRST, typename... ARGS>
|
template <typename FIRST, typename... ARGS>
|
||||||
void Apply(FIRST&& first, ARGS&&... args) {
|
void Apply(FIRST&& first, ARGS&&... args) {
|
||||||
|
@ -687,11 +717,12 @@ class ProgramBuilder {
|
||||||
/// @param attrs the optional attributes for the array
|
/// @param attrs the optional attributes for the array
|
||||||
/// @return the tint AST type for a array of size `n` of type `T`
|
/// @return the tint AST type for a array of size `n` of type `T`
|
||||||
template <typename EXPR = ast::Expression*>
|
template <typename EXPR = ast::Expression*>
|
||||||
const ast::Array* array(const ast::Type* subtype,
|
const ast::Array* array(
|
||||||
EXPR&& n = nullptr,
|
const ast::Type* subtype,
|
||||||
ast::AttributeList attrs = {}) const {
|
EXPR&& n = nullptr,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
|
||||||
return builder->create<ast::Array>(subtype, builder->Expr(std::forward<EXPR>(n)),
|
return builder->create<ast::Array>(subtype, builder->Expr(std::forward<EXPR>(n)),
|
||||||
attrs);
|
std::move(attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @param source the Source of the node
|
/// @param source the Source of the node
|
||||||
|
@ -700,12 +731,13 @@ class ProgramBuilder {
|
||||||
/// @param attrs the optional attributes for the array
|
/// @param attrs the optional attributes for the array
|
||||||
/// @return the tint AST type for a array of size `n` of type `T`
|
/// @return the tint AST type for a array of size `n` of type `T`
|
||||||
template <typename EXPR = ast::Expression*>
|
template <typename EXPR = ast::Expression*>
|
||||||
const ast::Array* array(const Source& source,
|
const ast::Array* array(
|
||||||
const ast::Type* subtype,
|
const Source& source,
|
||||||
EXPR&& n = nullptr,
|
const ast::Type* subtype,
|
||||||
ast::AttributeList attrs = {}) const {
|
EXPR&& n = nullptr,
|
||||||
return builder->create<ast::Array>(source, subtype,
|
utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
|
||||||
builder->Expr(std::forward<EXPR>(n)), attrs);
|
return builder->create<ast::Array>(
|
||||||
|
source, subtype, builder->Expr(std::forward<EXPR>(n)), std::move(attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @param subtype the array element type
|
/// @param subtype the array element type
|
||||||
|
@ -714,9 +746,9 @@ class ProgramBuilder {
|
||||||
/// @return the tint AST type for a array of size `n` of type `T`
|
/// @return the tint AST type for a array of size `n` of type `T`
|
||||||
template <typename EXPR>
|
template <typename EXPR>
|
||||||
const ast::Array* array(const ast::Type* subtype, EXPR&& n, uint32_t stride) const {
|
const ast::Array* array(const ast::Type* subtype, EXPR&& n, uint32_t stride) const {
|
||||||
ast::AttributeList attrs;
|
utils::Vector<const ast::Attribute*, 2> attrs;
|
||||||
if (stride) {
|
if (stride) {
|
||||||
attrs.emplace_back(builder->create<ast::StrideAttribute>(stride));
|
attrs.Push(builder->create<ast::StrideAttribute>(stride));
|
||||||
}
|
}
|
||||||
return array(subtype, std::forward<EXPR>(n), std::move(attrs));
|
return array(subtype, std::forward<EXPR>(n), std::move(attrs));
|
||||||
}
|
}
|
||||||
|
@ -731,9 +763,9 @@ class ProgramBuilder {
|
||||||
const ast::Type* subtype,
|
const ast::Type* subtype,
|
||||||
EXPR&& n,
|
EXPR&& n,
|
||||||
uint32_t stride) const {
|
uint32_t stride) const {
|
||||||
ast::AttributeList attrs;
|
utils::Vector<const ast::Attribute*, 2> attrs;
|
||||||
if (stride) {
|
if (stride) {
|
||||||
attrs.emplace_back(builder->create<ast::StrideAttribute>(stride));
|
attrs.Push(builder->create<ast::StrideAttribute>(stride));
|
||||||
}
|
}
|
||||||
return array(source, subtype, std::forward<EXPR>(n), std::move(attrs));
|
return array(source, subtype, std::forward<EXPR>(n), std::move(attrs));
|
||||||
}
|
}
|
||||||
|
@ -1182,9 +1214,9 @@ class ProgramBuilder {
|
||||||
/// `list`.
|
/// `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 <size_t N, typename ARG>
|
||||||
void Append(ast::ExpressionList& list, ARG&& arg) {
|
void Append(utils::Vector<const ast::Expression*, N>& list, ARG&& arg) {
|
||||||
list.emplace_back(Expr(std::forward<ARG>(arg)));
|
list.Push(Expr(std::forward<ARG>(arg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts `arg0` and `args` to `ast::Expression`s using `Expr()`,
|
/// Converts `arg0` and `args` to `ast::Expression`s using `Expr()`,
|
||||||
|
@ -1192,29 +1224,38 @@ class ProgramBuilder {
|
||||||
/// @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 <size_t N, typename ARG0, typename... ARGS>
|
||||||
void Append(ast::ExpressionList& list, ARG0&& arg0, ARGS&&... args) {
|
void Append(utils::Vector<const ast::Expression*, N>& list, ARG0&& arg0, ARGS&&... args) {
|
||||||
Append(list, std::forward<ARG0>(arg0));
|
Append(list, std::forward<ARG0>(arg0));
|
||||||
Append(list, std::forward<ARGS>(args)...);
|
Append(list, std::forward<ARGS>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @return an empty list of expressions
|
/// @return utils::EmptyType
|
||||||
ast::ExpressionList ExprList() { return {}; }
|
utils::EmptyType ExprList() { return utils::Empty; }
|
||||||
|
|
||||||
/// @param args the list of expressions
|
/// @param args the list of expressions
|
||||||
/// @return the list of expressions converted to `ast::Expression`s using
|
/// @return the list of expressions converted to `ast::Expression`s using
|
||||||
/// `Expr()`,
|
/// `Expr()`,
|
||||||
template <typename... ARGS>
|
template <typename... ARGS, typename = DisableIfVectorLike<ARGS...>>
|
||||||
ast::ExpressionList ExprList(ARGS&&... args) {
|
auto ExprList(ARGS&&... args) {
|
||||||
ast::ExpressionList list;
|
utils::Vector<const ast::Expression*, sizeof...(ARGS)> list;
|
||||||
list.reserve(sizeof...(args));
|
|
||||||
Append(list, std::forward<ARGS>(args)...);
|
Append(list, std::forward<ARGS>(args)...);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @param list the list of expressions
|
/// @param list the list of expressions
|
||||||
/// @return `list`
|
/// @return `list`
|
||||||
ast::ExpressionList ExprList(ast::ExpressionList list) { return list; }
|
template <typename T, size_t N>
|
||||||
|
utils::Vector<T, N> ExprList(utils::Vector<T, N>&& list) {
|
||||||
|
return std::move(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @param list the list of expressions
|
||||||
|
/// @return `list`
|
||||||
|
utils::VectorRef<const ast::Expression*> ExprList(
|
||||||
|
utils::VectorRef<const ast::Expression*> list) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
/// @param args the arguments for the type constructor
|
/// @param args the arguments for the type constructor
|
||||||
/// @return an `ast::CallExpression` of type `ty`, with the values
|
/// @return an `ast::CallExpression` of type `ty`, with the values
|
||||||
|
@ -1589,7 +1630,7 @@ class ProgramBuilder {
|
||||||
const ast::Const* Const(NAME&& name,
|
const ast::Const* Const(NAME&& name,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
const ast::Expression* constructor,
|
const ast::Expression* constructor,
|
||||||
ast::AttributeList attributes = {}) {
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
return create<ast::Const>(Sym(std::forward<NAME>(name)), type, constructor, attributes);
|
return create<ast::Const>(Sym(std::forward<NAME>(name)), type, constructor, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1604,7 +1645,7 @@ class ProgramBuilder {
|
||||||
NAME&& name,
|
NAME&& name,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
const ast::Expression* constructor,
|
const ast::Expression* constructor,
|
||||||
ast::AttributeList attributes = {}) {
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
return create<ast::Const>(source, Sym(std::forward<NAME>(name)), type, constructor,
|
return create<ast::Const>(source, Sym(std::forward<NAME>(name)), type, constructor,
|
||||||
attributes);
|
attributes);
|
||||||
}
|
}
|
||||||
|
@ -1618,7 +1659,7 @@ class ProgramBuilder {
|
||||||
const ast::Let* Let(NAME&& name,
|
const ast::Let* Let(NAME&& name,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
const ast::Expression* constructor,
|
const ast::Expression* constructor,
|
||||||
ast::AttributeList attributes = {}) {
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
return create<ast::Let>(Sym(std::forward<NAME>(name)), type, constructor, attributes);
|
return create<ast::Let>(Sym(std::forward<NAME>(name)), type, constructor, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1633,7 +1674,7 @@ class ProgramBuilder {
|
||||||
NAME&& name,
|
NAME&& name,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
const ast::Expression* constructor,
|
const ast::Expression* constructor,
|
||||||
ast::AttributeList attributes = {}) {
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
return create<ast::Let>(source, Sym(std::forward<NAME>(name)), type, constructor,
|
return create<ast::Let>(source, Sym(std::forward<NAME>(name)), type, constructor,
|
||||||
attributes);
|
attributes);
|
||||||
}
|
}
|
||||||
|
@ -1645,7 +1686,7 @@ class ProgramBuilder {
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
const ast::Parameter* Param(NAME&& name,
|
const ast::Parameter* Param(NAME&& name,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
ast::AttributeList attributes = {}) {
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
return create<ast::Parameter>(Sym(std::forward<NAME>(name)), type, attributes);
|
return create<ast::Parameter>(Sym(std::forward<NAME>(name)), type, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1658,7 +1699,7 @@ class ProgramBuilder {
|
||||||
const ast::Parameter* Param(const Source& source,
|
const ast::Parameter* Param(const Source& source,
|
||||||
NAME&& name,
|
NAME&& name,
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
ast::AttributeList attributes = {}) {
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
return create<ast::Parameter>(source, Sym(std::forward<NAME>(name)), type, attributes);
|
return create<ast::Parameter>(source, Sym(std::forward<NAME>(name)), type, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1712,10 +1753,11 @@ class ProgramBuilder {
|
||||||
/// @returns an `ast::Const` constructed by calling Const() with the arguments of `args`, which
|
/// @returns an `ast::Const` constructed by calling Const() with the arguments of `args`, which
|
||||||
/// is automatically registered as a global variable with the ast::Module.
|
/// is automatically registered as a global variable with the ast::Module.
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
const ast::Const* GlobalConst(NAME&& name,
|
const ast::Const* GlobalConst(
|
||||||
const ast::Type* type,
|
NAME&& name,
|
||||||
const ast::Expression* constructor,
|
const ast::Type* type,
|
||||||
ast::AttributeList attributes = {}) {
|
const ast::Expression* constructor,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
auto* var = Const(std::forward<NAME>(name), type, constructor, std::move(attributes));
|
auto* var = Const(std::forward<NAME>(name), type, constructor, std::move(attributes));
|
||||||
AST().AddGlobalVariable(var);
|
AST().AddGlobalVariable(var);
|
||||||
return var;
|
return var;
|
||||||
|
@ -1730,11 +1772,12 @@ class ProgramBuilder {
|
||||||
/// arguments of `args`, which is automatically registered as a global
|
/// arguments of `args`, which is automatically registered as a global
|
||||||
/// variable with the ast::Module.
|
/// variable with the ast::Module.
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
const ast::Const* GlobalConst(const Source& source,
|
const ast::Const* GlobalConst(
|
||||||
NAME&& name,
|
const Source& source,
|
||||||
const ast::Type* type,
|
NAME&& name,
|
||||||
const ast::Expression* constructor,
|
const ast::Type* type,
|
||||||
ast::AttributeList attributes = {}) {
|
const ast::Expression* constructor,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
auto* var =
|
auto* var =
|
||||||
Const(source, std::forward<NAME>(name), type, constructor, std::move(attributes));
|
Const(source, std::forward<NAME>(name), type, constructor, std::move(attributes));
|
||||||
AST().AddGlobalVariable(var);
|
AST().AddGlobalVariable(var);
|
||||||
|
@ -1748,10 +1791,11 @@ class ProgramBuilder {
|
||||||
/// @returns an `ast::Override` which is automatically registered as a global variable with the
|
/// @returns an `ast::Override` which is automatically registered as a global variable with the
|
||||||
/// ast::Module.
|
/// ast::Module.
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
const ast::Override* Override(NAME&& name,
|
const ast::Override* Override(
|
||||||
const ast::Type* type,
|
NAME&& name,
|
||||||
const ast::Expression* constructor,
|
const ast::Type* type,
|
||||||
ast::AttributeList attributes = {}) {
|
const ast::Expression* constructor,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
auto* var = create<ast::Override>(source_, Sym(std::forward<NAME>(name)), type, constructor,
|
auto* var = create<ast::Override>(source_, Sym(std::forward<NAME>(name)), type, constructor,
|
||||||
std::move(attributes));
|
std::move(attributes));
|
||||||
AST().AddGlobalVariable(var);
|
AST().AddGlobalVariable(var);
|
||||||
|
@ -1766,11 +1810,12 @@ class ProgramBuilder {
|
||||||
/// @returns an `ast::Override` constructed with the arguments of `args`, which is automatically
|
/// @returns an `ast::Override` constructed with the arguments of `args`, which is automatically
|
||||||
/// registered as a global variable with the ast::Module.
|
/// registered as a global variable with the ast::Module.
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
const ast::Override* Override(const Source& source,
|
const ast::Override* Override(
|
||||||
NAME&& name,
|
const Source& source,
|
||||||
const ast::Type* type,
|
NAME&& name,
|
||||||
const ast::Expression* constructor,
|
const ast::Type* type,
|
||||||
ast::AttributeList attributes = {}) {
|
const ast::Expression* constructor,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
auto* var = create<ast::Override>(source, Sym(std::forward<NAME>(name)), type, constructor,
|
auto* var = create<ast::Override>(source, Sym(std::forward<NAME>(name)), type, constructor,
|
||||||
std::move(attributes));
|
std::move(attributes));
|
||||||
AST().AddGlobalVariable(var);
|
AST().AddGlobalVariable(var);
|
||||||
|
@ -2158,7 +2203,7 @@ class ProgramBuilder {
|
||||||
/// @param group the group index
|
/// @param group the group index
|
||||||
/// @param binding the binding index
|
/// @param binding the binding index
|
||||||
/// @returns a attribute list with both the group and binding attributes
|
/// @returns a attribute list with both the group and binding attributes
|
||||||
ast::AttributeList GroupAndBinding(uint32_t group, uint32_t binding) {
|
utils::Vector<const ast::Attribute*, 2> GroupAndBinding(uint32_t group, uint32_t binding) {
|
||||||
return {Group(group), Binding(binding)};
|
return {Group(group), Binding(binding)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2173,16 +2218,18 @@ class ProgramBuilder {
|
||||||
/// attributes
|
/// attributes
|
||||||
/// @returns the function pointer
|
/// @returns the function pointer
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
const ast::Function* Func(const Source& source,
|
const ast::Function* Func(
|
||||||
NAME&& name,
|
const Source& source,
|
||||||
ast::ParameterList params,
|
NAME&& name,
|
||||||
const ast::Type* type,
|
utils::VectorRef<const ast::Parameter*> params,
|
||||||
ast::StatementList body,
|
const ast::Type* type,
|
||||||
ast::AttributeList attributes = {},
|
utils::VectorRef<const ast::Statement*> body,
|
||||||
ast::AttributeList return_type_attributes = {}) {
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
|
||||||
auto* func = create<ast::Function>(source, Sym(std::forward<NAME>(name)), params, type,
|
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
|
||||||
create<ast::BlockStatement>(body), attributes,
|
auto* func =
|
||||||
return_type_attributes);
|
create<ast::Function>(source, Sym(std::forward<NAME>(name)), std::move(params), type,
|
||||||
|
create<ast::BlockStatement>(std::move(body)),
|
||||||
|
std::move(attributes), std::move(return_type_attributes));
|
||||||
AST().AddFunction(func);
|
AST().AddFunction(func);
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
@ -2197,15 +2244,17 @@ class ProgramBuilder {
|
||||||
/// attributes
|
/// attributes
|
||||||
/// @returns the function pointer
|
/// @returns the function pointer
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
const ast::Function* Func(NAME&& name,
|
const ast::Function* Func(
|
||||||
ast::ParameterList params,
|
NAME&& name,
|
||||||
const ast::Type* type,
|
utils::VectorRef<const ast::Parameter*> params,
|
||||||
ast::StatementList body,
|
const ast::Type* type,
|
||||||
ast::AttributeList attributes = {},
|
utils::VectorRef<const ast::Statement*> body,
|
||||||
ast::AttributeList return_type_attributes = {}) {
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
|
||||||
auto* func = create<ast::Function>(Sym(std::forward<NAME>(name)), params, type,
|
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
|
||||||
create<ast::BlockStatement>(body), attributes,
|
auto* func =
|
||||||
return_type_attributes);
|
create<ast::Function>(Sym(std::forward<NAME>(name)), std::move(params), type,
|
||||||
|
create<ast::BlockStatement>(std::move(body)),
|
||||||
|
std::move(attributes), std::move(return_type_attributes));
|
||||||
AST().AddFunction(func);
|
AST().AddFunction(func);
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
@ -2300,9 +2349,11 @@ class ProgramBuilder {
|
||||||
/// @param members the struct members
|
/// @param members the struct members
|
||||||
/// @returns the struct type
|
/// @returns the struct type
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
const ast::Struct* Structure(const Source& source, NAME&& name, ast::StructMemberList members) {
|
const ast::Struct* Structure(const Source& source,
|
||||||
|
NAME&& name,
|
||||||
|
utils::VectorRef<const ast::StructMember*> members) {
|
||||||
auto sym = Sym(std::forward<NAME>(name));
|
auto sym = Sym(std::forward<NAME>(name));
|
||||||
auto* type = create<ast::Struct>(source, sym, std::move(members), ast::AttributeList{});
|
auto* type = create<ast::Struct>(source, sym, std::move(members), utils::Empty);
|
||||||
AST().AddTypeDecl(type);
|
AST().AddTypeDecl(type);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
@ -2312,9 +2363,9 @@ class ProgramBuilder {
|
||||||
/// @param members the struct members
|
/// @param members the struct members
|
||||||
/// @returns the struct type
|
/// @returns the struct type
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
const ast::Struct* Structure(NAME&& name, ast::StructMemberList members) {
|
const ast::Struct* Structure(NAME&& name, utils::VectorRef<const ast::StructMember*> members) {
|
||||||
auto sym = Sym(std::forward<NAME>(name));
|
auto sym = Sym(std::forward<NAME>(name));
|
||||||
auto* type = create<ast::Struct>(sym, std::move(members), ast::AttributeList{});
|
auto* type = create<ast::Struct>(sym, std::move(members), utils::Empty);
|
||||||
AST().AddTypeDecl(type);
|
AST().AddTypeDecl(type);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
@ -2326,10 +2377,11 @@ class ProgramBuilder {
|
||||||
/// @param attributes the optional struct member attributes
|
/// @param attributes the optional struct member attributes
|
||||||
/// @returns the struct member pointer
|
/// @returns the struct member pointer
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
const ast::StructMember* Member(const Source& source,
|
const ast::StructMember* Member(
|
||||||
NAME&& name,
|
const Source& source,
|
||||||
const ast::Type* type,
|
NAME&& name,
|
||||||
ast::AttributeList attributes = {}) {
|
const ast::Type* type,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
return create<ast::StructMember>(source, Sym(std::forward<NAME>(name)), type,
|
return create<ast::StructMember>(source, Sym(std::forward<NAME>(name)), type,
|
||||||
std::move(attributes));
|
std::move(attributes));
|
||||||
}
|
}
|
||||||
|
@ -2340,22 +2392,23 @@ class ProgramBuilder {
|
||||||
/// @param attributes the optional struct member attributes
|
/// @param attributes the optional struct member attributes
|
||||||
/// @returns the struct member pointer
|
/// @returns the struct member pointer
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
const ast::StructMember* Member(NAME&& name,
|
const ast::StructMember* Member(
|
||||||
const ast::Type* type,
|
NAME&& name,
|
||||||
ast::AttributeList attributes = {}) {
|
const ast::Type* type,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
return create<ast::StructMember>(source_, Sym(std::forward<NAME>(name)), type,
|
return create<ast::StructMember>(source_, Sym(std::forward<NAME>(name)), type,
|
||||||
std::move(attributes));
|
std::move(attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a ast::StructMember with the given byte offset
|
/// Creates a ast::StructMember with the given byte offset
|
||||||
/// @param offset the offset to use in the StructMemberOffsetattribute
|
/// @param offset the offset to use in the StructMemberOffsetAttribute
|
||||||
/// @param name the struct member name
|
/// @param name the struct member name
|
||||||
/// @param type the struct member type
|
/// @param type the struct member type
|
||||||
/// @returns the struct member pointer
|
/// @returns the struct member pointer
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
const ast::StructMember* Member(uint32_t offset, NAME&& name, const ast::Type* type) {
|
const ast::StructMember* Member(uint32_t offset, NAME&& name, const ast::Type* type) {
|
||||||
return create<ast::StructMember>(source_, Sym(std::forward<NAME>(name)), type,
|
return create<ast::StructMember>(source_, Sym(std::forward<NAME>(name)), type,
|
||||||
ast::AttributeList{
|
utils::Vector<const ast::Attribute*, 1>{
|
||||||
create<ast::StructMemberOffsetAttribute>(offset),
|
create<ast::StructMemberOffsetAttribute>(offset),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2367,7 +2420,9 @@ class ProgramBuilder {
|
||||||
template <typename... Statements>
|
template <typename... Statements>
|
||||||
const ast::BlockStatement* Block(const Source& source, Statements&&... statements) {
|
const ast::BlockStatement* Block(const Source& source, Statements&&... statements) {
|
||||||
return create<ast::BlockStatement>(
|
return create<ast::BlockStatement>(
|
||||||
source, ast::StatementList{std::forward<Statements>(statements)...});
|
source, utils::Vector<const ast::Statement*, sizeof...(statements)>{
|
||||||
|
std::forward<Statements>(statements)...,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a ast::BlockStatement with input statements
|
/// Creates a ast::BlockStatement with input statements
|
||||||
|
@ -2376,7 +2431,9 @@ class ProgramBuilder {
|
||||||
template <typename... STATEMENTS, typename = DisableIfSource<STATEMENTS...>>
|
template <typename... STATEMENTS, typename = DisableIfSource<STATEMENTS...>>
|
||||||
const ast::BlockStatement* Block(STATEMENTS&&... statements) {
|
const ast::BlockStatement* Block(STATEMENTS&&... statements) {
|
||||||
return create<ast::BlockStatement>(
|
return create<ast::BlockStatement>(
|
||||||
ast::StatementList{std::forward<STATEMENTS>(statements)...});
|
utils::Vector<const ast::Statement*, sizeof...(statements)>{
|
||||||
|
std::forward<STATEMENTS>(statements)...,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper type for the Else statement used to create If statements.
|
/// A wrapper type for the Else statement used to create If statements.
|
||||||
|
@ -2618,8 +2675,10 @@ class ProgramBuilder {
|
||||||
const ast::SwitchStatement* Switch(const Source& source,
|
const ast::SwitchStatement* Switch(const Source& source,
|
||||||
ExpressionInit&& condition,
|
ExpressionInit&& condition,
|
||||||
Cases&&... cases) {
|
Cases&&... cases) {
|
||||||
return create<ast::SwitchStatement>(source, Expr(std::forward<ExpressionInit>(condition)),
|
return create<ast::SwitchStatement>(
|
||||||
ast::CaseStatementList{std::forward<Cases>(cases)...});
|
source, Expr(std::forward<ExpressionInit>(condition)),
|
||||||
|
utils::Vector<const ast::CaseStatement*, sizeof...(cases)>{
|
||||||
|
std::forward<Cases>(cases)...});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a ast::SwitchStatement with input expression and cases
|
/// Creates a ast::SwitchStatement with input expression and cases
|
||||||
|
@ -2630,8 +2689,10 @@ class ProgramBuilder {
|
||||||
typename... Cases,
|
typename... Cases,
|
||||||
typename = DisableIfSource<ExpressionInit>>
|
typename = DisableIfSource<ExpressionInit>>
|
||||||
const ast::SwitchStatement* Switch(ExpressionInit&& condition, Cases&&... cases) {
|
const ast::SwitchStatement* Switch(ExpressionInit&& condition, Cases&&... cases) {
|
||||||
return create<ast::SwitchStatement>(Expr(std::forward<ExpressionInit>(condition)),
|
return create<ast::SwitchStatement>(
|
||||||
ast::CaseStatementList{std::forward<Cases>(cases)...});
|
Expr(std::forward<ExpressionInit>(condition)),
|
||||||
|
utils::Vector<const ast::CaseStatement*, sizeof...(cases)>{
|
||||||
|
std::forward<Cases>(cases)...});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a ast::CaseStatement with input list of selectors, and body
|
/// Creates a ast::CaseStatement with input list of selectors, and body
|
||||||
|
@ -2640,7 +2701,7 @@ class ProgramBuilder {
|
||||||
/// @param body the case body
|
/// @param body the case body
|
||||||
/// @returns the case statement pointer
|
/// @returns the case statement pointer
|
||||||
const ast::CaseStatement* Case(const Source& source,
|
const ast::CaseStatement* Case(const Source& source,
|
||||||
ast::CaseSelectorList selectors,
|
utils::VectorRef<const ast::IntLiteralExpression*> selectors,
|
||||||
const ast::BlockStatement* body = nullptr) {
|
const ast::BlockStatement* body = nullptr) {
|
||||||
return create<ast::CaseStatement>(source, std::move(selectors), body ? body : Block());
|
return create<ast::CaseStatement>(source, std::move(selectors), body ? body : Block());
|
||||||
}
|
}
|
||||||
|
@ -2649,7 +2710,7 @@ class ProgramBuilder {
|
||||||
/// @param selectors list of selectors
|
/// @param selectors list of selectors
|
||||||
/// @param body the case body
|
/// @param body the case body
|
||||||
/// @returns the case statement pointer
|
/// @returns the case statement pointer
|
||||||
const ast::CaseStatement* Case(ast::CaseSelectorList selectors,
|
const ast::CaseStatement* Case(utils::VectorRef<const ast::IntLiteralExpression*> selectors,
|
||||||
const ast::BlockStatement* body = nullptr) {
|
const ast::BlockStatement* body = nullptr) {
|
||||||
return create<ast::CaseStatement>(std::move(selectors), body ? body : Block());
|
return create<ast::CaseStatement>(std::move(selectors), body ? body : Block());
|
||||||
}
|
}
|
||||||
|
@ -2660,7 +2721,7 @@ class ProgramBuilder {
|
||||||
/// @returns the case statement pointer
|
/// @returns the case statement pointer
|
||||||
const ast::CaseStatement* Case(const ast::IntLiteralExpression* selector,
|
const ast::CaseStatement* Case(const ast::IntLiteralExpression* selector,
|
||||||
const ast::BlockStatement* body = nullptr) {
|
const ast::BlockStatement* body = nullptr) {
|
||||||
return Case(ast::CaseSelectorList{selector}, body);
|
return Case(utils::Vector{selector}, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience function that creates a 'default' ast::CaseStatement
|
/// Convenience function that creates a 'default' ast::CaseStatement
|
||||||
|
@ -2669,14 +2730,14 @@ class ProgramBuilder {
|
||||||
/// @returns the case statement pointer
|
/// @returns the case statement pointer
|
||||||
const ast::CaseStatement* DefaultCase(const Source& source,
|
const ast::CaseStatement* DefaultCase(const Source& source,
|
||||||
const ast::BlockStatement* body = nullptr) {
|
const ast::BlockStatement* body = nullptr) {
|
||||||
return Case(source, ast::CaseSelectorList{}, body);
|
return Case(source, utils::Empty, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience function that creates a 'default' ast::CaseStatement
|
/// Convenience function that creates a 'default' ast::CaseStatement
|
||||||
/// @param body the case body
|
/// @param body the case body
|
||||||
/// @returns the case statement pointer
|
/// @returns the case statement pointer
|
||||||
const ast::CaseStatement* DefaultCase(const ast::BlockStatement* body = nullptr) {
|
const ast::CaseStatement* DefaultCase(const ast::BlockStatement* body = nullptr) {
|
||||||
return Case(ast::CaseSelectorList{}, body);
|
return Case(utils::Empty, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an ast::FallthroughStatement
|
/// Creates an ast::FallthroughStatement
|
||||||
|
@ -2957,13 +3018,15 @@ class ProgramBuilder {
|
||||||
/// @returns the function
|
/// @returns the function
|
||||||
template <typename... ARGS>
|
template <typename... ARGS>
|
||||||
const ast::Function* WrapInFunction(ARGS&&... args) {
|
const ast::Function* WrapInFunction(ARGS&&... args) {
|
||||||
ast::StatementList stmts{WrapInStatement(std::forward<ARGS>(args))...};
|
utils::Vector stmts{
|
||||||
return WrapInFunction(std::move(stmts));
|
WrapInStatement(std::forward<ARGS>(args))...,
|
||||||
|
};
|
||||||
|
return WrapInFunction(utils::VectorRef<const ast::Statement*>{std::move(stmts)});
|
||||||
}
|
}
|
||||||
/// @param stmts a list of ast::Statement that will be wrapped by a function,
|
/// @param stmts a list of ast::Statement that will be wrapped by a function,
|
||||||
/// so that each statement is reachable by the Resolver.
|
/// so that each statement is reachable by the Resolver.
|
||||||
/// @returns the function
|
/// @returns the function
|
||||||
const ast::Function* WrapInFunction(ast::StatementList stmts);
|
const ast::Function* WrapInFunction(utils::VectorRef<const ast::Statement*> stmts);
|
||||||
|
|
||||||
/// The builder types
|
/// The builder types
|
||||||
TypesBuilder const ty{this};
|
TypesBuilder const ty{this};
|
||||||
|
|
|
@ -38,14 +38,14 @@ TEST_F(ProgramBuilderTest, WrapDoesntAffectInner) {
|
||||||
return builder;
|
return builder;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
ASSERT_EQ(inner.AST().Functions().size(), 1u);
|
ASSERT_EQ(inner.AST().Functions().Length(), 1u);
|
||||||
ASSERT_TRUE(inner.Symbols().Get("a").IsValid());
|
ASSERT_TRUE(inner.Symbols().Get("a").IsValid());
|
||||||
ASSERT_FALSE(inner.Symbols().Get("b").IsValid());
|
ASSERT_FALSE(inner.Symbols().Get("b").IsValid());
|
||||||
|
|
||||||
ProgramBuilder outer = ProgramBuilder::Wrap(&inner);
|
ProgramBuilder outer = ProgramBuilder::Wrap(&inner);
|
||||||
|
|
||||||
ASSERT_EQ(inner.AST().Functions().size(), 1u);
|
ASSERT_EQ(inner.AST().Functions().Length(), 1u);
|
||||||
ASSERT_EQ(outer.AST().Functions().size(), 1u);
|
ASSERT_EQ(outer.AST().Functions().Length(), 1u);
|
||||||
EXPECT_EQ(inner.AST().Functions()[0], outer.AST().Functions()[0]);
|
EXPECT_EQ(inner.AST().Functions()[0], outer.AST().Functions()[0]);
|
||||||
EXPECT_TRUE(inner.Symbols().Get("a").IsValid());
|
EXPECT_TRUE(inner.Symbols().Get("a").IsValid());
|
||||||
EXPECT_EQ(inner.Symbols().Get("a"), outer.Symbols().Get("a"));
|
EXPECT_EQ(inner.Symbols().Get("a"), outer.Symbols().Get("a"));
|
||||||
|
@ -57,8 +57,8 @@ TEST_F(ProgramBuilderTest, WrapDoesntAffectInner) {
|
||||||
auto* ty = outer.ty.f32();
|
auto* ty = outer.ty.f32();
|
||||||
outer.Func("b", {}, ty, {}, {});
|
outer.Func("b", {}, ty, {}, {});
|
||||||
|
|
||||||
ASSERT_EQ(inner.AST().Functions().size(), 1u);
|
ASSERT_EQ(inner.AST().Functions().Length(), 1u);
|
||||||
ASSERT_EQ(outer.AST().Functions().size(), 2u);
|
ASSERT_EQ(outer.AST().Functions().Length(), 2u);
|
||||||
EXPECT_EQ(inner.AST().Functions()[0], outer.AST().Functions()[0]);
|
EXPECT_EQ(inner.AST().Functions()[0], outer.AST().Functions()[0]);
|
||||||
EXPECT_EQ(outer.AST().Functions()[1]->symbol, outer.Symbols().Get("b"));
|
EXPECT_EQ(outer.AST().Functions()[1]->symbol, outer.Symbols().Get("b"));
|
||||||
EXPECT_EQ(inner.Symbols().Get("a"), outer.Symbols().Get("a"));
|
EXPECT_EQ(inner.Symbols().Get("a"), outer.Symbols().Get("a"));
|
||||||
|
|
|
@ -28,7 +28,7 @@ TEST_F(ProgramTest, Unbuilt) {
|
||||||
|
|
||||||
TEST_F(ProgramTest, Creation) {
|
TEST_F(ProgramTest, Creation) {
|
||||||
Program program(std::move(*this));
|
Program program(std::move(*this));
|
||||||
EXPECT_EQ(program.AST().Functions().size(), 0u);
|
EXPECT_EQ(program.AST().Functions().Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ProgramTest, EmptyIsValid) {
|
TEST_F(ProgramTest, EmptyIsValid) {
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
#include "src/tint/utils/vector.h"
|
||||||
|
|
||||||
namespace tint::reader::spirv {
|
namespace tint::reader::spirv {
|
||||||
|
|
||||||
|
@ -146,7 +147,7 @@ struct Construct {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ConstructList is a list of Construct unique pointers.
|
/// ConstructList is a list of Construct unique pointers.
|
||||||
using ConstructList = std::vector<std::unique_ptr<Construct>>;
|
using ConstructList = utils::Vector<std::unique_ptr<Construct>, 8>;
|
||||||
|
|
||||||
/// Converts a construct kind to a string.
|
/// Converts a construct kind to a string.
|
||||||
/// @param kind the construct kind to convert
|
/// @param kind the construct kind to convert
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -16,6 +16,7 @@
|
||||||
#define SRC_TINT_READER_SPIRV_FUNCTION_H_
|
#define SRC_TINT_READER_SPIRV_FUNCTION_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
@ -125,7 +126,7 @@ struct BlockInfo {
|
||||||
/// switch?
|
/// switch?
|
||||||
bool default_is_merge = false;
|
bool default_is_merge = false;
|
||||||
/// The list of switch values that cause a branch to this block.
|
/// The list of switch values that cause a branch to this block.
|
||||||
std::unique_ptr<std::vector<uint64_t>> case_values;
|
std::optional<utils::Vector<uint64_t, 4>> case_values;
|
||||||
|
|
||||||
/// The following fields record relationships among blocks in a selection
|
/// The following fields record relationships among blocks in a selection
|
||||||
/// construct for an OpBranchConditional instruction.
|
/// construct for an OpBranchConditional instruction.
|
||||||
|
@ -158,7 +159,7 @@ struct BlockInfo {
|
||||||
/// The result IDs that this block is responsible for declaring as a
|
/// The result IDs that this block is responsible for declaring as a
|
||||||
/// hoisted variable.
|
/// hoisted variable.
|
||||||
/// @see DefInfo#requires_hoisted_def
|
/// @see DefInfo#requires_hoisted_def
|
||||||
std::vector<uint32_t> hoisted_ids;
|
utils::Vector<uint32_t, 4> hoisted_ids;
|
||||||
|
|
||||||
/// A PhiAssignment represents the assignment of a value to the state
|
/// A PhiAssignment represents the assignment of a value to the state
|
||||||
/// variable associated with an OpPhi in a successor block.
|
/// variable associated with an OpPhi in a successor block.
|
||||||
|
@ -170,10 +171,10 @@ struct BlockInfo {
|
||||||
};
|
};
|
||||||
/// If this basic block branches to a visited basic block containing phis,
|
/// If this basic block branches to a visited basic block containing phis,
|
||||||
/// then this is the list of writes to the variables associated those phis.
|
/// then this is the list of writes to the variables associated those phis.
|
||||||
std::vector<PhiAssignment> phi_assignments;
|
utils::Vector<PhiAssignment, 4> phi_assignments;
|
||||||
/// The IDs of OpPhi instructions which require their associated state
|
/// The IDs of OpPhi instructions which require their associated state
|
||||||
/// variable to be declared in this basic block.
|
/// variable to be declared in this basic block.
|
||||||
std::vector<uint32_t> phis_needing_state_vars;
|
utils::Vector<uint32_t, 4> phis_needing_state_vars;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Writes the BlockInfo to the ostream
|
/// Writes the BlockInfo to the ostream
|
||||||
|
@ -388,6 +389,12 @@ class StatementBuilder : public Castable<StatementBuilder, ast::Statement> {
|
||||||
|
|
||||||
/// A FunctionEmitter emits a SPIR-V function onto a Tint AST module.
|
/// A FunctionEmitter emits a SPIR-V function onto a Tint AST module.
|
||||||
class FunctionEmitter {
|
class FunctionEmitter {
|
||||||
|
using AttributeList = utils::Vector<const ast::Attribute*, 8>;
|
||||||
|
using StructMemberList = utils::Vector<const ast::StructMember*, 8>;
|
||||||
|
using ExpressionList = utils::Vector<const ast::Expression*, 8>;
|
||||||
|
using ParameterList = utils::Vector<const ast::Parameter*, 8>;
|
||||||
|
using StatementList = utils::Vector<const ast::Statement*, 8>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Creates a FunctionEmitter, and prepares to write to the AST module
|
/// Creates a FunctionEmitter, and prepares to write to the AST module
|
||||||
/// in `pi`
|
/// in `pi`
|
||||||
|
@ -420,7 +427,7 @@ class FunctionEmitter {
|
||||||
/// Finalizes any StatementBuilders returns the body of the function.
|
/// Finalizes any StatementBuilders returns the body of the function.
|
||||||
/// Must only be called once, and to be used only for testing.
|
/// Must only be called once, and to be used only for testing.
|
||||||
/// @returns the body of the function.
|
/// @returns the body of the function.
|
||||||
const ast::StatementList ast_body();
|
StatementList ast_body();
|
||||||
|
|
||||||
/// Records failure.
|
/// Records failure.
|
||||||
/// @returns a FailStream on which to emit diagnostics.
|
/// @returns a FailStream on which to emit diagnostics.
|
||||||
|
@ -455,12 +462,12 @@ class FunctionEmitter {
|
||||||
/// @returns false if emission failed
|
/// @returns false if emission failed
|
||||||
bool EmitPipelineInput(std::string var_name,
|
bool EmitPipelineInput(std::string var_name,
|
||||||
const Type* var_type,
|
const Type* var_type,
|
||||||
ast::AttributeList* decos,
|
AttributeList* decos,
|
||||||
std::vector<int> index_prefix,
|
utils::Vector<int, 8> index_prefix,
|
||||||
const Type* tip_type,
|
const Type* tip_type,
|
||||||
const Type* forced_param_type,
|
const Type* forced_param_type,
|
||||||
ast::ParameterList* params,
|
ParameterList* params,
|
||||||
ast::StatementList* statements);
|
StatementList* statements);
|
||||||
|
|
||||||
/// Creates one or more struct members from an output variable, and the
|
/// Creates one or more struct members from an output variable, and the
|
||||||
/// expressions that compute the value they contribute to the entry point
|
/// expressions that compute the value they contribute to the entry point
|
||||||
|
@ -471,37 +478,30 @@ class FunctionEmitter {
|
||||||
/// @param var_name The name of the variable
|
/// @param var_name The name of the variable
|
||||||
/// @param var_type The store type of the variable
|
/// @param var_type The store type of the variable
|
||||||
/// @param decos The variable's decorations
|
/// @param decos The variable's decorations
|
||||||
/// @param index_prefix Indices stepping into the variable, indicating
|
/// @param index_prefix Indices stepping into the variable, indicating what part of the variable
|
||||||
/// what part of the variable to populate.
|
/// to populate.
|
||||||
/// @param tip_type The type of the component inside variable, after indexing
|
/// @param tip_type The type of the component inside variable, after indexing with the indices
|
||||||
/// with the indices in `index_prefix`.
|
/// in `index_prefix`.
|
||||||
/// @param forced_member_type The type forced by WGSL, if the variable is a
|
/// @param forced_member_type The type forced by WGSL, if the variable is a builtin, otherwise
|
||||||
/// builtin, otherwise the same as var_type.
|
/// the same as var_type.
|
||||||
/// @param return_members The struct member list where the new member is
|
/// @param return_members The struct member list where the new member is added.
|
||||||
/// added.
|
/// @param return_exprs The expression list where the return expression is added.
|
||||||
/// @param return_exprs The expression list where the return expression is
|
|
||||||
/// added.
|
|
||||||
/// @returns false if emission failed
|
/// @returns false if emission failed
|
||||||
bool EmitPipelineOutput(std::string var_name,
|
bool EmitPipelineOutput(std::string var_name,
|
||||||
const Type* var_type,
|
const Type* var_type,
|
||||||
ast::AttributeList* decos,
|
AttributeList* decos,
|
||||||
std::vector<int> index_prefix,
|
utils::Vector<int, 8> index_prefix,
|
||||||
const Type* tip_type,
|
const Type* tip_type,
|
||||||
const Type* forced_member_type,
|
const Type* forced_member_type,
|
||||||
ast::StructMemberList* return_members,
|
StructMemberList* return_members,
|
||||||
ast::ExpressionList* return_exprs);
|
ExpressionList* return_exprs);
|
||||||
|
|
||||||
/// Updates the attribute list, replacing an existing Location attribute
|
/// Updates the attribute list, replacing an existing Location attribute
|
||||||
/// with another having one higher location value. Does nothing if no
|
/// with another having one higher location value. Does nothing if no
|
||||||
/// location attribute exists.
|
/// location attribute exists.
|
||||||
/// Assumes the list contains at most one Location attribute.
|
/// Assumes the list contains at most one Location attribute.
|
||||||
/// @param attributes the attribute list to modify
|
/// @param attributes the attribute list to modify
|
||||||
void IncrementLocation(ast::AttributeList* attributes);
|
void IncrementLocation(AttributeList* attributes);
|
||||||
|
|
||||||
/// Returns the Location attribute, if it exists.
|
|
||||||
/// @param attributes the list of attributes to search
|
|
||||||
/// @returns the Location attribute, or nullptr if it doesn't exist
|
|
||||||
const ast::Attribute* GetLocation(const ast::AttributeList& attributes);
|
|
||||||
|
|
||||||
/// Create an ast::BlockStatement representing the body of the function.
|
/// Create an ast::BlockStatement representing the body of the function.
|
||||||
/// This creates the statement stack, which is non-empty for the lifetime
|
/// This creates the statement stack, which is non-empty for the lifetime
|
||||||
|
@ -913,7 +913,7 @@ class FunctionEmitter {
|
||||||
/// On failure, issues an error and returns an empty expression list.
|
/// On failure, issues an error and returns an empty expression list.
|
||||||
/// @param image_access the image access instruction
|
/// @param image_access the image access instruction
|
||||||
/// @returns an ExpressionList of the coordinate and array index (if any)
|
/// @returns an ExpressionList of the coordinate and array index (if any)
|
||||||
ast::ExpressionList MakeCoordinateOperandsForImageAccess(
|
ExpressionList MakeCoordinateOperandsForImageAccess(
|
||||||
const spvtools::opt::Instruction& image_access);
|
const spvtools::opt::Instruction& image_access);
|
||||||
|
|
||||||
/// Returns the given value as an I32. If it's already an I32 then this
|
/// Returns the given value as an I32. If it's already an I32 then this
|
||||||
|
@ -951,11 +951,11 @@ class FunctionEmitter {
|
||||||
/// Function name
|
/// Function name
|
||||||
std::string name;
|
std::string name;
|
||||||
/// Function parameters
|
/// Function parameters
|
||||||
ast::ParameterList params;
|
ParameterList params;
|
||||||
/// Function return type
|
/// Function return type
|
||||||
const Type* return_type;
|
const Type* return_type;
|
||||||
/// Function attributes
|
/// Function attributes
|
||||||
ast::AttributeList attributes;
|
AttributeList attributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parse the function declaration, which comprises the name, parameters, and
|
/// Parse the function declaration, which comprises the name, parameters, and
|
||||||
|
@ -1117,8 +1117,8 @@ class FunctionEmitter {
|
||||||
/// @return the built StatementBuilder
|
/// @return the built StatementBuilder
|
||||||
template <typename T, typename... ARGS>
|
template <typename T, typename... ARGS>
|
||||||
T* AddStatementBuilder(ARGS&&... args) {
|
T* AddStatementBuilder(ARGS&&... args) {
|
||||||
TINT_ASSERT(Reader, !statements_stack_.empty());
|
TINT_ASSERT(Reader, !statements_stack_.IsEmpty());
|
||||||
return statements_stack_.back().AddStatementBuilder<T>(std::forward<ARGS>(args)...);
|
return statements_stack_.Back().AddStatementBuilder<T>(std::forward<ARGS>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the source record for the given instruction.
|
/// Returns the source record for the given instruction.
|
||||||
|
@ -1126,10 +1126,10 @@ class FunctionEmitter {
|
||||||
/// @return the Source record, or a default one
|
/// @return the Source record, or a default one
|
||||||
Source GetSourceForInst(const spvtools::opt::Instruction& inst) const;
|
Source GetSourceForInst(const spvtools::opt::Instruction& inst) const;
|
||||||
|
|
||||||
/// @returns the last statetment in the top of the statement stack.
|
/// @returns the last statement in the top of the statement stack.
|
||||||
const ast::Statement* LastStatement();
|
const ast::Statement* LastStatement();
|
||||||
|
|
||||||
using CompletionAction = std::function<void(const ast::StatementList&)>;
|
using CompletionAction = std::function<void(const StatementList&)>;
|
||||||
|
|
||||||
// A StatementBlock represents a braced-list of statements while it is being
|
// A StatementBlock represents a braced-list of statements while it is being
|
||||||
// constructed.
|
// constructed.
|
||||||
|
@ -1181,7 +1181,7 @@ class FunctionEmitter {
|
||||||
|
|
||||||
/// @return the list of statements being built, if this construct is not a
|
/// @return the list of statements being built, if this construct is not a
|
||||||
/// switch.
|
/// switch.
|
||||||
const ast::StatementList& GetStatements() const { return statements_; }
|
const StatementList& GetStatements() const { return statements_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The construct to which this construct constributes.
|
/// The construct to which this construct constributes.
|
||||||
|
@ -1193,7 +1193,7 @@ class FunctionEmitter {
|
||||||
/// The completion action finishes processing this statement block.
|
/// The completion action finishes processing this statement block.
|
||||||
FunctionEmitter::CompletionAction const completion_action_;
|
FunctionEmitter::CompletionAction const completion_action_;
|
||||||
/// The list of statements being built, if this construct is not a switch.
|
/// The list of statements being built, if this construct is not a switch.
|
||||||
ast::StatementList statements_;
|
StatementList statements_;
|
||||||
|
|
||||||
/// Owned statement builders
|
/// Owned statement builders
|
||||||
std::vector<std::unique_ptr<StatementBuilder>> builders_;
|
std::vector<std::unique_ptr<StatementBuilder>> builders_;
|
||||||
|
@ -1251,7 +1251,6 @@ class FunctionEmitter {
|
||||||
return builder_.create<T>(std::forward<ARGS>(args)...);
|
return builder_.create<T>(std::forward<ARGS>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
using StatementsStack = std::vector<StatementBlock>;
|
|
||||||
using PtrAs = ParserImpl::PtrAs;
|
using PtrAs = ParserImpl::PtrAs;
|
||||||
|
|
||||||
ParserImpl& parser_impl_;
|
ParserImpl& parser_impl_;
|
||||||
|
@ -1275,7 +1274,7 @@ class FunctionEmitter {
|
||||||
// for the entire function. This stack is never empty.
|
// for the entire function. This stack is never empty.
|
||||||
// The `construct` member for the 0th element is only valid during the
|
// The `construct` member for the 0th element is only valid during the
|
||||||
// lifetime of the EmitFunctionBodyStatements method.
|
// lifetime of the EmitFunctionBodyStatements method.
|
||||||
StatementsStack statements_stack_;
|
utils::Vector<StatementBlock, 8> statements_stack_;
|
||||||
|
|
||||||
// The map of IDs that have already had an identifier name generated for it,
|
// The map of IDs that have already had an identifier name generated for it,
|
||||||
// to their Type.
|
// to their Type.
|
||||||
|
|
|
@ -87,13 +87,13 @@ TEST_F(SpvParserTest, EmitStatement_ScalarCallNoParams) {
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
)"));
|
)"));
|
||||||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
ast::StatementList f100;
|
utils::Vector<const ast::Statement*, 4> f100;
|
||||||
{
|
{
|
||||||
auto fe = p->function_emitter(100);
|
auto fe = p->function_emitter(100);
|
||||||
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
f100 = fe.ast_body();
|
f100 = fe.ast_body();
|
||||||
}
|
}
|
||||||
ast::StatementList f50;
|
utils::Vector<const ast::Statement*, 4> f50;
|
||||||
{
|
{
|
||||||
auto fe = p->function_emitter(50);
|
auto fe = p->function_emitter(50);
|
||||||
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
@ -128,13 +128,13 @@ TEST_F(SpvParserTest, EmitStatement_ScalarCallNoParamsUsedTwice) {
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
)"));
|
)"));
|
||||||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
ast::StatementList f100;
|
utils::Vector<const ast::Statement*, 4> f100;
|
||||||
{
|
{
|
||||||
auto fe = p->function_emitter(100);
|
auto fe = p->function_emitter(100);
|
||||||
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
f100 = fe.ast_body();
|
f100 = fe.ast_body();
|
||||||
}
|
}
|
||||||
ast::StatementList f50;
|
utils::Vector<const ast::Statement*, 4> f50;
|
||||||
{
|
{
|
||||||
auto fe = p->function_emitter(50);
|
auto fe = p->function_emitter(50);
|
||||||
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
|
|
@ -2894,8 +2894,8 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_OuterConstructIsFunction_Sin
|
||||||
fe.ComputeBlockOrderAndPositions();
|
fe.ComputeBlockOrderAndPositions();
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
EXPECT_EQ(fe.constructs().size(), 1u);
|
EXPECT_EQ(fe.constructs().Length(), 1u);
|
||||||
auto& c = fe.constructs().front();
|
auto& c = fe.constructs().Front();
|
||||||
EXPECT_THAT(ToString(c), Eq("Construct{ Function [0,1) begin_id:10 end_id:0 "
|
EXPECT_THAT(ToString(c), Eq("Construct{ Function [0,1) begin_id:10 end_id:0 "
|
||||||
"depth:0 parent:null }"));
|
"depth:0 parent:null }"));
|
||||||
EXPECT_EQ(fe.GetBlockInfo(10)->construct, c.get());
|
EXPECT_EQ(fe.GetBlockInfo(10)->construct, c.get());
|
||||||
|
@ -2920,8 +2920,8 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_OuterConstructIsFunction_Mul
|
||||||
fe.ComputeBlockOrderAndPositions();
|
fe.ComputeBlockOrderAndPositions();
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
EXPECT_EQ(fe.constructs().size(), 1u);
|
EXPECT_EQ(fe.constructs().Length(), 1u);
|
||||||
auto& c = fe.constructs().front();
|
auto& c = fe.constructs().Front();
|
||||||
EXPECT_THAT(ToString(c), Eq("Construct{ Function [0,2) begin_id:10 end_id:0 "
|
EXPECT_THAT(ToString(c), Eq("Construct{ Function [0,2) begin_id:10 end_id:0 "
|
||||||
"depth:0 parent:null }"));
|
"depth:0 parent:null }"));
|
||||||
EXPECT_EQ(fe.GetBlockInfo(10)->construct, c.get());
|
EXPECT_EQ(fe.GetBlockInfo(10)->construct, c.get());
|
||||||
|
@ -2955,7 +2955,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_FunctionIsOnlyIfSelectionAnd
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 2u);
|
EXPECT_EQ(constructs.Length(), 2u);
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
Construct{ Function [0,4) begin_id:10 end_id:0 depth:0 parent:null }
|
Construct{ Function [0,4) begin_id:10 end_id:0 depth:0 parent:null }
|
||||||
Construct{ IfSelection [0,3) begin_id:10 end_id:99 depth:1 parent:Function@10 }
|
Construct{ IfSelection [0,3) begin_id:10 end_id:99 depth:1 parent:Function@10 }
|
||||||
|
@ -3001,7 +3001,7 @@ TEST_F(SpvParserCFGTest,
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 2u);
|
EXPECT_EQ(constructs.Length(), 2u);
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
Construct{ Function [0,6) begin_id:5 end_id:0 depth:0 parent:null }
|
Construct{ Function [0,6) begin_id:5 end_id:0 depth:0 parent:null }
|
||||||
Construct{ IfSelection [1,4) begin_id:10 end_id:99 depth:1 parent:Function@5 }
|
Construct{ IfSelection [1,4) begin_id:10 end_id:99 depth:1 parent:Function@5 }
|
||||||
|
@ -3045,7 +3045,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_SwitchSelection) {
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 2u);
|
EXPECT_EQ(constructs.Length(), 2u);
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
Construct{ Function [0,5) begin_id:10 end_id:0 depth:0 parent:null }
|
Construct{ Function [0,5) begin_id:10 end_id:0 depth:0 parent:null }
|
||||||
Construct{ SwitchSelection [0,4) begin_id:10 end_id:99 depth:1 parent:Function@10 in-c-l-s:SwitchSelection@10 }
|
Construct{ SwitchSelection [0,4) begin_id:10 end_id:99 depth:1 parent:Function@10 in-c-l-s:SwitchSelection@10 }
|
||||||
|
@ -3082,7 +3082,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_SingleBlockLoop) {
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 2u);
|
EXPECT_EQ(constructs.Length(), 2u);
|
||||||
// A single-block loop consists *only* of a continue target with one block in
|
// A single-block loop consists *only* of a continue target with one block in
|
||||||
// it.
|
// it.
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
|
@ -3223,7 +3223,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_MergeBlockIsAlsoSingleBlockL
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 3u);
|
EXPECT_EQ(constructs.Length(), 3u);
|
||||||
// A single-block loop consists *only* of a continue target with one block in
|
// A single-block loop consists *only* of a continue target with one block in
|
||||||
// it.
|
// it.
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
|
@ -3271,7 +3271,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_MergeBlockIsAlsoMultiBlockLo
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 4u);
|
EXPECT_EQ(constructs.Length(), 4u);
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
Construct{ Function [0,5) begin_id:10 end_id:0 depth:0 parent:null }
|
Construct{ Function [0,5) begin_id:10 end_id:0 depth:0 parent:null }
|
||||||
Construct{ IfSelection [0,2) begin_id:10 end_id:50 depth:1 parent:Function@10 }
|
Construct{ IfSelection [0,2) begin_id:10 end_id:50 depth:1 parent:Function@10 }
|
||||||
|
@ -3330,7 +3330,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_If_If) {
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 4u);
|
EXPECT_EQ(constructs.Length(), 4u);
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
Construct{ Function [0,9) begin_id:10 end_id:0 depth:0 parent:null }
|
Construct{ Function [0,9) begin_id:10 end_id:0 depth:0 parent:null }
|
||||||
Construct{ IfSelection [0,8) begin_id:10 end_id:99 depth:1 parent:Function@10 }
|
Construct{ IfSelection [0,8) begin_id:10 end_id:99 depth:1 parent:Function@10 }
|
||||||
|
@ -3390,7 +3390,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_Switch_If) {
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 4u);
|
EXPECT_EQ(constructs.Length(), 4u);
|
||||||
// The ordering among siblings depends on the computed block order.
|
// The ordering among siblings depends on the computed block order.
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
Construct{ Function [0,8) begin_id:10 end_id:0 depth:0 parent:null }
|
Construct{ Function [0,8) begin_id:10 end_id:0 depth:0 parent:null }
|
||||||
|
@ -3440,7 +3440,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_If_Switch) {
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 3u);
|
EXPECT_EQ(constructs.Length(), 3u);
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
Construct{ Function [0,5) begin_id:10 end_id:0 depth:0 parent:null }
|
Construct{ Function [0,5) begin_id:10 end_id:0 depth:0 parent:null }
|
||||||
Construct{ IfSelection [0,4) begin_id:10 end_id:99 depth:1 parent:Function@10 }
|
Construct{ IfSelection [0,4) begin_id:10 end_id:99 depth:1 parent:Function@10 }
|
||||||
|
@ -3494,7 +3494,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_Loop_Loop) {
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 4u);
|
EXPECT_EQ(constructs.Length(), 4u);
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
Construct{ Function [0,8) begin_id:10 end_id:0 depth:0 parent:null }
|
Construct{ Function [0,8) begin_id:10 end_id:0 depth:0 parent:null }
|
||||||
Construct{ Continue [4,6) begin_id:50 end_id:89 depth:1 parent:Function@10 in-c:Continue@50 }
|
Construct{ Continue [4,6) begin_id:50 end_id:89 depth:1 parent:Function@10 in-c:Continue@50 }
|
||||||
|
@ -3549,7 +3549,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_Loop_If) {
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 4u);
|
EXPECT_EQ(constructs.Length(), 4u);
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
Construct{ Function [0,7) begin_id:10 end_id:0 depth:0 parent:null }
|
Construct{ Function [0,7) begin_id:10 end_id:0 depth:0 parent:null }
|
||||||
Construct{ Continue [5,6) begin_id:80 end_id:99 depth:1 parent:Function@10 in-c:Continue@80 }
|
Construct{ Continue [5,6) begin_id:80 end_id:99 depth:1 parent:Function@10 in-c:Continue@80 }
|
||||||
|
@ -3600,7 +3600,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_LoopContinue_If) {
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 4u);
|
EXPECT_EQ(constructs.Length(), 4u);
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null }
|
Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null }
|
||||||
Construct{ Continue [2,5) begin_id:30 end_id:99 depth:1 parent:Function@10 in-c:Continue@30 }
|
Construct{ Continue [2,5) begin_id:30 end_id:99 depth:1 parent:Function@10 in-c:Continue@30 }
|
||||||
|
@ -3644,7 +3644,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_If_SingleBlockLoop) {
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 3u);
|
EXPECT_EQ(constructs.Length(), 3u);
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
Construct{ Function [0,4) begin_id:10 end_id:0 depth:0 parent:null }
|
Construct{ Function [0,4) begin_id:10 end_id:0 depth:0 parent:null }
|
||||||
Construct{ IfSelection [0,3) begin_id:10 end_id:99 depth:1 parent:Function@10 }
|
Construct{ IfSelection [0,3) begin_id:10 end_id:99 depth:1 parent:Function@10 }
|
||||||
|
@ -3693,7 +3693,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_If_MultiBlockLoop) {
|
||||||
fe.RegisterMerges();
|
fe.RegisterMerges();
|
||||||
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
EXPECT_TRUE(fe.LabelControlFlowConstructs());
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 4u);
|
EXPECT_EQ(constructs.Length(), 4u);
|
||||||
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
Construct{ Function [0,7) begin_id:10 end_id:0 depth:0 parent:null }
|
Construct{ Function [0,7) begin_id:10 end_id:0 depth:0 parent:null }
|
||||||
Construct{ IfSelection [0,6) begin_id:10 end_id:99 depth:1 parent:Function@10 }
|
Construct{ IfSelection [0,6) begin_id:10 end_id:99 depth:1 parent:Function@10 }
|
||||||
|
@ -3743,7 +3743,7 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_LoopInterallyDiverge) {
|
||||||
auto fe = p->function_emitter(100);
|
auto fe = p->function_emitter(100);
|
||||||
ASSERT_TRUE(FlowLabelControlFlowConstructs(&fe)) << p->error();
|
ASSERT_TRUE(FlowLabelControlFlowConstructs(&fe)) << p->error();
|
||||||
const auto& constructs = fe.constructs();
|
const auto& constructs = fe.constructs();
|
||||||
EXPECT_EQ(constructs.size(), 4u);
|
EXPECT_EQ(constructs.Length(), 4u);
|
||||||
ASSERT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
ASSERT_THAT(ToString(constructs), Eq(R"(ConstructList{
|
||||||
Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null }
|
Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null }
|
||||||
Construct{ Continue [4,5) begin_id:90 end_id:99 depth:1 parent:Function@10 in-c:Continue@90 }
|
Construct{ Continue [4,5) begin_id:90 end_id:99 depth:1 parent:Function@10 in-c:Continue@90 }
|
||||||
|
@ -4157,7 +4157,7 @@ TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_NoSwitch) {
|
||||||
EXPECT_EQ(bi10->case_head_for, nullptr);
|
EXPECT_EQ(bi10->case_head_for, nullptr);
|
||||||
EXPECT_EQ(bi10->default_head_for, nullptr);
|
EXPECT_EQ(bi10->default_head_for, nullptr);
|
||||||
EXPECT_FALSE(bi10->default_is_merge);
|
EXPECT_FALSE(bi10->default_is_merge);
|
||||||
EXPECT_EQ(bi10->case_values.get(), nullptr);
|
EXPECT_FALSE(bi10->case_values.has_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_DefaultIsMerge) {
|
TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_DefaultIsMerge) {
|
||||||
|
@ -4192,7 +4192,7 @@ TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_DefaultIsMerge) {
|
||||||
ASSERT_NE(bi99->default_head_for, nullptr);
|
ASSERT_NE(bi99->default_head_for, nullptr);
|
||||||
EXPECT_EQ(bi99->default_head_for->begin_id, 10u);
|
EXPECT_EQ(bi99->default_head_for->begin_id, 10u);
|
||||||
EXPECT_TRUE(bi99->default_is_merge);
|
EXPECT_TRUE(bi99->default_is_merge);
|
||||||
EXPECT_EQ(bi99->case_values.get(), nullptr);
|
EXPECT_FALSE(bi99->case_values.has_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_DefaultIsNotMerge) {
|
TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_DefaultIsNotMerge) {
|
||||||
|
@ -4230,7 +4230,7 @@ TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_DefaultIsNotMerge) {
|
||||||
ASSERT_NE(bi30->default_head_for, nullptr);
|
ASSERT_NE(bi30->default_head_for, nullptr);
|
||||||
EXPECT_EQ(bi30->default_head_for->begin_id, 10u);
|
EXPECT_EQ(bi30->default_head_for->begin_id, 10u);
|
||||||
EXPECT_FALSE(bi30->default_is_merge);
|
EXPECT_FALSE(bi30->default_is_merge);
|
||||||
EXPECT_EQ(bi30->case_values.get(), nullptr);
|
EXPECT_FALSE(bi30->case_values.has_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_CaseIsNotDefault) {
|
TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_CaseIsNotDefault) {
|
||||||
|
@ -4268,7 +4268,7 @@ TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_CaseIsNotDefault) {
|
||||||
EXPECT_EQ(bi20->case_head_for->begin_id, 10u);
|
EXPECT_EQ(bi20->case_head_for->begin_id, 10u);
|
||||||
EXPECT_EQ(bi20->default_head_for, nullptr);
|
EXPECT_EQ(bi20->default_head_for, nullptr);
|
||||||
EXPECT_FALSE(bi20->default_is_merge);
|
EXPECT_FALSE(bi20->default_is_merge);
|
||||||
EXPECT_THAT(*(bi20->case_values.get()), UnorderedElementsAre(200));
|
EXPECT_THAT(bi20->case_values.value(), UnorderedElementsAre(200));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_CaseIsDefault) {
|
TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_CaseIsDefault) {
|
||||||
|
@ -4303,7 +4303,7 @@ TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_CaseIsDefault) {
|
||||||
EXPECT_EQ(bi20->case_head_for->begin_id, 10u);
|
EXPECT_EQ(bi20->case_head_for->begin_id, 10u);
|
||||||
EXPECT_EQ(bi20->default_head_for, bi20->case_head_for);
|
EXPECT_EQ(bi20->default_head_for, bi20->case_head_for);
|
||||||
EXPECT_FALSE(bi20->default_is_merge);
|
EXPECT_FALSE(bi20->default_is_merge);
|
||||||
EXPECT_THAT(*(bi20->case_values.get()), UnorderedElementsAre(200));
|
EXPECT_THAT(bi20->case_values.value(), UnorderedElementsAre(200));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_ManyCasesWithSameValue_IsError) {
|
TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_ManyCasesWithSameValue_IsError) {
|
||||||
|
@ -4370,7 +4370,7 @@ TEST_F(SpvParserCFGTest, FindSwitchCaseHeaders_ManyValuesWithSameCase) {
|
||||||
EXPECT_EQ(bi20->case_head_for->begin_id, 10u);
|
EXPECT_EQ(bi20->case_head_for->begin_id, 10u);
|
||||||
EXPECT_EQ(bi20->default_head_for, nullptr);
|
EXPECT_EQ(bi20->default_head_for, nullptr);
|
||||||
EXPECT_FALSE(bi20->default_is_merge);
|
EXPECT_FALSE(bi20->default_is_merge);
|
||||||
EXPECT_THAT(*(bi20->case_values.get()), UnorderedElementsAre(200, 300));
|
EXPECT_THAT(bi20->case_values.value(), UnorderedElementsAre(200, 300));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SpvParserCFGTest, ClassifyCFGEdges_BranchEscapesIfConstruct) {
|
TEST_F(SpvParserCFGTest, ClassifyCFGEdges_BranchEscapesIfConstruct) {
|
||||||
|
|
|
@ -447,10 +447,10 @@ std::string ParserImpl::ShowType(uint32_t type_id) {
|
||||||
return "SPIR-V type " + std::to_string(type_id);
|
return "SPIR-V type " + std::to_string(type_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::AttributeList ParserImpl::ConvertMemberDecoration(uint32_t struct_type_id,
|
ParserImpl::AttributeList ParserImpl::ConvertMemberDecoration(uint32_t struct_type_id,
|
||||||
uint32_t member_index,
|
uint32_t member_index,
|
||||||
const Type* member_ty,
|
const Type* member_ty,
|
||||||
const Decoration& decoration) {
|
const Decoration& decoration) {
|
||||||
if (decoration.empty()) {
|
if (decoration.empty()) {
|
||||||
Fail() << "malformed SPIR-V decoration: it's empty";
|
Fail() << "malformed SPIR-V decoration: it's empty";
|
||||||
return {};
|
return {};
|
||||||
|
@ -1067,7 +1067,7 @@ const Type* ParserImpl::ConvertType(uint32_t type_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute members
|
// Compute members
|
||||||
ast::StructMemberList ast_members;
|
utils::Vector<const ast::StructMember*, 8> ast_members;
|
||||||
const auto members = struct_ty->element_types();
|
const auto members = struct_ty->element_types();
|
||||||
if (members.empty()) {
|
if (members.empty()) {
|
||||||
Fail() << "WGSL does not support empty structures. can't convert type: "
|
Fail() << "WGSL does not support empty structures. can't convert type: "
|
||||||
|
@ -1123,7 +1123,7 @@ const Type* ParserImpl::ConvertType(uint32_t type_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_non_writable = false;
|
bool is_non_writable = false;
|
||||||
ast::AttributeList ast_member_decorations;
|
AttributeList ast_member_decorations;
|
||||||
for (auto& decoration : GetDecorationsForMember(type_id, member_index)) {
|
for (auto& decoration : GetDecorationsForMember(type_id, member_index)) {
|
||||||
if (IsPipelineDecoration(decoration)) {
|
if (IsPipelineDecoration(decoration)) {
|
||||||
// IO decorations are handled when emitting the entry point.
|
// IO decorations are handled when emitting the entry point.
|
||||||
|
@ -1137,7 +1137,7 @@ const Type* ParserImpl::ConvertType(uint32_t type_id,
|
||||||
auto decos =
|
auto decos =
|
||||||
ConvertMemberDecoration(type_id, member_index, ast_member_ty, decoration);
|
ConvertMemberDecoration(type_id, member_index, ast_member_ty, decoration);
|
||||||
for (auto* deco : decos) {
|
for (auto* deco : decos) {
|
||||||
ast_member_decorations.emplace_back(deco);
|
ast_member_decorations.Push(deco);
|
||||||
}
|
}
|
||||||
if (!success_) {
|
if (!success_) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1154,10 +1154,10 @@ const Type* ParserImpl::ConvertType(uint32_t type_id,
|
||||||
auto* ast_struct_member = create<ast::StructMember>(
|
auto* ast_struct_member = create<ast::StructMember>(
|
||||||
Source{}, builder_.Symbols().Register(member_name), ast_member_ty->Build(builder_),
|
Source{}, builder_.Symbols().Register(member_name), ast_member_ty->Build(builder_),
|
||||||
std::move(ast_member_decorations));
|
std::move(ast_member_decorations));
|
||||||
ast_members.push_back(ast_struct_member);
|
ast_members.Push(ast_struct_member);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ast_members.empty()) {
|
if (ast_members.IsEmpty()) {
|
||||||
// All members were likely built-ins. Don't generate an empty AST structure.
|
// All members were likely built-ins. Don't generate an empty AST structure.
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1168,8 +1168,7 @@ const Type* ParserImpl::ConvertType(uint32_t type_id,
|
||||||
|
|
||||||
// Now make the struct.
|
// Now make the struct.
|
||||||
auto sym = builder_.Symbols().Register(name);
|
auto sym = builder_.Symbols().Register(name);
|
||||||
auto* ast_struct =
|
auto* ast_struct = create<ast::Struct>(Source{}, sym, std::move(ast_members), utils::Empty);
|
||||||
create<ast::Struct>(Source{}, sym, std::move(ast_members), ast::AttributeList());
|
|
||||||
if (num_non_writable_members == members.size()) {
|
if (num_non_writable_members == members.size()) {
|
||||||
read_only_struct_types_.insert(ast_struct->name);
|
read_only_struct_types_.insert(ast_struct->name);
|
||||||
}
|
}
|
||||||
|
@ -1358,7 +1357,7 @@ bool ParserImpl::EmitScalarSpecConstants() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ast_type && ast_expr) {
|
if (ast_type && ast_expr) {
|
||||||
ast::AttributeList spec_id_decos;
|
AttributeList spec_id_decos;
|
||||||
for (const auto& deco : GetDecorationsFor(inst.result_id())) {
|
for (const auto& deco : GetDecorationsFor(inst.result_id())) {
|
||||||
if ((deco.size() == 2) && (deco[0] == SpvDecorationSpecId)) {
|
if ((deco.size() == 2) && (deco[0] == SpvDecorationSpecId)) {
|
||||||
const uint32_t id = deco[1];
|
const uint32_t id = deco[1];
|
||||||
|
@ -1368,7 +1367,7 @@ bool ParserImpl::EmitScalarSpecConstants() {
|
||||||
<< inst.result_id() << " has SpecId " << id;
|
<< inst.result_id() << " has SpecId " << id;
|
||||||
}
|
}
|
||||||
auto* cid = create<ast::IdAttribute>(Source{}, id);
|
auto* cid = create<ast::IdAttribute>(Source{}, id);
|
||||||
spec_id_decos.push_back(cid);
|
spec_id_decos.Push(cid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1491,7 +1490,7 @@ bool ParserImpl::EmitModuleScopeVariables() {
|
||||||
ast_constructor = MakeConstantExpression(var.GetSingleWordInOperand(1)).expr;
|
ast_constructor = MakeConstantExpression(var.GetSingleWordInOperand(1)).expr;
|
||||||
}
|
}
|
||||||
auto* ast_var = MakeVar(var.result_id(), ast_storage_class, ast_store_type, ast_constructor,
|
auto* ast_var = MakeVar(var.result_id(), ast_storage_class, ast_store_type, ast_constructor,
|
||||||
ast::AttributeList{});
|
utils::Empty);
|
||||||
// TODO(dneto): initializers (a.k.a. constructor expression)
|
// TODO(dneto): initializers (a.k.a. constructor expression)
|
||||||
if (ast_var) {
|
if (ast_var) {
|
||||||
builder_.AST().AddGlobalVariable(ast_var);
|
builder_.AST().AddGlobalVariable(ast_var);
|
||||||
|
@ -1558,7 +1557,7 @@ ast::Var* ParserImpl::MakeVar(uint32_t id,
|
||||||
ast::StorageClass sc,
|
ast::StorageClass sc,
|
||||||
const Type* storage_type,
|
const Type* storage_type,
|
||||||
const ast::Expression* constructor,
|
const ast::Expression* constructor,
|
||||||
ast::AttributeList decorations) {
|
AttributeList decorations) {
|
||||||
if (storage_type == nullptr) {
|
if (storage_type == nullptr) {
|
||||||
Fail() << "internal error: can't make ast::Variable for null type";
|
Fail() << "internal error: can't make ast::Variable for null type";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1593,14 +1592,13 @@ ast::Var* ParserImpl::MakeVar(uint32_t id,
|
||||||
|
|
||||||
ast::Let* ParserImpl::MakeLet(uint32_t id, const Type* type, const ast::Expression* constructor) {
|
ast::Let* ParserImpl::MakeLet(uint32_t id, const Type* type, const ast::Expression* constructor) {
|
||||||
auto sym = builder_.Symbols().Register(namer_.Name(id));
|
auto sym = builder_.Symbols().Register(namer_.Name(id));
|
||||||
return create<ast::Let>(Source{}, sym, type->Build(builder_), constructor,
|
return create<ast::Let>(Source{}, sym, type->Build(builder_), constructor, utils::Empty);
|
||||||
ast::AttributeList{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::Override* ParserImpl::MakeOverride(uint32_t id,
|
ast::Override* ParserImpl::MakeOverride(uint32_t id,
|
||||||
const Type* type,
|
const Type* type,
|
||||||
const ast::Expression* constructor,
|
const ast::Expression* constructor,
|
||||||
ast::AttributeList decorations) {
|
AttributeList decorations) {
|
||||||
if (!ConvertDecorationsForVariable(id, &type, &decorations, false)) {
|
if (!ConvertDecorationsForVariable(id, &type, &decorations, false)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1610,7 +1608,7 @@ ast::Override* ParserImpl::MakeOverride(uint32_t id,
|
||||||
|
|
||||||
ast::Parameter* ParserImpl::MakeParameter(uint32_t id,
|
ast::Parameter* ParserImpl::MakeParameter(uint32_t id,
|
||||||
const Type* type,
|
const Type* type,
|
||||||
ast::AttributeList decorations) {
|
AttributeList decorations) {
|
||||||
if (!ConvertDecorationsForVariable(id, &type, &decorations, false)) {
|
if (!ConvertDecorationsForVariable(id, &type, &decorations, false)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1621,7 +1619,7 @@ ast::Parameter* ParserImpl::MakeParameter(uint32_t id,
|
||||||
|
|
||||||
bool ParserImpl::ConvertDecorationsForVariable(uint32_t id,
|
bool ParserImpl::ConvertDecorationsForVariable(uint32_t id,
|
||||||
const Type** store_type,
|
const Type** store_type,
|
||||||
ast::AttributeList* decorations,
|
AttributeList* decorations,
|
||||||
bool transfer_pipeline_io) {
|
bool transfer_pipeline_io) {
|
||||||
DecorationList non_builtin_pipeline_decorations;
|
DecorationList non_builtin_pipeline_decorations;
|
||||||
for (auto& deco : GetDecorationsFor(id)) {
|
for (auto& deco : GetDecorationsFor(id)) {
|
||||||
|
@ -1681,7 +1679,7 @@ bool ParserImpl::ConvertDecorationsForVariable(uint32_t id,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (transfer_pipeline_io) {
|
if (transfer_pipeline_io) {
|
||||||
decorations->emplace_back(create<ast::BuiltinAttribute>(Source{}, ast_builtin));
|
decorations->Push(create<ast::BuiltinAttribute>(Source{}, ast_builtin));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (transfer_pipeline_io && IsPipelineDecoration(deco)) {
|
if (transfer_pipeline_io && IsPipelineDecoration(deco)) {
|
||||||
|
@ -1692,13 +1690,13 @@ bool ParserImpl::ConvertDecorationsForVariable(uint32_t id,
|
||||||
return Fail() << "malformed DescriptorSet decoration on ID " << id
|
return Fail() << "malformed DescriptorSet decoration on ID " << id
|
||||||
<< ": has no operand";
|
<< ": has no operand";
|
||||||
}
|
}
|
||||||
decorations->emplace_back(create<ast::GroupAttribute>(Source{}, deco[1]));
|
decorations->Push(create<ast::GroupAttribute>(Source{}, deco[1]));
|
||||||
}
|
}
|
||||||
if (deco[0] == SpvDecorationBinding) {
|
if (deco[0] == SpvDecorationBinding) {
|
||||||
if (deco.size() == 1) {
|
if (deco.size() == 1) {
|
||||||
return Fail() << "malformed Binding decoration on ID " << id << ": has no operand";
|
return Fail() << "malformed Binding decoration on ID " << id << ": has no operand";
|
||||||
}
|
}
|
||||||
decorations->emplace_back(create<ast::BindingAttribute>(Source{}, deco[1]));
|
decorations->Push(create<ast::BindingAttribute>(Source{}, deco[1]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1725,7 +1723,7 @@ DecorationList ParserImpl::GetMemberPipelineDecorations(const Struct& struct_typ
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Attribute* ParserImpl::SetLocation(ast::AttributeList* attributes,
|
const ast::Attribute* ParserImpl::SetLocation(AttributeList* attributes,
|
||||||
const ast::Attribute* replacement) {
|
const ast::Attribute* replacement) {
|
||||||
if (!replacement) {
|
if (!replacement) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1742,13 +1740,13 @@ const ast::Attribute* ParserImpl::SetLocation(ast::AttributeList* attributes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The list didn't have a location. Add it.
|
// The list didn't have a location. Add it.
|
||||||
attributes->push_back(replacement);
|
attributes->Push(replacement);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ParserImpl::ConvertPipelineDecorations(const Type* store_type,
|
bool ParserImpl::ConvertPipelineDecorations(const Type* store_type,
|
||||||
const DecorationList& decorations,
|
const DecorationList& decorations,
|
||||||
ast::AttributeList* attributes) {
|
AttributeList* attributes) {
|
||||||
// Vulkan defaults to perspective-correct interpolation.
|
// Vulkan defaults to perspective-correct interpolation.
|
||||||
ast::InterpolationType type = ast::InterpolationType::kPerspective;
|
ast::InterpolationType type = ast::InterpolationType::kPerspective;
|
||||||
ast::InterpolationSampling sampling = ast::InterpolationSampling::kNone;
|
ast::InterpolationSampling sampling = ast::InterpolationSampling::kNone;
|
||||||
|
@ -1809,7 +1807,7 @@ bool ParserImpl::ConvertPipelineDecorations(const Type* store_type,
|
||||||
sampling == ast::InterpolationSampling::kNone) {
|
sampling == ast::InterpolationSampling::kNone) {
|
||||||
// This is the default. Don't add a decoration.
|
// This is the default. Don't add a decoration.
|
||||||
} else {
|
} else {
|
||||||
attributes->emplace_back(create<ast::InterpolateAttribute>(type, sampling));
|
attributes->Push(create<ast::InterpolateAttribute>(type, sampling));
|
||||||
}
|
}
|
||||||
|
|
||||||
return success();
|
return success();
|
||||||
|
@ -1842,7 +1840,7 @@ TypedExpression ParserImpl::MakeConstantExpression(uint32_t id) {
|
||||||
auto z = MakeConstantExpression(workgroup_size_builtin_.z_id);
|
auto z = MakeConstantExpression(workgroup_size_builtin_.z_id);
|
||||||
auto* ast_type = ty_.Vector(x.type, 3);
|
auto* ast_type = ty_.Vector(x.type, 3);
|
||||||
return {ast_type, builder_.Construct(Source{}, ast_type->Build(builder_),
|
return {ast_type, builder_.Construct(Source{}, ast_type->Build(builder_),
|
||||||
ast::ExpressionList{x.expr, y.expr, z.expr})};
|
utils::Vector{x.expr, y.expr, z.expr})};
|
||||||
} else if (id == workgroup_size_builtin_.x_id) {
|
} else if (id == workgroup_size_builtin_.x_id) {
|
||||||
return MakeConstantExpressionForScalarSpirvConstant(
|
return MakeConstantExpressionForScalarSpirvConstant(
|
||||||
Source{}, ConvertType(workgroup_size_builtin_.component_type_id),
|
Source{}, ConvertType(workgroup_size_builtin_.component_type_id),
|
||||||
|
@ -1898,14 +1896,14 @@ TypedExpression ParserImpl::MakeConstantExpression(uint32_t id) {
|
||||||
// Handle vector, matrix, array, and struct
|
// Handle vector, matrix, array, and struct
|
||||||
|
|
||||||
// Generate a composite from explicit components.
|
// Generate a composite from explicit components.
|
||||||
ast::ExpressionList ast_components;
|
ExpressionList ast_components;
|
||||||
if (!inst->WhileEachInId([&](const uint32_t* id_ref) -> bool {
|
if (!inst->WhileEachInId([&](const uint32_t* id_ref) -> bool {
|
||||||
auto component = MakeConstantExpression(*id_ref);
|
auto component = MakeConstantExpression(*id_ref);
|
||||||
if (!component) {
|
if (!component) {
|
||||||
this->Fail() << "invalid constant with ID " << *id_ref;
|
this->Fail() << "invalid constant with ID " << *id_ref;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ast_components.emplace_back(component.expr);
|
ast_components.Push(component.expr);
|
||||||
return true;
|
return true;
|
||||||
})) {
|
})) {
|
||||||
// We've already emitted a diagnostic.
|
// We've already emitted a diagnostic.
|
||||||
|
@ -1996,9 +1994,9 @@ const ast::Expression* ParserImpl::MakeNullValue(const Type* type) {
|
||||||
[&](const Array*) { return builder_.Construct(Source{}, type->Build(builder_)); },
|
[&](const Array*) { return builder_.Construct(Source{}, type->Build(builder_)); },
|
||||||
[&](const Bool*) { return create<ast::BoolLiteralExpression>(Source{}, false); },
|
[&](const Bool*) { return create<ast::BoolLiteralExpression>(Source{}, false); },
|
||||||
[&](const Struct* struct_ty) {
|
[&](const Struct* struct_ty) {
|
||||||
ast::ExpressionList ast_components;
|
ExpressionList ast_components;
|
||||||
for (auto* member : struct_ty->members) {
|
for (auto* member : struct_ty->members) {
|
||||||
ast_components.emplace_back(MakeNullValue(member));
|
ast_components.Push(MakeNullValue(member));
|
||||||
}
|
}
|
||||||
return builder_.Construct(Source{}, original_type->Build(builder_),
|
return builder_.Construct(Source{}, original_type->Build(builder_),
|
||||||
std::move(ast_components));
|
std::move(ast_components));
|
||||||
|
|
|
@ -123,6 +123,9 @@ struct WorkgroupSizeInfo {
|
||||||
|
|
||||||
/// Parser implementation for SPIR-V.
|
/// Parser implementation for SPIR-V.
|
||||||
class ParserImpl : Reader {
|
class ParserImpl : Reader {
|
||||||
|
using AttributeList = utils::Vector<const ast::Attribute*, 8>;
|
||||||
|
using ExpressionList = utils::Vector<const ast::Expression*, 8>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Creates a new parser
|
/// Creates a new parser
|
||||||
/// @param input the input data to parse
|
/// @param input the input data to parse
|
||||||
|
@ -252,15 +255,14 @@ class ParserImpl : Reader {
|
||||||
/// a diagnostic), or when the variable should not be emitted, e.g. for a
|
/// a diagnostic), or when the variable should not be emitted, e.g. for a
|
||||||
/// PointSize builtin.
|
/// PointSize builtin.
|
||||||
/// @param id the ID of the SPIR-V variable
|
/// @param id the ID of the SPIR-V variable
|
||||||
/// @param store_type the WGSL store type for the variable, which should be
|
/// @param store_type the WGSL store type for the variable, which should be prepopulated
|
||||||
/// prepopulatd
|
|
||||||
/// @param attributes the attribute list to populate
|
/// @param attributes the attribute list to populate
|
||||||
/// @param transfer_pipeline_io true if pipeline IO decorations (builtins,
|
/// @param transfer_pipeline_io true if pipeline IO decorations (builtins,
|
||||||
/// or locations) will update the store type and the decorations list
|
/// or locations) will update the store type and the decorations list
|
||||||
/// @returns false when the variable should not be emitted as a variable
|
/// @returns false when the variable should not be emitted as a variable
|
||||||
bool ConvertDecorationsForVariable(uint32_t id,
|
bool ConvertDecorationsForVariable(uint32_t id,
|
||||||
const Type** store_type,
|
const Type** store_type,
|
||||||
ast::AttributeList* attributes,
|
AttributeList* attributes,
|
||||||
bool transfer_pipeline_io);
|
bool transfer_pipeline_io);
|
||||||
|
|
||||||
/// Converts SPIR-V decorations for pipeline IO into AST decorations.
|
/// Converts SPIR-V decorations for pipeline IO into AST decorations.
|
||||||
|
@ -270,7 +272,7 @@ class ParserImpl : Reader {
|
||||||
/// @returns false if conversion fails
|
/// @returns false if conversion fails
|
||||||
bool ConvertPipelineDecorations(const Type* store_type,
|
bool ConvertPipelineDecorations(const Type* store_type,
|
||||||
const DecorationList& decorations,
|
const DecorationList& decorations,
|
||||||
ast::AttributeList* attributes);
|
AttributeList* attributes);
|
||||||
|
|
||||||
/// Updates the attribute list, placing a non-null location decoration into
|
/// Updates the attribute list, placing a non-null location decoration into
|
||||||
/// the list, replacing an existing one if it exists. Does nothing if the
|
/// the list, replacing an existing one if it exists. Does nothing if the
|
||||||
|
@ -280,7 +282,7 @@ class ParserImpl : Reader {
|
||||||
/// @param replacement the location decoration to place into the list
|
/// @param replacement the location decoration to place into the list
|
||||||
/// @returns the location decoration that was replaced, if one was replaced,
|
/// @returns the location decoration that was replaced, if one was replaced,
|
||||||
/// or null otherwise.
|
/// or null otherwise.
|
||||||
const ast::Attribute* SetLocation(ast::AttributeList* decos, const ast::Attribute* replacement);
|
const ast::Attribute* SetLocation(AttributeList* decos, const ast::Attribute* replacement);
|
||||||
|
|
||||||
/// Converts a SPIR-V struct member decoration into a number of AST
|
/// Converts a SPIR-V struct member decoration into a number of AST
|
||||||
/// decorations. If the decoration is recognized but deliberately dropped,
|
/// decorations. If the decoration is recognized but deliberately dropped,
|
||||||
|
@ -291,10 +293,10 @@ class ParserImpl : Reader {
|
||||||
/// @param member_ty the type of the member
|
/// @param member_ty the type of the member
|
||||||
/// @param decoration an encoded SPIR-V Decoration
|
/// @param decoration an encoded SPIR-V Decoration
|
||||||
/// @returns the AST decorations
|
/// @returns the AST decorations
|
||||||
ast::AttributeList ConvertMemberDecoration(uint32_t struct_type_id,
|
AttributeList ConvertMemberDecoration(uint32_t struct_type_id,
|
||||||
uint32_t member_index,
|
uint32_t member_index,
|
||||||
const Type* member_ty,
|
const Type* member_ty,
|
||||||
const Decoration& decoration);
|
const Decoration& decoration);
|
||||||
|
|
||||||
/// Returns a string for the given type. If the type ID is invalid,
|
/// Returns a string for the given type. If the type ID is invalid,
|
||||||
/// then the resulting string only names the type ID.
|
/// then the resulting string only names the type ID.
|
||||||
|
@ -434,7 +436,7 @@ class ParserImpl : Reader {
|
||||||
ast::StorageClass sc,
|
ast::StorageClass sc,
|
||||||
const Type* storage_type,
|
const Type* storage_type,
|
||||||
const ast::Expression* constructor,
|
const ast::Expression* constructor,
|
||||||
ast::AttributeList decorations);
|
AttributeList decorations);
|
||||||
|
|
||||||
/// Creates an AST 'let' node for a SPIR-V ID, including any attached decorations,.
|
/// Creates an AST 'let' node for a SPIR-V ID, including any attached decorations,.
|
||||||
/// @param id the SPIR-V result ID
|
/// @param id the SPIR-V result ID
|
||||||
|
@ -452,7 +454,7 @@ class ParserImpl : Reader {
|
||||||
ast::Override* MakeOverride(uint32_t id,
|
ast::Override* MakeOverride(uint32_t id,
|
||||||
const Type* type,
|
const Type* type,
|
||||||
const ast::Expression* constructor,
|
const ast::Expression* constructor,
|
||||||
ast::AttributeList decorations);
|
AttributeList decorations);
|
||||||
|
|
||||||
/// Creates an AST parameter node for a SPIR-V ID, including any attached decorations, unless
|
/// Creates an AST parameter node for a SPIR-V ID, including any attached decorations, unless
|
||||||
/// it's an ignorable builtin variable.
|
/// it's an ignorable builtin variable.
|
||||||
|
@ -460,7 +462,7 @@ class ParserImpl : Reader {
|
||||||
/// @param type the type of the parameter
|
/// @param type the type of the parameter
|
||||||
/// @param decorations the parameter decorations
|
/// @param decorations the parameter decorations
|
||||||
/// @returns the AST parameter node
|
/// @returns the AST parameter node
|
||||||
ast::Parameter* MakeParameter(uint32_t id, const Type* type, ast::AttributeList decorations);
|
ast::Parameter* MakeParameter(uint32_t id, const Type* type, AttributeList decorations);
|
||||||
|
|
||||||
/// Returns true if a constant expression can be generated.
|
/// Returns true if a constant expression can be generated.
|
||||||
/// @param id the SPIR-V ID of the value
|
/// @param id the SPIR-V ID of the value
|
||||||
|
|
|
@ -65,10 +65,10 @@ TEST_F(SpvParserTest, WorkgroupBarrier) {
|
||||||
ASSERT_TRUE(program.IsValid()) << program.Diagnostics().str();
|
ASSERT_TRUE(program.IsValid()) << program.Diagnostics().str();
|
||||||
auto* helper = program.AST().Functions().Find(program.Symbols().Get("helper"));
|
auto* helper = program.AST().Functions().Find(program.Symbols().Get("helper"));
|
||||||
ASSERT_NE(helper, nullptr);
|
ASSERT_NE(helper, nullptr);
|
||||||
ASSERT_GT(helper->body->statements.size(), 0u);
|
ASSERT_GT(helper->body->statements.Length(), 0u);
|
||||||
auto* call = helper->body->statements[0]->As<ast::CallStatement>();
|
auto* call = helper->body->statements[0]->As<ast::CallStatement>();
|
||||||
ASSERT_NE(call, nullptr);
|
ASSERT_NE(call, nullptr);
|
||||||
EXPECT_EQ(call->expr->args.size(), 0u);
|
EXPECT_EQ(call->expr->args.Length(), 0u);
|
||||||
auto* sem_call = program.Sem().Get<sem::Call>(call->expr);
|
auto* sem_call = program.Sem().Get<sem::Call>(call->expr);
|
||||||
ASSERT_NE(sem_call, nullptr);
|
ASSERT_NE(sem_call, nullptr);
|
||||||
auto* builtin = sem_call->Target()->As<sem::Builtin>();
|
auto* builtin = sem_call->Target()->As<sem::Builtin>();
|
||||||
|
@ -98,10 +98,10 @@ TEST_F(SpvParserTest, StorageBarrier) {
|
||||||
ASSERT_TRUE(program.IsValid()) << program.Diagnostics().str();
|
ASSERT_TRUE(program.IsValid()) << program.Diagnostics().str();
|
||||||
auto* helper = program.AST().Functions().Find(program.Symbols().Get("helper"));
|
auto* helper = program.AST().Functions().Find(program.Symbols().Get("helper"));
|
||||||
ASSERT_NE(helper, nullptr);
|
ASSERT_NE(helper, nullptr);
|
||||||
ASSERT_GT(helper->body->statements.size(), 0u);
|
ASSERT_GT(helper->body->statements.Length(), 0u);
|
||||||
auto* call = helper->body->statements[0]->As<ast::CallStatement>();
|
auto* call = helper->body->statements[0]->As<ast::CallStatement>();
|
||||||
ASSERT_NE(call, nullptr);
|
ASSERT_NE(call, nullptr);
|
||||||
EXPECT_EQ(call->expr->args.size(), 0u);
|
EXPECT_EQ(call->expr->args.Length(), 0u);
|
||||||
auto* sem_call = program.Sem().Get<sem::Call>(call->expr);
|
auto* sem_call = program.Sem().Get<sem::Call>(call->expr);
|
||||||
ASSERT_NE(sem_call, nullptr);
|
ASSERT_NE(sem_call, nullptr);
|
||||||
auto* builtin = sem_call->Target()->As<sem::Builtin>();
|
auto* builtin = sem_call->Target()->As<sem::Builtin>();
|
||||||
|
|
|
@ -20,11 +20,11 @@ namespace {
|
||||||
|
|
||||||
using ::testing::Eq;
|
using ::testing::Eq;
|
||||||
|
|
||||||
TEST_F(SpvParserTest, ConvertMemberDecoration_Empty) {
|
TEST_F(SpvParserTest, ConvertMemberDecoration_IsEmpty) {
|
||||||
auto p = parser(std::vector<uint32_t>{});
|
auto p = parser(std::vector<uint32_t>{});
|
||||||
|
|
||||||
auto result = p->ConvertMemberDecoration(1, 1, nullptr, {});
|
auto result = p->ConvertMemberDecoration(1, 1, nullptr, {});
|
||||||
EXPECT_TRUE(result.empty());
|
EXPECT_TRUE(result.IsEmpty());
|
||||||
EXPECT_THAT(p->error(), Eq("malformed SPIR-V decoration: it's empty"));
|
EXPECT_THAT(p->error(), Eq("malformed SPIR-V decoration: it's empty"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_OffsetWithoutOperand) {
|
||||||
auto p = parser(std::vector<uint32_t>{});
|
auto p = parser(std::vector<uint32_t>{});
|
||||||
|
|
||||||
auto result = p->ConvertMemberDecoration(12, 13, nullptr, {SpvDecorationOffset});
|
auto result = p->ConvertMemberDecoration(12, 13, nullptr, {SpvDecorationOffset});
|
||||||
EXPECT_TRUE(result.empty());
|
EXPECT_TRUE(result.IsEmpty());
|
||||||
EXPECT_THAT(p->error(), Eq("malformed Offset decoration: expected 1 literal "
|
EXPECT_THAT(p->error(), Eq("malformed Offset decoration: expected 1 literal "
|
||||||
"operand, has 0: member 13 of SPIR-V type 12"));
|
"operand, has 0: member 13 of SPIR-V type 12"));
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_OffsetWithTooManyOperands) {
|
||||||
auto p = parser(std::vector<uint32_t>{});
|
auto p = parser(std::vector<uint32_t>{});
|
||||||
|
|
||||||
auto result = p->ConvertMemberDecoration(12, 13, nullptr, {SpvDecorationOffset, 3, 4});
|
auto result = p->ConvertMemberDecoration(12, 13, nullptr, {SpvDecorationOffset, 3, 4});
|
||||||
EXPECT_TRUE(result.empty());
|
EXPECT_TRUE(result.IsEmpty());
|
||||||
EXPECT_THAT(p->error(), Eq("malformed Offset decoration: expected 1 literal "
|
EXPECT_THAT(p->error(), Eq("malformed Offset decoration: expected 1 literal "
|
||||||
"operand, has 2: member 13 of SPIR-V type 12"));
|
"operand, has 2: member 13 of SPIR-V type 12"));
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_Offset) {
|
||||||
auto p = parser(std::vector<uint32_t>{});
|
auto p = parser(std::vector<uint32_t>{});
|
||||||
|
|
||||||
auto result = p->ConvertMemberDecoration(1, 1, nullptr, {SpvDecorationOffset, 8});
|
auto result = p->ConvertMemberDecoration(1, 1, nullptr, {SpvDecorationOffset, 8});
|
||||||
ASSERT_FALSE(result.empty());
|
ASSERT_FALSE(result.IsEmpty());
|
||||||
EXPECT_TRUE(result[0]->Is<ast::StructMemberOffsetAttribute>());
|
EXPECT_TRUE(result[0]->Is<ast::StructMemberOffsetAttribute>());
|
||||||
auto* offset_deco = result[0]->As<ast::StructMemberOffsetAttribute>();
|
auto* offset_deco = result[0]->As<ast::StructMemberOffsetAttribute>();
|
||||||
ASSERT_NE(offset_deco, nullptr);
|
ASSERT_NE(offset_deco, nullptr);
|
||||||
|
@ -64,7 +64,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_Matrix2x2_Stride_Natural) {
|
||||||
spirv::F32 f32;
|
spirv::F32 f32;
|
||||||
spirv::Matrix matrix(&f32, 2, 2);
|
spirv::Matrix matrix(&f32, 2, 2);
|
||||||
auto result = p->ConvertMemberDecoration(1, 1, &matrix, {SpvDecorationMatrixStride, 8});
|
auto result = p->ConvertMemberDecoration(1, 1, &matrix, {SpvDecorationMatrixStride, 8});
|
||||||
EXPECT_TRUE(result.empty());
|
EXPECT_TRUE(result.IsEmpty());
|
||||||
EXPECT_TRUE(p->error().empty());
|
EXPECT_TRUE(p->error().empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_Matrix2x2_Stride_Custom) {
|
||||||
spirv::F32 f32;
|
spirv::F32 f32;
|
||||||
spirv::Matrix matrix(&f32, 2, 2);
|
spirv::Matrix matrix(&f32, 2, 2);
|
||||||
auto result = p->ConvertMemberDecoration(1, 1, &matrix, {SpvDecorationMatrixStride, 16});
|
auto result = p->ConvertMemberDecoration(1, 1, &matrix, {SpvDecorationMatrixStride, 16});
|
||||||
ASSERT_FALSE(result.empty());
|
ASSERT_FALSE(result.IsEmpty());
|
||||||
EXPECT_TRUE(result[0]->Is<ast::StrideAttribute>());
|
EXPECT_TRUE(result[0]->Is<ast::StrideAttribute>());
|
||||||
auto* stride_deco = result[0]->As<ast::StrideAttribute>();
|
auto* stride_deco = result[0]->As<ast::StrideAttribute>();
|
||||||
ASSERT_NE(stride_deco, nullptr);
|
ASSERT_NE(stride_deco, nullptr);
|
||||||
|
@ -88,7 +88,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_Matrix2x4_Stride_Natural) {
|
||||||
spirv::F32 f32;
|
spirv::F32 f32;
|
||||||
spirv::Matrix matrix(&f32, 2, 4);
|
spirv::Matrix matrix(&f32, 2, 4);
|
||||||
auto result = p->ConvertMemberDecoration(1, 1, &matrix, {SpvDecorationMatrixStride, 16});
|
auto result = p->ConvertMemberDecoration(1, 1, &matrix, {SpvDecorationMatrixStride, 16});
|
||||||
EXPECT_TRUE(result.empty());
|
EXPECT_TRUE(result.IsEmpty());
|
||||||
EXPECT_TRUE(p->error().empty());
|
EXPECT_TRUE(p->error().empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_Matrix2x4_Stride_Custom) {
|
||||||
spirv::F32 f32;
|
spirv::F32 f32;
|
||||||
spirv::Matrix matrix(&f32, 2, 4);
|
spirv::Matrix matrix(&f32, 2, 4);
|
||||||
auto result = p->ConvertMemberDecoration(1, 1, &matrix, {SpvDecorationMatrixStride, 64});
|
auto result = p->ConvertMemberDecoration(1, 1, &matrix, {SpvDecorationMatrixStride, 64});
|
||||||
ASSERT_FALSE(result.empty());
|
ASSERT_FALSE(result.IsEmpty());
|
||||||
EXPECT_TRUE(result[0]->Is<ast::StrideAttribute>());
|
EXPECT_TRUE(result[0]->Is<ast::StrideAttribute>());
|
||||||
auto* stride_deco = result[0]->As<ast::StrideAttribute>();
|
auto* stride_deco = result[0]->As<ast::StrideAttribute>();
|
||||||
ASSERT_NE(stride_deco, nullptr);
|
ASSERT_NE(stride_deco, nullptr);
|
||||||
|
@ -112,7 +112,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_Matrix2x3_Stride_Custom) {
|
||||||
spirv::F32 f32;
|
spirv::F32 f32;
|
||||||
spirv::Matrix matrix(&f32, 2, 3);
|
spirv::Matrix matrix(&f32, 2, 3);
|
||||||
auto result = p->ConvertMemberDecoration(1, 1, &matrix, {SpvDecorationMatrixStride, 32});
|
auto result = p->ConvertMemberDecoration(1, 1, &matrix, {SpvDecorationMatrixStride, 32});
|
||||||
ASSERT_FALSE(result.empty());
|
ASSERT_FALSE(result.IsEmpty());
|
||||||
EXPECT_TRUE(result[0]->Is<ast::StrideAttribute>());
|
EXPECT_TRUE(result[0]->Is<ast::StrideAttribute>());
|
||||||
auto* stride_deco = result[0]->As<ast::StrideAttribute>();
|
auto* stride_deco = result[0]->As<ast::StrideAttribute>();
|
||||||
ASSERT_NE(stride_deco, nullptr);
|
ASSERT_NE(stride_deco, nullptr);
|
||||||
|
@ -127,7 +127,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_RelaxedPrecision) {
|
||||||
auto p = parser(std::vector<uint32_t>{});
|
auto p = parser(std::vector<uint32_t>{});
|
||||||
|
|
||||||
auto result = p->ConvertMemberDecoration(1, 1, nullptr, {SpvDecorationRelaxedPrecision});
|
auto result = p->ConvertMemberDecoration(1, 1, nullptr, {SpvDecorationRelaxedPrecision});
|
||||||
EXPECT_TRUE(result.empty());
|
EXPECT_TRUE(result.IsEmpty());
|
||||||
EXPECT_TRUE(p->error().empty());
|
EXPECT_TRUE(p->error().empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_UnhandledDecoration) {
|
||||||
auto p = parser(std::vector<uint32_t>{});
|
auto p = parser(std::vector<uint32_t>{});
|
||||||
|
|
||||||
auto result = p->ConvertMemberDecoration(12, 13, nullptr, {12345678});
|
auto result = p->ConvertMemberDecoration(12, 13, nullptr, {12345678});
|
||||||
EXPECT_TRUE(result.empty());
|
EXPECT_TRUE(result.IsEmpty());
|
||||||
EXPECT_THAT(p->error(), Eq("unhandled member decoration: 12345678 on member "
|
EXPECT_THAT(p->error(), Eq("unhandled member decoration: 12345678 on member "
|
||||||
"13 of SPIR-V type 12"));
|
"13 of SPIR-V type 12"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -3076,7 +3076,7 @@ TEST_P(SpvParserHandleTest_ImageCoordsTest, MakeCoordinateOperandsForImageAccess
|
||||||
ASSERT_NE(anchor, nullptr);
|
ASSERT_NE(anchor, nullptr);
|
||||||
const spvtools::opt::Instruction& image_access = *(anchor->PreviousNode());
|
const spvtools::opt::Instruction& image_access = *(anchor->PreviousNode());
|
||||||
|
|
||||||
ast::ExpressionList result = fe.MakeCoordinateOperandsForImageAccess(image_access);
|
auto result = fe.MakeCoordinateOperandsForImageAccess(image_access);
|
||||||
if (GetParam().expected_error.empty()) {
|
if (GetParam().expected_error.empty()) {
|
||||||
EXPECT_TRUE(fe.success()) << p->error();
|
EXPECT_TRUE(fe.success()) << p->error();
|
||||||
EXPECT_TRUE(p->error().empty());
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
@ -3090,7 +3090,7 @@ TEST_P(SpvParserHandleTest_ImageCoordsTest, MakeCoordinateOperandsForImageAccess
|
||||||
} else {
|
} else {
|
||||||
EXPECT_FALSE(fe.success());
|
EXPECT_FALSE(fe.success());
|
||||||
EXPECT_THAT(p->error(), Eq(GetParam().expected_error)) << assembly;
|
EXPECT_THAT(p->error(), Eq(GetParam().expected_error)) << assembly;
|
||||||
EXPECT_TRUE(result.empty());
|
EXPECT_TRUE(result.IsEmpty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ std::string ToString(const Program& program) {
|
||||||
return writer.result();
|
return writer.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToString(const Program& program, const ast::StatementList& stmts) {
|
std::string ToString(const Program& program, utils::VectorRef<const ast::Statement*> stmts) {
|
||||||
writer::wgsl::GeneratorImpl writer(&program);
|
writer::wgsl::GeneratorImpl writer(&program);
|
||||||
for (const auto* stmt : stmts) {
|
for (const auto* stmt : stmts) {
|
||||||
if (!writer.EmitStatement(stmt)) {
|
if (!writer.EmitStatement(stmt)) {
|
||||||
|
|
|
@ -195,10 +195,10 @@ class ParserImplWrapperForTest {
|
||||||
/// @param member_ty the type of the member
|
/// @param member_ty the type of the member
|
||||||
/// @param decoration an encoded SPIR-V Decoration
|
/// @param decoration an encoded SPIR-V Decoration
|
||||||
/// @returns the AST decorations
|
/// @returns the AST decorations
|
||||||
ast::AttributeList ConvertMemberDecoration(uint32_t struct_type_id,
|
auto ConvertMemberDecoration(uint32_t struct_type_id,
|
||||||
uint32_t member_index,
|
uint32_t member_index,
|
||||||
const Type* member_ty,
|
const Type* member_ty,
|
||||||
const Decoration& decoration) {
|
const Decoration& decoration) {
|
||||||
return impl_.ConvertMemberDecoration(struct_type_id, member_index, member_ty, decoration);
|
return impl_.ConvertMemberDecoration(struct_type_id, member_index, member_ty, decoration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +275,7 @@ std::string ToString(const Program& program);
|
||||||
/// @param program the Program
|
/// @param program the Program
|
||||||
/// @param stmts the statement list
|
/// @param stmts the statement list
|
||||||
/// @returns the WGSL printed string of a statement list.
|
/// @returns the WGSL printed string of a statement list.
|
||||||
std::string ToString(const Program& program, const ast::StatementList& stmts);
|
std::string ToString(const Program& program, utils::VectorRef<const ast::Statement*> stmts);
|
||||||
|
|
||||||
/// Returns the WGSL printed string of an AST node.
|
/// Returns the WGSL printed string of an AST node.
|
||||||
/// @param program the Program
|
/// @param program the Program
|
||||||
|
|
|
@ -170,9 +170,9 @@ ParserImpl::FunctionHeader::FunctionHeader(const FunctionHeader&) = default;
|
||||||
|
|
||||||
ParserImpl::FunctionHeader::FunctionHeader(Source src,
|
ParserImpl::FunctionHeader::FunctionHeader(Source src,
|
||||||
std::string n,
|
std::string n,
|
||||||
ast::ParameterList p,
|
utils::VectorRef<const ast::Parameter*> p,
|
||||||
const ast::Type* ret_ty,
|
const ast::Type* ret_ty,
|
||||||
ast::AttributeList ret_attrs)
|
utils::VectorRef<const ast::Attribute*> ret_attrs)
|
||||||
: source(src),
|
: source(src),
|
||||||
name(n),
|
name(n),
|
||||||
params(std::move(p)),
|
params(std::move(p)),
|
||||||
|
@ -507,7 +507,7 @@ Maybe<bool> ParserImpl::global_decl() {
|
||||||
// Invalid syntax found - try and determine the best error message
|
// Invalid syntax found - try and determine the best error message
|
||||||
|
|
||||||
// We have attributes parsed, but nothing to consume them?
|
// We have attributes parsed, but nothing to consume them?
|
||||||
if (attrs.value.size() > 0) {
|
if (attrs.value.Length() > 0) {
|
||||||
return add_error(next(), "expected declaration after attributes");
|
return add_error(next(), "expected declaration after attributes");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,7 +540,7 @@ Maybe<bool> ParserImpl::global_decl() {
|
||||||
// global_variable_decl
|
// global_variable_decl
|
||||||
// : variable_attribute_list* variable_decl
|
// : variable_attribute_list* variable_decl
|
||||||
// | variable_attribute_list* variable_decl EQUAL const_expr
|
// | variable_attribute_list* variable_decl EQUAL const_expr
|
||||||
Maybe<const ast::Variable*> ParserImpl::global_variable_decl(ast::AttributeList& attrs) {
|
Maybe<const ast::Variable*> ParserImpl::global_variable_decl(AttributeList& attrs) {
|
||||||
auto decl = variable_decl();
|
auto decl = variable_decl();
|
||||||
if (decl.errored) {
|
if (decl.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
|
@ -549,24 +549,26 @@ Maybe<const ast::Variable*> ParserImpl::global_variable_decl(ast::AttributeList&
|
||||||
return Failure::kNoMatch;
|
return Failure::kNoMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Expression* initalizer = nullptr;
|
const ast::Expression* initializer = nullptr;
|
||||||
if (match(Token::Type::kEqual)) {
|
if (match(Token::Type::kEqual)) {
|
||||||
auto expr = logical_or_expression();
|
auto expr = logical_or_expression();
|
||||||
if (expr.errored) {
|
if (expr.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
if (!expr.matched) {
|
if (!expr.matched) {
|
||||||
return add_error(peek(), "missing initalizer for 'var' declaration");
|
return add_error(peek(), "missing initializer for 'var' declaration");
|
||||||
}
|
}
|
||||||
initalizer = expr.value;
|
initializer = expr.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TINT_DEFER(attrs.Clear());
|
||||||
|
|
||||||
return create<ast::Var>(decl->source, // source
|
return create<ast::Var>(decl->source, // source
|
||||||
builder_.Symbols().Register(decl->name), // symbol
|
builder_.Symbols().Register(decl->name), // symbol
|
||||||
decl->type, // type
|
decl->type, // type
|
||||||
decl->storage_class, // storage class
|
decl->storage_class, // storage class
|
||||||
decl->access, // access control
|
decl->access, // access control
|
||||||
initalizer, // initializer
|
initializer, // initializer
|
||||||
std::move(attrs)); // attributes
|
std::move(attrs)); // attributes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,7 +577,7 @@ Maybe<const ast::Variable*> ParserImpl::global_variable_decl(ast::AttributeList&
|
||||||
// | attribute* override (ident | variable_ident_decl) (equal expression)?
|
// | attribute* override (ident | variable_ident_decl) (equal expression)?
|
||||||
// global_const_initializer
|
// global_const_initializer
|
||||||
// : EQUAL const_expr
|
// : EQUAL const_expr
|
||||||
Maybe<const ast::Variable*> ParserImpl::global_constant_decl(ast::AttributeList& attrs) {
|
Maybe<const ast::Variable*> ParserImpl::global_constant_decl(AttributeList& attrs) {
|
||||||
bool is_const = false;
|
bool is_const = false;
|
||||||
bool is_overridable = false;
|
bool is_overridable = false;
|
||||||
const char* use = nullptr;
|
const char* use = nullptr;
|
||||||
|
@ -619,6 +621,8 @@ Maybe<const ast::Variable*> ParserImpl::global_constant_decl(ast::AttributeList&
|
||||||
initializer = std::move(expr.value);
|
initializer = std::move(expr.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TINT_DEFER(attrs.Clear());
|
||||||
|
|
||||||
if (is_const) {
|
if (is_const) {
|
||||||
return create<ast::Const>(decl->source, // source
|
return create<ast::Const>(decl->source, // source
|
||||||
builder_.Symbols().Register(decl->name), // symbol
|
builder_.Symbols().Register(decl->name), // symbol
|
||||||
|
@ -1273,14 +1277,14 @@ Maybe<const ast::Struct*> ParserImpl::struct_decl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sym = builder_.Symbols().Register(name.value);
|
auto sym = builder_.Symbols().Register(name.value);
|
||||||
return create<ast::Struct>(t.source(), sym, std::move(body.value), ast::AttributeList{});
|
return create<ast::Struct>(t.source(), sym, std::move(body.value), utils::Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct_body_decl
|
// struct_body_decl
|
||||||
// : BRACE_LEFT (struct_member COMMA)* struct_member COMMA? BRACE_RIGHT
|
// : BRACE_LEFT (struct_member COMMA)* struct_member COMMA? BRACE_RIGHT
|
||||||
Expect<ast::StructMemberList> ParserImpl::expect_struct_body_decl() {
|
Expect<ParserImpl::StructMemberList> ParserImpl::expect_struct_body_decl() {
|
||||||
return expect_brace_block("struct declaration", [&]() -> Expect<ast::StructMemberList> {
|
return expect_brace_block("struct declaration", [&]() -> Expect<StructMemberList> {
|
||||||
ast::StructMemberList members;
|
StructMemberList members;
|
||||||
bool errored = false;
|
bool errored = false;
|
||||||
while (continue_parsing()) {
|
while (continue_parsing()) {
|
||||||
// Check for the end of the list.
|
// Check for the end of the list.
|
||||||
|
@ -1296,7 +1300,7 @@ Expect<ast::StructMemberList> ParserImpl::expect_struct_body_decl() {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
members.push_back(member.value);
|
members.Push(member.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!match(Token::Type::kComma)) {
|
if (!match(Token::Type::kComma)) {
|
||||||
|
@ -1330,7 +1334,7 @@ Expect<ast::StructMember*> ParserImpl::expect_struct_member() {
|
||||||
|
|
||||||
// function_decl
|
// function_decl
|
||||||
// : function_header body_stmt
|
// : function_header body_stmt
|
||||||
Maybe<const ast::Function*> ParserImpl::function_decl(ast::AttributeList& attrs) {
|
Maybe<const ast::Function*> ParserImpl::function_decl(AttributeList& attrs) {
|
||||||
auto header = function_header();
|
auto header = function_header();
|
||||||
if (header.errored) {
|
if (header.errored) {
|
||||||
if (sync_to(Token::Type::kBraceLeft, /* consume: */ false)) {
|
if (sync_to(Token::Type::kBraceLeft, /* consume: */ false)) {
|
||||||
|
@ -1359,8 +1363,10 @@ Maybe<const ast::Function*> ParserImpl::function_decl(ast::AttributeList& attrs)
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TINT_DEFER(attrs.Clear());
|
||||||
|
|
||||||
return create<ast::Function>(header->source, builder_.Symbols().Register(header->name),
|
return create<ast::Function>(header->source, builder_.Symbols().Register(header->name),
|
||||||
header->params, header->return_type, body.value, attrs,
|
header->params, header->return_type, body.value, std::move(attrs),
|
||||||
header->return_type_attributes);
|
header->return_type_attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1395,7 +1401,7 @@ Maybe<ParserImpl::FunctionHeader> ParserImpl::function_header() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Type* return_type = nullptr;
|
const ast::Type* return_type = nullptr;
|
||||||
ast::AttributeList return_attributes;
|
AttributeList return_attributes;
|
||||||
|
|
||||||
if (match(Token::Type::kArrow)) {
|
if (match(Token::Type::kArrow)) {
|
||||||
auto attrs = attribute_list();
|
auto attrs = attribute_list();
|
||||||
|
@ -1420,15 +1426,17 @@ Maybe<ParserImpl::FunctionHeader> ParserImpl::function_header() {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FunctionHeader{source, name.value, std::move(params.value), return_type,
|
return FunctionHeader{
|
||||||
std::move(return_attributes)};
|
source, std::move(name.value), std::move(params.value),
|
||||||
|
return_type, std::move(return_attributes),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// param_list
|
// param_list
|
||||||
// :
|
// :
|
||||||
// | (param COMMA)* param COMMA?
|
// | (param COMMA)* param COMMA?
|
||||||
Expect<ast::ParameterList> ParserImpl::expect_param_list() {
|
Expect<ParserImpl::ParameterList> ParserImpl::expect_param_list() {
|
||||||
ast::ParameterList ret;
|
ParameterList ret;
|
||||||
while (continue_parsing()) {
|
while (continue_parsing()) {
|
||||||
// Check for the end of the list.
|
// Check for the end of the list.
|
||||||
auto& t = peek();
|
auto& t = peek();
|
||||||
|
@ -1440,7 +1448,7 @@ Expect<ast::ParameterList> ParserImpl::expect_param_list() {
|
||||||
if (param.errored) {
|
if (param.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
ret.push_back(param.value);
|
ret.Push(param.value);
|
||||||
|
|
||||||
if (!match(Token::Type::kComma)) {
|
if (!match(Token::Type::kComma)) {
|
||||||
break;
|
break;
|
||||||
|
@ -1532,16 +1540,16 @@ Expect<const ast::Expression*> ParserImpl::expect_paren_expression() {
|
||||||
|
|
||||||
// statements
|
// statements
|
||||||
// : statement*
|
// : statement*
|
||||||
Expect<ast::StatementList> ParserImpl::expect_statements() {
|
Expect<ParserImpl::StatementList> ParserImpl::expect_statements() {
|
||||||
bool errored = false;
|
bool errored = false;
|
||||||
ast::StatementList stmts;
|
StatementList stmts;
|
||||||
|
|
||||||
while (continue_parsing()) {
|
while (continue_parsing()) {
|
||||||
auto stmt = statement();
|
auto stmt = statement();
|
||||||
if (stmt.errored) {
|
if (stmt.errored) {
|
||||||
errored = true;
|
errored = true;
|
||||||
} else if (stmt.matched) {
|
} else if (stmt.matched) {
|
||||||
stmts.emplace_back(stmt.value);
|
stmts.Push(stmt.value);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1762,7 +1770,7 @@ Maybe<const ast::VariableDeclStatement*> ParserImpl::variable_stmt() {
|
||||||
builder_.Symbols().Register(decl->name), // symbol
|
builder_.Symbols().Register(decl->name), // symbol
|
||||||
decl->type, // type
|
decl->type, // type
|
||||||
initializer.value, // initializer
|
initializer.value, // initializer
|
||||||
ast::AttributeList{}); // attributes
|
utils::Empty); // attributes
|
||||||
|
|
||||||
return create<ast::VariableDeclStatement>(decl->source, const_);
|
return create<ast::VariableDeclStatement>(decl->source, const_);
|
||||||
}
|
}
|
||||||
|
@ -1790,7 +1798,7 @@ Maybe<const ast::VariableDeclStatement*> ParserImpl::variable_stmt() {
|
||||||
builder_.Symbols().Register(decl->name), // symbol
|
builder_.Symbols().Register(decl->name), // symbol
|
||||||
decl->type, // type
|
decl->type, // type
|
||||||
initializer.value, // initializer
|
initializer.value, // initializer
|
||||||
ast::AttributeList{}); // attributes
|
utils::Empty); // attributes
|
||||||
|
|
||||||
return create<ast::VariableDeclStatement>(decl->source, let);
|
return create<ast::VariableDeclStatement>(decl->source, let);
|
||||||
}
|
}
|
||||||
|
@ -1822,7 +1830,7 @@ Maybe<const ast::VariableDeclStatement*> ParserImpl::variable_stmt() {
|
||||||
decl->storage_class, // storage class
|
decl->storage_class, // storage class
|
||||||
decl->access, // access control
|
decl->access, // access control
|
||||||
initializer, // initializer
|
initializer, // initializer
|
||||||
ast::AttributeList{}); // attributes
|
utils::Empty); // attributes
|
||||||
|
|
||||||
return create<ast::VariableDeclStatement>(var->source, var);
|
return create<ast::VariableDeclStatement>(var->source, var);
|
||||||
}
|
}
|
||||||
|
@ -1925,9 +1933,9 @@ Maybe<const ast::SwitchStatement*> ParserImpl::switch_stmt() {
|
||||||
return add_error(peek(), "unable to parse selector expression");
|
return add_error(peek(), "unable to parse selector expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto body = expect_brace_block("switch statement", [&]() -> Expect<ast::CaseStatementList> {
|
auto body = expect_brace_block("switch statement", [&]() -> Expect<CaseStatementList> {
|
||||||
bool errored = false;
|
bool errored = false;
|
||||||
ast::CaseStatementList list;
|
CaseStatementList list;
|
||||||
while (continue_parsing()) {
|
while (continue_parsing()) {
|
||||||
auto stmt = switch_body();
|
auto stmt = switch_body();
|
||||||
if (stmt.errored) {
|
if (stmt.errored) {
|
||||||
|
@ -1937,7 +1945,7 @@ Maybe<const ast::SwitchStatement*> ParserImpl::switch_stmt() {
|
||||||
if (!stmt.matched) {
|
if (!stmt.matched) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
list.push_back(stmt.value);
|
list.Push(stmt.value);
|
||||||
}
|
}
|
||||||
if (errored) {
|
if (errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
|
@ -1962,7 +1970,7 @@ Maybe<const ast::CaseStatement*> ParserImpl::switch_body() {
|
||||||
|
|
||||||
auto& t = next();
|
auto& t = next();
|
||||||
|
|
||||||
ast::CaseSelectorList selector_list;
|
CaseSelectorList selector_list;
|
||||||
if (t.Is(Token::Type::kCase)) {
|
if (t.Is(Token::Type::kCase)) {
|
||||||
auto selectors = expect_case_selectors();
|
auto selectors = expect_case_selectors();
|
||||||
if (selectors.errored) {
|
if (selectors.errored) {
|
||||||
|
@ -1990,8 +1998,8 @@ Maybe<const ast::CaseStatement*> ParserImpl::switch_body() {
|
||||||
|
|
||||||
// case_selectors
|
// case_selectors
|
||||||
// : const_literal (COMMA const_literal)* COMMA?
|
// : const_literal (COMMA const_literal)* COMMA?
|
||||||
Expect<ast::CaseSelectorList> ParserImpl::expect_case_selectors() {
|
Expect<ParserImpl::CaseSelectorList> ParserImpl::expect_case_selectors() {
|
||||||
ast::CaseSelectorList selectors;
|
CaseSelectorList selectors;
|
||||||
|
|
||||||
while (continue_parsing()) {
|
while (continue_parsing()) {
|
||||||
auto cond = const_literal();
|
auto cond = const_literal();
|
||||||
|
@ -2003,14 +2011,14 @@ Expect<ast::CaseSelectorList> ParserImpl::expect_case_selectors() {
|
||||||
return add_error(cond.value->source, "invalid case selector must be an integer value");
|
return add_error(cond.value->source, "invalid case selector must be an integer value");
|
||||||
}
|
}
|
||||||
|
|
||||||
selectors.push_back(cond.value->As<ast::IntLiteralExpression>());
|
selectors.Push(cond.value->As<ast::IntLiteralExpression>());
|
||||||
|
|
||||||
if (!match(Token::Type::kComma)) {
|
if (!match(Token::Type::kComma)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectors.empty()) {
|
if (selectors.IsEmpty()) {
|
||||||
return add_error(peek(), "unable to parse case selectors");
|
return add_error(peek(), "unable to parse case selectors");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2022,7 +2030,7 @@ Expect<ast::CaseSelectorList> ParserImpl::expect_case_selectors() {
|
||||||
// | statement case_body
|
// | statement case_body
|
||||||
// | FALLTHROUGH SEMICOLON
|
// | FALLTHROUGH SEMICOLON
|
||||||
Maybe<const ast::BlockStatement*> ParserImpl::case_body() {
|
Maybe<const ast::BlockStatement*> ParserImpl::case_body() {
|
||||||
ast::StatementList stmts;
|
StatementList stmts;
|
||||||
while (continue_parsing()) {
|
while (continue_parsing()) {
|
||||||
Source source;
|
Source source;
|
||||||
if (match(Token::Type::kFallthrough, &source)) {
|
if (match(Token::Type::kFallthrough, &source)) {
|
||||||
|
@ -2030,7 +2038,7 @@ Maybe<const ast::BlockStatement*> ParserImpl::case_body() {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
|
||||||
stmts.emplace_back(create<ast::FallthroughStatement>(source));
|
stmts.Push(create<ast::FallthroughStatement>(source));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2042,7 +2050,7 @@ Maybe<const ast::BlockStatement*> ParserImpl::case_body() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
stmts.emplace_back(stmt.value);
|
stmts.Push(stmt.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return create<ast::BlockStatement>(Source{}, stmts);
|
return create<ast::BlockStatement>(Source{}, stmts);
|
||||||
|
@ -2259,7 +2267,7 @@ Maybe<const ast::ContinueStatement*> ParserImpl::continue_stmt() {
|
||||||
// : CONTINUING body_stmt
|
// : CONTINUING body_stmt
|
||||||
Maybe<const ast::BlockStatement*> ParserImpl::continuing_stmt() {
|
Maybe<const ast::BlockStatement*> ParserImpl::continuing_stmt() {
|
||||||
if (!match(Token::Type::kContinuing)) {
|
if (!match(Token::Type::kContinuing)) {
|
||||||
return create<ast::BlockStatement>(Source{}, ast::StatementList{});
|
return create<ast::BlockStatement>(Source{}, utils::Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
return expect_body_stmt();
|
return expect_body_stmt();
|
||||||
|
@ -2409,9 +2417,10 @@ Maybe<const ast::Expression*> ParserImpl::singular_expression() {
|
||||||
// argument_expression_list
|
// argument_expression_list
|
||||||
// : PAREN_LEFT ((logical_or_expression COMMA)* logical_or_expression COMMA?)?
|
// : PAREN_LEFT ((logical_or_expression COMMA)* logical_or_expression COMMA?)?
|
||||||
// PAREN_RIGHT
|
// PAREN_RIGHT
|
||||||
Expect<ast::ExpressionList> ParserImpl::expect_argument_expression_list(std::string_view use) {
|
Expect<ParserImpl::ExpressionList> ParserImpl::expect_argument_expression_list(
|
||||||
return expect_paren_block(use, [&]() -> Expect<ast::ExpressionList> {
|
std::string_view use) {
|
||||||
ast::ExpressionList ret;
|
return expect_paren_block(use, [&]() -> Expect<ExpressionList> {
|
||||||
|
ExpressionList ret;
|
||||||
while (continue_parsing()) {
|
while (continue_parsing()) {
|
||||||
auto arg = logical_or_expression();
|
auto arg = logical_or_expression();
|
||||||
if (arg.errored) {
|
if (arg.errored) {
|
||||||
|
@ -2419,7 +2428,7 @@ Expect<ast::ExpressionList> ParserImpl::expect_argument_expression_list(std::str
|
||||||
} else if (!arg.matched) {
|
} else if (!arg.matched) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret.push_back(arg.value);
|
ret.Push(arg.value);
|
||||||
|
|
||||||
if (!match(Token::Type::kComma)) {
|
if (!match(Token::Type::kComma)) {
|
||||||
break;
|
break;
|
||||||
|
@ -3051,16 +3060,16 @@ Maybe<const ast::LiteralExpression*> ParserImpl::const_literal() {
|
||||||
return Failure::kNoMatch;
|
return Failure::kNoMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe<ast::AttributeList> ParserImpl::attribute_list() {
|
Maybe<ParserImpl::AttributeList> ParserImpl::attribute_list() {
|
||||||
bool errored = false;
|
bool errored = false;
|
||||||
ast::AttributeList attrs;
|
AttributeList attrs;
|
||||||
|
|
||||||
while (continue_parsing()) {
|
while (continue_parsing()) {
|
||||||
if (match(Token::Type::kAttr)) {
|
if (match(Token::Type::kAttr)) {
|
||||||
if (auto attr = expect_attribute(); attr.errored) {
|
if (auto attr = expect_attribute(); attr.errored) {
|
||||||
errored = true;
|
errored = true;
|
||||||
} else {
|
} else {
|
||||||
attrs.emplace_back(attr.value);
|
attrs.Push(attr.value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -3071,7 +3080,7 @@ Maybe<ast::AttributeList> ParserImpl::attribute_list() {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attrs.empty()) {
|
if (attrs.IsEmpty()) {
|
||||||
return Failure::kNoMatch;
|
return Failure::kNoMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3312,8 +3321,8 @@ Maybe<const ast::Attribute*> ParserImpl::attribute() {
|
||||||
return Failure::kNoMatch;
|
return Failure::kNoMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ParserImpl::expect_attributes_consumed(ast::AttributeList& in) {
|
bool ParserImpl::expect_attributes_consumed(utils::VectorRef<const ast::Attribute*> in) {
|
||||||
if (in.empty()) {
|
if (in.IsEmpty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
add_error(in[0]->source, "unexpected attributes");
|
add_error(in[0]->source, "unexpected attributes");
|
||||||
|
|
|
@ -71,6 +71,17 @@ class ParserImpl {
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// Pre-determined small vector sizes for AST pointers
|
||||||
|
//! @cond Doxygen_Suppress
|
||||||
|
using AttributeList = utils::Vector<const ast::Attribute*, 4>;
|
||||||
|
using CaseSelectorList = utils::Vector<const ast::IntLiteralExpression*, 4>;
|
||||||
|
using CaseStatementList = utils::Vector<const ast::CaseStatement*, 4>;
|
||||||
|
using ExpressionList = utils::Vector<const ast::Expression*, 8>;
|
||||||
|
using ParameterList = utils::Vector<const ast::Parameter*, 8>;
|
||||||
|
using StatementList = utils::Vector<const ast::Statement*, 8>;
|
||||||
|
using StructMemberList = utils::Vector<const ast::StructMember*, 8>;
|
||||||
|
//! @endcond
|
||||||
|
|
||||||
/// Expect is the return type of the parser methods that are expected to
|
/// Expect is the return type of the parser methods that are expected to
|
||||||
/// return a parsed value of type T, unless there was an parse error.
|
/// return a parsed value of type T, unless there was an parse error.
|
||||||
/// In the case of a parse error the called method will have called
|
/// In the case of a parse error the called method will have called
|
||||||
|
@ -231,9 +242,9 @@ class ParserImpl {
|
||||||
/// @param ret_attrs return type attributes
|
/// @param ret_attrs return type attributes
|
||||||
FunctionHeader(Source src,
|
FunctionHeader(Source src,
|
||||||
std::string n,
|
std::string n,
|
||||||
ast::ParameterList p,
|
utils::VectorRef<const ast::Parameter*> p,
|
||||||
const ast::Type* ret_ty,
|
const ast::Type* ret_ty,
|
||||||
ast::AttributeList ret_attrs);
|
utils::VectorRef<const ast::Attribute*> ret_attrs);
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~FunctionHeader();
|
~FunctionHeader();
|
||||||
/// Assignment operator
|
/// Assignment operator
|
||||||
|
@ -246,11 +257,11 @@ class ParserImpl {
|
||||||
/// Function name
|
/// Function name
|
||||||
std::string name;
|
std::string name;
|
||||||
/// Function parameters
|
/// Function parameters
|
||||||
ast::ParameterList params;
|
utils::Vector<const ast::Parameter*, 8> params;
|
||||||
/// Function return type
|
/// Function return type
|
||||||
const ast::Type* return_type = nullptr;
|
const ast::Type* return_type = nullptr;
|
||||||
/// Function return type attributes
|
/// Function return type attributes
|
||||||
ast::AttributeList return_type_attributes;
|
AttributeList return_type_attributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// VarDeclInfo contains the parsed information for variable declaration.
|
/// VarDeclInfo contains the parsed information for variable declaration.
|
||||||
|
@ -383,13 +394,15 @@ class ParserImpl {
|
||||||
/// Parses a `global_variable_decl` grammar element with the initial
|
/// Parses a `global_variable_decl` grammar element with the initial
|
||||||
/// `variable_attribute_list*` provided as `attrs`
|
/// `variable_attribute_list*` provided as `attrs`
|
||||||
/// @returns the variable parsed or nullptr
|
/// @returns the variable parsed or nullptr
|
||||||
/// @param attrs the list of attributes for the variable declaration.
|
/// @param attrs the list of attributes for the variable declaration. If attributes are consumed
|
||||||
Maybe<const ast::Variable*> global_variable_decl(ast::AttributeList& attrs);
|
/// by the declaration, then this vector is cleared before returning.
|
||||||
|
Maybe<const ast::Variable*> global_variable_decl(AttributeList& attrs);
|
||||||
/// Parses a `global_constant_decl` grammar element with the initial
|
/// Parses a `global_constant_decl` grammar element with the initial
|
||||||
/// `variable_attribute_list*` provided as `attrs`
|
/// `variable_attribute_list*` provided as `attrs`
|
||||||
/// @returns the const object or nullptr
|
/// @returns the const object or nullptr
|
||||||
/// @param attrs the list of attributes for the constant declaration.
|
/// @param attrs the list of attributes for the constant declaration. If attributes are consumed
|
||||||
Maybe<const ast::Variable*> global_constant_decl(ast::AttributeList& attrs);
|
/// by the declaration, then this vector is cleared before returning.
|
||||||
|
Maybe<const ast::Variable*> global_constant_decl(AttributeList& attrs);
|
||||||
/// Parses a `variable_decl` grammar element
|
/// Parses a `variable_decl` grammar element
|
||||||
/// @returns the parsed variable declaration info
|
/// @returns the parsed variable declaration info
|
||||||
Maybe<VarDeclInfo> variable_decl();
|
Maybe<VarDeclInfo> variable_decl();
|
||||||
|
@ -418,15 +431,16 @@ class ParserImpl {
|
||||||
Maybe<const ast::Struct*> struct_decl();
|
Maybe<const ast::Struct*> struct_decl();
|
||||||
/// Parses a `struct_body_decl` grammar element, erroring on parse failure.
|
/// Parses a `struct_body_decl` grammar element, erroring on parse failure.
|
||||||
/// @returns the struct members
|
/// @returns the struct members
|
||||||
Expect<ast::StructMemberList> expect_struct_body_decl();
|
Expect<StructMemberList> expect_struct_body_decl();
|
||||||
/// Parses a `struct_member` grammar element, erroring on parse failure.
|
/// Parses a `struct_member` grammar element, erroring on parse failure.
|
||||||
/// @returns the struct member or nullptr
|
/// @returns the struct member or nullptr
|
||||||
Expect<ast::StructMember*> expect_struct_member();
|
Expect<ast::StructMember*> expect_struct_member();
|
||||||
/// Parses a `function_decl` grammar element with the initial
|
/// Parses a `function_decl` grammar element with the initial
|
||||||
/// `function_attribute_decl*` provided as `attrs`.
|
/// `function_attribute_decl*` provided as `attrs`.
|
||||||
/// @param attrs the list of attributes for the function declaration.
|
/// @param attrs the list of attributes for the function declaration. If attributes are consumed
|
||||||
|
/// by the declaration, then this vector is cleared before returning.
|
||||||
/// @returns the parsed function, nullptr otherwise
|
/// @returns the parsed function, nullptr otherwise
|
||||||
Maybe<const ast::Function*> function_decl(ast::AttributeList& attrs);
|
Maybe<const ast::Function*> function_decl(AttributeList& attrs);
|
||||||
/// Parses a `texture_samplers` grammar element
|
/// Parses a `texture_samplers` grammar element
|
||||||
/// @returns the parsed Type or nullptr if none matched.
|
/// @returns the parsed Type or nullptr if none matched.
|
||||||
Maybe<const ast::Type*> texture_samplers();
|
Maybe<const ast::Type*> texture_samplers();
|
||||||
|
@ -459,7 +473,7 @@ class ParserImpl {
|
||||||
Maybe<FunctionHeader> function_header();
|
Maybe<FunctionHeader> function_header();
|
||||||
/// Parses a `param_list` grammar element, erroring on parse failure.
|
/// Parses a `param_list` grammar element, erroring on parse failure.
|
||||||
/// @returns the parsed variables
|
/// @returns the parsed variables
|
||||||
Expect<ast::ParameterList> expect_param_list();
|
Expect<ParameterList> expect_param_list();
|
||||||
/// Parses a `param` grammar element, erroring on parse failure.
|
/// Parses a `param` grammar element, erroring on parse failure.
|
||||||
/// @returns the parsed variable
|
/// @returns the parsed variable
|
||||||
Expect<ast::Parameter*> expect_param();
|
Expect<ast::Parameter*> expect_param();
|
||||||
|
@ -484,7 +498,7 @@ class ParserImpl {
|
||||||
Expect<const ast::Expression*> expect_paren_expression();
|
Expect<const ast::Expression*> expect_paren_expression();
|
||||||
/// Parses a `statements` grammar element
|
/// Parses a `statements` grammar element
|
||||||
/// @returns the statements parsed
|
/// @returns the statements parsed
|
||||||
Expect<ast::StatementList> expect_statements();
|
Expect<StatementList> expect_statements();
|
||||||
/// Parses a `statement` grammar element
|
/// Parses a `statement` grammar element
|
||||||
/// @returns the parsed statement or nullptr
|
/// @returns the parsed statement or nullptr
|
||||||
Maybe<const ast::Statement*> statement();
|
Maybe<const ast::Statement*> statement();
|
||||||
|
@ -511,7 +525,7 @@ class ParserImpl {
|
||||||
Maybe<const ast::CaseStatement*> switch_body();
|
Maybe<const ast::CaseStatement*> switch_body();
|
||||||
/// Parses a `case_selectors` grammar element
|
/// Parses a `case_selectors` grammar element
|
||||||
/// @returns the list of literals
|
/// @returns the list of literals
|
||||||
Expect<ast::CaseSelectorList> expect_case_selectors();
|
Expect<CaseSelectorList> expect_case_selectors();
|
||||||
/// Parses a `case_body` grammar element
|
/// Parses a `case_body` grammar element
|
||||||
/// @returns the parsed statements
|
/// @returns the parsed statements
|
||||||
Maybe<const ast::BlockStatement*> case_body();
|
Maybe<const ast::BlockStatement*> case_body();
|
||||||
|
@ -543,7 +557,7 @@ class ParserImpl {
|
||||||
/// failure.
|
/// failure.
|
||||||
/// @param use a description of what was being parsed if an error was raised
|
/// @param use a description of what was being parsed if an error was raised
|
||||||
/// @returns the list of arguments
|
/// @returns the list of arguments
|
||||||
Expect<ast::ExpressionList> expect_argument_expression_list(std::string_view use);
|
Expect<ExpressionList> expect_argument_expression_list(std::string_view use);
|
||||||
/// Parses the recursive portion of the postfix_expression
|
/// Parses the recursive portion of the postfix_expression
|
||||||
/// @param prefix the left side of the expression
|
/// @param prefix the left side of the expression
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
|
@ -642,7 +656,7 @@ class ParserImpl {
|
||||||
Maybe<const ast::Statement*> assignment_stmt();
|
Maybe<const ast::Statement*> assignment_stmt();
|
||||||
/// Parses one or more attribute lists.
|
/// Parses one or more attribute lists.
|
||||||
/// @return the parsed attribute list, or an empty list on error.
|
/// @return the parsed attribute list, or an empty list on error.
|
||||||
Maybe<ast::AttributeList> attribute_list();
|
Maybe<AttributeList> attribute_list();
|
||||||
/// Parses a single attribute of the following types:
|
/// Parses a single attribute of the following types:
|
||||||
/// * `struct_attribute`
|
/// * `struct_attribute`
|
||||||
/// * `struct_member_attribute`
|
/// * `struct_member_attribute`
|
||||||
|
@ -813,7 +827,7 @@ class ParserImpl {
|
||||||
|
|
||||||
/// Reports an error if the attribute list `list` is not empty.
|
/// Reports an error if the attribute list `list` is not empty.
|
||||||
/// Used to ensure that all attributes are consumed.
|
/// Used to ensure that all attributes are consumed.
|
||||||
bool expect_attributes_consumed(ast::AttributeList& list);
|
bool expect_attributes_consumed(utils::VectorRef<const ast::Attribute*> list);
|
||||||
|
|
||||||
Expect<const ast::Type*> expect_type_decl_pointer(const Token& t);
|
Expect<const ast::Type*> expect_type_decl_pointer(const Token& t);
|
||||||
Expect<const ast::Type*> expect_type_decl_atomic(const Token& t);
|
Expect<const ast::Type*> expect_type_decl_atomic(const Token& t);
|
||||||
|
|
|
@ -23,7 +23,7 @@ TEST_F(ParserImplTest, ArgumentExpressionList_Parses) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
|
|
||||||
ASSERT_EQ(e.value.size(), 1u);
|
ASSERT_EQ(e.value.Length(), 1u);
|
||||||
ASSERT_TRUE(e.value[0]->Is<ast::IdentifierExpression>());
|
ASSERT_TRUE(e.value[0]->Is<ast::IdentifierExpression>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ TEST_F(ParserImplTest, ArgumentExpressionList_ParsesEmptyList) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
|
|
||||||
ASSERT_EQ(e.value.size(), 0u);
|
ASSERT_EQ(e.value.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ArgumentExpressionList_ParsesMultiple) {
|
TEST_F(ParserImplTest, ArgumentExpressionList_ParsesMultiple) {
|
||||||
|
@ -42,7 +42,7 @@ TEST_F(ParserImplTest, ArgumentExpressionList_ParsesMultiple) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
|
|
||||||
ASSERT_EQ(e.value.size(), 3u);
|
ASSERT_EQ(e.value.Length(), 3u);
|
||||||
ASSERT_TRUE(e.value[0]->Is<ast::IdentifierExpression>());
|
ASSERT_TRUE(e.value[0]->Is<ast::IdentifierExpression>());
|
||||||
ASSERT_TRUE(e.value[1]->Is<ast::LiteralExpression>());
|
ASSERT_TRUE(e.value[1]->Is<ast::LiteralExpression>());
|
||||||
ASSERT_TRUE(e.value[2]->Is<ast::BinaryExpression>());
|
ASSERT_TRUE(e.value[2]->Is<ast::BinaryExpression>());
|
||||||
|
@ -54,7 +54,7 @@ TEST_F(ParserImplTest, ArgumentExpressionList_TrailingComma) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
|
|
||||||
ASSERT_EQ(e.value.size(), 2u);
|
ASSERT_EQ(e.value.Length(), 2u);
|
||||||
ASSERT_TRUE(e.value[0]->Is<ast::IdentifierExpression>());
|
ASSERT_TRUE(e.value[0]->Is<ast::IdentifierExpression>());
|
||||||
ASSERT_TRUE(e.value[1]->Is<ast::LiteralExpression>());
|
ASSERT_TRUE(e.value[1]->Is<ast::LiteralExpression>());
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ TEST_F(ParserImplTest, BodyStmt) {
|
||||||
auto e = p->expect_body_stmt();
|
auto e = p->expect_body_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
ASSERT_EQ(e->statements.size(), 2u);
|
ASSERT_EQ(e->statements.Length(), 2u);
|
||||||
EXPECT_TRUE(e->statements[0]->Is<ast::DiscardStatement>());
|
EXPECT_TRUE(e->statements[0]->Is<ast::DiscardStatement>());
|
||||||
EXPECT_TRUE(e->statements[1]->Is<ast::ReturnStatement>());
|
EXPECT_TRUE(e->statements[1]->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ TEST_F(ParserImplTest, BodyStmt_Empty) {
|
||||||
auto e = p->expect_body_stmt();
|
auto e = p->expect_body_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
EXPECT_EQ(e->statements.size(), 0u);
|
EXPECT_EQ(e->statements.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, BodyStmt_InvalidStmt) {
|
TEST_F(ParserImplTest, BodyStmt_InvalidStmt) {
|
||||||
|
|
|
@ -36,7 +36,7 @@ TEST_F(ParserImplTest, Statement_Call) {
|
||||||
|
|
||||||
EXPECT_EQ(c->target.name->symbol, p->builder().Symbols().Get("a"));
|
EXPECT_EQ(c->target.name->symbol, p->builder().Symbols().Get("a"));
|
||||||
|
|
||||||
EXPECT_EQ(c->args.size(), 0u);
|
EXPECT_EQ(c->args.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Call_WithParams) {
|
TEST_F(ParserImplTest, Statement_Call_WithParams) {
|
||||||
|
@ -52,7 +52,7 @@ TEST_F(ParserImplTest, Statement_Call_WithParams) {
|
||||||
|
|
||||||
EXPECT_EQ(c->target.name->symbol, p->builder().Symbols().Get("a"));
|
EXPECT_EQ(c->target.name->symbol, p->builder().Symbols().Get("a"));
|
||||||
|
|
||||||
EXPECT_EQ(c->args.size(), 3u);
|
EXPECT_EQ(c->args.Length(), 3u);
|
||||||
EXPECT_TRUE(c->args[0]->Is<ast::IntLiteralExpression>());
|
EXPECT_TRUE(c->args[0]->Is<ast::IntLiteralExpression>());
|
||||||
EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>());
|
EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>());
|
||||||
EXPECT_TRUE(c->args[2]->Is<ast::BinaryExpression>());
|
EXPECT_TRUE(c->args[2]->Is<ast::BinaryExpression>());
|
||||||
|
@ -71,7 +71,7 @@ TEST_F(ParserImplTest, Statement_Call_WithParams_TrailingComma) {
|
||||||
|
|
||||||
EXPECT_EQ(c->target.name->symbol, p->builder().Symbols().Get("a"));
|
EXPECT_EQ(c->target.name->symbol, p->builder().Symbols().Get("a"));
|
||||||
|
|
||||||
EXPECT_EQ(c->args.size(), 2u);
|
EXPECT_EQ(c->args.Length(), 2u);
|
||||||
EXPECT_TRUE(c->args[0]->Is<ast::IntLiteralExpression>());
|
EXPECT_TRUE(c->args[0]->Is<ast::IntLiteralExpression>());
|
||||||
EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>());
|
EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>());
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ TEST_F(ParserImplTest, CaseBody_Empty) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_EQ(e->statements.size(), 0u);
|
EXPECT_EQ(e->statements.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, CaseBody_Statements) {
|
TEST_F(ParserImplTest, CaseBody_Statements) {
|
||||||
|
@ -36,7 +36,7 @@ TEST_F(ParserImplTest, CaseBody_Statements) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_EQ(e->statements.size(), 2u);
|
ASSERT_EQ(e->statements.Length(), 2u);
|
||||||
EXPECT_TRUE(e->statements[0]->Is<ast::VariableDeclStatement>());
|
EXPECT_TRUE(e->statements[0]->Is<ast::VariableDeclStatement>());
|
||||||
EXPECT_TRUE(e->statements[1]->Is<ast::AssignmentStatement>());
|
EXPECT_TRUE(e->statements[1]->Is<ast::AssignmentStatement>());
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ TEST_F(ParserImplTest, CaseBody_Fallthrough) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_EQ(e->statements.size(), 1u);
|
ASSERT_EQ(e->statements.Length(), 1u);
|
||||||
EXPECT_TRUE(e->statements[0]->Is<ast::FallthroughStatement>());
|
EXPECT_TRUE(e->statements[0]->Is<ast::FallthroughStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ TEST_F(ParserImplTest, ContinuingStmt) {
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e->statements.size(), 1u);
|
ASSERT_EQ(e->statements.Length(), 1u);
|
||||||
ASSERT_TRUE(e->statements[0]->Is<ast::DiscardStatement>());
|
ASSERT_TRUE(e->statements[0]->Is<ast::DiscardStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,10 @@ TEST_F(EnableDirectiveTest, Valid) {
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
ASSERT_EQ(ast.Enables().size(), 1u);
|
ASSERT_EQ(ast.Enables().Length(), 1u);
|
||||||
auto* enable = ast.Enables()[0];
|
auto* enable = ast.Enables()[0];
|
||||||
EXPECT_EQ(enable->extension, ast::Extension::kF16);
|
EXPECT_EQ(enable->extension, ast::Extension::kF16);
|
||||||
ASSERT_EQ(ast.GlobalDeclarations().size(), 1u);
|
ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
|
||||||
EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
|
EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,12 +45,12 @@ enable f16;
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
ASSERT_EQ(ast.Enables().size(), 2u);
|
ASSERT_EQ(ast.Enables().Length(), 2u);
|
||||||
auto* enable_a = ast.Enables()[0];
|
auto* enable_a = ast.Enables()[0];
|
||||||
auto* enable_b = ast.Enables()[1];
|
auto* enable_b = ast.Enables()[1];
|
||||||
EXPECT_EQ(enable_a->extension, ast::Extension::kF16);
|
EXPECT_EQ(enable_a->extension, ast::Extension::kF16);
|
||||||
EXPECT_EQ(enable_b->extension, ast::Extension::kF16);
|
EXPECT_EQ(enable_b->extension, ast::Extension::kF16);
|
||||||
ASSERT_EQ(ast.GlobalDeclarations().size(), 2u);
|
ASSERT_EQ(ast.GlobalDeclarations().Length(), 2u);
|
||||||
EXPECT_EQ(ast.GlobalDeclarations()[0], enable_a);
|
EXPECT_EQ(ast.GlobalDeclarations()[0], enable_a);
|
||||||
EXPECT_EQ(ast.GlobalDeclarations()[1], enable_b);
|
EXPECT_EQ(ast.GlobalDeclarations()[1], enable_b);
|
||||||
}
|
}
|
||||||
|
@ -64,8 +64,8 @@ TEST_F(EnableDirectiveTest, InvalidIdentifier) {
|
||||||
EXPECT_EQ(p->error(), "1:8: unsupported extension: 'NotAValidExtensionName'");
|
EXPECT_EQ(p->error(), "1:8: unsupported extension: 'NotAValidExtensionName'");
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
EXPECT_EQ(ast.Enables().size(), 0u);
|
EXPECT_EQ(ast.Enables().Length(), 0u);
|
||||||
EXPECT_EQ(ast.GlobalDeclarations().size(), 0u);
|
EXPECT_EQ(ast.GlobalDeclarations().Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test an enable directive missing ending semicolon.
|
// Test an enable directive missing ending semicolon.
|
||||||
|
@ -76,8 +76,8 @@ TEST_F(EnableDirectiveTest, MissingEndingSemicolon) {
|
||||||
EXPECT_EQ(p->error(), "1:11: expected ';' for enable directive");
|
EXPECT_EQ(p->error(), "1:11: expected ';' for enable directive");
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
EXPECT_EQ(ast.Enables().size(), 0u);
|
EXPECT_EQ(ast.Enables().Length(), 0u);
|
||||||
EXPECT_EQ(ast.GlobalDeclarations().size(), 0u);
|
EXPECT_EQ(ast.GlobalDeclarations().Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the special error message when enable are used with parenthesis.
|
// Test the special error message when enable are used with parenthesis.
|
||||||
|
@ -88,8 +88,8 @@ TEST_F(EnableDirectiveTest, ParenthesisSpecialCase) {
|
||||||
EXPECT_EQ(p->error(), "1:7: enable directives don't take parenthesis");
|
EXPECT_EQ(p->error(), "1:7: enable directives don't take parenthesis");
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
EXPECT_EQ(ast.Enables().size(), 0u);
|
EXPECT_EQ(ast.Enables().Length(), 0u);
|
||||||
EXPECT_EQ(ast.GlobalDeclarations().size(), 0u);
|
EXPECT_EQ(ast.GlobalDeclarations().Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test using invalid tokens in an enable directive.
|
// Test using invalid tokens in an enable directive.
|
||||||
|
@ -101,8 +101,8 @@ TEST_F(EnableDirectiveTest, InvalidTokens) {
|
||||||
EXPECT_EQ(p->error(), "1:11: expected ';' for enable directive");
|
EXPECT_EQ(p->error(), "1:11: expected ';' for enable directive");
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
EXPECT_EQ(ast.Enables().size(), 0u);
|
EXPECT_EQ(ast.Enables().Length(), 0u);
|
||||||
EXPECT_EQ(ast.GlobalDeclarations().size(), 0u);
|
EXPECT_EQ(ast.GlobalDeclarations().Length(), 0u);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = parser("enable <f16;");
|
auto p = parser("enable <f16;");
|
||||||
|
@ -111,8 +111,8 @@ TEST_F(EnableDirectiveTest, InvalidTokens) {
|
||||||
EXPECT_EQ(p->error(), "1:8: invalid extension name");
|
EXPECT_EQ(p->error(), "1:8: invalid extension name");
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
EXPECT_EQ(ast.Enables().size(), 0u);
|
EXPECT_EQ(ast.Enables().Length(), 0u);
|
||||||
EXPECT_EQ(ast.GlobalDeclarations().size(), 0u);
|
EXPECT_EQ(ast.GlobalDeclarations().Length(), 0u);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = parser("enable =;");
|
auto p = parser("enable =;");
|
||||||
|
@ -121,8 +121,8 @@ TEST_F(EnableDirectiveTest, InvalidTokens) {
|
||||||
EXPECT_EQ(p->error(), "1:8: invalid extension name");
|
EXPECT_EQ(p->error(), "1:8: invalid extension name");
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
EXPECT_EQ(ast.Enables().size(), 0u);
|
EXPECT_EQ(ast.Enables().Length(), 0u);
|
||||||
EXPECT_EQ(ast.GlobalDeclarations().size(), 0u);
|
EXPECT_EQ(ast.GlobalDeclarations().Length(), 0u);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p = parser("enable vec4;");
|
auto p = parser("enable vec4;");
|
||||||
|
@ -131,8 +131,8 @@ TEST_F(EnableDirectiveTest, InvalidTokens) {
|
||||||
EXPECT_EQ(p->error(), "1:8: invalid extension name");
|
EXPECT_EQ(p->error(), "1:8: invalid extension name");
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
EXPECT_EQ(ast.Enables().size(), 0u);
|
EXPECT_EQ(ast.Enables().Length(), 0u);
|
||||||
EXPECT_EQ(ast.GlobalDeclarations().size(), 0u);
|
EXPECT_EQ(ast.GlobalDeclarations().Length(), 0u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,10 +148,10 @@ enable f16;
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
// Accept the enable directive although it caused an error
|
// Accept the enable directive although it caused an error
|
||||||
ASSERT_EQ(ast.Enables().size(), 1u);
|
ASSERT_EQ(ast.Enables().Length(), 1u);
|
||||||
auto* enable = ast.Enables()[0];
|
auto* enable = ast.Enables()[0];
|
||||||
EXPECT_EQ(enable->extension, ast::Extension::kF16);
|
EXPECT_EQ(enable->extension, ast::Extension::kF16);
|
||||||
ASSERT_EQ(ast.GlobalDeclarations().size(), 2u);
|
ASSERT_EQ(ast.GlobalDeclarations().Length(), 2u);
|
||||||
EXPECT_EQ(ast.GlobalDeclarations()[1], enable);
|
EXPECT_EQ(ast.GlobalDeclarations()[1], enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,10 +168,10 @@ enable f16;
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
// Accept the enable directive although it cause an error
|
// Accept the enable directive although it cause an error
|
||||||
ASSERT_EQ(ast.Enables().size(), 1u);
|
ASSERT_EQ(ast.Enables().Length(), 1u);
|
||||||
auto* enable = ast.Enables()[0];
|
auto* enable = ast.Enables()[0];
|
||||||
EXPECT_EQ(enable->extension, ast::Extension::kF16);
|
EXPECT_EQ(enable->extension, ast::Extension::kF16);
|
||||||
ASSERT_EQ(ast.GlobalDeclarations().size(), 1u);
|
ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
|
||||||
EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
|
EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ TEST_F(ForStmtTest, Body) {
|
||||||
EXPECT_EQ(fl->initializer, nullptr);
|
EXPECT_EQ(fl->initializer, nullptr);
|
||||||
EXPECT_EQ(fl->condition, nullptr);
|
EXPECT_EQ(fl->condition, nullptr);
|
||||||
EXPECT_EQ(fl->continuing, nullptr);
|
EXPECT_EQ(fl->continuing, nullptr);
|
||||||
ASSERT_EQ(fl->body->statements.size(), 1u);
|
ASSERT_EQ(fl->body->statements.Length(), 1u);
|
||||||
EXPECT_TRUE(fl->body->statements[0]->Is<ast::DiscardStatement>());
|
EXPECT_TRUE(fl->body->statements[0]->Is<ast::DiscardStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ TEST_F(ParserImplTest, AttributeList_Parses_Stage) {
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_FALSE(attrs.errored);
|
EXPECT_FALSE(attrs.errored);
|
||||||
EXPECT_TRUE(attrs.matched);
|
EXPECT_TRUE(attrs.matched);
|
||||||
ASSERT_EQ(attrs.value.size(), 2u);
|
ASSERT_EQ(attrs.value.Length(), 2u);
|
||||||
|
|
||||||
auto* attr_0 = attrs.value[0]->As<ast::Attribute>();
|
auto* attr_0 = attrs.value[0]->As<ast::Attribute>();
|
||||||
auto* attr_1 = attrs.value[1]->As<ast::Attribute>();
|
auto* attr_1 = attrs.value[1]->As<ast::Attribute>();
|
||||||
|
@ -51,7 +51,7 @@ TEST_F(ParserImplTest, AttributeList_Parses) {
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_FALSE(attrs.errored);
|
EXPECT_FALSE(attrs.errored);
|
||||||
EXPECT_TRUE(attrs.matched);
|
EXPECT_TRUE(attrs.matched);
|
||||||
ASSERT_EQ(attrs.value.size(), 2u);
|
ASSERT_EQ(attrs.value.Length(), 2u);
|
||||||
|
|
||||||
auto* attr_0 = attrs.value[0]->As<ast::Attribute>();
|
auto* attr_0 = attrs.value[0]->As<ast::Attribute>();
|
||||||
auto* attr_1 = attrs.value[1]->As<ast::Attribute>();
|
auto* attr_1 = attrs.value[1]->As<ast::Attribute>();
|
||||||
|
@ -77,7 +77,7 @@ TEST_F(ParserImplTest, AttributeList_Invalid) {
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_TRUE(attrs.errored);
|
EXPECT_TRUE(attrs.errored);
|
||||||
EXPECT_FALSE(attrs.matched);
|
EXPECT_FALSE(attrs.matched);
|
||||||
EXPECT_TRUE(attrs.value.empty());
|
EXPECT_TRUE(attrs.value.IsEmpty());
|
||||||
EXPECT_EQ(p->error(), "1:2: expected attribute");
|
EXPECT_EQ(p->error(), "1:2: expected attribute");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ TEST_F(ParserImplTest, FunctionDecl) {
|
||||||
ASSERT_NE(f->return_type, nullptr);
|
ASSERT_NE(f->return_type, nullptr);
|
||||||
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
||||||
|
|
||||||
ASSERT_EQ(f->params.size(), 2u);
|
ASSERT_EQ(f->params.Length(), 2u);
|
||||||
EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get("a"));
|
EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get("a"));
|
||||||
EXPECT_EQ(f->params[1]->symbol, p->builder().Symbols().Get("b"));
|
EXPECT_EQ(f->params[1]->symbol, p->builder().Symbols().Get("b"));
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ TEST_F(ParserImplTest, FunctionDecl) {
|
||||||
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
||||||
|
|
||||||
auto* body = f->body;
|
auto* body = f->body;
|
||||||
ASSERT_EQ(body->statements.size(), 1u);
|
ASSERT_EQ(body->statements.Length(), 1u);
|
||||||
EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
|
EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ TEST_F(ParserImplTest, FunctionDecl_Unicode) {
|
||||||
ASSERT_NE(f->return_type, nullptr);
|
ASSERT_NE(f->return_type, nullptr);
|
||||||
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
||||||
|
|
||||||
ASSERT_EQ(f->params.size(), 2u);
|
ASSERT_EQ(f->params.Length(), 2u);
|
||||||
EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get(param_a_ident));
|
EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get(param_a_ident));
|
||||||
EXPECT_EQ(f->params[1]->symbol, p->builder().Symbols().Get(param_b_ident));
|
EXPECT_EQ(f->params[1]->symbol, p->builder().Symbols().Get(param_b_ident));
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ TEST_F(ParserImplTest, FunctionDecl_Unicode) {
|
||||||
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
||||||
|
|
||||||
auto* body = f->body;
|
auto* body = f->body;
|
||||||
ASSERT_EQ(body->statements.size(), 1u);
|
ASSERT_EQ(body->statements.Length(), 1u);
|
||||||
EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
|
EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,10 +107,10 @@ TEST_F(ParserImplTest, FunctionDecl_AttributeList) {
|
||||||
EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
|
EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
|
||||||
ASSERT_NE(f->return_type, nullptr);
|
ASSERT_NE(f->return_type, nullptr);
|
||||||
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
||||||
ASSERT_EQ(f->params.size(), 0u);
|
ASSERT_EQ(f->params.Length(), 0u);
|
||||||
|
|
||||||
auto& attributes = f->attributes;
|
auto& attributes = f->attributes;
|
||||||
ASSERT_EQ(attributes.size(), 1u);
|
ASSERT_EQ(attributes.Length(), 1u);
|
||||||
ASSERT_TRUE(attributes[0]->Is<ast::WorkgroupAttribute>());
|
ASSERT_TRUE(attributes[0]->Is<ast::WorkgroupAttribute>());
|
||||||
|
|
||||||
auto values = attributes[0]->As<ast::WorkgroupAttribute>()->Values();
|
auto values = attributes[0]->As<ast::WorkgroupAttribute>()->Values();
|
||||||
|
@ -131,7 +131,7 @@ TEST_F(ParserImplTest, FunctionDecl_AttributeList) {
|
||||||
ast::IntLiteralExpression::Suffix::kNone);
|
ast::IntLiteralExpression::Suffix::kNone);
|
||||||
|
|
||||||
auto* body = f->body;
|
auto* body = f->body;
|
||||||
ASSERT_EQ(body->statements.size(), 1u);
|
ASSERT_EQ(body->statements.Length(), 1u);
|
||||||
EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
|
EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,10 +152,10 @@ fn main() { return; })");
|
||||||
EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
|
EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
|
||||||
ASSERT_NE(f->return_type, nullptr);
|
ASSERT_NE(f->return_type, nullptr);
|
||||||
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
||||||
ASSERT_EQ(f->params.size(), 0u);
|
ASSERT_EQ(f->params.Length(), 0u);
|
||||||
|
|
||||||
auto& attributes = f->attributes;
|
auto& attributes = f->attributes;
|
||||||
ASSERT_EQ(attributes.size(), 2u);
|
ASSERT_EQ(attributes.Length(), 2u);
|
||||||
|
|
||||||
ASSERT_TRUE(attributes[0]->Is<ast::WorkgroupAttribute>());
|
ASSERT_TRUE(attributes[0]->Is<ast::WorkgroupAttribute>());
|
||||||
auto values = attributes[0]->As<ast::WorkgroupAttribute>()->Values();
|
auto values = attributes[0]->As<ast::WorkgroupAttribute>()->Values();
|
||||||
|
@ -179,7 +179,7 @@ fn main() { return; })");
|
||||||
EXPECT_EQ(attributes[1]->As<ast::StageAttribute>()->stage, ast::PipelineStage::kCompute);
|
EXPECT_EQ(attributes[1]->As<ast::StageAttribute>()->stage, ast::PipelineStage::kCompute);
|
||||||
|
|
||||||
auto* body = f->body;
|
auto* body = f->body;
|
||||||
ASSERT_EQ(body->statements.size(), 1u);
|
ASSERT_EQ(body->statements.Length(), 1u);
|
||||||
EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
|
EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,10 +201,10 @@ fn main() { return; })");
|
||||||
EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
|
EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
|
||||||
ASSERT_NE(f->return_type, nullptr);
|
ASSERT_NE(f->return_type, nullptr);
|
||||||
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
||||||
ASSERT_EQ(f->params.size(), 0u);
|
ASSERT_EQ(f->params.Length(), 0u);
|
||||||
|
|
||||||
auto& attrs = f->attributes;
|
auto& attrs = f->attributes;
|
||||||
ASSERT_EQ(attrs.size(), 2u);
|
ASSERT_EQ(attrs.Length(), 2u);
|
||||||
|
|
||||||
ASSERT_TRUE(attrs[0]->Is<ast::WorkgroupAttribute>());
|
ASSERT_TRUE(attrs[0]->Is<ast::WorkgroupAttribute>());
|
||||||
auto values = attrs[0]->As<ast::WorkgroupAttribute>()->Values();
|
auto values = attrs[0]->As<ast::WorkgroupAttribute>()->Values();
|
||||||
|
@ -228,7 +228,7 @@ fn main() { return; })");
|
||||||
EXPECT_EQ(attrs[1]->As<ast::StageAttribute>()->stage, ast::PipelineStage::kCompute);
|
EXPECT_EQ(attrs[1]->As<ast::StageAttribute>()->stage, ast::PipelineStage::kCompute);
|
||||||
|
|
||||||
auto* body = f->body;
|
auto* body = f->body;
|
||||||
ASSERT_EQ(body->statements.size(), 1u);
|
ASSERT_EQ(body->statements.Length(), 1u);
|
||||||
EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
|
EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,19 +247,19 @@ TEST_F(ParserImplTest, FunctionDecl_ReturnTypeAttributeList) {
|
||||||
EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
|
EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
|
||||||
ASSERT_NE(f->return_type, nullptr);
|
ASSERT_NE(f->return_type, nullptr);
|
||||||
EXPECT_TRUE(f->return_type->Is<ast::F32>());
|
EXPECT_TRUE(f->return_type->Is<ast::F32>());
|
||||||
ASSERT_EQ(f->params.size(), 0u);
|
ASSERT_EQ(f->params.Length(), 0u);
|
||||||
|
|
||||||
auto& attributes = f->attributes;
|
auto& attributes = f->attributes;
|
||||||
EXPECT_EQ(attributes.size(), 0u);
|
EXPECT_EQ(attributes.Length(), 0u);
|
||||||
|
|
||||||
auto& ret_type_attributes = f->return_type_attributes;
|
auto& ret_type_attributes = f->return_type_attributes;
|
||||||
ASSERT_EQ(ret_type_attributes.size(), 1u);
|
ASSERT_EQ(ret_type_attributes.Length(), 1u);
|
||||||
auto* loc = ret_type_attributes[0]->As<ast::LocationAttribute>();
|
auto* loc = ret_type_attributes[0]->As<ast::LocationAttribute>();
|
||||||
ASSERT_TRUE(loc != nullptr);
|
ASSERT_TRUE(loc != nullptr);
|
||||||
EXPECT_EQ(loc->value, 1u);
|
EXPECT_EQ(loc->value, 1u);
|
||||||
|
|
||||||
auto* body = f->body;
|
auto* body = f->body;
|
||||||
ASSERT_EQ(body->statements.size(), 1u);
|
ASSERT_EQ(body->statements.Length(), 1u);
|
||||||
EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
|
EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ TEST_F(ParserImplTest, FunctionHeader) {
|
||||||
EXPECT_FALSE(f.errored);
|
EXPECT_FALSE(f.errored);
|
||||||
|
|
||||||
EXPECT_EQ(f->name, "main");
|
EXPECT_EQ(f->name, "main");
|
||||||
ASSERT_EQ(f->params.size(), 2u);
|
ASSERT_EQ(f->params.Length(), 2u);
|
||||||
EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get("a"));
|
EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get("a"));
|
||||||
EXPECT_EQ(f->params[1]->symbol, p->builder().Symbols().Get("b"));
|
EXPECT_EQ(f->params[1]->symbol, p->builder().Symbols().Get("b"));
|
||||||
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
||||||
|
@ -38,7 +38,7 @@ TEST_F(ParserImplTest, FunctionHeader_TrailingComma) {
|
||||||
EXPECT_FALSE(f.errored);
|
EXPECT_FALSE(f.errored);
|
||||||
|
|
||||||
EXPECT_EQ(f->name, "main");
|
EXPECT_EQ(f->name, "main");
|
||||||
ASSERT_EQ(f->params.size(), 1u);
|
ASSERT_EQ(f->params.Length(), 1u);
|
||||||
EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get("a"));
|
EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get("a"));
|
||||||
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
||||||
}
|
}
|
||||||
|
@ -51,9 +51,9 @@ TEST_F(ParserImplTest, FunctionHeader_AttributeReturnType) {
|
||||||
EXPECT_FALSE(f.errored);
|
EXPECT_FALSE(f.errored);
|
||||||
|
|
||||||
EXPECT_EQ(f->name, "main");
|
EXPECT_EQ(f->name, "main");
|
||||||
EXPECT_EQ(f->params.size(), 0u);
|
EXPECT_EQ(f->params.Length(), 0u);
|
||||||
EXPECT_TRUE(f->return_type->Is<ast::F32>());
|
EXPECT_TRUE(f->return_type->Is<ast::F32>());
|
||||||
ASSERT_EQ(f->return_type_attributes.size(), 1u);
|
ASSERT_EQ(f->return_type_attributes.Length(), 1u);
|
||||||
auto* loc = f->return_type_attributes[0]->As<ast::LocationAttribute>();
|
auto* loc = f->return_type_attributes[0]->As<ast::LocationAttribute>();
|
||||||
ASSERT_TRUE(loc != nullptr);
|
ASSERT_TRUE(loc != nullptr);
|
||||||
EXPECT_EQ(loc->value, 1u);
|
EXPECT_EQ(loc->value, 1u);
|
||||||
|
@ -67,9 +67,9 @@ TEST_F(ParserImplTest, FunctionHeader_InvariantReturnType) {
|
||||||
EXPECT_FALSE(f.errored);
|
EXPECT_FALSE(f.errored);
|
||||||
|
|
||||||
EXPECT_EQ(f->name, "main");
|
EXPECT_EQ(f->name, "main");
|
||||||
EXPECT_EQ(f->params.size(), 0u);
|
EXPECT_EQ(f->params.Length(), 0u);
|
||||||
EXPECT_TRUE(f->return_type->Is<ast::F32>());
|
EXPECT_TRUE(f->return_type->Is<ast::F32>());
|
||||||
ASSERT_EQ(f->return_type_attributes.size(), 1u);
|
ASSERT_EQ(f->return_type_attributes.Length(), 1u);
|
||||||
EXPECT_TRUE(f->return_type_attributes[0]->Is<ast::InvariantAttribute>());
|
EXPECT_TRUE(f->return_type_attributes[0]->Is<ast::InvariantAttribute>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ TEST_F(ParserImplTest, GlobalDecl_GlobalVariable) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
ASSERT_EQ(program.AST().GlobalVariables().size(), 1u);
|
ASSERT_EQ(program.AST().GlobalVariables().Length(), 1u);
|
||||||
|
|
||||||
auto* v = program.AST().GlobalVariables()[0];
|
auto* v = program.AST().GlobalVariables()[0];
|
||||||
EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
|
EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
|
||||||
|
@ -42,7 +42,7 @@ TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_Inferred) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
ASSERT_EQ(program.AST().GlobalVariables().size(), 1u);
|
ASSERT_EQ(program.AST().GlobalVariables().Length(), 1u);
|
||||||
|
|
||||||
auto* v = program.AST().GlobalVariables()[0];
|
auto* v = program.AST().GlobalVariables()[0];
|
||||||
EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
|
EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
|
||||||
|
@ -62,7 +62,7 @@ TEST_F(ParserImplTest, GlobalDecl_GlobalLet) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
ASSERT_EQ(program.AST().GlobalVariables().size(), 1u);
|
ASSERT_EQ(program.AST().GlobalVariables().Length(), 1u);
|
||||||
|
|
||||||
auto* v = program.AST().GlobalVariables()[0];
|
auto* v = program.AST().GlobalVariables()[0];
|
||||||
EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
|
EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
|
||||||
|
@ -104,7 +104,7 @@ TEST_F(ParserImplTest, GlobalDecl_GlobalConst) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
ASSERT_EQ(program.AST().GlobalVariables().size(), 1u);
|
ASSERT_EQ(program.AST().GlobalVariables().Length(), 1u);
|
||||||
|
|
||||||
auto* v = program.AST().GlobalVariables()[0];
|
auto* v = program.AST().GlobalVariables()[0];
|
||||||
EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
|
EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
|
||||||
|
@ -137,7 +137,7 @@ TEST_F(ParserImplTest, GlobalDecl_TypeAlias) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
ASSERT_EQ(program.AST().TypeDecls().size(), 1u);
|
ASSERT_EQ(program.AST().TypeDecls().Length(), 1u);
|
||||||
ASSERT_TRUE(program.AST().TypeDecls()[0]->Is<ast::Alias>());
|
ASSERT_TRUE(program.AST().TypeDecls()[0]->Is<ast::Alias>());
|
||||||
EXPECT_EQ(program.Symbols().NameFor(program.AST().TypeDecls()[0]->As<ast::Alias>()->name), "A");
|
EXPECT_EQ(program.Symbols().NameFor(program.AST().TypeDecls()[0]->As<ast::Alias>()->name), "A");
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ type B = A;)");
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
ASSERT_EQ(program.AST().TypeDecls().size(), 2u);
|
ASSERT_EQ(program.AST().TypeDecls().Length(), 2u);
|
||||||
ASSERT_TRUE(program.AST().TypeDecls()[0]->Is<ast::Struct>());
|
ASSERT_TRUE(program.AST().TypeDecls()[0]->Is<ast::Struct>());
|
||||||
auto* str = program.AST().TypeDecls()[0]->As<ast::Struct>();
|
auto* str = program.AST().TypeDecls()[0]->As<ast::Struct>();
|
||||||
EXPECT_EQ(str->name, program.Symbols().Get("A"));
|
EXPECT_EQ(str->name, program.Symbols().Get("A"));
|
||||||
|
@ -178,7 +178,7 @@ TEST_F(ParserImplTest, GlobalDecl_Function) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
ASSERT_EQ(program.AST().Functions().size(), 1u);
|
ASSERT_EQ(program.AST().Functions().Length(), 1u);
|
||||||
EXPECT_EQ(program.Symbols().NameFor(program.AST().Functions()[0]->symbol), "main");
|
EXPECT_EQ(program.Symbols().NameFor(program.AST().Functions()[0]->symbol), "main");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ TEST_F(ParserImplTest, GlobalDecl_Function_WithAttribute) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
ASSERT_EQ(program.AST().Functions().size(), 1u);
|
ASSERT_EQ(program.AST().Functions().Length(), 1u);
|
||||||
EXPECT_EQ(program.Symbols().NameFor(program.AST().Functions()[0]->symbol), "main");
|
EXPECT_EQ(program.Symbols().NameFor(program.AST().Functions()[0]->symbol), "main");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ TEST_F(ParserImplTest, GlobalDecl_ParsesStruct) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
ASSERT_EQ(program.AST().TypeDecls().size(), 1u);
|
ASSERT_EQ(program.AST().TypeDecls().Length(), 1u);
|
||||||
|
|
||||||
auto* t = program.AST().TypeDecls()[0];
|
auto* t = program.AST().TypeDecls()[0];
|
||||||
ASSERT_NE(t, nullptr);
|
ASSERT_NE(t, nullptr);
|
||||||
|
@ -213,7 +213,7 @@ TEST_F(ParserImplTest, GlobalDecl_ParsesStruct) {
|
||||||
|
|
||||||
auto* str = t->As<ast::Struct>();
|
auto* str = t->As<ast::Struct>();
|
||||||
EXPECT_EQ(str->name, program.Symbols().Get("A"));
|
EXPECT_EQ(str->name, program.Symbols().Get("A"));
|
||||||
EXPECT_EQ(str->members.size(), 2u);
|
EXPECT_EQ(str->members.Length(), 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalDecl_Struct_Invalid) {
|
TEST_F(ParserImplTest, GlobalDecl_Struct_Invalid) {
|
||||||
|
|
|
@ -91,7 +91,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithAttribute) {
|
||||||
ASSERT_EQ(var->constructor, nullptr);
|
ASSERT_EQ(var->constructor, nullptr);
|
||||||
|
|
||||||
auto& attributes = var->attributes;
|
auto& attributes = var->attributes;
|
||||||
ASSERT_EQ(attributes.size(), 2u);
|
ASSERT_EQ(attributes.Length(), 2u);
|
||||||
ASSERT_TRUE(attributes[0]->Is<ast::BindingAttribute>());
|
ASSERT_TRUE(attributes[0]->Is<ast::BindingAttribute>());
|
||||||
ASSERT_TRUE(attributes[1]->Is<ast::GroupAttribute>());
|
ASSERT_TRUE(attributes[1]->Is<ast::GroupAttribute>());
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithAttribute_MulitpleGroups) {
|
||||||
ASSERT_EQ(var->constructor, nullptr);
|
ASSERT_EQ(var->constructor, nullptr);
|
||||||
|
|
||||||
auto& attributes = var->attributes;
|
auto& attributes = var->attributes;
|
||||||
ASSERT_EQ(attributes.size(), 2u);
|
ASSERT_EQ(attributes.Length(), 2u);
|
||||||
ASSERT_TRUE(attributes[0]->Is<ast::BindingAttribute>());
|
ASSERT_TRUE(attributes[0]->Is<ast::BindingAttribute>());
|
||||||
ASSERT_TRUE(attributes[1]->Is<ast::GroupAttribute>());
|
ASSERT_TRUE(attributes[1]->Is<ast::GroupAttribute>());
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_InvalidConstExpr) {
|
||||||
EXPECT_TRUE(e.errored);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_FALSE(e.matched);
|
EXPECT_FALSE(e.matched);
|
||||||
EXPECT_EQ(e.value, nullptr);
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:24: missing initalizer for 'var' declaration");
|
EXPECT_EQ(p->error(), "1:24: missing initializer for 'var' declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidVariableDecl) {
|
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidVariableDecl) {
|
||||||
|
|
|
@ -28,7 +28,7 @@ TEST_F(ParserImplTest, IfStmt) {
|
||||||
ASSERT_TRUE(e->Is<ast::IfStatement>());
|
ASSERT_TRUE(e->Is<ast::IfStatement>());
|
||||||
ASSERT_NE(e->condition, nullptr);
|
ASSERT_NE(e->condition, nullptr);
|
||||||
ASSERT_TRUE(e->condition->Is<ast::BinaryExpression>());
|
ASSERT_TRUE(e->condition->Is<ast::BinaryExpression>());
|
||||||
EXPECT_EQ(e->body->statements.size(), 2u);
|
EXPECT_EQ(e->body->statements.Length(), 2u);
|
||||||
EXPECT_EQ(e->else_statement, nullptr);
|
EXPECT_EQ(e->else_statement, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,16 +43,16 @@ TEST_F(ParserImplTest, IfStmt_WithElse) {
|
||||||
ASSERT_TRUE(e->Is<ast::IfStatement>());
|
ASSERT_TRUE(e->Is<ast::IfStatement>());
|
||||||
ASSERT_NE(e->condition, nullptr);
|
ASSERT_NE(e->condition, nullptr);
|
||||||
ASSERT_TRUE(e->condition->Is<ast::BinaryExpression>());
|
ASSERT_TRUE(e->condition->Is<ast::BinaryExpression>());
|
||||||
EXPECT_EQ(e->body->statements.size(), 2u);
|
EXPECT_EQ(e->body->statements.Length(), 2u);
|
||||||
|
|
||||||
auto* elseif = As<ast::IfStatement>(e->else_statement);
|
auto* elseif = As<ast::IfStatement>(e->else_statement);
|
||||||
ASSERT_NE(elseif, nullptr);
|
ASSERT_NE(elseif, nullptr);
|
||||||
ASSERT_TRUE(elseif->condition->Is<ast::IdentifierExpression>());
|
ASSERT_TRUE(elseif->condition->Is<ast::IdentifierExpression>());
|
||||||
EXPECT_EQ(elseif->body->statements.size(), 1u);
|
EXPECT_EQ(elseif->body->statements.Length(), 1u);
|
||||||
|
|
||||||
auto* el = As<ast::BlockStatement>(elseif->else_statement);
|
auto* el = As<ast::BlockStatement>(elseif->else_statement);
|
||||||
ASSERT_NE(el, nullptr);
|
ASSERT_NE(el, nullptr);
|
||||||
EXPECT_EQ(el->statements.size(), 0u);
|
EXPECT_EQ(el->statements.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, IfStmt_WithElse_WithParens) {
|
TEST_F(ParserImplTest, IfStmt_WithElse_WithParens) {
|
||||||
|
@ -66,16 +66,16 @@ TEST_F(ParserImplTest, IfStmt_WithElse_WithParens) {
|
||||||
ASSERT_TRUE(e->Is<ast::IfStatement>());
|
ASSERT_TRUE(e->Is<ast::IfStatement>());
|
||||||
ASSERT_NE(e->condition, nullptr);
|
ASSERT_NE(e->condition, nullptr);
|
||||||
ASSERT_TRUE(e->condition->Is<ast::BinaryExpression>());
|
ASSERT_TRUE(e->condition->Is<ast::BinaryExpression>());
|
||||||
EXPECT_EQ(e->body->statements.size(), 2u);
|
EXPECT_EQ(e->body->statements.Length(), 2u);
|
||||||
|
|
||||||
auto* elseif = As<ast::IfStatement>(e->else_statement);
|
auto* elseif = As<ast::IfStatement>(e->else_statement);
|
||||||
ASSERT_NE(elseif, nullptr);
|
ASSERT_NE(elseif, nullptr);
|
||||||
ASSERT_TRUE(elseif->condition->Is<ast::IdentifierExpression>());
|
ASSERT_TRUE(elseif->condition->Is<ast::IdentifierExpression>());
|
||||||
EXPECT_EQ(elseif->body->statements.size(), 1u);
|
EXPECT_EQ(elseif->body->statements.Length(), 1u);
|
||||||
|
|
||||||
auto* el = As<ast::BlockStatement>(elseif->else_statement);
|
auto* el = As<ast::BlockStatement>(elseif->else_statement);
|
||||||
ASSERT_NE(el, nullptr);
|
ASSERT_NE(el, nullptr);
|
||||||
EXPECT_EQ(el->statements.size(), 0u);
|
EXPECT_EQ(el->statements.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, IfStmt_InvalidCondition) {
|
TEST_F(ParserImplTest, IfStmt_InvalidCondition) {
|
||||||
|
|
|
@ -26,10 +26,10 @@ TEST_F(ParserImplTest, LoopStmt_BodyNoContinuing) {
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(e->body->statements.size(), 1u);
|
ASSERT_EQ(e->body->statements.Length(), 1u);
|
||||||
EXPECT_TRUE(e->body->statements[0]->Is<ast::DiscardStatement>());
|
EXPECT_TRUE(e->body->statements[0]->Is<ast::DiscardStatement>());
|
||||||
|
|
||||||
EXPECT_EQ(e->continuing->statements.size(), 0u);
|
EXPECT_EQ(e->continuing->statements.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LoopStmt_BodyWithContinuing) {
|
TEST_F(ParserImplTest, LoopStmt_BodyWithContinuing) {
|
||||||
|
@ -40,10 +40,10 @@ TEST_F(ParserImplTest, LoopStmt_BodyWithContinuing) {
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(e->body->statements.size(), 1u);
|
ASSERT_EQ(e->body->statements.Length(), 1u);
|
||||||
EXPECT_TRUE(e->body->statements[0]->Is<ast::DiscardStatement>());
|
EXPECT_TRUE(e->body->statements[0]->Is<ast::DiscardStatement>());
|
||||||
|
|
||||||
EXPECT_EQ(e->continuing->statements.size(), 1u);
|
EXPECT_EQ(e->continuing->statements.Length(), 1u);
|
||||||
EXPECT_TRUE(e->continuing->statements[0]->Is<ast::DiscardStatement>());
|
EXPECT_TRUE(e->continuing->statements[0]->Is<ast::DiscardStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,8 +54,8 @@ TEST_F(ParserImplTest, LoopStmt_NoBodyNoContinuing) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_EQ(e->body->statements.size(), 0u);
|
ASSERT_EQ(e->body->statements.Length(), 0u);
|
||||||
ASSERT_EQ(e->continuing->statements.size(), 0u);
|
ASSERT_EQ(e->continuing->statements.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LoopStmt_NoBodyWithContinuing) {
|
TEST_F(ParserImplTest, LoopStmt_NoBodyWithContinuing) {
|
||||||
|
@ -65,8 +65,8 @@ TEST_F(ParserImplTest, LoopStmt_NoBodyWithContinuing) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_EQ(e->body->statements.size(), 0u);
|
ASSERT_EQ(e->body->statements.Length(), 0u);
|
||||||
ASSERT_EQ(e->continuing->statements.size(), 1u);
|
ASSERT_EQ(e->continuing->statements.Length(), 1u);
|
||||||
EXPECT_TRUE(e->continuing->statements[0]->Is<ast::DiscardStatement>());
|
EXPECT_TRUE(e->continuing->statements[0]->Is<ast::DiscardStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ TEST_F(ParserImplTest, ParamList_Single) {
|
||||||
auto e = p->expect_param_list();
|
auto e = p->expect_param_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
EXPECT_EQ(e.value.size(), 1u);
|
EXPECT_EQ(e.value.Length(), 1u);
|
||||||
|
|
||||||
EXPECT_EQ(e.value[0]->symbol, p->builder().Symbols().Get("a"));
|
EXPECT_EQ(e.value[0]->symbol, p->builder().Symbols().Get("a"));
|
||||||
EXPECT_TRUE(e.value[0]->type->Is<ast::I32>());
|
EXPECT_TRUE(e.value[0]->type->Is<ast::I32>());
|
||||||
|
@ -41,7 +41,7 @@ TEST_F(ParserImplTest, ParamList_Multiple) {
|
||||||
auto e = p->expect_param_list();
|
auto e = p->expect_param_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
EXPECT_EQ(e.value.size(), 3u);
|
EXPECT_EQ(e.value.Length(), 3u);
|
||||||
|
|
||||||
EXPECT_EQ(e.value[0]->symbol, p->builder().Symbols().Get("a"));
|
EXPECT_EQ(e.value[0]->symbol, p->builder().Symbols().Get("a"));
|
||||||
EXPECT_TRUE(e.value[0]->type->Is<ast::I32>());
|
EXPECT_TRUE(e.value[0]->type->Is<ast::I32>());
|
||||||
|
@ -78,7 +78,7 @@ TEST_F(ParserImplTest, ParamList_Empty) {
|
||||||
auto e = p->expect_param_list();
|
auto e = p->expect_param_list();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
EXPECT_EQ(e.value.size(), 0u);
|
EXPECT_EQ(e.value.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ParamList_TrailingComma) {
|
TEST_F(ParserImplTest, ParamList_TrailingComma) {
|
||||||
|
@ -86,7 +86,7 @@ TEST_F(ParserImplTest, ParamList_TrailingComma) {
|
||||||
auto e = p->expect_param_list();
|
auto e = p->expect_param_list();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
EXPECT_EQ(e.value.size(), 1u);
|
EXPECT_EQ(e.value.Length(), 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ParamList_Attributes) {
|
TEST_F(ParserImplTest, ParamList_Attributes) {
|
||||||
|
@ -95,7 +95,7 @@ TEST_F(ParserImplTest, ParamList_Attributes) {
|
||||||
auto e = p->expect_param_list();
|
auto e = p->expect_param_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
ASSERT_EQ(e.value.size(), 2u);
|
ASSERT_EQ(e.value.Length(), 2u);
|
||||||
|
|
||||||
EXPECT_EQ(e.value[0]->symbol, p->builder().Symbols().Get("coord"));
|
EXPECT_EQ(e.value[0]->symbol, p->builder().Symbols().Get("coord"));
|
||||||
ASSERT_TRUE(e.value[0]->type->Is<ast::Vector>());
|
ASSERT_TRUE(e.value[0]->type->Is<ast::Vector>());
|
||||||
|
@ -103,7 +103,7 @@ TEST_F(ParserImplTest, ParamList_Attributes) {
|
||||||
EXPECT_EQ(e.value[0]->type->As<ast::Vector>()->width, 4u);
|
EXPECT_EQ(e.value[0]->type->As<ast::Vector>()->width, 4u);
|
||||||
EXPECT_TRUE(e.value[0]->Is<ast::Parameter>());
|
EXPECT_TRUE(e.value[0]->Is<ast::Parameter>());
|
||||||
auto attrs_0 = e.value[0]->attributes;
|
auto attrs_0 = e.value[0]->attributes;
|
||||||
ASSERT_EQ(attrs_0.size(), 1u);
|
ASSERT_EQ(attrs_0.Length(), 1u);
|
||||||
EXPECT_TRUE(attrs_0[0]->Is<ast::BuiltinAttribute>());
|
EXPECT_TRUE(attrs_0[0]->Is<ast::BuiltinAttribute>());
|
||||||
EXPECT_EQ(attrs_0[0]->As<ast::BuiltinAttribute>()->builtin, ast::BuiltinValue::kPosition);
|
EXPECT_EQ(attrs_0[0]->As<ast::BuiltinAttribute>()->builtin, ast::BuiltinValue::kPosition);
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ TEST_F(ParserImplTest, ParamList_Attributes) {
|
||||||
EXPECT_TRUE(e.value[1]->type->Is<ast::F32>());
|
EXPECT_TRUE(e.value[1]->type->Is<ast::F32>());
|
||||||
EXPECT_TRUE(e.value[1]->Is<ast::Parameter>());
|
EXPECT_TRUE(e.value[1]->Is<ast::Parameter>());
|
||||||
auto attrs_1 = e.value[1]->attributes;
|
auto attrs_1 = e.value[1]->attributes;
|
||||||
ASSERT_EQ(attrs_1.size(), 1u);
|
ASSERT_EQ(attrs_1.Length(), 1u);
|
||||||
EXPECT_TRUE(attrs_1[0]->Is<ast::LocationAttribute>());
|
EXPECT_TRUE(attrs_1[0]->Is<ast::LocationAttribute>());
|
||||||
EXPECT_EQ(attrs_1[0]->As<ast::LocationAttribute>()->value, 1u);
|
EXPECT_EQ(attrs_1[0]->As<ast::LocationAttribute>()->value, 1u);
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
|
||||||
|
|
||||||
EXPECT_NE(call->target.type, nullptr);
|
EXPECT_NE(call->target.type, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(call->args.size(), 4u);
|
ASSERT_EQ(call->args.Length(), 4u);
|
||||||
const auto& val = call->args;
|
const auto& val = call->args;
|
||||||
ASSERT_TRUE(val[0]->Is<ast::IntLiteralExpression>());
|
ASSERT_TRUE(val[0]->Is<ast::IntLiteralExpression>());
|
||||||
EXPECT_EQ(val[0]->As<ast::IntLiteralExpression>()->value, 1);
|
EXPECT_EQ(val[0]->As<ast::IntLiteralExpression>()->value, 1);
|
||||||
|
@ -76,7 +76,7 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_ZeroConstructor) {
|
||||||
ASSERT_TRUE(e->Is<ast::CallExpression>());
|
ASSERT_TRUE(e->Is<ast::CallExpression>());
|
||||||
auto* call = e->As<ast::CallExpression>();
|
auto* call = e->As<ast::CallExpression>();
|
||||||
|
|
||||||
ASSERT_EQ(call->args.size(), 0u);
|
ASSERT_EQ(call->args.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidTypeDecl) {
|
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidTypeDecl) {
|
||||||
|
@ -140,7 +140,7 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_StructConstructor_Empty) {
|
||||||
ASSERT_NE(call->target.name, nullptr);
|
ASSERT_NE(call->target.name, nullptr);
|
||||||
EXPECT_EQ(call->target.name->symbol, p->builder().Symbols().Get("S"));
|
EXPECT_EQ(call->target.name->symbol, p->builder().Symbols().Get("S"));
|
||||||
|
|
||||||
ASSERT_EQ(call->args.size(), 0u);
|
ASSERT_EQ(call->args.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_StructConstructor_NotEmpty) {
|
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_StructConstructor_NotEmpty) {
|
||||||
|
@ -164,7 +164,7 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_StructConstructor_NotEmpty) {
|
||||||
ASSERT_NE(call->target.name, nullptr);
|
ASSERT_NE(call->target.name, nullptr);
|
||||||
EXPECT_EQ(call->target.name->symbol, p->builder().Symbols().Get("S"));
|
EXPECT_EQ(call->target.name->symbol, p->builder().Symbols().Get("S"));
|
||||||
|
|
||||||
ASSERT_EQ(call->args.size(), 2u);
|
ASSERT_EQ(call->args.Length(), 2u);
|
||||||
|
|
||||||
ASSERT_TRUE(call->args[0]->Is<ast::IntLiteralExpression>());
|
ASSERT_TRUE(call->args[0]->Is<ast::IntLiteralExpression>());
|
||||||
EXPECT_EQ(call->args[0]->As<ast::IntLiteralExpression>()->value, 1u);
|
EXPECT_EQ(call->args[0]->As<ast::IntLiteralExpression>()->value, 1u);
|
||||||
|
@ -239,7 +239,7 @@ TEST_F(ParserImplTest, PrimaryExpression_Cast) {
|
||||||
auto* call = e->As<ast::CallExpression>();
|
auto* call = e->As<ast::CallExpression>();
|
||||||
|
|
||||||
ASSERT_TRUE(call->target.type->Is<ast::F32>());
|
ASSERT_TRUE(call->target.type->Is<ast::F32>());
|
||||||
ASSERT_EQ(call->args.size(), 1u);
|
ASSERT_EQ(call->args.Length(), 1u);
|
||||||
|
|
||||||
ASSERT_TRUE(call->args[0]->Is<ast::IntLiteralExpression>());
|
ASSERT_TRUE(call->args[0]->Is<ast::IntLiteralExpression>());
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ TEST_F(ParserImplTest, SingularExpression_Call_Empty) {
|
||||||
|
|
||||||
EXPECT_EQ(c->target.name->symbol, p->builder().Symbols().Get("a"));
|
EXPECT_EQ(c->target.name->symbol, p->builder().Symbols().Get("a"));
|
||||||
|
|
||||||
EXPECT_EQ(c->args.size(), 0u);
|
EXPECT_EQ(c->args.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SingularExpression_Call_WithArgs) {
|
TEST_F(ParserImplTest, SingularExpression_Call_WithArgs) {
|
||||||
|
@ -115,7 +115,7 @@ TEST_F(ParserImplTest, SingularExpression_Call_WithArgs) {
|
||||||
|
|
||||||
EXPECT_EQ(c->target.name->symbol, p->builder().Symbols().Get("test"));
|
EXPECT_EQ(c->target.name->symbol, p->builder().Symbols().Get("test"));
|
||||||
|
|
||||||
EXPECT_EQ(c->args.size(), 3u);
|
EXPECT_EQ(c->args.Length(), 3u);
|
||||||
EXPECT_TRUE(c->args[0]->Is<ast::IntLiteralExpression>());
|
EXPECT_TRUE(c->args[0]->Is<ast::IntLiteralExpression>());
|
||||||
EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>());
|
EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>());
|
||||||
EXPECT_TRUE(c->args[2]->Is<ast::BinaryExpression>());
|
EXPECT_TRUE(c->args[2]->Is<ast::BinaryExpression>());
|
||||||
|
@ -130,7 +130,7 @@ TEST_F(ParserImplTest, SingularExpression_Call_TrailingComma) {
|
||||||
|
|
||||||
ASSERT_TRUE(e->Is<ast::CallExpression>());
|
ASSERT_TRUE(e->Is<ast::CallExpression>());
|
||||||
auto* c = e->As<ast::CallExpression>();
|
auto* c = e->As<ast::CallExpression>();
|
||||||
EXPECT_EQ(c->args.size(), 1u);
|
EXPECT_EQ(c->args.Length(), 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SingularExpression_Call_InvalidArg) {
|
TEST_F(ParserImplTest, SingularExpression_Call_InvalidArg) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ TEST_F(ParserImplTest, Statements) {
|
||||||
auto e = p->expect_statements();
|
auto e = p->expect_statements();
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e->size(), 2u);
|
ASSERT_EQ(e->Length(), 2u);
|
||||||
EXPECT_TRUE(e.value[0]->Is<ast::DiscardStatement>());
|
EXPECT_TRUE(e.value[0]->Is<ast::DiscardStatement>());
|
||||||
EXPECT_TRUE(e.value[1]->Is<ast::ReturnStatement>());
|
EXPECT_TRUE(e.value[1]->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ TEST_F(ParserImplTest, Statements_Empty) {
|
||||||
auto e = p->expect_statements();
|
auto e = p->expect_statements();
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e->size(), 0u);
|
ASSERT_EQ(e->Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -24,7 +24,7 @@ TEST_F(ParserImplTest, AttributeDecl_Parses) {
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_FALSE(attrs.errored);
|
EXPECT_FALSE(attrs.errored);
|
||||||
EXPECT_TRUE(attrs.matched);
|
EXPECT_TRUE(attrs.matched);
|
||||||
ASSERT_EQ(attrs.value.size(), 1u);
|
ASSERT_EQ(attrs.value.Length(), 1u);
|
||||||
auto* invariant = attrs.value[0]->As<ast::Attribute>();
|
auto* invariant = attrs.value[0]->As<ast::Attribute>();
|
||||||
EXPECT_TRUE(invariant->Is<ast::InvariantAttribute>());
|
EXPECT_TRUE(invariant->Is<ast::InvariantAttribute>());
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ TEST_F(ParserImplTest, AttributeDecl_MissingParenLeft) {
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_TRUE(attrs.errored);
|
EXPECT_TRUE(attrs.errored);
|
||||||
EXPECT_FALSE(attrs.matched);
|
EXPECT_FALSE(attrs.matched);
|
||||||
EXPECT_TRUE(attrs.value.empty());
|
EXPECT_TRUE(attrs.value.IsEmpty());
|
||||||
EXPECT_EQ(p->error(), "1:11: expected '(' for location attribute");
|
EXPECT_EQ(p->error(), "1:11: expected '(' for location attribute");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ TEST_F(ParserImplTest, AttributeDecl_MissingValue) {
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_TRUE(attrs.errored);
|
EXPECT_TRUE(attrs.errored);
|
||||||
EXPECT_FALSE(attrs.matched);
|
EXPECT_FALSE(attrs.matched);
|
||||||
EXPECT_TRUE(attrs.value.empty());
|
EXPECT_TRUE(attrs.value.IsEmpty());
|
||||||
EXPECT_EQ(p->error(), "1:11: expected signed integer literal for location attribute");
|
EXPECT_EQ(p->error(), "1:11: expected signed integer literal for location attribute");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ TEST_F(ParserImplTest, AttributeDecl_MissingParenRight) {
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_TRUE(attrs.errored);
|
EXPECT_TRUE(attrs.errored);
|
||||||
EXPECT_FALSE(attrs.matched);
|
EXPECT_FALSE(attrs.matched);
|
||||||
EXPECT_TRUE(attrs.value.empty());
|
EXPECT_TRUE(attrs.value.IsEmpty());
|
||||||
EXPECT_EQ(p->error(), "1:12: expected ')' for location attribute");
|
EXPECT_EQ(p->error(), "1:12: expected ')' for location attribute");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ TEST_F(ParserImplTest, AttributeDecl_Invalidattribute) {
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_TRUE(attrs.errored);
|
EXPECT_TRUE(attrs.errored);
|
||||||
EXPECT_FALSE(attrs.matched);
|
EXPECT_FALSE(attrs.matched);
|
||||||
EXPECT_TRUE(attrs.value.empty());
|
EXPECT_TRUE(attrs.value.IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -25,12 +25,12 @@ TEST_F(ParserImplTest, StructBodyDecl_Parses) {
|
||||||
auto m = p->expect_struct_body_decl();
|
auto m = p->expect_struct_body_decl();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_FALSE(m.errored);
|
ASSERT_FALSE(m.errored);
|
||||||
ASSERT_EQ(m.value.size(), 1u);
|
ASSERT_EQ(m.value.Length(), 1u);
|
||||||
|
|
||||||
const auto* mem = m.value[0];
|
const auto* mem = m.value[0];
|
||||||
EXPECT_EQ(mem->symbol, builder.Symbols().Get("a"));
|
EXPECT_EQ(mem->symbol, builder.Symbols().Get("a"));
|
||||||
EXPECT_TRUE(mem->type->Is<ast::I32>());
|
EXPECT_TRUE(mem->type->Is<ast::I32>());
|
||||||
EXPECT_EQ(mem->attributes.size(), 0u);
|
EXPECT_EQ(mem->attributes.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructBodyDecl_Parses_TrailingComma) {
|
TEST_F(ParserImplTest, StructBodyDecl_Parses_TrailingComma) {
|
||||||
|
@ -41,12 +41,12 @@ TEST_F(ParserImplTest, StructBodyDecl_Parses_TrailingComma) {
|
||||||
auto m = p->expect_struct_body_decl();
|
auto m = p->expect_struct_body_decl();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_FALSE(m.errored);
|
ASSERT_FALSE(m.errored);
|
||||||
ASSERT_EQ(m.value.size(), 1u);
|
ASSERT_EQ(m.value.Length(), 1u);
|
||||||
|
|
||||||
const auto* mem = m.value[0];
|
const auto* mem = m.value[0];
|
||||||
EXPECT_EQ(mem->symbol, builder.Symbols().Get("a"));
|
EXPECT_EQ(mem->symbol, builder.Symbols().Get("a"));
|
||||||
EXPECT_TRUE(mem->type->Is<ast::I32>());
|
EXPECT_TRUE(mem->type->Is<ast::I32>());
|
||||||
EXPECT_EQ(mem->attributes.size(), 0u);
|
EXPECT_EQ(mem->attributes.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructBodyDecl_ParsesEmpty) {
|
TEST_F(ParserImplTest, StructBodyDecl_ParsesEmpty) {
|
||||||
|
@ -54,7 +54,7 @@ TEST_F(ParserImplTest, StructBodyDecl_ParsesEmpty) {
|
||||||
auto m = p->expect_struct_body_decl();
|
auto m = p->expect_struct_body_decl();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_FALSE(m.errored);
|
ASSERT_FALSE(m.errored);
|
||||||
ASSERT_EQ(m.value.size(), 0u);
|
ASSERT_EQ(m.value.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructBodyDecl_InvalidAlign) {
|
TEST_F(ParserImplTest, StructBodyDecl_InvalidAlign) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ struct S {
|
||||||
EXPECT_TRUE(s.matched);
|
EXPECT_TRUE(s.matched);
|
||||||
ASSERT_NE(s.value, nullptr);
|
ASSERT_NE(s.value, nullptr);
|
||||||
ASSERT_EQ(s->name, p->builder().Symbols().Register("S"));
|
ASSERT_EQ(s->name, p->builder().Symbols().Register("S"));
|
||||||
ASSERT_EQ(s->members.size(), 2u);
|
ASSERT_EQ(s->members.Length(), 2u);
|
||||||
EXPECT_EQ(s->members[0]->symbol, p->builder().Symbols().Register("a"));
|
EXPECT_EQ(s->members[0]->symbol, p->builder().Symbols().Register("a"));
|
||||||
EXPECT_EQ(s->members[1]->symbol, p->builder().Symbols().Register("b"));
|
EXPECT_EQ(s->members[1]->symbol, p->builder().Symbols().Register("b"));
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ struct $struct {
|
||||||
EXPECT_TRUE(s.matched);
|
EXPECT_TRUE(s.matched);
|
||||||
ASSERT_NE(s.value, nullptr);
|
ASSERT_NE(s.value, nullptr);
|
||||||
ASSERT_EQ(s->name, p->builder().Symbols().Register(struct_ident));
|
ASSERT_EQ(s->name, p->builder().Symbols().Register(struct_ident));
|
||||||
ASSERT_EQ(s->members.size(), 2u);
|
ASSERT_EQ(s->members.Length(), 2u);
|
||||||
EXPECT_EQ(s->members[0]->symbol, p->builder().Symbols().Register(member_a_ident));
|
EXPECT_EQ(s->members[0]->symbol, p->builder().Symbols().Register(member_a_ident));
|
||||||
EXPECT_EQ(s->members[1]->symbol, p->builder().Symbols().Register(member_b_ident));
|
EXPECT_EQ(s->members[1]->symbol, p->builder().Symbols().Register(member_b_ident));
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ TEST_F(ParserImplTest, StructDecl_EmptyMembers) {
|
||||||
EXPECT_FALSE(s.errored);
|
EXPECT_FALSE(s.errored);
|
||||||
EXPECT_TRUE(s.matched);
|
EXPECT_TRUE(s.matched);
|
||||||
ASSERT_NE(s.value, nullptr);
|
ASSERT_NE(s.value, nullptr);
|
||||||
ASSERT_EQ(s->members.size(), 0u);
|
ASSERT_EQ(s->members.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructDecl_MissingIdent) {
|
TEST_F(ParserImplTest, StructDecl_MissingIdent) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ TEST_F(ParserImplTest, AttributeDecl_EmptyStr) {
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_FALSE(attrs.errored);
|
EXPECT_FALSE(attrs.errored);
|
||||||
EXPECT_FALSE(attrs.matched);
|
EXPECT_FALSE(attrs.matched);
|
||||||
EXPECT_EQ(attrs.value.size(), 0u);
|
EXPECT_EQ(attrs.value.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, AttributeDecl_Single) {
|
TEST_F(ParserImplTest, AttributeDecl_Single) {
|
||||||
|
@ -32,7 +32,7 @@ TEST_F(ParserImplTest, AttributeDecl_Single) {
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_FALSE(attrs.errored);
|
EXPECT_FALSE(attrs.errored);
|
||||||
EXPECT_TRUE(attrs.matched);
|
EXPECT_TRUE(attrs.matched);
|
||||||
ASSERT_EQ(attrs.value.size(), 1u);
|
ASSERT_EQ(attrs.value.Length(), 1u);
|
||||||
auto* attr = attrs.value[0]->As<ast::Attribute>();
|
auto* attr = attrs.value[0]->As<ast::Attribute>();
|
||||||
ASSERT_NE(attr, nullptr);
|
ASSERT_NE(attr, nullptr);
|
||||||
EXPECT_TRUE(attr->Is<ast::StructMemberSizeAttribute>());
|
EXPECT_TRUE(attr->Is<ast::StructMemberSizeAttribute>());
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue